From e20e23fe6dcd2a5c56ee09a820329174f740b5a8 Mon Sep 17 00:00:00 2001 From: Naveed Jooma Date: Tue, 30 Jul 2024 11:00:04 -0400 Subject: [PATCH] [RSDK-8312] Collect and send API and SDK version in metadata (#53) --- .github/workflows/update-protos.yml | 4 ++++ Makefile | 9 +++++++-- api_version.lock | 1 + buf.gen.yaml | 6 +++--- build.gradle | 3 +++ core/sdk/build.gradle | 20 +++++++++++++++++++ .../sdk/core/rpc/BasicManagedChannel.java | 15 +++++++------- .../java/com/viam/sdk/core/rpc/Dialer.java | 5 +---- .../viam/sdk/core/webrtc/ClientStream.java | 8 +++++--- .../kotlin/com/viam/sdk/core/util/Media.kt | 2 -- .../kotlin/com/viam/sdk/core/util/Metadata.kt | 14 +++++++++++++ .../com/viam/sdk/core/util/VersionInfo.kt | 4 ++++ .../com/viam/sdk/core/util/MetadataTest.kt | 19 ++++++++++++++++++ 13 files changed, 89 insertions(+), 21 deletions(-) create mode 100644 api_version.lock create mode 100644 core/sdk/src/main/kotlin/com/viam/sdk/core/util/Metadata.kt create mode 100644 core/sdk/src/main/kotlin/com/viam/sdk/core/util/VersionInfo.kt create mode 100644 core/sdk/src/test/kotlin/com/viam/sdk/core/util/MetadataTest.kt diff --git a/.github/workflows/update-protos.yml b/.github/workflows/update-protos.yml index 685f90575..90dd83c06 100644 --- a/.github/workflows/update-protos.yml +++ b/.github/workflows/update-protos.yml @@ -19,6 +19,10 @@ jobs: with: repo-token: ${{ secrets.GITHUB_TOKEN }} + - name: Set API Version + run: | + echo ${{ github.event.client_payload.tag }} > api_version.lock + - name: Generate buf run: make buf diff --git a/Makefile b/Makefile index 4448a7813..131e629ff 100644 --- a/Makefile +++ b/Makefile @@ -1,20 +1,25 @@ +.PHONY: buf buf: rm -rf core/sdk/src/main/gen rm -rf core/sdk/src/main/resources/protofds mkdir -p core/sdk/src/main/resources/protofds - buf build --as-file-descriptor-set=true -o core/sdk/src/main/resources/protofds/viam.api buf.build/viamrobotics/api - buf generate --template buf.gen.yaml buf.build/viamrobotics/api + buf build --as-file-descriptor-set=true -o core/sdk/src/main/resources/protofds/viam.api buf.build/viamrobotics/api:$$(cat api_version.lock) + buf generate --template buf.gen.yaml buf.build/viamrobotics/api:$$(cat api_version.lock) buf generate --template buf.gen.yaml buf.build/viamrobotics/goutils buf generate --template buf.gen.yaml buf.build/googleapis/googleapis +.PHONY: run_client run_client: ./gradlew runExample1Client --args="localhost:8080" +.PHONY: run_client_webrtc_auth run_client_webrtc_auth: ./gradlew runExample2Client +.PHONY: run_client_grpc_auth run_client_grpc_auth: ./gradlew runExample3Client +.PHONY: run_server run_server: ./gradlew runExample1Server --args="8080" diff --git a/api_version.lock b/api_version.lock new file mode 100644 index 000000000..35d19fbfb --- /dev/null +++ b/api_version.lock @@ -0,0 +1 @@ +v0.1.327 diff --git a/buf.gen.yaml b/buf.gen.yaml index 577697250..78fa09115 100644 --- a/buf.gen.yaml +++ b/buf.gen.yaml @@ -1,8 +1,8 @@ -version: v1 +version: v2 plugins: - - plugin: buf.build/protocolbuffers/java:v25.2 + - remote: buf.build/protocolbuffers/java:v27.2 out: core/sdk/src/main/gen opt: lite - - plugin: buf.build/grpc/java:v1.61.1 + - remote: buf.build/grpc/java:v1.65.1 out: core/sdk/src/main/gen opt: lite diff --git a/build.gradle b/build.gradle index a9e3346ef..7a8cc1339 100644 --- a/build.gradle +++ b/build.gradle @@ -41,6 +41,9 @@ subprojects { ext { min_api = 29 target_api = 34 + api_version = "unreleased" + File file = rootProject.file("api_version.lock") + file.withReader { reader -> api_version = reader.readLine() } } def pomConfig = { diff --git a/core/sdk/build.gradle b/core/sdk/build.gradle index 29895ceea..dab20c260 100644 --- a/core/sdk/build.gradle +++ b/core/sdk/build.gradle @@ -55,3 +55,23 @@ repositories { kotlin { jvmToolchain(11) } + +abstract class CreateVersionFileTask extends DefaultTask { + @TaskAction + def action() { + File root = project.file("src/main/kotlin/com/viam/sdk/core/util/VersionInfo.kt") + root.withWriter { + writer -> { + writer.writeLine("package com.viam.sdk.core.util\n") + writer.writeLine("const val SDK_VERSION = \"v$project.version\"") + writer.writeLine("const val API_VERSION = \"$project.api_version\"") + } + } + } +} + +tasks.register("createVersionsFile", CreateVersionFileTask) + +afterEvaluate { + tasks.compileJava.dependsOn 'createVersionsFile' +} diff --git a/core/sdk/src/main/java/com/viam/sdk/core/rpc/BasicManagedChannel.java b/core/sdk/src/main/java/com/viam/sdk/core/rpc/BasicManagedChannel.java index 371ff5177..5400a08fe 100644 --- a/core/sdk/src/main/java/com/viam/sdk/core/rpc/BasicManagedChannel.java +++ b/core/sdk/src/main/java/com/viam/sdk/core/rpc/BasicManagedChannel.java @@ -1,15 +1,15 @@ package com.viam.sdk.core.rpc; -import io.grpc.CallCredentials; -import io.grpc.CallOptions; -import io.grpc.ClientCall; -import io.grpc.ManagedChannel; -import io.grpc.MethodDescriptor; +import io.grpc.*; +import io.grpc.stub.MetadataUtils; + import java.util.Optional; +import com.viam.sdk.core.util.Metadata; + public class BasicManagedChannel extends Channel { - private final ManagedChannel channel; + private final io.grpc.Channel channel; private final CallCredentials callCreds; public BasicManagedChannel(final ManagedChannel channel) { @@ -17,7 +17,8 @@ public BasicManagedChannel(final ManagedChannel channel) { } public BasicManagedChannel(final ManagedChannel channel, final CallCredentials callCreds) { - this.channel = channel; + ClientInterceptor versionInterceptor = MetadataUtils.newAttachHeadersInterceptor(Metadata.getVERSION_METADATA()); + this.channel = ClientInterceptors.intercept(channel, versionInterceptor); this.callCreds = callCreds; } diff --git a/core/sdk/src/main/java/com/viam/sdk/core/rpc/Dialer.java b/core/sdk/src/main/java/com/viam/sdk/core/rpc/Dialer.java index cf72e3692..acce4cdea 100644 --- a/core/sdk/src/main/java/com/viam/sdk/core/rpc/Dialer.java +++ b/core/sdk/src/main/java/com/viam/sdk/core/rpc/Dialer.java @@ -14,10 +14,7 @@ import com.viam.sdk.core.webrtc.PeerConnection; import com.viam.sdk.core.webrtc.PeerConnectionFactory; import com.viam.sdk.core.webrtc.SessionDescription; -import io.grpc.CallCredentials; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import io.grpc.Metadata; +import io.grpc.*; import io.grpc.stub.MetadataUtils; import java.io.Closeable; import java.nio.charset.StandardCharsets; diff --git a/core/sdk/src/main/java/com/viam/sdk/core/webrtc/ClientStream.java b/core/sdk/src/main/java/com/viam/sdk/core/webrtc/ClientStream.java index 66ecd55dd..2d9fd9a61 100644 --- a/core/sdk/src/main/java/com/viam/sdk/core/webrtc/ClientStream.java +++ b/core/sdk/src/main/java/com/viam/sdk/core/webrtc/ClientStream.java @@ -84,6 +84,8 @@ private static Metadata toGRPCMetadata(final Grpc.Metadata metadata) { @Override public void start(final Listener responseListener, Metadata headers) { + headers.merge(com.viam.sdk.core.util.Metadata.getVERSION_METADATA()); + this.responseListener = responseListener; final String method = "/" + this.methodDescriptor.getFullMethodName(); final Grpc.RequestHeaders requestHeaders = Grpc.RequestHeaders.newBuilder() @@ -136,7 +138,7 @@ public void sendMessage(RequestT message) { } private void writeMessage(boolean eos, List msgBytes) { - if (msgBytes == null || msgBytes.size() == 0) { + if (msgBytes == null || msgBytes.isEmpty()) { final Grpc.PacketMessage packet = Grpc.PacketMessage.newBuilder() .setEom(true) .build(); @@ -149,12 +151,12 @@ private void writeMessage(boolean eos, List msgBytes) { return; } - while (msgBytes.size() != 0) { + while (!msgBytes.isEmpty()) { final int amountToSend = Math.min(msgBytes.size(), MAX_REQUEST_MESSAGE_PACKET_DATA_SIZE); final Grpc.PacketMessage.Builder packetBuilder = Grpc.PacketMessage.newBuilder(); packetBuilder.setData(ByteString.copyFrom(Bytes.toArray(msgBytes.subList(0, amountToSend)))); msgBytes = msgBytes.subList(amountToSend, msgBytes.size()); - if (msgBytes.size() == 0) { + if (msgBytes.isEmpty()) { packetBuilder.setEom(true); } final Grpc.RequestMessage requestMessage = Grpc.RequestMessage.newBuilder() diff --git a/core/sdk/src/main/kotlin/com/viam/sdk/core/util/Media.kt b/core/sdk/src/main/kotlin/com/viam/sdk/core/util/Media.kt index ed7ddfd58..c7a0586d3 100644 --- a/core/sdk/src/main/kotlin/com/viam/sdk/core/util/Media.kt +++ b/core/sdk/src/main/kotlin/com/viam/sdk/core/util/Media.kt @@ -1,5 +1,4 @@ @file:JvmName("MediaUtils") - package com.viam.sdk.core.util import com.viam.component.camera.v1.Camera.Format @@ -153,7 +152,6 @@ private fun getDimensionsFromPNG(image: Iterable): ImageDimensions { val width = header.getInt(4) val height = header.getInt(8) return ImageDimensions(width, height) - } private fun getDimensionsFromViamRGBA(image: Iterable): ImageDimensions { diff --git a/core/sdk/src/main/kotlin/com/viam/sdk/core/util/Metadata.kt b/core/sdk/src/main/kotlin/com/viam/sdk/core/util/Metadata.kt new file mode 100644 index 000000000..0340bc25d --- /dev/null +++ b/core/sdk/src/main/kotlin/com/viam/sdk/core/util/Metadata.kt @@ -0,0 +1,14 @@ +@file:JvmName("Metadata") +package com.viam.sdk.core.util + +import io.grpc.Metadata + +/** + * Metadata containing client and API versions + */ +val VERSION_METADATA: Metadata + get() { + val md = Metadata() + md.put(Metadata.Key.of("viam_client", Metadata.ASCII_STRING_MARSHALLER), "java;$SDK_VERSION;$API_VERSION") + return md; + } diff --git a/core/sdk/src/main/kotlin/com/viam/sdk/core/util/VersionInfo.kt b/core/sdk/src/main/kotlin/com/viam/sdk/core/util/VersionInfo.kt new file mode 100644 index 000000000..fb9acbd45 --- /dev/null +++ b/core/sdk/src/main/kotlin/com/viam/sdk/core/util/VersionInfo.kt @@ -0,0 +1,4 @@ +package com.viam.sdk.core.util + +const val SDK_VERSION = "v0.0.5" +const val API_VERSION = "v0.1.327" diff --git a/core/sdk/src/test/kotlin/com/viam/sdk/core/util/MetadataTest.kt b/core/sdk/src/test/kotlin/com/viam/sdk/core/util/MetadataTest.kt new file mode 100644 index 000000000..2617bc5b7 --- /dev/null +++ b/core/sdk/src/test/kotlin/com/viam/sdk/core/util/MetadataTest.kt @@ -0,0 +1,19 @@ +package com.viam.sdk.core.util + +import io.grpc.Metadata +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.Assertions.* + +class MetadataTest { + + @Test + fun getVersionMetadata() { + val metadata = VERSION_METADATA + val versionString = metadata.get(Metadata.Key.of("viam_client", Metadata.ASCII_STRING_MARSHALLER)) + assertNotNull(versionString) + val components = versionString!!.split(";") + assertEquals(components[0], "java") + assertTrue(components[1].matches("v[0-9]+\\.[0-9]+\\.[0-9]+".toRegex())) + assertTrue(components[2].matches("(v[0-9]+\\.[0-9]+\\.[0-9]+)|unreleased".toRegex())) + } +}