diff --git a/MODULE.bazel b/MODULE.bazel index 4465f46e6c5..afef9a2e976 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -2,7 +2,7 @@ module( name = "grpc-java", compatibility_level = 0, repo_name = "io_grpc_grpc_java", - version = "1.76.0-SNAPSHOT", # CURRENT_GRPC_VERSION + version = "1.76.4-SNAPSHOT", # CURRENT_GRPC_VERSION ) # GRPC_DEPS_START diff --git a/README.md b/README.md index d696164ee32..ec778ab7191 100644 --- a/README.md +++ b/README.md @@ -44,8 +44,8 @@ For a guided tour, take a look at the [quick start guide](https://grpc.io/docs/languages/java/quickstart) or the more explanatory [gRPC basics](https://grpc.io/docs/languages/java/basics). -The [examples](https://github.com/grpc/grpc-java/tree/v1.75.0/examples) and the -[Android example](https://github.com/grpc/grpc-java/tree/v1.75.0/examples/android) +The [examples](https://github.com/grpc/grpc-java/tree/v1.76.3/examples) and the +[Android example](https://github.com/grpc/grpc-java/tree/v1.76.3/examples/android) are standalone projects that showcase the usage of gRPC. Download @@ -56,34 +56,34 @@ Download [the JARs][]. Or for Maven with non-Android, add to your `pom.xml`: io.grpc grpc-netty-shaded - 1.75.0 + 1.76.3 runtime io.grpc grpc-protobuf - 1.75.0 + 1.76.3 io.grpc grpc-stub - 1.75.0 + 1.76.3 ``` Or for Gradle with non-Android, add to your dependencies: ```gradle -runtimeOnly 'io.grpc:grpc-netty-shaded:1.75.0' -implementation 'io.grpc:grpc-protobuf:1.75.0' -implementation 'io.grpc:grpc-stub:1.75.0' +runtimeOnly 'io.grpc:grpc-netty-shaded:1.76.3' +implementation 'io.grpc:grpc-protobuf:1.76.3' +implementation 'io.grpc:grpc-stub:1.76.3' ``` For Android client, use `grpc-okhttp` instead of `grpc-netty-shaded` and `grpc-protobuf-lite` instead of `grpc-protobuf`: ```gradle -implementation 'io.grpc:grpc-okhttp:1.75.0' -implementation 'io.grpc:grpc-protobuf-lite:1.75.0' -implementation 'io.grpc:grpc-stub:1.75.0' +implementation 'io.grpc:grpc-okhttp:1.76.3' +implementation 'io.grpc:grpc-protobuf-lite:1.76.3' +implementation 'io.grpc:grpc-stub:1.76.3' ``` For [Bazel](https://bazel.build), you can either @@ -91,7 +91,7 @@ For [Bazel](https://bazel.build), you can either (with the GAVs from above), or use `@io_grpc_grpc_java//api` et al (see below). [the JARs]: -https://search.maven.org/search?q=g:io.grpc%20AND%20v:1.75.0 +https://search.maven.org/search?q=g:io.grpc%20AND%20v:1.76.3 Development snapshots are available in [Sonatypes's snapshot repository](https://central.sonatype.com/repository/maven-snapshots/). @@ -121,9 +121,9 @@ For protobuf-based codegen integrated with the Maven build system, you can use protobuf-maven-plugin 0.6.1 - com.google.protobuf:protoc:3.25.5:exe:${os.detected.classifier} + com.google.protobuf:protoc:3.25.8:exe:${os.detected.classifier} grpc-java - io.grpc:protoc-gen-grpc-java:1.75.0:exe:${os.detected.classifier} + io.grpc:protoc-gen-grpc-java:1.76.3:exe:${os.detected.classifier} @@ -149,11 +149,11 @@ plugins { protobuf { protoc { - artifact = "com.google.protobuf:protoc:3.25.5" + artifact = "com.google.protobuf:protoc:3.25.8" } plugins { grpc { - artifact = 'io.grpc:protoc-gen-grpc-java:1.75.0' + artifact = 'io.grpc:protoc-gen-grpc-java:1.76.3' } } generateProtoTasks { @@ -182,11 +182,11 @@ plugins { protobuf { protoc { - artifact = "com.google.protobuf:protoc:3.25.5" + artifact = "com.google.protobuf:protoc:3.25.8" } plugins { grpc { - artifact = 'io.grpc:protoc-gen-grpc-java:1.75.0' + artifact = 'io.grpc:protoc-gen-grpc-java:1.76.3' } } generateProtoTasks { diff --git a/api/src/main/java/io/grpc/StatusOr.java b/api/src/main/java/io/grpc/StatusOr.java index 0f1e9da3c75..b7dd68cfd7b 100644 --- a/api/src/main/java/io/grpc/StatusOr.java +++ b/api/src/main/java/io/grpc/StatusOr.java @@ -33,7 +33,7 @@ private StatusOr(Status status, T value) { } /** Construct from a value. */ - public static StatusOr fromValue(@Nullable T value) { + public static StatusOr fromValue(T value) { StatusOr result = new StatusOr(null, value); return result; } @@ -54,7 +54,7 @@ public boolean hasValue() { * Returns the value if set or throws exception if there is no value set. This method is meant * to be called after checking the return value of hasValue() first. */ - public @Nullable T getValue() { + public T getValue() { if (status != null) { throw new IllegalStateException("No value present."); } @@ -105,6 +105,7 @@ public String toString() { return stringHelper.toString(); } + @Nullable private final Status status; private final T value; } diff --git a/build.gradle b/build.gradle index 366edf1b9e5..3bcabc5b8bf 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ subprojects { apply plugin: "net.ltgt.errorprone" group = "io.grpc" - version = "1.76.0-SNAPSHOT" // CURRENT_GRPC_VERSION + version = "1.76.4-SNAPSHOT" // CURRENT_GRPC_VERSION repositories { maven { // The google mirror is less flaky than mavenCentral() diff --git a/buildscripts/cloudbuild-testing.yaml b/buildscripts/cloudbuild-testing.yaml new file mode 100644 index 00000000000..623b85b6882 --- /dev/null +++ b/buildscripts/cloudbuild-testing.yaml @@ -0,0 +1,64 @@ +substitutions: + _GAE_SERVICE_ACCOUNT: appengine-testing-java@grpc-testing.iam.gserviceaccount.com +options: + env: + - BUILD_ID=$BUILD_ID + - KOKORO_GAE_SERVICE=java-gae-interop-test + - DUMMY_DEFAULT_VERSION=dummy-default + - GRADLE_OPTS=-Dorg.gradle.jvmargs='-Xmx1g' + - GRADLE_FLAGS=-PskipCodegen=true -PskipAndroid=true + logging: CLOUD_LOGGING_ONLY + machineType: E2_HIGHCPU_8 + +steps: +- id: clean-stale-deploys + name: gcr.io/cloud-builders/gcloud + allowFailure: true + script: | + #!/usr/bin/env bash + set -e + echo "Cleaning out stale deploys from previous runs, it is ok if this part fails" + # If the test fails, the deployment is leaked. + # Delete all versions whose name is not 'dummy-default' and is older than 1 hour. + # This expression is an ISO8601 relative date: + # https://cloud.google.com/sdk/gcloud/reference/topic/datetimes + (gcloud app versions list --format="get(version.id)" \ + --filter="service=$KOKORO_GAE_SERVICE AND NOT version : '$DUMMY_DEFAULT_VERSION' AND version.createTime<'-p1h'" \ + | xargs -i gcloud app services delete "$KOKORO_GAE_SERVICE" --version {} --quiet) || true + +- name: gcr.io/cloud-builders/docker + args: ['build', '-t', 'gae-build', 'buildscripts/gae-build/'] + +- id: build + name: gae-build + script: | + #!/usr/bin/env bash + exec ./gradlew $GRADLE_FLAGS :grpc-gae-interop-testing-jdk8:appengineStage + +- id: deploy + name: gcr.io/cloud-builders/gcloud + args: + - app + - deploy + - gae-interop-testing/gae-jdk8/build/staged-app/app.yaml + - --service-account=$_GAE_SERVICE_ACCOUNT + - --no-promote + - --no-stop-previous-version + - --version=cb-$BUILD_ID + +- id: runInteropTestRemote + name: eclipse-temurin:17-jdk + env: + - PROJECT_ID=$PROJECT_ID + script: | + #!/usr/bin/env bash + exec ./gradlew $GRADLE_FLAGS --stacktrace -PgaeDeployVersion="cb-$BUILD_ID" \ + -PgaeProjectId="$PROJECT_ID" :grpc-gae-interop-testing-jdk8:runInteropTestRemote + +- id: cleanup + name: gcr.io/cloud-builders/gcloud + script: | + #!/usr/bin/env bash + set -e + echo "Performing cleanup now." + gcloud app services delete "$KOKORO_GAE_SERVICE" --version "cb-$BUILD_ID" --quiet diff --git a/buildscripts/gae-build/Dockerfile b/buildscripts/gae-build/Dockerfile new file mode 100644 index 00000000000..7e68b270801 --- /dev/null +++ b/buildscripts/gae-build/Dockerfile @@ -0,0 +1,10 @@ +FROM eclipse-temurin:17-jdk + +# The AppEngine Gradle plugin downloads and runs its own gcloud to get the .jar +# to link against, so we need Python even if we use gcloud deploy directly +# instead of using the plugin. +RUN export DEBIAN_FRONTEND=noninteractive && \ + apt-get update && \ + apt-get upgrade -y && \ + apt-get install -y --no-install-recommends python3 && \ + rm -rf /var/lib/apt/lists/* diff --git a/buildscripts/kokoro/android.sh b/buildscripts/kokoro/android.sh index 5af55b2f551..677825ae66b 100755 --- a/buildscripts/kokoro/android.sh +++ b/buildscripts/kokoro/android.sh @@ -132,15 +132,18 @@ fi # Update the statuses with the deltas +set +x gsutil cp gs://grpc-testing-secrets/github_credentials/oauth_token.txt ~/ desc="New DEX reference count: $(printf "%'d" "$new_dex_count") (delta: $(printf "%'d" "$dex_count_delta"))" +echo "Setting status: $desc" curl -f -s -X POST -H "Content-Type: application/json" \ -H "Authorization: token $(cat ~/oauth_token.txt | tr -d '\n')" \ -d '{"state": "success", "context": "android/dex_diff", "description": "'"${desc}"'"}' \ "https://api.github.com/repos/grpc/grpc-java/statuses/${KOKORO_GITHUB_PULL_REQUEST_COMMIT}" desc="New APK size in bytes: $(printf "%'d" "$new_apk_size") (delta: $(printf "%'d" "$apk_size_delta"))" +echo "Setting status: $desc" curl -f -s -X POST -H "Content-Type: application/json" \ -H "Authorization: token $(cat ~/oauth_token.txt | tr -d '\n')" \ -d '{"state": "success", "context": "android/apk_diff", "description": "'"${desc}"'"}' \ diff --git a/buildscripts/kokoro/gae-interop.sh b/buildscripts/kokoro/gae-interop.sh deleted file mode 100755 index c4ce56cac52..00000000000 --- a/buildscripts/kokoro/gae-interop.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/bash - -set -exu -o pipefail -if [[ -f /VERSION ]]; then - cat /VERSION -fi - -KOKORO_GAE_SERVICE="java-gae-interop-test" - -# We deploy as different versions of a single service, this way any stale -# lingering deploys can be easily cleaned up by purging all running versions -# of this service. -KOKORO_GAE_APP_VERSION=$(hostname) - -# A dummy version that can be the recipient of all traffic, so that the kokoro test version can be -# set to 0 traffic. This is a requirement in order to delete it. -DUMMY_DEFAULT_VERSION='dummy-default' - -function cleanup() { - echo "Performing cleanup now." - gcloud app services delete $KOKORO_GAE_SERVICE --version $KOKORO_GAE_APP_VERSION --quiet -} -trap cleanup SIGHUP SIGINT SIGTERM EXIT - -readonly GRPC_JAVA_DIR="$(cd "$(dirname "$0")"/../.. && pwd)" -cd "$GRPC_JAVA_DIR" - -## -## Deploy the dummy 'default' version of the service -## -GRADLE_FLAGS="--stacktrace -DgaeStopPreviousVersion=false -PskipCodegen=true -PskipAndroid=true" -export GRADLE_OPTS="-Dorg.gradle.jvmargs='-Xmx1g'" - -# Deploy the dummy 'default' version. We only require that it exists when cleanup() is called. -# It ok if we race with another run and fail here, because the end result is idempotent. -set +e -if ! gcloud app versions describe "$DUMMY_DEFAULT_VERSION" --service="$KOKORO_GAE_SERVICE"; then - ./gradlew $GRADLE_FLAGS -DgaeDeployVersion="$DUMMY_DEFAULT_VERSION" -DgaePromote=true :grpc-gae-interop-testing-jdk8:appengineDeploy -else - echo "default version already exists: $DUMMY_DEFAULT_VERSION" -fi -set -e - -# Deploy and test the real app (jdk8) -./gradlew $GRADLE_FLAGS -DgaeDeployVersion="$KOKORO_GAE_APP_VERSION" :grpc-gae-interop-testing-jdk8:runInteropTestRemote - -set +e -echo "Cleaning out stale deploys from previous runs, it is ok if this part fails" - -# Sometimes the trap based cleanup fails. -# Delete all versions whose name is not 'dummy-default' and is older than 1 hour. -# This expression is an ISO8601 relative date: -# https://cloud.google.com/sdk/gcloud/reference/topic/datetimes -gcloud app versions list --format="get(version.id)" --filter="service=$KOKORO_GAE_SERVICE AND NOT version : 'dummy-default' AND version.createTime<'-p1h'" | xargs -i gcloud app services delete "$KOKORO_GAE_SERVICE" --version {} --quiet -exit 0 diff --git a/compiler/src/test/golden/TestDeprecatedService.java.txt b/compiler/src/test/golden/TestDeprecatedService.java.txt index 22d3491be95..61f882ef59a 100644 --- a/compiler/src/test/golden/TestDeprecatedService.java.txt +++ b/compiler/src/test/golden/TestDeprecatedService.java.txt @@ -8,7 +8,7 @@ import static io.grpc.MethodDescriptor.generateFullMethodName; * */ @javax.annotation.Generated( - value = "by gRPC proto compiler (version 1.76.0-SNAPSHOT)", + value = "by gRPC proto compiler (version 1.76.4-SNAPSHOT)", comments = "Source: grpc/testing/compiler/test.proto") @io.grpc.stub.annotations.GrpcGenerated @java.lang.Deprecated diff --git a/compiler/src/test/golden/TestService.java.txt b/compiler/src/test/golden/TestService.java.txt index 22978149759..8ef06cbb805 100644 --- a/compiler/src/test/golden/TestService.java.txt +++ b/compiler/src/test/golden/TestService.java.txt @@ -8,7 +8,7 @@ import static io.grpc.MethodDescriptor.generateFullMethodName; * */ @javax.annotation.Generated( - value = "by gRPC proto compiler (version 1.76.0-SNAPSHOT)", + value = "by gRPC proto compiler (version 1.76.4-SNAPSHOT)", comments = "Source: grpc/testing/compiler/test.proto") @io.grpc.stub.annotations.GrpcGenerated public final class TestServiceGrpc { diff --git a/core/src/main/java/io/grpc/internal/GrpcUtil.java b/core/src/main/java/io/grpc/internal/GrpcUtil.java index 2ad4a01d9e6..b25f032b755 100644 --- a/core/src/main/java/io/grpc/internal/GrpcUtil.java +++ b/core/src/main/java/io/grpc/internal/GrpcUtil.java @@ -219,7 +219,7 @@ public byte[] parseAsciiString(byte[] serialized) { public static final Splitter ACCEPT_ENCODING_SPLITTER = Splitter.on(',').trimResults(); - public static final String IMPLEMENTATION_VERSION = "1.76.0-SNAPSHOT"; // CURRENT_GRPC_VERSION + public static final String IMPLEMENTATION_VERSION = "1.76.4-SNAPSHOT"; // CURRENT_GRPC_VERSION /** * The default timeout in nanos for a keepalive ping request. diff --git a/core/src/main/java/io/grpc/internal/PickFirstLeafLoadBalancer.java b/core/src/main/java/io/grpc/internal/PickFirstLeafLoadBalancer.java index ebe329ca591..2689d7d2308 100644 --- a/core/src/main/java/io/grpc/internal/PickFirstLeafLoadBalancer.java +++ b/core/src/main/java/io/grpc/internal/PickFirstLeafLoadBalancer.java @@ -137,9 +137,13 @@ public Status acceptResolvedAddresses(ResolvedAddresses resolvedAddresses) { final ImmutableList newImmutableAddressGroups = ImmutableList.builder().addAll(cleanServers).build(); - if (rawConnectivityState == READY || rawConnectivityState == CONNECTING) { + if (rawConnectivityState == READY + || (rawConnectivityState == CONNECTING + && (!enableHappyEyeballs || addressIndex.isValid()))) { // If the previous ready (or connecting) subchannel exists in new address list, - // keep this connection and don't create new subchannels + // keep this connection and don't create new subchannels. Happy Eyeballs is excluded when + // connecting, because it allows multiple attempts simultaneously, thus is fine to start at + // the beginning. SocketAddress previousAddress = addressIndex.getCurrentAddress(); addressIndex.updateGroups(newImmutableAddressGroups); if (addressIndex.seekTo(previousAddress)) { diff --git a/core/src/test/java/io/grpc/internal/PickFirstLeafLoadBalancerTest.java b/core/src/test/java/io/grpc/internal/PickFirstLeafLoadBalancerTest.java index 0e902bfdd56..8b09fce2aa2 100644 --- a/core/src/test/java/io/grpc/internal/PickFirstLeafLoadBalancerTest.java +++ b/core/src/test/java/io/grpc/internal/PickFirstLeafLoadBalancerTest.java @@ -1872,6 +1872,45 @@ public void updateAddresses_identical_transient_failure() { assertEquals(PickResult.withSubchannel(mockSubchannel1), picker.pickSubchannel(mockArgs)); } + @Test + public void updateAddresses_identicalSingleAddress_connecting() { + // Creating first set of endpoints/addresses + List oldServers = Lists.newArrayList(servers.get(0)); + + // Accept Addresses and verify proper connection flow + assertEquals(IDLE, loadBalancer.getConcludedConnectivityState()); + loadBalancer.acceptResolvedAddresses( + ResolvedAddresses.newBuilder().setAddresses(oldServers).setAttributes(affinity).build()); + verify(mockSubchannel1).start(stateListenerCaptor.capture()); + SubchannelStateListener stateListener = stateListenerCaptor.getValue(); + assertEquals(CONNECTING, loadBalancer.getConcludedConnectivityState()); + + // First connection attempt is successful + stateListener.onSubchannelState(ConnectivityStateInfo.forNonError(CONNECTING)); + assertEquals(CONNECTING, loadBalancer.getConcludedConnectivityState()); + fakeClock.forwardTime(CONNECTION_DELAY_INTERVAL_MS, TimeUnit.MILLISECONDS); + + // verify that picker returns no subchannel + verify(mockHelper).updateBalancingState(eq(CONNECTING), pickerCaptor.capture()); + SubchannelPicker picker = pickerCaptor.getValue(); + assertEquals(PickResult.withNoResult(), picker.pickSubchannel(mockArgs)); + + // Accept same resolved addresses to update + reset(mockHelper); + loadBalancer.acceptResolvedAddresses( + ResolvedAddresses.newBuilder().setAddresses(oldServers).setAttributes(affinity).build()); + fakeClock.forwardTime(CONNECTION_DELAY_INTERVAL_MS, TimeUnit.MILLISECONDS); + + // Verify that no new subchannels were created or started + verify(mockSubchannel2, never()).start(any()); + assertEquals(CONNECTING, loadBalancer.getConcludedConnectivityState()); + + // verify that picker hasn't changed via checking mock helper's interactions + verify(mockHelper, atLeast(0)).getSynchronizationContext(); // Don't care + verify(mockHelper, atLeast(0)).getScheduledExecutorService(); + verifyNoMoreInteractions(mockHelper); + } + @Test public void twoAddressesSeriallyConnect() { // Starting first connection attempt diff --git a/examples/MODULE.bazel b/examples/MODULE.bazel index 18d74d86973..b4238ddd599 100644 --- a/examples/MODULE.bazel +++ b/examples/MODULE.bazel @@ -1,4 +1,4 @@ -bazel_dep(name = "grpc-java", repo_name = "io_grpc_grpc_java", version = "1.76.0-SNAPSHOT") # CURRENT_GRPC_VERSION +bazel_dep(name = "grpc-java", repo_name = "io_grpc_grpc_java", version = "1.76.4-SNAPSHOT") # CURRENT_GRPC_VERSION bazel_dep(name = "grpc-proto", repo_name = "io_grpc_grpc_proto", version = "0.0.0-20240627-ec30f58") bazel_dep(name = "protobuf", repo_name = "com_google_protobuf", version = "23.1") bazel_dep(name = "rules_jvm_external", version = "6.0") diff --git a/examples/android/clientcache/app/build.gradle b/examples/android/clientcache/app/build.gradle index 8048eba73ab..14b692772bb 100644 --- a/examples/android/clientcache/app/build.gradle +++ b/examples/android/clientcache/app/build.gradle @@ -34,7 +34,7 @@ android { protobuf { protoc { artifact = 'com.google.protobuf:protoc:3.25.1' } plugins { - grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION + grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION } } generateProtoTasks { @@ -54,11 +54,11 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.0.0' // You need to build grpc-java to obtain these libraries below. - implementation 'io.grpc:grpc-okhttp:1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-protobuf-lite:1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-stub:1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-okhttp:1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-protobuf-lite:1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-stub:1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION testImplementation 'junit:junit:4.13.2' testImplementation 'com.google.truth:truth:1.1.5' - testImplementation 'io.grpc:grpc-testing:1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION + testImplementation 'io.grpc:grpc-testing:1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION } diff --git a/examples/android/helloworld/app/build.gradle b/examples/android/helloworld/app/build.gradle index 69519c8e4ab..3c8110b7102 100644 --- a/examples/android/helloworld/app/build.gradle +++ b/examples/android/helloworld/app/build.gradle @@ -32,7 +32,7 @@ android { protobuf { protoc { artifact = 'com.google.protobuf:protoc:3.25.1' } plugins { - grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION + grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION } } generateProtoTasks { @@ -52,7 +52,7 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.0.0' // You need to build grpc-java to obtain these libraries below. - implementation 'io.grpc:grpc-okhttp:1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-protobuf-lite:1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-stub:1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-okhttp:1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-protobuf-lite:1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-stub:1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION } diff --git a/examples/android/routeguide/app/build.gradle b/examples/android/routeguide/app/build.gradle index a09de35e994..eca469ec43c 100644 --- a/examples/android/routeguide/app/build.gradle +++ b/examples/android/routeguide/app/build.gradle @@ -32,7 +32,7 @@ android { protobuf { protoc { artifact = 'com.google.protobuf:protoc:3.25.1' } plugins { - grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION + grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION } } generateProtoTasks { @@ -52,7 +52,7 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.0.0' // You need to build grpc-java to obtain these libraries below. - implementation 'io.grpc:grpc-okhttp:1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-protobuf-lite:1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-stub:1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-okhttp:1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-protobuf-lite:1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-stub:1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION } diff --git a/examples/android/strictmode/app/build.gradle b/examples/android/strictmode/app/build.gradle index c0447a42af1..a1d944d1ff9 100644 --- a/examples/android/strictmode/app/build.gradle +++ b/examples/android/strictmode/app/build.gradle @@ -33,7 +33,7 @@ android { protobuf { protoc { artifact = 'com.google.protobuf:protoc:3.25.1' } plugins { - grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION + grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION } } generateProtoTasks { @@ -53,7 +53,7 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.0.0' // You need to build grpc-java to obtain these libraries below. - implementation 'io.grpc:grpc-okhttp:1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-protobuf-lite:1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-stub:1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-okhttp:1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-protobuf-lite:1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-stub:1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION } diff --git a/examples/build.gradle b/examples/build.gradle index ddd8e7b3a65..c181dfab1f5 100644 --- a/examples/build.gradle +++ b/examples/build.gradle @@ -21,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION def protobufVersion = '3.25.8' def protocVersion = protobufVersion diff --git a/examples/example-alts/build.gradle b/examples/example-alts/build.gradle index 9f86adb0aeb..8e0ddd9e02b 100644 --- a/examples/example-alts/build.gradle +++ b/examples/example-alts/build.gradle @@ -21,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION def protocVersion = '3.25.8' dependencies { diff --git a/examples/example-debug/build.gradle b/examples/example-debug/build.gradle index 3dc873e179b..6f7c43a8fa9 100644 --- a/examples/example-debug/build.gradle +++ b/examples/example-debug/build.gradle @@ -23,7 +23,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION def protobufVersion = '3.25.8' dependencies { diff --git a/examples/example-debug/pom.xml b/examples/example-debug/pom.xml index c4fce2d793b..c3639a4dc91 100644 --- a/examples/example-debug/pom.xml +++ b/examples/example-debug/pom.xml @@ -6,13 +6,13 @@ jar - 1.76.0-SNAPSHOT + 1.76.4-SNAPSHOT example-debug https://github.com/grpc/grpc-java UTF-8 - 1.76.0-SNAPSHOT + 1.76.4-SNAPSHOT 3.25.8 1.8 diff --git a/examples/example-dualstack/build.gradle b/examples/example-dualstack/build.gradle index 5d8c30b2127..37dc497ecc6 100644 --- a/examples/example-dualstack/build.gradle +++ b/examples/example-dualstack/build.gradle @@ -23,7 +23,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION def protobufVersion = '3.25.8' dependencies { diff --git a/examples/example-dualstack/pom.xml b/examples/example-dualstack/pom.xml index b65beb84103..ee2a41730f2 100644 --- a/examples/example-dualstack/pom.xml +++ b/examples/example-dualstack/pom.xml @@ -6,13 +6,13 @@ jar - 1.76.0-SNAPSHOT + 1.76.4-SNAPSHOT example-dualstack https://github.com/grpc/grpc-java UTF-8 - 1.76.0-SNAPSHOT + 1.76.4-SNAPSHOT 3.25.8 1.8 diff --git a/examples/example-gauth/build.gradle b/examples/example-gauth/build.gradle index befc2f7c0c7..64a5a969d60 100644 --- a/examples/example-gauth/build.gradle +++ b/examples/example-gauth/build.gradle @@ -21,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION def protobufVersion = '3.25.8' def protocVersion = protobufVersion diff --git a/examples/example-gauth/pom.xml b/examples/example-gauth/pom.xml index 98bbebd114a..e054ef0da12 100644 --- a/examples/example-gauth/pom.xml +++ b/examples/example-gauth/pom.xml @@ -6,13 +6,13 @@ jar - 1.76.0-SNAPSHOT + 1.76.4-SNAPSHOT example-gauth https://github.com/grpc/grpc-java UTF-8 - 1.76.0-SNAPSHOT + 1.76.4-SNAPSHOT 3.25.8 1.8 diff --git a/examples/example-gcp-csm-observability/build.gradle b/examples/example-gcp-csm-observability/build.gradle index abb2dd8a220..d895088688d 100644 --- a/examples/example-gcp-csm-observability/build.gradle +++ b/examples/example-gcp-csm-observability/build.gradle @@ -22,7 +22,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION def protocVersion = '3.25.8' def openTelemetryVersion = '1.52.0' def openTelemetryPrometheusVersion = '1.52.0-alpha' diff --git a/examples/example-gcp-observability/build.gradle b/examples/example-gcp-observability/build.gradle index 08e00294452..4e7ce9dfa3a 100644 --- a/examples/example-gcp-observability/build.gradle +++ b/examples/example-gcp-observability/build.gradle @@ -22,7 +22,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION def protocVersion = '3.25.8' dependencies { diff --git a/examples/example-hostname/build.gradle b/examples/example-hostname/build.gradle index 94a85e8f8ab..5a01920cf61 100644 --- a/examples/example-hostname/build.gradle +++ b/examples/example-hostname/build.gradle @@ -21,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION def protobufVersion = '3.25.8' dependencies { diff --git a/examples/example-hostname/pom.xml b/examples/example-hostname/pom.xml index e93b36e39d1..5ec633bb187 100644 --- a/examples/example-hostname/pom.xml +++ b/examples/example-hostname/pom.xml @@ -6,13 +6,13 @@ jar - 1.76.0-SNAPSHOT + 1.76.4-SNAPSHOT example-hostname https://github.com/grpc/grpc-java UTF-8 - 1.76.0-SNAPSHOT + 1.76.4-SNAPSHOT 3.25.8 1.8 diff --git a/examples/example-jwt-auth/build.gradle b/examples/example-jwt-auth/build.gradle index 28df68e4fc7..c5efd90afb7 100644 --- a/examples/example-jwt-auth/build.gradle +++ b/examples/example-jwt-auth/build.gradle @@ -21,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION def protobufVersion = '3.25.8' def protocVersion = protobufVersion diff --git a/examples/example-jwt-auth/pom.xml b/examples/example-jwt-auth/pom.xml index 4834cfa09ef..32e5d240960 100644 --- a/examples/example-jwt-auth/pom.xml +++ b/examples/example-jwt-auth/pom.xml @@ -7,13 +7,13 @@ jar - 1.76.0-SNAPSHOT + 1.76.4-SNAPSHOT example-jwt-auth https://github.com/grpc/grpc-java UTF-8 - 1.76.0-SNAPSHOT + 1.76.4-SNAPSHOT 3.25.8 3.25.8 diff --git a/examples/example-oauth/build.gradle b/examples/example-oauth/build.gradle index 05a450dcc8d..313c72b127c 100644 --- a/examples/example-oauth/build.gradle +++ b/examples/example-oauth/build.gradle @@ -21,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION def protobufVersion = '3.25.8' def protocVersion = protobufVersion diff --git a/examples/example-oauth/pom.xml b/examples/example-oauth/pom.xml index a2f61e38467..0a1a17420d8 100644 --- a/examples/example-oauth/pom.xml +++ b/examples/example-oauth/pom.xml @@ -7,13 +7,13 @@ jar - 1.76.0-SNAPSHOT + 1.76.4-SNAPSHOT example-oauth https://github.com/grpc/grpc-java UTF-8 - 1.76.0-SNAPSHOT + 1.76.4-SNAPSHOT 3.25.8 3.25.8 diff --git a/examples/example-opentelemetry/build.gradle b/examples/example-opentelemetry/build.gradle index edcca46480e..f470449c6ad 100644 --- a/examples/example-opentelemetry/build.gradle +++ b/examples/example-opentelemetry/build.gradle @@ -21,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION def protocVersion = '3.25.8' def openTelemetryVersion = '1.52.0' def openTelemetryPrometheusVersion = '1.52.0-alpha' diff --git a/examples/example-orca/build.gradle b/examples/example-orca/build.gradle index f21c89ee0a4..9663531834d 100644 --- a/examples/example-orca/build.gradle +++ b/examples/example-orca/build.gradle @@ -16,7 +16,7 @@ java { targetCompatibility = JavaVersion.VERSION_1_8 } -def grpcVersion = '1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION def protocVersion = '3.25.8' dependencies { diff --git a/examples/example-reflection/build.gradle b/examples/example-reflection/build.gradle index a5bda680ef4..e1bf34938a3 100644 --- a/examples/example-reflection/build.gradle +++ b/examples/example-reflection/build.gradle @@ -16,7 +16,7 @@ java { targetCompatibility = JavaVersion.VERSION_1_8 } -def grpcVersion = '1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION def protocVersion = '3.25.8' dependencies { diff --git a/examples/example-servlet/build.gradle b/examples/example-servlet/build.gradle index d0f475f1833..32dfdac0136 100644 --- a/examples/example-servlet/build.gradle +++ b/examples/example-servlet/build.gradle @@ -15,7 +15,7 @@ java { targetCompatibility = JavaVersion.VERSION_1_8 } -def grpcVersion = '1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION def protocVersion = '3.25.8' dependencies { diff --git a/examples/example-tls/build.gradle b/examples/example-tls/build.gradle index 0b3914febf3..15694c85010 100644 --- a/examples/example-tls/build.gradle +++ b/examples/example-tls/build.gradle @@ -21,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION def protocVersion = '3.25.8' dependencies { diff --git a/examples/example-tls/pom.xml b/examples/example-tls/pom.xml index 3932f4c32f4..6d11c2e6cb0 100644 --- a/examples/example-tls/pom.xml +++ b/examples/example-tls/pom.xml @@ -6,13 +6,13 @@ jar - 1.76.0-SNAPSHOT + 1.76.4-SNAPSHOT example-tls https://github.com/grpc/grpc-java UTF-8 - 1.76.0-SNAPSHOT + 1.76.4-SNAPSHOT 3.25.8 1.8 diff --git a/examples/example-xds/build.gradle b/examples/example-xds/build.gradle index 3914aa3fea0..1f0aed26c27 100644 --- a/examples/example-xds/build.gradle +++ b/examples/example-xds/build.gradle @@ -21,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.76.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.76.4-SNAPSHOT' // CURRENT_GRPC_VERSION def protocVersion = '3.25.8' dependencies { diff --git a/examples/pom.xml b/examples/pom.xml index 4da1eb14f90..69cdcdd5aa5 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -6,13 +6,13 @@ jar - 1.76.0-SNAPSHOT + 1.76.4-SNAPSHOT examples https://github.com/grpc/grpc-java UTF-8 - 1.76.0-SNAPSHOT + 1.76.4-SNAPSHOT 3.25.8 3.25.8 diff --git a/gae-interop-testing/gae-jdk8/build.gradle b/gae-interop-testing/gae-jdk8/build.gradle index 14abbc05a9b..07033f403de 100644 --- a/gae-interop-testing/gae-jdk8/build.gradle +++ b/gae-interop-testing/gae-jdk8/build.gradle @@ -58,6 +58,7 @@ def createDefaultVersion() { return new java.text.SimpleDateFormat("yyyyMMdd't'HHmmss").format(new Date()) } +def nonShadowedProject = project // [START model] appengine { // App Engine tasks configuration @@ -67,13 +68,13 @@ appengine { deploy { // deploy configuration - projectId = 'GCLOUD_CONFIG' + projectId = nonShadowedProject.findProperty('gaeProjectId') ?: 'GCLOUD_CONFIG' // default - stop the current version - stopPreviousVersion = System.getProperty('gaeStopPreviousVersion') ?: true + stopPreviousVersion = nonShadowedProject.findProperty('gaeStopPreviousVersion') ?: true // default - do not make this the promoted version - promote = System.getProperty('gaePromote') ?: false - // Use -DgaeDeployVersion if set, otherwise the version is null and the plugin will generate it - version = System.getProperty('gaeDeployVersion', createDefaultVersion()) + promote = nonShadowedProject.findProperty('gaePromote') ?: false + // Use -PgaeDeployVersion if set, otherwise the version is null and the plugin will generate it + version = nonShadowedProject.findProperty('gaeDeployVersion') ?: createDefaultVersion() } } // [END model] @@ -83,6 +84,10 @@ version = '1.0-SNAPSHOT' // Version in generated output /** Returns the service name. */ String getGaeProject() { + def configuredProjectId = appengine.deploy.projectId + if (!"GCLOUD_CONFIG".equals(configuredProjectId)) { + return configuredProjectId + } def stream = new ByteArrayOutputStream() exec { executable 'gcloud' @@ -110,11 +115,8 @@ String getAppUrl(String project, String service, String version) { } tasks.register("runInteropTestRemote") { - dependsOn appengineDeploy + mustRunAfter appengineDeploy doLast { - // give remote app some time to settle down - sleep(20000) - def appUrl = getAppUrl( getGaeProject(), getService(project.getProjectDir().toPath()), diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index cb5dce02843..cae9223ee0b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -85,11 +85,11 @@ opencensus-contrib-grpc-metrics = { module = "io.opencensus:opencensus-contrib-g opencensus-exporter-stats-stackdriver = { module = "io.opencensus:opencensus-exporter-stats-stackdriver", version.ref = "opencensus" } opencensus-exporter-trace-stackdriver = { module = "io.opencensus:opencensus-exporter-trace-stackdriver", version.ref = "opencensus" } opencensus-impl = { module = "io.opencensus:opencensus-impl", version.ref = "opencensus" } -opentelemetry-api = "io.opentelemetry:opentelemetry-api:1.52.0" -opentelemetry-exporter-prometheus = "io.opentelemetry:opentelemetry-exporter-prometheus:1.52.0-alpha" -opentelemetry-gcp-resources = "io.opentelemetry.contrib:opentelemetry-gcp-resources:1.48.0-alpha" -opentelemetry-sdk-extension-autoconfigure = "io.opentelemetry:opentelemetry-sdk-extension-autoconfigure:1.52.0" -opentelemetry-sdk-testing = "io.opentelemetry:opentelemetry-sdk-testing:1.52.0" +opentelemetry-api = "io.opentelemetry:opentelemetry-api:1.51.0" +opentelemetry-exporter-prometheus = "io.opentelemetry:opentelemetry-exporter-prometheus:1.51.0-alpha" +opentelemetry-gcp-resources = "io.opentelemetry.contrib:opentelemetry-gcp-resources:1.47.0-alpha" +opentelemetry-sdk-extension-autoconfigure = "io.opentelemetry:opentelemetry-sdk-extension-autoconfigure:1.51.0" +opentelemetry-sdk-testing = "io.opentelemetry:opentelemetry-sdk-testing:1.51.0" perfmark-api = "io.perfmark:perfmark-api:0.27.0" protobuf-java = { module = "com.google.protobuf:protobuf-java", version.ref = "protobuf" } protobuf-java-util = { module = "com.google.protobuf:protobuf-java-util", version.ref = "protobuf" } diff --git a/netty/shaded/build.gradle b/netty/shaded/build.gradle index f805a4f4a1f..27816f9380b 100644 --- a/netty/shaded/build.gradle +++ b/netty/shaded/build.gradle @@ -153,7 +153,11 @@ class NettyResourceTransformer implements Transformer { @Override boolean canTransformResource(FileTreeElement fileTreeElement) { - fileTreeElement.name.startsWith("META-INF/native-image/io.netty") + // io.netty.versions.properties can't actually be shaded successfully, + // as io.netty.util.Version still looks for the unshaded name. But we + // keep the file for manual inspection. + fileTreeElement.name.startsWith("META-INF/native-image/io.netty") || + fileTreeElement.name.startsWith("META-INF/io.netty.versions.properties") } @Override diff --git a/netty/src/main/java/io/grpc/netty/GrpcHttp2ConnectionHandler.java b/netty/src/main/java/io/grpc/netty/GrpcHttp2ConnectionHandler.java index a463cf01d95..ee5227484fb 100644 --- a/netty/src/main/java/io/grpc/netty/GrpcHttp2ConnectionHandler.java +++ b/netty/src/main/java/io/grpc/netty/GrpcHttp2ConnectionHandler.java @@ -18,7 +18,6 @@ import static com.google.common.base.Preconditions.checkState; -import com.google.common.annotations.VisibleForTesting; import io.grpc.Attributes; import io.grpc.ChannelLogger; import io.grpc.Internal; @@ -28,7 +27,6 @@ import io.netty.handler.codec.http2.Http2ConnectionEncoder; import io.netty.handler.codec.http2.Http2ConnectionHandler; import io.netty.handler.codec.http2.Http2Settings; -import io.netty.util.Version; import javax.annotation.Nullable; /** @@ -36,37 +34,9 @@ */ @Internal public abstract class GrpcHttp2ConnectionHandler extends Http2ConnectionHandler { - static final int ADAPTIVE_CUMULATOR_COMPOSE_MIN_SIZE_DEFAULT = 1024; - static final Cumulator ADAPTIVE_CUMULATOR = - new NettyAdaptiveCumulator(ADAPTIVE_CUMULATOR_COMPOSE_MIN_SIZE_DEFAULT); - @Nullable protected final ChannelPromise channelUnused; private final ChannelLogger negotiationLogger; - private static final boolean usingPre4_1_111_Netty; - - static { - // Netty 4.1.111 introduced a change in the behavior of duplicate() method - // that breaks the assumption of the cumulator. We need to detect this version - // and adjust the behavior accordingly. - - boolean identifiedOldVersion = false; - try { - Version version = Version.identify().get("netty-buffer"); - if (version != null) { - String[] split = version.artifactVersion().split("\\."); - if (split.length >= 3 - && Integer.parseInt(split[0]) == 4 - && Integer.parseInt(split[1]) <= 1 - && Integer.parseInt(split[2]) < 111) { - identifiedOldVersion = true; - } - } - } catch (Exception e) { - // Ignore, we'll assume it's a new version. - } - usingPre4_1_111_Netty = identifiedOldVersion; - } @SuppressWarnings("this-escape") protected GrpcHttp2ConnectionHandler( @@ -78,16 +48,6 @@ protected GrpcHttp2ConnectionHandler( super(decoder, encoder, initialSettings); this.channelUnused = channelUnused; this.negotiationLogger = negotiationLogger; - if (usingPre4_1_111_Netty()) { - // We need to use the adaptive cumulator only if we're using a version of Netty that - // doesn't have the behavior that breaks it. - setCumulator(ADAPTIVE_CUMULATOR); - } - } - - @VisibleForTesting - static boolean usingPre4_1_111_Netty() { - return usingPre4_1_111_Netty; } /** diff --git a/netty/src/test/java/io/grpc/netty/NettyAdaptiveCumulatorTest.java b/netty/src/test/java/io/grpc/netty/NettyAdaptiveCumulatorTest.java index 68dc6dc0c80..b19f247b5cf 100644 --- a/netty/src/test/java/io/grpc/netty/NettyAdaptiveCumulatorTest.java +++ b/netty/src/test/java/io/grpc/netty/NettyAdaptiveCumulatorTest.java @@ -52,6 +52,9 @@ @RunWith(Enclosed.class) public class NettyAdaptiveCumulatorTest { + private static boolean usingPre4_1_111_Netty() { + return false; // Disabled detection because it was unreliable + } private static Collection cartesianProductParams(List... lists) { return Lists.transform(Lists.cartesianProduct(lists), List::toArray); @@ -385,9 +388,8 @@ public void mergeWithCompositeTail_tailExpandable_reallocateInMemory() { } private void assertTailExpanded(String expectedTailReadableData, int expectedNewTailCapacity) { - if (!GrpcHttp2ConnectionHandler.usingPre4_1_111_Netty()) { - return; // Netty 4.1.111 doesn't work with NettyAdaptiveCumulator - } + assume().withMessage("Netty 4.1.111 doesn't work with NettyAdaptiveCumulator") + .that(usingPre4_1_111_Netty()).isTrue(); int originalNumComponents = composite.numComponents(); // Handle the case when reader index is beyond all readable bytes of the cumulation. @@ -628,9 +630,8 @@ public void mergeWithCompositeTail_outOfSyncComposite() { alloc.compositeBuffer(8).addFlattenedComponents(true, composite1); assertThat(composite2.toString(US_ASCII)).isEqualTo("01234"); - if (!GrpcHttp2ConnectionHandler.usingPre4_1_111_Netty()) { - return; // Netty 4.1.111 doesn't work with NettyAdaptiveCumulator - } + assume().withMessage("Netty 4.1.111 doesn't work with NettyAdaptiveCumulator") + .that(usingPre4_1_111_Netty()).isTrue(); // The previous operation does not adjust the read indexes of the underlying buffers, // only the internal Component offsets. When the cumulator attempts to append the input to diff --git a/rls/src/main/java/io/grpc/rls/LbPolicyConfiguration.java b/rls/src/main/java/io/grpc/rls/LbPolicyConfiguration.java index 226176d25ff..1da12939937 100644 --- a/rls/src/main/java/io/grpc/rls/LbPolicyConfiguration.java +++ b/rls/src/main/java/io/grpc/rls/LbPolicyConfiguration.java @@ -248,10 +248,10 @@ ChildPolicyWrapper createOrGet(String target) { RefCountedChildPolicyWrapper pooledChildPolicyWrapper = childPolicyMap.get(target); if (pooledChildPolicyWrapper == null) { ChildPolicyWrapper childPolicyWrapper = new ChildPolicyWrapper( - target, childPolicy, childLbResolvedAddressFactory, childLbHelperProvider, - childLbStatusListener); + target, childPolicy, childLbHelperProvider, childLbStatusListener); pooledChildPolicyWrapper = RefCountedChildPolicyWrapper.of(childPolicyWrapper); childPolicyMap.put(target, pooledChildPolicyWrapper); + childPolicyWrapper.start(childLbResolvedAddressFactory); return pooledChildPolicyWrapper.getObject(); } else { ChildPolicyWrapper childPolicyWrapper = pooledChildPolicyWrapper.getObject(); @@ -298,7 +298,6 @@ static final class ChildPolicyWrapper { public ChildPolicyWrapper( String target, ChildLoadBalancingPolicy childPolicy, - final ResolvedAddressFactory childLbResolvedAddressFactory, ChildLoadBalancerHelperProvider childLbHelperProvider, ChildLbStatusListener childLbStatusListener) { this.target = target; @@ -313,6 +312,9 @@ public ChildPolicyWrapper( this.childLbConfig = lbConfig.getConfig(); helper.getChannelLogger().log( ChannelLogLevel.DEBUG, "RLS child lb created. config: {0}", childLbConfig); + } + + void start(ResolvedAddressFactory childLbResolvedAddressFactory) { helper.getSynchronizationContext().execute( new Runnable() { @Override diff --git a/rls/src/test/java/io/grpc/rls/LbPolicyConfigurationTest.java b/rls/src/test/java/io/grpc/rls/LbPolicyConfigurationTest.java index d6025d5bad4..e4c21bd48a6 100644 --- a/rls/src/test/java/io/grpc/rls/LbPolicyConfigurationTest.java +++ b/rls/src/test/java/io/grpc/rls/LbPolicyConfigurationTest.java @@ -21,6 +21,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -45,8 +46,8 @@ import io.grpc.rls.LbPolicyConfiguration.ChildPolicyWrapper.ChildPolicyReportingHelper; import io.grpc.rls.LbPolicyConfiguration.InvalidChildPolicyConfigException; import io.grpc.rls.LbPolicyConfiguration.RefCountedChildPolicyWrapperFactory; -import java.lang.Thread.UncaughtExceptionHandler; import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -61,6 +62,9 @@ public class LbPolicyConfigurationTest { private final LoadBalancer lb = mock(LoadBalancer.class); private final SubchannelStateManager subchannelStateManager = new SubchannelStateManagerImpl(); private final SubchannelPicker picker = mock(SubchannelPicker.class); + private final SynchronizationContext syncContext = new SynchronizationContext((t, e) -> { + throw new AssertionError(e); + }); private final ChildLbStatusListener childLbStatusListener = mock(ChildLbStatusListener.class); private final ResolvedAddressFactory resolvedAddressFactory = new ResolvedAddressFactory() { @@ -84,15 +88,7 @@ public ResolvedAddresses create(Object childLbConfig) { @Before public void setUp() { doReturn(mock(ChannelLogger.class)).when(helper).getChannelLogger(); - doReturn( - new SynchronizationContext( - new UncaughtExceptionHandler() { - @Override - public void uncaughtException(Thread t, Throwable e) { - throw new AssertionError(e); - } - })) - .when(helper).getSynchronizationContext(); + doReturn(syncContext).when(helper).getSynchronizationContext(); doReturn(lb).when(lbProvider).newLoadBalancer(any(Helper.class)); doReturn(ConfigOrError.fromConfig(new Object())) .when(lbProvider).parseLoadBalancingPolicyConfig(ArgumentMatchers.>any()); @@ -190,4 +186,22 @@ public void updateBalancingState_triggersListener() { // picker governs childPickers will be reported to parent LB verify(helper).updateBalancingState(ConnectivityState.READY, picker); } + + @Test + public void refCountedGetOrCreate_addsChildBeforeConfiguringChild() { + AtomicBoolean calledAlready = new AtomicBoolean(); + when(lb.acceptResolvedAddresses(any(ResolvedAddresses.class))).thenAnswer(i -> { + if (!calledAlready.get()) { + calledAlready.set(true); + // Should end up calling this function again, as this child should already be added to the + // list of children. In practice, this can be caused by CDS is_dynamic=true starting a watch + // when XdsClient already has the cluster cached (e.g., from another channel). + syncContext.execute(() -> + factory.acceptResolvedAddressFactory(resolvedAddressFactory)); + } + return Status.OK; + }); + ChildPolicyWrapper unused = factory.createOrGet("foo.google.com"); + verify(lb, times(2)).acceptResolvedAddresses(any(ResolvedAddresses.class)); + } } diff --git a/servlet/src/tomcatTest/java/io/grpc/servlet/TomcatInteropTest.java b/servlet/src/tomcatTest/java/io/grpc/servlet/TomcatInteropTest.java index 1422b5388fd..d072fea93a1 100644 --- a/servlet/src/tomcatTest/java/io/grpc/servlet/TomcatInteropTest.java +++ b/servlet/src/tomcatTest/java/io/grpc/servlet/TomcatInteropTest.java @@ -113,27 +113,28 @@ protected boolean metricsExpected() { @Test public void gracefulShutdown() {} - // FIXME @Override @Ignore("Tomcat is not able to send trailer only") @Test public void specialStatusMessage() {} - // FIXME @Override @Ignore("Tomcat is not able to send trailer only") @Test public void unimplementedMethod() {} - // FIXME @Override @Ignore("Tomcat is not able to send trailer only") @Test public void statusCodeAndMessage() {} - // FIXME @Override @Ignore("Tomcat is not able to send trailer only") @Test public void emptyStream() {} + + @Override + @Ignore("Tomcat is not able to send trailer only") + @Test + public void timeoutOnSleepingServer() {} } diff --git a/servlet/src/tomcatTest/java/io/grpc/servlet/TomcatTransportTest.java b/servlet/src/tomcatTest/java/io/grpc/servlet/TomcatTransportTest.java index 2171c6eb2df..cd73b096ccb 100644 --- a/servlet/src/tomcatTest/java/io/grpc/servlet/TomcatTransportTest.java +++ b/servlet/src/tomcatTest/java/io/grpc/servlet/TomcatTransportTest.java @@ -93,6 +93,10 @@ public void start(ServerListener listener) throws IOException { .setAsyncSupported(true); ctx.addServletMappingDecoded("/*", "TomcatTransportTest"); tomcatServer.getConnector().addUpgradeProtocol(new Http2Protocol()); + // Workaround for https://github.com/grpc/grpc-java/issues/12540 + // Prevent premature OutputBuffer recycling by disabling facade recycling. + // This should be revisited once the root cause is fixed. + tomcatServer.getConnector().setDiscardFacades(false); try { tomcatServer.start(); } catch (LifecycleException e) {