From 178fc28d03c6a65b97c0e5d03a01b73c0997f9c7 Mon Sep 17 00:00:00 2001 From: Scott Mitchell Date: Wed, 20 Apr 2022 22:22:15 -0700 Subject: [PATCH 01/40] Combine publish-docs.sh and release.sh (#2196) Motivation: publish-docs.sh expects to only run on the main branch. However we also want to generate javadocs on branches other than main, for example to publish updated deprecation notices. Modifications: - Remove publish-docs.sh, and move its logic into release.sh Result: Non-main branches will have javadocs published during release. --- scripts/publish-docs.sh | 135 ---------------------------------------- scripts/release.sh | 108 +++++++++++++++++++++++++------- 2 files changed, 84 insertions(+), 159 deletions(-) delete mode 100755 scripts/publish-docs.sh diff --git a/scripts/publish-docs.sh b/scripts/publish-docs.sh deleted file mode 100755 index 34ef20b0ac..0000000000 --- a/scripts/publish-docs.sh +++ /dev/null @@ -1,135 +0,0 @@ -#!/bin/bash -# -# Copyright © 2019 Apple Inc. and the ServiceTalk project authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -set -eu - -cd "$(dirname "$0")" -cd .. - -version="" -DOCS_FOLDER="docs/generation/.out/remote" -JAVADOC_FOLDER="build/javadoc" -BRANCH_NAME=$(git symbolic-ref -q HEAD) -BRANCH_NAME=${BRANCH_NAME##refs/heads/} -GIT_AUTHOR=$(git --no-pager show -s --format='%an <%ae>' HEAD) - -if [ -z "${DRYRUN:-}" ]; then - git="git" -else - git="echo git" -fi - -function usage() { - echo "Usage: $0 [release_version]" - echo "No arguments - update the SNAPSHOT version of docs website only" - echo "release_version - publish docs for a new release version and update the SNAPSHOT version" -} - -function clean_up_gh_pages() { - if git worktree list | grep -q gh-pages; then - echo "Cleanup 'gh-pages' worktree" - git worktree remove -f gh-pages - fi - if git branch --list | grep -q "^\s*gh-pages$"; then - echo "Remove 'gh-pages' branch" - git branch -Df gh-pages - fi - # Just in case of the undefined initial state make sure there is no gh-pages folder - rm -rf gh-pages -} - -# Enforce JDK17 to get latest LTS javadoc format/features (search, etc.): -java_version=$(./gradlew --no-daemon -version | grep ^JVM: | awk -F\. '{gsub(/^JVM:[ \t]*/,"",$1); print $1"."$2}') -if [ "$java_version" != "17.0" ]; then - echo "Docs can be published only using Java 17, current version: $java_version" - exit 1 -fi - -if [ "$#" -eq "0" ]; then - echo "Publishing docs website for the SNAPSHOT version only" -elif [ "$#" -eq "1" ]; then - version="$1" - if ( echo "$version" | grep -Eqv "^\d+\.\d+$" ); then - echo "Release version should match 'major.minor' pattern was: $1" - exit 1 - fi - echo "Publishing docs website for the release version $version" -else - usage - exit 1 -fi - -echo "" - -# Clean up the state at the beginning in case the previous run did not finish successfully -clean_up_gh_pages - -echo "Generate docs website" -pushd docs/generation -./gradlew --no-daemon clean validateRemoteSite -popd -echo "Docs website generated, see ./$DOCS_FOLDER" - -echo "Generate javadoc" -./gradlew --no-daemon clean javadocAll -echo "Javadoc generated, see ./$JAVADOC_FOLDER" -`` -if ( ! git remote get-url docs ); then - git remote add docs git@github.com:apple/servicetalk.git -fi - -git fetch docs +gh-pages:gh-pages -git worktree add gh-pages gh-pages - -touch gh-pages/.nojekyll -\cp -r $DOCS_FOLDER/* gh-pages -echo "Copy javadoc to gh-pages/servicetalk/SNAPSHOT" -# Avoid accumulating old javadocs for classes that have been moved, renamed or deleted. -rm -rf gh-pages/servicetalk/SNAPSHOT/javadoc -\cp -r $JAVADOC_FOLDER gh-pages/servicetalk/SNAPSHOT -if [ ! -z "$version" ]; then - echo "Copy javadoc to gh-pages/servicetalk/$version" - rm -rf gh-pages/servicetalk/$version/javadoc - \cp -r $JAVADOC_FOLDER gh-pages/servicetalk/$version -fi - -pushd gh-pages -# Do not override older javadoc with Antora's placeholder: -files_to_revert=$(git diff --name-only | grep 'javadoc/index.html' | grep -v SNAPSHOT) -if [ ! -z "$version" ]; then - files_to_revert=$(echo $files_to_revert | grep -v $version) -fi -echo $files_to_revert | xargs git checkout -- - -$git add * .nojekyll -if [ -z "$version" ]; then - $git commit --author="$GIT_AUTHOR" -m "Update SNAPSHOT doc website" -else - $git commit --author="$GIT_AUTHOR" -m "Publish docs website $version" -fi - -$git push docs gh-pages -popd - -# Clean up the state (worktree and temporary branch) after publication of the docs -clean_up_gh_pages - -if [ -z "$version" ]; then - echo "Docs website for the SNAPSHOT version successfully updated" -else - echo "Docs website for the release version $version successfully published" -fi diff --git a/scripts/release.sh b/scripts/release.sh index 2fffd63e9a..ee5ee211e8 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -1,6 +1,6 @@ #!/bin/bash # -# Copyright © 2019, 2021 Apple Inc. and the ServiceTalk project authors +# Copyright © 2019, 2021-2022 Apple Inc. and the ServiceTalk project authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -22,29 +22,47 @@ set -eu DEFAULT_BRANCH="main" JAPICMP_SKIP_VERSION="skip" +DOCS_FOLDER="docs/generation/.out/remote" +JAVADOC_FOLDER="build/javadoc" +BRANCH_NAME=$(git symbolic-ref -q HEAD) +BRANCH_NAME=${BRANCH_NAME##refs/heads/} +GIT_AUTHOR=$(git --no-pager show -s --format='%an <%ae>' HEAD) function usage() { - echo "Usage: $0 old_version next_version [branch_name]" + echo "Usage: $0 old_version next_version" echo "old_version - the previous version to run japicmp against. \"${JAPICMP_SKIP_VERSION}\" to skip japicmp" echo "next_version - the next version to update gradle.properties, \"-SNAPSHOT\" suffix expected" - echo "branch_name - the branch name to release from (default is \"${DEFAULT_BRANCH})]" echo "Example to release 0.42.10: $0 0.42.9 0.42.11-SNAPSHOT" } -if [ "$#" -lt "2" ]; then +function clean_up_gh_pages() { + if git worktree list | grep -q gh-pages; then + echo "Cleanup 'gh-pages' worktree" + git worktree remove -f gh-pages + fi + if git branch --list | grep -q "^\s*gh-pages$"; then + echo "Remove 'gh-pages' branch" + git branch -Df gh-pages + fi + # Just in case of the undefined initial state make sure there is no gh-pages folder + rm -rf gh-pages +} + +if [ "$#" -ne "2" ]; then usage exit 1 fi +# Enforce JDK17 to get latest LTS javadoc format/features (search, etc.): +java_version=$(./gradlew --no-daemon -version | grep ^JVM: | awk -F\. '{gsub(/^JVM:[ \t]*/,"",$1); print $1"."$2}') +if [ "$java_version" != "17.0" ]; then + echo "Docs can be published only using Java 17, current version: $java_version" + exit 1 +fi + oldVersion="$1" nextVersion="$2" -if [ "$#" -gt "2" ]; then - branchName="$3" -else - branchName=DEFAULT_BRANCH -fi - if ( echo "$nextVersion" | grep -qv "SNAPSHOT" ); then echo "Expected next version to be a SNAPSHOT version" usage @@ -67,10 +85,13 @@ if ( echo "$version" | grep -q "SNAPSHOT" ); then exit 1 fi +# Clean up the state at the beginning in case the previous run did not finish successfully +clean_up_gh_pages + if [ -z "${DRYRUN:-}" ]; then - gradle_build_args="--no-build-cache --warning-mode all --refresh-dependencies clean build publishToMavenLocal" + gradle_build_args="--no-build-cache --warning-mode all --refresh-dependencies clean assemble" else - gradle_build_args="build publishToMavenLocal" + gradle_build_args="assemble" echo "DRYRUN mode is enabled, using cached build." fi @@ -100,17 +121,19 @@ else fi $git fetch -p -if $git rev-parse --quiet --verify ${branchName} > /dev/null; then - $git checkout ${branchName} -else - $git checkout --track ${remote_name}/${branchName} -fi $git pull $git log -n1 +# No need to clean, it has been done above +echo "Generate javadoc..." +./gradlew --no-daemon javadocAll +echo "Javadoc generated, see ./$JAVADOC_FOLDER" + +echo "Generate docs website..." pushd docs/generation ./gradlew --no-daemon clean validateRemoteSite popd +echo "Docs website generated, see ./$DOCS_FOLDER" sed "s/^version=.*/version=$version/" gradle.properties > gradle.properties.tmp mv gradle.properties.tmp gradle.properties @@ -147,7 +170,7 @@ done sed "s/^version=.*/version=$nextVersion/" gradle.properties > gradle.properties.tmp mv gradle.properties.tmp gradle.properties -if [[ "$branchName" == "$DEFAULT_BRANCH" ]]; then +if [[ "$BRANCH_NAME" == "$DEFAULT_BRANCH" ]]; then for file in docs/antora.yml */docs/antora.yml; do sed "s/^version:.*/version: SNAPSHOT/" "$file" > "$file.tmp" mv "$file.tmp" "$file" @@ -159,14 +182,51 @@ if [[ "$branchName" == "$DEFAULT_BRANCH" ]]; then fi $git commit -a -m "Preparing for $nextVersion development" -$git push -u ${remote_name} "$branchName" +$git push -u ${remote_name} "$BRANCH_NAME" # Push tag after branch otherwise, CodeQL GH Action will fail. $git push ${remote_name} "$version" -# Antora docs are published as a single bundle which includes all versions from site-remote.yml. We only publish docs -# from main branch or else we may publish docs that are incomplete and missing newer versions. -if [[ "$branchName" == "$DEFAULT_BRANCH" ]]; then - ./scripts/publish-docs.sh "$version_majorminor" +# Publish docs to gh-pages +if ( ! git remote get-url docs ); then + git remote add docs git@github.com:apple/servicetalk.git +fi +git fetch docs +gh-pages:gh-pages +git worktree add gh-pages gh-pages + +touch gh-pages/.nojekyll + +echo "Copy javadoc to gh-pages/servicetalk/$version_majorminor" +rm -rf gh-pages/servicetalk/$version_majorminor/javadoc +\cp -r $JAVADOC_FOLDER gh-pages/servicetalk/$version_majorminor + +if [[ "$BRANCH_NAME" == "$DEFAULT_BRANCH" ]]; then + echo "Copy Antora docs to gh-pages" + \cp -r $DOCS_FOLDER/* gh-pages + + # Avoid accumulating old javadocs for classes that have been moved, renamed or deleted. + echo "Copy javadoc to gh-pages/servicetalk/SNAPSHOT" + rm -rf gh-pages/servicetalk/SNAPSHOT/javadoc + \cp -r $JAVADOC_FOLDER gh-pages/servicetalk/SNAPSHOT else - echo "Skipping publish-docs.sh. Cherry-pick site-remote.yml changes to $DEFAULT_BRANCH and run manually if desired." + # Antora docs are published as a single bundle which includes all versions from site-remote.yml. We only publish docs + # from main branch or else we may publish docs that are incomplete and missing newer versions. + echo "Skipping Antora unless on $DEFAULT_BRANCH branch. Cherry-pick site-remote.yml changes to $DEFAULT_BRANCH." fi + +pushd gh-pages +# Do not override older javadoc with Antora placeholder +files_to_revert=$(git diff --name-only | grep 'javadoc/index.html' | grep -v SNAPSHOT) +if [[ "$BRANCH_NAME" != "$DEFAULT_BRANCH" ]]; then + files_to_revert=$(echo ${files_to_revert} | grep -v ${version_majorminor}) || echo "empty files_to_revert" +fi +echo $files_to_revert | xargs git checkout -- + +$git add * .nojekyll +$git commit --author="$GIT_AUTHOR" -m "Publish docs website $version_majorminor" +$git push docs gh-pages +popd + +# Clean up the state (worktree and temporary branch) after publication of the docs +clean_up_gh_pages + +echo "Docs website for the release version $version_majorminor successfully published" From 759a20f1b9706848c2e1d972aa950ab828875d97 Mon Sep 17 00:00:00 2001 From: Scott Mitchell Date: Tue, 26 Apr 2022 07:18:43 -0700 Subject: [PATCH 02/40] Clarify AsyncContext concurrency docs (#2199) Modifications: async-context.adoc provides some examples to describe control flow and potential concurrent modification scenarios. The example with the operator flow doesn't provide enough explanation to understand the expected control flow. Modifications: - Add more comments to the example and code which shows expected values on key modified "later" in the operator chain. --- .../modules/ROOT/pages/async-context.adoc | 42 ++++++++++++------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/servicetalk-concurrent-api/docs/modules/ROOT/pages/async-context.adoc b/servicetalk-concurrent-api/docs/modules/ROOT/pages/async-context.adoc index 3c623dbf1c..6e3714e4da 100644 --- a/servicetalk-concurrent-api/docs/modules/ROOT/pages/async-context.adoc +++ b/servicetalk-concurrent-api/docs/modules/ROOT/pages/async-context.adoc @@ -145,18 +145,30 @@ examples below: [source, java] ---- Publisher publisher = ...; -publisher -.flatMapSingle(v -> { - // (1) AsyncContext will be saved before the async boundary - - // AsyncContext will be copied/isolated when this async source is subscribed to - client.request(/*do something with v*/) -) -.map(v -> { - // AsyncContext before the async boundary (1) is restored - - // Note that modifications made to AsyncContext here may introduce concurrency - // and be visible before the async boundary above (1). +AsyncContext.put(KEY, 10); // (1) put a value into AsyncContext before a .subscribe(..) +publisher.flatMapMergeSingle(v -> { + Integer contextValue = AsyncContext.get(KEY); + assert contextValue == 10 || contextValue == 30; // (2) Subscriber chain may see either value. + + // AsyncContext will be copied when Single.subscribe(..) is called. Changes to the AsyncContext map from operators on + // the inner Single operator chain will therefore not be visible in the outer Publisher operator chain. + return client.request(/*do something with v*/) + .map(x -> { + AsyncContext.put(KEY, 20); // (3) put a new value for the same key + return x; + }); +}).map(v -> { + Integer contextValue = AsyncContext.get(KEY); + assert contextValue == 10 || contextValue == 30; + + // `publisher` may emit more items, and if it does then `flatMapMergeSingle` `Function` may be invoked concurrently + // with this code. This is because `client.request(..)` may complete on a different thread than `publisher` is + // delivering data on. This code has access to the same map as (2) which may result in concurrent modifications on + // `AsyncContext`. This is allowed by `AsyncContext` but may not be obvious due to modifications made "later" in the + // operator chain being visible "earlier" in the operator chain. + AsyncContext.put(KEY, 30); + + return v; }) ---- @@ -167,11 +179,11 @@ visible outside the asynchronous boundary. ---- Executor executor = ... -AsyncContext.put(key, "foo") +AsyncContext.put(KEY, "foo"); executor.execute(() -> { - AsyncContext.put(key, "bar") + AsyncContext.put(KEY, "bar"); }); -String value = AsyncContext.get(key); +String value = AsyncContext.get(KEY); // value maybe "foo" or "bar" due to concurrent modifications ---- From 291f7aa0b6b18998c5fe40b3e0a7613fb28326bd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Apr 2022 18:30:32 -0700 Subject: [PATCH 03/40] Bump github/codeql-action from 1 to 2 (#2200) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 1 to 2. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/v1...v2) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 0144b7f687..9312bd288f 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -20,10 +20,10 @@ jobs: - name: Checkout Code uses: actions/checkout@v3 - name: Initialize CodeQL - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }} - name: Execute gradle build run: ./gradlew --parallel clean assemble - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + uses: github/codeql-action/analyze@v2 From 9aec0e075261037d7753ea521e9fb612cdebd048 Mon Sep 17 00:00:00 2001 From: Scott Mitchell Date: Fri, 6 May 2022 14:35:03 -0700 Subject: [PATCH 04/40] Avoid deadlock consuming from blocking Iterator (#2204) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Motivation: The blocking streaming APIs allow for specifying a Iterator as input which is consumed by ServiceTalk. ServiceTalk assumes it can consume in batches from the same thread in order to make progress. However if the Iterator `next()` method is dependent on external input we may deadlock: - `PublisherAsBlockingIterable.onSubscribe(..)` does a `request(16)` - `FromIterablePublisher.request(..)` loops calling `hasNext()` and `next()` until demand is exhausted. Each loop iteration calls `subscriber.onNext(next())`. - The same thread looping in `FromIterablePublisher.request(..)` is also responsible for draining the queue in `PublisherAsBlockingIterable`. This means that no data will be sent downstream until `FromIterablePublisher` exits the loop. This maybe perceived as “dead lock” because no data is sent even if the `Iterable` provides an element. Modifications: - `FromIterablePublisher` and `FromBlockingIterablePublisher` check to unwrap from `PublisherAsBlockingIterable` if possible to directly access the underlying `Publisher`. This skips thee consumption via thee `Iterable` API and avoids the dead lock loop. Result: No more dead lock when using HTTP / gRPC API conversions and providing `Iterable` that is dependent upon external events to make progress. --- .../api/FromBlockingIterablePublisher.java | 13 +- .../concurrent/api/FromIterablePublisher.java | 9 +- .../servicetalk/concurrent/api/Publisher.java | 4 +- .../api/PublisherAsBlockingIterable.java | 2 +- .../BlockingStreamingHttpClientTest.java | 151 ++++++++++++++++++ 5 files changed, 172 insertions(+), 7 deletions(-) create mode 100644 servicetalk-http-netty/src/test/java/io/servicetalk/http/netty/BlockingStreamingHttpClientTest.java diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/FromBlockingIterablePublisher.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/FromBlockingIterablePublisher.java index ba58e8e7ec..73b5c9fa84 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/FromBlockingIterablePublisher.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/FromBlockingIterablePublisher.java @@ -33,14 +33,21 @@ final class FromBlockingIterablePublisher extends AbstractSynchronousPublishe private final LongSupplier timeoutSupplier; private final TimeUnit unit; - FromBlockingIterablePublisher(final BlockingIterable iterable, - final LongSupplier timeoutSupplier, - final TimeUnit unit) { + private FromBlockingIterablePublisher( + final BlockingIterable iterable, final LongSupplier timeoutSupplier, final TimeUnit unit) { this.iterable = requireNonNull(iterable); this.timeoutSupplier = requireNonNull(timeoutSupplier); this.unit = requireNonNull(unit); } + @SuppressWarnings("unchecked") + static Publisher fromBlockingIterable0( + BlockingIterable iterable, LongSupplier timeoutSupplier, TimeUnit unit) { + // Unwrap and grab the Publisher directly if possible to avoid conversion layers. + return iterable instanceof PublisherAsBlockingIterable ? ((PublisherAsBlockingIterable) iterable).original : + new FromBlockingIterablePublisher<>(iterable, timeoutSupplier, unit); + } + @Override void doSubscribe(final Subscriber subscriber) { try { diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/FromIterablePublisher.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/FromIterablePublisher.java index 5dd0e24012..f3c38fd6e0 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/FromIterablePublisher.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/FromIterablePublisher.java @@ -33,10 +33,17 @@ final class FromIterablePublisher extends AbstractSynchronousPublisher { private final Iterable iterable; - FromIterablePublisher(Iterable iterable) { + private FromIterablePublisher(Iterable iterable) { this.iterable = requireNonNull(iterable); } + @SuppressWarnings("unchecked") + static Publisher fromIterable0(Iterable iterable) { + // Unwrap and grab the Publisher directly if possible to avoid conversion layers. + return iterable instanceof PublisherAsBlockingIterable ? ((PublisherAsBlockingIterable) iterable).original : + new FromIterablePublisher<>(iterable); + } + @Override void doSubscribe(final Subscriber subscriber) { try { diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/Publisher.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/Publisher.java index b96c402a5a..6d4b2f9e9a 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/Publisher.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/Publisher.java @@ -3827,7 +3827,7 @@ public static Publisher from(T... values) { * and emit all values to the {@link Subscriber} and then {@link Subscriber#onComplete()}. */ public static Publisher fromIterable(Iterable iterable) { - return new FromIterablePublisher<>(iterable); + return FromIterablePublisher.fromIterable0(iterable); } /** @@ -3855,7 +3855,7 @@ public static Publisher fromIterable(Iterable iterable) { public static Publisher fromBlockingIterable(BlockingIterable iterable, LongSupplier timeoutSupplier, TimeUnit unit) { - return new FromBlockingIterablePublisher<>(iterable, timeoutSupplier, unit); + return FromBlockingIterablePublisher.fromBlockingIterable0(iterable, timeoutSupplier, unit); } /** diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/PublisherAsBlockingIterable.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/PublisherAsBlockingIterable.java index 9fce10aa0b..4ba4ba35ef 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/PublisherAsBlockingIterable.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/PublisherAsBlockingIterable.java @@ -49,7 +49,7 @@ * @param Type of items emitted by the {@link Publisher} from which this {@link BlockingIterable} is created. */ final class PublisherAsBlockingIterable implements BlockingIterable { - private final Publisher original; + final Publisher original; private final int queueCapacityHint; PublisherAsBlockingIterable(final Publisher original) { diff --git a/servicetalk-http-netty/src/test/java/io/servicetalk/http/netty/BlockingStreamingHttpClientTest.java b/servicetalk-http-netty/src/test/java/io/servicetalk/http/netty/BlockingStreamingHttpClientTest.java new file mode 100644 index 0000000000..a26500255f --- /dev/null +++ b/servicetalk-http-netty/src/test/java/io/servicetalk/http/netty/BlockingStreamingHttpClientTest.java @@ -0,0 +1,151 @@ +/* + * Copyright © 2022 Apple Inc. and the ServiceTalk project authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.servicetalk.http.netty; + +import io.servicetalk.http.api.BlockingStreamingHttpClient; +import io.servicetalk.http.api.BlockingStreamingHttpResponse; +import io.servicetalk.http.api.HttpPayloadWriter; +import io.servicetalk.transport.api.ServerContext; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.BooleanSupplier; +import java.util.function.Supplier; + +import static io.servicetalk.http.api.HttpSerializers.appSerializerAsciiFixLen; +import static io.servicetalk.transport.netty.internal.AddressUtils.localAddress; +import static io.servicetalk.transport.netty.internal.AddressUtils.serverHostAndPort; +import static io.servicetalk.utils.internal.PlatformDependent.throwException; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; + +final class BlockingStreamingHttpClientTest { + @ParameterizedTest + @ValueSource(ints = {1, 100}) + void iterableSequentialConsumptionDoesNotDeadLock(int numItems) throws Exception { + try (ServerContext ctx = HttpServers.forAddress(localAddress(0)) + .listenBlockingStreamingAndAwait((ctx1, request, response) -> { + HttpPayloadWriter output = response.sendMetaData(appSerializerAsciiFixLen()); + for (String input : request.payloadBody(appSerializerAsciiFixLen())) { + output.write(input); + } + output.close(); + }); + BlockingStreamingHttpClient client = HttpClients.forResolvedAddress(serverHostAndPort(ctx)) + .buildBlockingStreaming()) { + NextSuppliers nextSuppliers = NextSuppliers.stringSuppliers(numItems); + // Allow first item in Iterator to return from next(). + nextSuppliers.countDownNextLatch(); + BlockingStreamingHttpResponse resp = client.request(client.get("/") + .payloadBody(new TestBlockingIterable<>(nextSuppliers, nextSuppliers), appSerializerAsciiFixLen())); + StringBuilder responseBody = new StringBuilder(numItems); + int i = 0; + for (String respChunk : resp.payloadBody(appSerializerAsciiFixLen())) { + // Goal is to ensure we can write each individual chunk independently without blocking threads or having + // to batch multiple items. As each chunk is echoed back, unblock the next one. + nextSuppliers.countDownNextLatch(); + responseBody.append(respChunk); + ++i; + } + assertThat("num items: " + i + " responseBody: " + responseBody, i, equalTo(numItems)); + } + } + + private static final class NextSuppliers implements Supplier, BooleanSupplier { + private final List> items; + private final AtomicInteger nextIndex = new AtomicInteger(); + private final AtomicInteger latchIndex = new AtomicInteger(); + + NextSuppliers(List> items) { + this.items = items; + } + + static NextSuppliers stringSuppliers(final int numItems) { + List> items = new ArrayList<>(numItems); + for (int i = 0; i < numItems; ++i) { + items.add(new NextSupplier<>(String.valueOf(i))); + } + return new NextSuppliers<>(items); + } + + void countDownNextLatch() { + final int i = latchIndex.getAndIncrement(); + if (i < items.size()) { + items.get(i).latch.countDown(); + } + } + + @Override + public boolean getAsBoolean() { + return nextIndex.get() < items.size(); + } + + @Override + public T get() { + return items.get(nextIndex.getAndIncrement()).get(); + } + } + + private static final class NextSupplier implements Supplier { + final CountDownLatch latch = new CountDownLatch(1); + final T next; + + private NextSupplier(final T next) { + this.next = next; + } + + @Override + public T get() { + try { + latch.await(); + } catch (InterruptedException e) { + throwException(e); + } + return next; + } + } + + private static final class TestBlockingIterable implements Iterable { + private final BooleanSupplier hasNextSupplier; + private final Supplier nextSupplier; + + private TestBlockingIterable(final BooleanSupplier hasNextSupplier, final Supplier nextSupplier) { + this.hasNextSupplier = hasNextSupplier; + this.nextSupplier = nextSupplier; + } + + @Override + public Iterator iterator() { + return new Iterator() { + @Override + public boolean hasNext() { + return hasNextSupplier.getAsBoolean(); + } + + @Override + public T next() { + return nextSupplier.get(); + } + }; + } + } +} From 7cd1c787445567b068d002d1f90901999ae988a2 Mon Sep 17 00:00:00 2001 From: Scott Mitchell Date: Fri, 6 May 2022 15:19:43 -0700 Subject: [PATCH 05/40] Add example for h2 keep alive (#2203) Motivation: Add an example demonstrating how the HTTP/2 transport keep alive feature can be used for gRPC clients and servers. --- .../ROOT/pages/_partials/nav-versioned.adoc | 1 + .../docs/modules/ROOT/pages/grpc/index.adoc | 15 +++ .../grpc/keepalive/README.adoc | 13 +++ .../grpc/keepalive/build.gradle | 80 +++++++++++++++ servicetalk-examples/grpc/keepalive/pom.xml | 97 +++++++++++++++++++ .../grpc/keepalive/KeepAliveClient.java | 91 +++++++++++++++++ .../grpc/keepalive/KeepAliveServer.java | 51 ++++++++++ .../examples/grpc/keepalive/package-info.java | 19 ++++ .../keepalive/src/main/proto/helloworld.proto | 32 ++++++ .../keepalive/src/main/resources/log4j2.xml | 38 ++++++++ settings.gradle | 2 + 11 files changed, 439 insertions(+) create mode 100644 servicetalk-examples/grpc/keepalive/README.adoc create mode 100644 servicetalk-examples/grpc/keepalive/build.gradle create mode 100644 servicetalk-examples/grpc/keepalive/pom.xml create mode 100644 servicetalk-examples/grpc/keepalive/src/main/java/io/servicetalk/examples/grpc/keepalive/KeepAliveClient.java create mode 100644 servicetalk-examples/grpc/keepalive/src/main/java/io/servicetalk/examples/grpc/keepalive/KeepAliveServer.java create mode 100644 servicetalk-examples/grpc/keepalive/src/main/java/io/servicetalk/examples/grpc/keepalive/package-info.java create mode 100644 servicetalk-examples/grpc/keepalive/src/main/proto/helloworld.proto create mode 100644 servicetalk-examples/grpc/keepalive/src/main/resources/log4j2.xml diff --git a/servicetalk-examples/docs/modules/ROOT/pages/_partials/nav-versioned.adoc b/servicetalk-examples/docs/modules/ROOT/pages/_partials/nav-versioned.adoc index 1994cbcb2f..7f5140971e 100644 --- a/servicetalk-examples/docs/modules/ROOT/pages/_partials/nav-versioned.adoc +++ b/servicetalk-examples/docs/modules/ROOT/pages/_partials/nav-versioned.adoc @@ -20,6 +20,7 @@ ** xref:{page-version}@servicetalk-examples::grpc/index.adoc#HelloWorld[Hello World] ** xref:{page-version}@servicetalk-examples::grpc/index.adoc#Compression[Compression] ** xref:{page-version}@servicetalk-examples::grpc/index.adoc#Deadlines[Deadlines] +** xref:{page-version}@servicetalk-examples::grpc/index.adoc#KeepAlive[Keep Alive] ** xref:{page-version}@servicetalk-examples::grpc/index.adoc#Observer[Observer] ** xref:{page-version}@servicetalk-examples::grpc/index.adoc#Health[Health Checking] ** xref:{page-version}@servicetalk-examples::grpc/index.adoc#errors[Application Errors] diff --git a/servicetalk-examples/docs/modules/ROOT/pages/grpc/index.adoc b/servicetalk-examples/docs/modules/ROOT/pages/grpc/index.adoc index 961770886c..6e4646b597 100644 --- a/servicetalk-examples/docs/modules/ROOT/pages/grpc/index.adoc +++ b/servicetalk-examples/docs/modules/ROOT/pages/grpc/index.adoc @@ -96,6 +96,21 @@ https://grpc.io/docs/what-is-grpc/core-concepts/#deadlines[gRPC deadlines] (aka – Sends hello requests to the server with 1 minute deadline and 3 second deadline and receives a greeting response within that time or cancels the request. +[#KeepAlive] +== Keep Alive + +Demonstrates how to use HTTP/2 keep alive for gRPC +link:{source-root}/servicetalk-examples/grpc/keepalive/src/main/java/io/servicetalk/examples/grpc/keepalive/KeepAliveServer.java[server] +and +link:{source-root}/servicetalk-examples/grpc/keepalive/src/main/java/io/servicetalk/examples/grpc/keepalive/KeepAliveClient.java[client]. +Keep alive uses transport control frames to ensure the peer is still able to read and write to open connections. If the +peer is not able to respond to the control frame within the configured amount of time, the connection is closed. This +is useful if your environment doesn't provide other forms of connection keep alive (e.g. +link:https://docs.oracle.com/javase/8/docs/api/java/net/StandardSocketOptions.html#SO_KEEPALIVE[SO_KEEPALIVE], and maybe +preferred to lower level keep alive because it is closer the application logic (more likely if this check works, that +your application is able to read/write). Keep alive can be helpful to detect scenarios such as non-graceful disconnects +(e.g. power outage, ethernet cable pulled, buggy middle box) and general network disconnects. + [#Debugging] == Debugging diff --git a/servicetalk-examples/grpc/keepalive/README.adoc b/servicetalk-examples/grpc/keepalive/README.adoc new file mode 100644 index 0000000000..65ca5d88ec --- /dev/null +++ b/servicetalk-examples/grpc/keepalive/README.adoc @@ -0,0 +1,13 @@ +== ServiceTalk gRPC KeepAlive Example + +Demonstrates how to use HTTP/2 keep alive for gRPC +link:{source-root}/servicetalk-examples/grpc/keepalive/src/main/java/io/servicetalk/examples/grpc/keepalive/KeepAliveServer.java[server] +and +link:{source-root}/servicetalk-examples/grpc/keepalive/src/main/java/io/servicetalk/examples/grpc/keepalive/KeepAliveClient.java[client]. +Keep alive uses transport control frames to ensure the peer is still able to read and write to open connections. If the +peer is not able to respond to the control frame within the configured amount of time, the connection is closed. This +is useful if your environment doesn't provide other forms of connection keep alive (e.g. +link:https://docs.oracle.com/javase/8/docs/api/java/net/StandardSocketOptions.html#SO_KEEPALIVE[SO_KEEPALIVE], and maybe +preferred to lower level keep alive because it is closer the application logic (more likely if this check works, that +your application is able to read/write). Keep alive can be helpful to detect scenarios such as non-graceful disconnects +(e.g. power outage, ethernet cable pulled, buggy middle box) and general network disconnects. \ No newline at end of file diff --git a/servicetalk-examples/grpc/keepalive/build.gradle b/servicetalk-examples/grpc/keepalive/build.gradle new file mode 100644 index 0000000000..23e050aac0 --- /dev/null +++ b/servicetalk-examples/grpc/keepalive/build.gradle @@ -0,0 +1,80 @@ +/* + * Copyright © 2019 Apple Inc. and the ServiceTalk project authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +buildscript { + dependencies { + classpath "com.google.protobuf:protobuf-gradle-plugin:$protobufGradlePluginVersion" + } +} + +apply plugin: "java" +apply plugin: "com.google.protobuf" +apply from: "../../gradle/idea.gradle" + +dependencies { + implementation project(":servicetalk-annotations") + implementation project(":servicetalk-grpc-netty") + implementation project(":servicetalk-grpc-protoc") + implementation project(":servicetalk-grpc-protobuf") + + implementation "org.slf4j:slf4j-api:$slf4jVersion" + runtimeOnly "org.apache.logging.log4j:log4j-slf4j-impl:$log4jVersion" +} + +protobuf { + protoc { + artifact = "com.google.protobuf:protoc:$protobufVersion" + } + + //// REMOVE if outside of ServiceTalk gradle project + def pluginJar = file("${project.rootProject.rootDir}/servicetalk-grpc-protoc/build" + + "/buildExecutable/servicetalk-grpc-protoc-${project.version}-all.jar") + //// REMOVE if outside of ServiceTalk gradle project + + plugins { + servicetalk_grpc { + //// REMOVE if outside of ServiceTalk gradle project - use "artifact" as demonstrated below + //// "path" is used only because we want to use the gradle project local version of the plugin. + path = pluginJar.path + //// REMOVE if outside of ServiceTalk gradle project - use "artifact" as demonstrated below + + // artifact = "io.servicetalk:servicetalk-grpc-protoc:$serviceTalkVersion:all@jar" + } + } + generateProtoTasks { + all().each { task -> + //// REMOVE if outside of ServiceTalk gradle project + task.dependsOn(":servicetalk-grpc-protoc:buildExecutable") // use gradle project local grpc-protoc dependency + + // you may need to manually add the artifact name as an input + task.inputs + .file(pluginJar) + .withNormalizer(ClasspathNormalizer) + .withPropertyName("servicetalkPluginJar") + .withPathSensitivity(PathSensitivity.RELATIVE) + //// REMOVE if outside of ServiceTalk gradle project + + task.plugins { + servicetalk_grpc { + // Need to tell protobuf-gradle-plugin to output in the correct directory if all generated + // code for a single proto goes to a single file (e.g. "java_multiple_files = false" in the .proto). + outputSubDir = "java" + } + } + } + } + generatedFilesBaseDir = "$buildDir/generated/sources/proto" +} diff --git a/servicetalk-examples/grpc/keepalive/pom.xml b/servicetalk-examples/grpc/keepalive/pom.xml new file mode 100644 index 0000000000..9406c0df65 --- /dev/null +++ b/servicetalk-examples/grpc/keepalive/pom.xml @@ -0,0 +1,97 @@ + + 4.0.0 + io.servicetalk.examples.grpc.helloworld + helloworld-maven + jar + 1.0-SNAPSHOT + st-examples + https://servicetalk.io + + + + 0.42.0 + 0.6.1 + 3.19.2 + 1.6.0 + 3.8.1 + + + + + + kr.motd.maven + os-maven-plugin + ${os-maven-plugin.version} + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + + + org.xolstice.maven.plugins + protobuf-maven-plugin + ${protobuf-maven-plugin.version} + true + + + + compile + + + com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier} + + + servicetalk-grpc-protoc + io.servicetalk + servicetalk-grpc-protoc + ${servicetalk.version} + io.servicetalk.grpc.protoc.Main + + + + + + + + + + + + + io.servicetalk + servicetalk-bom + ${servicetalk.version} + pom + import + + + + + + + io.servicetalk + servicetalk-annotations + + + io.servicetalk + servicetalk-grpc-netty + + + io.servicetalk + servicetalk-grpc-protoc + + + io.servicetalk + servicetalk-grpc-protobuf + + + diff --git a/servicetalk-examples/grpc/keepalive/src/main/java/io/servicetalk/examples/grpc/keepalive/KeepAliveClient.java b/servicetalk-examples/grpc/keepalive/src/main/java/io/servicetalk/examples/grpc/keepalive/KeepAliveClient.java new file mode 100644 index 0000000000..44502bb3cb --- /dev/null +++ b/servicetalk-examples/grpc/keepalive/src/main/java/io/servicetalk/examples/grpc/keepalive/KeepAliveClient.java @@ -0,0 +1,91 @@ +/* + * Copyright © 2022 Apple Inc. and the ServiceTalk project authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.servicetalk.examples.grpc.keepalive; + +import io.servicetalk.grpc.netty.GrpcClients; + +import io.grpc.examples.keepalive.HelloReply; +import io.grpc.examples.keepalive.HelloRequest; +import io.grpc.examples.keepalive.StreamingGreeter.BlockingStreamingGreeterClient; +import io.grpc.examples.keepalive.StreamingGreeter.ClientFactory; + +import java.io.IOException; +import java.util.Iterator; +import java.util.function.Supplier; + +import static io.servicetalk.http.netty.H2KeepAlivePolicies.whenIdleFor; +import static io.servicetalk.http.netty.HttpProtocolConfigs.h2; +import static io.servicetalk.logging.api.LogLevel.TRACE; +import static java.time.Duration.ofSeconds; + +/** + * Example that demonstrates how to enable HTTP/2 keep alive for a gRPC client. + */ +public final class KeepAliveClient { + public static void main(String... args) throws Exception { + try (BlockingStreamingGreeterClient client = GrpcClients.forAddress("localhost", 8080) + .initializeHttp(httpBuilder -> httpBuilder.protocols( + // 4 second timeout is typically much shorter than necessary, but demonstrates PING frame traffic. + // Using the default value is suitable in most scenarios, but if you want to customize the value + // consider how many resources (network traffic, CPU for local timer management) vs time to detect + // bad connection. + // The keep alive is only sent when no traffic is detected, so if both peers have keep alive the + // faster interval will be the primary sender. + h2().keepAlivePolicy(whenIdleFor(ofSeconds(4))) + // Enable frame logging so we can see the PING frames sent/received. + .enableFrameLogging("servicetalk-examples-h2-frame-logger", TRACE, () -> true) + .build())) + .buildBlocking(new ClientFactory())) { + HelloReply reply = client.streamHello(new StdInIterable<>(() -> + HelloRequest.newBuilder().setName("World").build())); + System.out.println("Got reply: " + reply); + } + } + + /** + * Infinite input stream, each item is sent when data is read from std in. + * @param The type of items to iterate. + */ + private static final class StdInIterable implements Iterable { + private final Supplier itemSupplier; + + private StdInIterable(final Supplier itemSupplier) { + this.itemSupplier = itemSupplier; + } + + @Override + public Iterator iterator() { + return new Iterator() { + @Override + public boolean hasNext() { + System.out.println("Press any key to send next item..."); + try { + @SuppressWarnings("unused") + int r = System.in.read(); + } catch (IOException e) { + throw new RuntimeException("Unexpected exception waiting for input", e); + } + return true; + } + + @Override + public T next() { + return itemSupplier.get(); + } + }; + } + } +} diff --git a/servicetalk-examples/grpc/keepalive/src/main/java/io/servicetalk/examples/grpc/keepalive/KeepAliveServer.java b/servicetalk-examples/grpc/keepalive/src/main/java/io/servicetalk/examples/grpc/keepalive/KeepAliveServer.java new file mode 100644 index 0000000000..a11b31edd3 --- /dev/null +++ b/servicetalk-examples/grpc/keepalive/src/main/java/io/servicetalk/examples/grpc/keepalive/KeepAliveServer.java @@ -0,0 +1,51 @@ +/* + * Copyright © 2022 Apple Inc. and the ServiceTalk project authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.servicetalk.examples.grpc.keepalive; + +import io.servicetalk.concurrent.api.Single; +import io.servicetalk.grpc.netty.GrpcServers; + +import io.grpc.examples.keepalive.StreamingGreeter.StreamingGreeterService; + +import static io.servicetalk.http.netty.H2KeepAlivePolicies.whenIdleFor; +import static io.servicetalk.http.netty.HttpProtocolConfigs.h2; +import static io.servicetalk.logging.api.LogLevel.TRACE; +import static java.time.Duration.ofSeconds; + +/** + * Example that demonstrates how to enable HTTP/2 keep alive for a gRPC server. + */ +public final class KeepAliveServer { + public static void main(String... args) throws Exception { + GrpcServers.forPort(8080) + .initializeHttp(httpBuilder -> httpBuilder.protocols( + // 6 second timeout is typically much shorter than necessary, but demonstrates PING frame traffic. + // Using the default value is suitable in most scenarios, but if you want to customize the value + // consider how many resources (network traffic, CPU for local timer management) vs time to detect + // bad connection. + // The keep alive is only sent when no traffic is detected, so if both peers have keep alive the + // faster interval will be the primary sender. + h2().keepAlivePolicy(whenIdleFor(ofSeconds(6))) + // Enable frame logging so we can see the PING frames sent/received. + .enableFrameLogging("servicetalk-examples-h2-frame-logger", TRACE, () -> true) + .build())) + .listenAndAwait((StreamingGreeterService) (ctx, request) -> + request.whenOnNext(item -> System.out.println("Got request: " + item)).ignoreElements() + // Never return a response so we can see keep alive in action. + .concat(Single.never())) + .awaitShutdown(); + } +} diff --git a/servicetalk-examples/grpc/keepalive/src/main/java/io/servicetalk/examples/grpc/keepalive/package-info.java b/servicetalk-examples/grpc/keepalive/src/main/java/io/servicetalk/examples/grpc/keepalive/package-info.java new file mode 100644 index 0000000000..4f1b1f8573 --- /dev/null +++ b/servicetalk-examples/grpc/keepalive/src/main/java/io/servicetalk/examples/grpc/keepalive/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright © 2022 Apple Inc. and the ServiceTalk project authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@ElementsAreNonnullByDefault +package io.servicetalk.examples.grpc.keepalive; + +import io.servicetalk.annotations.ElementsAreNonnullByDefault; diff --git a/servicetalk-examples/grpc/keepalive/src/main/proto/helloworld.proto b/servicetalk-examples/grpc/keepalive/src/main/proto/helloworld.proto new file mode 100644 index 0000000000..b5719e50bd --- /dev/null +++ b/servicetalk-examples/grpc/keepalive/src/main/proto/helloworld.proto @@ -0,0 +1,32 @@ +// Copyright 2015 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "io.grpc.examples.keepalive"; +option java_outer_classname = "KeepAliveProto"; + +package keepalive; + +service StreamingGreeter { + rpc StreamHello (stream HelloRequest) returns (HelloReply) {} +} + +message HelloRequest { + string name = 1; +} + +message HelloReply { + string message = 1; +} diff --git a/servicetalk-examples/grpc/keepalive/src/main/resources/log4j2.xml b/servicetalk-examples/grpc/keepalive/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..f2b28781b3 --- /dev/null +++ b/servicetalk-examples/grpc/keepalive/src/main/resources/log4j2.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/settings.gradle b/settings.gradle index c142ddc673..1952486853 100644 --- a/settings.gradle +++ b/settings.gradle @@ -50,6 +50,7 @@ include "servicetalk-annotations", "servicetalk-examples:grpc:execution-strategy", "servicetalk-examples:grpc:observer", "servicetalk-examples:grpc:health", + "servicetalk-examples:grpc:keepalive", "servicetalk-examples:http:helloworld", "servicetalk-examples:http:mutual-tls", "servicetalk-examples:http:redirects", @@ -117,6 +118,7 @@ project(":servicetalk-examples:grpc:errors").name = "servicetalk-examples-grpc-e project(":servicetalk-examples:grpc:execution-strategy").name = "servicetalk-examples-grpc-execution-strategy" project(":servicetalk-examples:grpc:observer").name = "servicetalk-examples-grpc-observer" project(":servicetalk-examples:grpc:health").name = "servicetalk-examples-grpc-health" +project(":servicetalk-examples:grpc:keepalive").name = "servicetalk-examples-grpc-keepalive" project(":servicetalk-examples:http:http2").name = "servicetalk-examples-http-http2" project(":servicetalk-examples:http:helloworld").name = "servicetalk-examples-http-helloworld" project(":servicetalk-examples:http:debugging").name = "servicetalk-examples-http-debugging" From e4fd15791c021ee7ed0de595066f159fa79a0c84 Mon Sep 17 00:00:00 2001 From: Scott Mitchell Date: Fri, 6 May 2022 15:44:17 -0700 Subject: [PATCH 06/40] Remove pom.xml from gRPC KeepAlive example (#2206) Motivation: The gRPC KeepAlive example was copy/pasted from helloworld which brought a pom.xml that isn't necessary and not updated for this project. --- .../grpc/keepalive/README.adoc | 4 +- servicetalk-examples/grpc/keepalive/pom.xml | 97 ------------------- 2 files changed, 2 insertions(+), 99 deletions(-) delete mode 100644 servicetalk-examples/grpc/keepalive/pom.xml diff --git a/servicetalk-examples/grpc/keepalive/README.adoc b/servicetalk-examples/grpc/keepalive/README.adoc index 65ca5d88ec..088a0013a3 100644 --- a/servicetalk-examples/grpc/keepalive/README.adoc +++ b/servicetalk-examples/grpc/keepalive/README.adoc @@ -1,9 +1,9 @@ == ServiceTalk gRPC KeepAlive Example Demonstrates how to use HTTP/2 keep alive for gRPC -link:{source-root}/servicetalk-examples/grpc/keepalive/src/main/java/io/servicetalk/examples/grpc/keepalive/KeepAliveServer.java[server] +link:src/main/java/io/servicetalk/examples/grpc/keepalive/KeepAliveServer.java[server] and -link:{source-root}/servicetalk-examples/grpc/keepalive/src/main/java/io/servicetalk/examples/grpc/keepalive/KeepAliveClient.java[client]. +link:src/main/java/io/servicetalk/examples/grpc/keepalive/KeepAliveClient.java[client]. Keep alive uses transport control frames to ensure the peer is still able to read and write to open connections. If the peer is not able to respond to the control frame within the configured amount of time, the connection is closed. This is useful if your environment doesn't provide other forms of connection keep alive (e.g. diff --git a/servicetalk-examples/grpc/keepalive/pom.xml b/servicetalk-examples/grpc/keepalive/pom.xml deleted file mode 100644 index 9406c0df65..0000000000 --- a/servicetalk-examples/grpc/keepalive/pom.xml +++ /dev/null @@ -1,97 +0,0 @@ - - 4.0.0 - io.servicetalk.examples.grpc.helloworld - helloworld-maven - jar - 1.0-SNAPSHOT - st-examples - https://servicetalk.io - - - - 0.42.0 - 0.6.1 - 3.19.2 - 1.6.0 - 3.8.1 - - - - - - kr.motd.maven - os-maven-plugin - ${os-maven-plugin.version} - - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin.version} - - 1.8 - 1.8 - - - - org.xolstice.maven.plugins - protobuf-maven-plugin - ${protobuf-maven-plugin.version} - true - - - - compile - - - com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier} - - - servicetalk-grpc-protoc - io.servicetalk - servicetalk-grpc-protoc - ${servicetalk.version} - io.servicetalk.grpc.protoc.Main - - - - - - - - - - - - - io.servicetalk - servicetalk-bom - ${servicetalk.version} - pom - import - - - - - - - io.servicetalk - servicetalk-annotations - - - io.servicetalk - servicetalk-grpc-netty - - - io.servicetalk - servicetalk-grpc-protoc - - - io.servicetalk - servicetalk-grpc-protobuf - - - From 8b0cf587aff89a4d7b91bcaa72eaa3093aa372f5 Mon Sep 17 00:00:00 2001 From: Scott Mitchell Date: Fri, 6 May 2022 17:50:08 -0700 Subject: [PATCH 07/40] Update Netty 4.1.76 -> 4.1.77 (#2207) --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index bf808be4eb..88d7953d34 100644 --- a/gradle.properties +++ b/gradle.properties @@ -29,7 +29,7 @@ issueManagementUrl=https://github.com/apple/servicetalk/issues ciManagementUrl=https://github.com/apple/servicetalk/actions # dependency versions -nettyVersion=4.1.76.Final +nettyVersion=4.1.77.Final nettyIoUringVersion=0.0.13.Final jsr305Version=3.0.2 From 4bcfe24b46ea2b47c9f93d7e6b0ee6a5a5e686aa Mon Sep 17 00:00:00 2001 From: Mike Duigou Date: Tue, 10 May 2022 10:17:49 -0700 Subject: [PATCH 08/40] Generate JavaDoc only for API JavaDoc tasks (#2202) Motivation: Some modules generate JavaDoc to check that source code they generate includes conforming JavaDoc. This test JavaDoc should not be included in the consolidated project JavaDocs. Modifications: Filter JavaDoc tasks using task name to include only the default JavaDoc task. Result: Mysterious test code JavaDoc excluded from project JavaDocs. --- .../gradle/plugin/internal/ServiceTalkRootPlugin.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/servicetalk-gradle-plugin-internal/src/main/groovy/io/servicetalk/gradle/plugin/internal/ServiceTalkRootPlugin.groovy b/servicetalk-gradle-plugin-internal/src/main/groovy/io/servicetalk/gradle/plugin/internal/ServiceTalkRootPlugin.groovy index ba048ecb29..3239361796 100644 --- a/servicetalk-gradle-plugin-internal/src/main/groovy/io/servicetalk/gradle/plugin/internal/ServiceTalkRootPlugin.groovy +++ b/servicetalk-gradle-plugin-internal/src/main/groovy/io/servicetalk/gradle/plugin/internal/ServiceTalkRootPlugin.groovy @@ -52,7 +52,7 @@ final class ServiceTalkRootPlugin extends ServiceTalkCorePlugin { gradle.projectsEvaluated { subprojects.findAll {!it.name.contains("examples")}.each { prj -> - prj.tasks.withType(Javadoc).each { javadocTask -> + prj.tasks.withType(Javadoc).findAll {it.name.equals("javadoc")}.each { javadocTask -> source += javadocTask.source classpath += javadocTask.classpath excludes += javadocTask.excludes From 4ce81d513c9598043c5ffba49478bb72ed06a8e5 Mon Sep 17 00:00:00 2001 From: Mike Duigou Date: Tue, 10 May 2022 18:30:23 -0700 Subject: [PATCH 09/40] Tighter dependency for protoc plugin (#2209) Motivation: Currently the `servicetalk-grpc-protoc` module exposes javapoet and protobuf-java as dependencies though they are used only in the protoc plugin and are not accurately dependencies of the module. Modifications: Use `compileOnly` for protoc plugin dependencies and change shadowJar to build using `compileClasspath` configuration. The dependencies are also needed for `testImplementation`. Result: Fewer exposed dependencies, especially dependency which is not actually used by module outside of protoc plugin. --- servicetalk-grpc-protoc/build.gradle | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/servicetalk-grpc-protoc/build.gradle b/servicetalk-grpc-protoc/build.gradle index 9d29e7b042..fbfea22680 100644 --- a/servicetalk-grpc-protoc/build.gradle +++ b/servicetalk-grpc-protoc/build.gradle @@ -26,15 +26,15 @@ dependencies { implementation project(":servicetalk-annotations") - // runtimeOnly is enough for this module in isolation, but we want transitive modules to include at compile time too. + // Needed for the generated classes api project(":servicetalk-data-protobuf") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" - implementation "com.google.protobuf:protobuf-java:$protobufVersion" - implementation "com.squareup:javapoet:$javaPoetVersion" + compileOnly "com.google.code.findbugs:jsr305:$jsr305Version" + compileOnly "com.squareup:javapoet:$javaPoetVersion" testImplementation project(":servicetalk-grpc-api") testImplementation project(":servicetalk-grpc-protobuf") + testImplementation "com.squareup:javapoet:$javaPoetVersion" testImplementation "org.junit.jupiter:junit-jupiter-api" testImplementation "org.hamcrest:hamcrest:$hamcrestVersion" } @@ -48,6 +48,8 @@ jar { } shadowJar { + // includes javaPoet and Google protobufs + configurations = [project.configurations.compileClasspath] archiveBaseName = project.name classifier = 'all' } From 3d260462dce23d126892ecf5206a3c15fecad3c5 Mon Sep 17 00:00:00 2001 From: Idel Pivnitskiy Date: Wed, 11 May 2022 17:10:56 -0500 Subject: [PATCH 10/40] Avoid self-suppression for exceptions (#2211) Motivation: In case a processing function re-throws the original exception, we risk to face `IllegalArgumentException("Self-suppression not permitted)` when operator adds a re-thrown exception as suppressed. Modifications: - Add utility that verifies the suppressed exception is not the same as the original one; Result: No `IllegalArgumentException("Self-suppression not permitted)`. --- .../concurrent/api/AbstractPubToSingle.java | 3 ++- .../api/BeforeFinallyCompletable.java | 4 ++-- .../concurrent/api/BeforeFinallyPublisher.java | 4 ++-- .../concurrent/api/BeforeFinallySingle.java | 4 ++-- .../api/BeforeSubscriberCompletable.java | 4 ++-- .../api/BeforeSubscriberPublisher.java | 4 ++-- .../concurrent/api/BeforeSubscriberSingle.java | 4 ++-- .../api/CompletableMergeSubscriber.java | 5 ++--- .../concurrent/api/CompositeCancellable.java | 3 ++- .../api/CompositeExceptionUtils.java | 4 +++- .../api/OnErrorResumeCompletable.java | 4 ++-- .../concurrent/api/OnErrorResumePublisher.java | 12 ++++++------ .../concurrent/api/OnErrorResumeSingle.java | 4 ++-- .../concurrent/api/RedoPublisher.java | 3 ++- .../concurrent/api/RedoWhenPublisher.java | 3 ++- .../concurrent/api/RetrySingle.java | 5 +++-- .../concurrent/api/RetryWhenSingle.java | 4 ++-- .../concurrent/api/TestCompletable.java | 3 ++- .../concurrent/api/TestPublisher.java | 3 ++- .../servicetalk/concurrent/api/TestSingle.java | 3 ++- .../internal/TerminalNotification.java | 7 +++---- .../dns/discovery/netty/DefaultDnsClient.java | 3 ++- .../grpc/netty/ProtocolCompatibilityTest.java | 3 ++- .../api/HttpDataSourceTransformations.java | 3 ++- .../AbstractLifecycleObserverHttpFilter.java | 3 ++- .../netty/H2ClientParentConnectionContext.java | 3 ++- .../http/utils/BeforeFinallyHttpOperator.java | 7 ++++--- servicetalk-serialization-api/build.gradle | 1 + .../serialization/api/DefaultSerializer.java | 5 +++-- servicetalk-test-resources/build.gradle | 5 +++-- .../servicetalk/test/resources/TestUtils.java | 3 ++- servicetalk-transport-api/build.gradle | 1 + .../api/CatchAllTransportObserver.java | 3 ++- .../build.gradle | 1 + .../transport/netty/internal/Flush.java | 3 ++- .../netty/internal/WriteStreamSubscriber.java | 3 ++- .../netty/internal/EmbeddedDuplexChannel.java | 3 ++- .../utils/internal/ThrowableUtils.java | 18 +++++++++++++++--- 38 files changed, 97 insertions(+), 61 deletions(-) diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/AbstractPubToSingle.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/AbstractPubToSingle.java index bf25095474..11239c2430 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/AbstractPubToSingle.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/AbstractPubToSingle.java @@ -27,6 +27,7 @@ import static io.servicetalk.concurrent.Cancellable.IGNORE_CANCEL; import static io.servicetalk.concurrent.api.SubscriberApiUtils.unwrapNullUnchecked; import static io.servicetalk.concurrent.internal.SubscriberUtils.checkDuplicateSubscription; +import static io.servicetalk.utils.internal.ThrowableUtils.addSuppressed; abstract class AbstractPubToSingle extends AbstractNoHandleSubscribeSingle { private final Publisher source; @@ -110,7 +111,7 @@ void terminate(Object terminal) { subscriber.onSubscribe(IGNORE_CANCEL); } catch (Throwable t) { if (terminal instanceof Throwable) { - ((Throwable) terminal).addSuppressed(t); + addSuppressed((Throwable) terminal, t); } else { LOGGER.warn("Unexpected exception from onSubscribe from subscriber {}. Discarding result {}.", subscriber, terminal, t); diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/BeforeFinallyCompletable.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/BeforeFinallyCompletable.java index f08ab5ce44..4570438cfa 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/BeforeFinallyCompletable.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/BeforeFinallyCompletable.java @@ -19,6 +19,7 @@ import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; +import static io.servicetalk.utils.internal.ThrowableUtils.addSuppressed; import static java.util.Objects.requireNonNull; final class BeforeFinallyCompletable extends AbstractSynchronousCompletableOperator { @@ -78,8 +79,7 @@ public void onError(Throwable cause) { doFinally.onError(cause); } } catch (Throwable error) { - error.addSuppressed(cause); - original.onError(error); + original.onError(addSuppressed(error, cause)); return; } original.onError(cause); diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/BeforeFinallyPublisher.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/BeforeFinallyPublisher.java index afd403ee24..648b6b758e 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/BeforeFinallyPublisher.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/BeforeFinallyPublisher.java @@ -17,6 +17,7 @@ import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; +import static io.servicetalk.utils.internal.ThrowableUtils.addSuppressed; import static java.util.Objects.requireNonNull; final class BeforeFinallyPublisher extends AbstractSynchronousPublisherOperator { @@ -93,8 +94,7 @@ public void onError(Throwable cause) { doFinally.onError(cause); } } catch (Throwable err) { - err.addSuppressed(cause); - original.onError(err); + original.onError(addSuppressed(err, cause)); return; } original.onError(cause); diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/BeforeFinallySingle.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/BeforeFinallySingle.java index ca9fa546d6..26392ad9df 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/BeforeFinallySingle.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/BeforeFinallySingle.java @@ -19,6 +19,7 @@ import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; +import static io.servicetalk.utils.internal.ThrowableUtils.addSuppressed; import static java.util.Objects.requireNonNull; final class BeforeFinallySingle extends AbstractSynchronousSingleOperator { @@ -79,8 +80,7 @@ public void onError(Throwable cause) { doFinally.onError(cause); } } catch (Throwable err) { - err.addSuppressed(cause); - original.onError(err); + original.onError(addSuppressed(err, cause)); return; } original.onError(cause); diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/BeforeSubscriberCompletable.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/BeforeSubscriberCompletable.java index b12b6682ab..6ac0ec71ab 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/BeforeSubscriberCompletable.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/BeforeSubscriberCompletable.java @@ -19,6 +19,7 @@ import java.util.function.Supplier; +import static io.servicetalk.utils.internal.ThrowableUtils.addSuppressed; import static java.util.Objects.requireNonNull; final class BeforeSubscriberCompletable extends AbstractSynchronousCompletableOperator { @@ -67,8 +68,7 @@ public void onError(Throwable t) { try { subscriber.onError(t); } catch (Throwable cause) { - t.addSuppressed(cause); - original.onError(t); + original.onError(addSuppressed(t, cause)); return; } original.onError(t); diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/BeforeSubscriberPublisher.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/BeforeSubscriberPublisher.java index c9a00d532c..f3b220bc6c 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/BeforeSubscriberPublisher.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/BeforeSubscriberPublisher.java @@ -17,6 +17,7 @@ import java.util.function.Supplier; +import static io.servicetalk.utils.internal.ThrowableUtils.addSuppressed; import static java.util.Objects.requireNonNull; final class BeforeSubscriberPublisher extends AbstractSynchronousPublisherOperator { @@ -70,8 +71,7 @@ public void onError(Throwable t) { try { subscriber.onError(t); } catch (Throwable cause) { - t.addSuppressed(cause); - original.onError(t); + original.onError(addSuppressed(t, cause)); return; } original.onError(t); diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/BeforeSubscriberSingle.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/BeforeSubscriberSingle.java index b6cf245018..7b30fc5173 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/BeforeSubscriberSingle.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/BeforeSubscriberSingle.java @@ -19,6 +19,7 @@ import java.util.function.Supplier; +import static io.servicetalk.utils.internal.ThrowableUtils.addSuppressed; import static java.util.Objects.requireNonNull; final class BeforeSubscriberSingle extends AbstractSynchronousSingleOperator { @@ -66,8 +67,7 @@ public void onError(Throwable t) { try { subscriber.onError(t); } catch (Throwable cause) { - t.addSuppressed(cause); - original.onError(t); + original.onError(addSuppressed(t, cause)); return; } original.onError(t); diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/CompletableMergeSubscriber.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/CompletableMergeSubscriber.java index 5647ece984..e2ff3aff83 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/CompletableMergeSubscriber.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/CompletableMergeSubscriber.java @@ -21,6 +21,7 @@ import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import javax.annotation.Nullable; +import static io.servicetalk.utils.internal.ThrowableUtils.addSuppressed; import static java.util.concurrent.atomic.AtomicReferenceFieldUpdater.newUpdater; abstract class CompletableMergeSubscriber implements Subscriber { @@ -68,9 +69,7 @@ public final void onError(Throwable t) { return; } } else { - Throwable tmpT = (Throwable) terminalNotification; - tmpT.addSuppressed(t); - t = tmpT; + t = addSuppressed((Throwable) terminalNotification, t); break; } } diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/CompositeCancellable.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/CompositeCancellable.java index 9f6389e7a0..9aa16dae87 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/CompositeCancellable.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/CompositeCancellable.java @@ -20,6 +20,7 @@ import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; import static io.servicetalk.utils.internal.PlatformDependent.throwException; +import static io.servicetalk.utils.internal.ThrowableUtils.addSuppressed; import static java.util.Objects.requireNonNull; /** @@ -56,7 +57,7 @@ public void cancel() { if (t == null) { t = tt; } else { - t.addSuppressed(tt); + addSuppressed(t, tt); } } } diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/CompositeExceptionUtils.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/CompositeExceptionUtils.java index bc7db72045..7175eb98ac 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/CompositeExceptionUtils.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/CompositeExceptionUtils.java @@ -17,6 +17,8 @@ import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; +import static io.servicetalk.utils.internal.ThrowableUtils.addSuppressed; + final class CompositeExceptionUtils { /** * Default to {@code 1} so {@link Throwable#addSuppressed(Throwable)} will not be used by default. @@ -33,7 +35,7 @@ static void addPendingError(AtomicIntegerFieldUpdater updater, T owner, i if (newSize < 0) { updater.set(owner, Integer.MAX_VALUE); } else if (newSize < maxDelayedErrors && original != causeToAdd) { - original.addSuppressed(causeToAdd); + addSuppressed(original, causeToAdd); } else { updater.decrementAndGet(owner); } diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/OnErrorResumeCompletable.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/OnErrorResumeCompletable.java index 3291807cb2..20f1968538 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/OnErrorResumeCompletable.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/OnErrorResumeCompletable.java @@ -23,6 +23,7 @@ import java.util.function.Predicate; import javax.annotation.Nullable; +import static io.servicetalk.utils.internal.ThrowableUtils.addSuppressed; import static java.util.Objects.requireNonNull; final class OnErrorResumeCompletable extends AbstractNoHandleSubscribeCompletable { @@ -86,8 +87,7 @@ public void onError(Throwable throwable) { requireNonNull(parent.nextFactory.apply(throwable)) : null; } catch (Throwable t) { - t.addSuppressed(throwable); - subscriber.onError(t); + subscriber.onError(addSuppressed(t, throwable)); return; } diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/OnErrorResumePublisher.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/OnErrorResumePublisher.java index 34ddc970e9..23642bae6e 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/OnErrorResumePublisher.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/OnErrorResumePublisher.java @@ -21,6 +21,7 @@ import java.util.function.Predicate; import javax.annotation.Nullable; +import static io.servicetalk.utils.internal.ThrowableUtils.addSuppressed; import static java.util.Objects.requireNonNull; final class OnErrorResumePublisher extends AbstractNoHandleSubscribePublisher { @@ -76,18 +77,17 @@ public void onNext(T t) { } @Override - public void onError(Throwable t) { + public void onError(Throwable throwable) { final Publisher next; try { - next = !resubscribed && predicate.test(t) ? requireNonNull(nextFactory.apply(t)) : null; - } catch (Throwable throwable) { - throwable.addSuppressed(t); - subscriber.onError(throwable); + next = !resubscribed && predicate.test(throwable) ? requireNonNull(nextFactory.apply(throwable)) : null; + } catch (Throwable t) { + subscriber.onError(addSuppressed(t, throwable)); return; } if (next == null) { - subscriber.onError(t); + subscriber.onError(throwable); } else { final Subscriber offloadedSubscriber = contextProvider.wrapPublisherSubscriber(this, contextMap); diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/OnErrorResumeSingle.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/OnErrorResumeSingle.java index 59db57a067..8c92ac938e 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/OnErrorResumeSingle.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/OnErrorResumeSingle.java @@ -23,6 +23,7 @@ import java.util.function.Predicate; import javax.annotation.Nullable; +import static io.servicetalk.utils.internal.ThrowableUtils.addSuppressed; import static java.util.Objects.requireNonNull; final class OnErrorResumeSingle extends AbstractNoHandleSubscribeSingle { @@ -81,8 +82,7 @@ public void onError(Throwable throwable) { try { next = !resubscribed && predicate.test(throwable) ? requireNonNull(nextFactory.apply(throwable)) : null; } catch (Throwable t) { - t.addSuppressed(throwable); - subscriber.onError(t); + subscriber.onError(addSuppressed(t, throwable)); return; } diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/RedoPublisher.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/RedoPublisher.java index 15c1d03aef..321f2d529f 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/RedoPublisher.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/RedoPublisher.java @@ -22,6 +22,7 @@ import java.util.function.IntPredicate; import static io.servicetalk.concurrent.internal.TerminalNotification.complete; +import static io.servicetalk.utils.internal.ThrowableUtils.addSuppressed; /** * {@link Publisher} to do {@link Publisher#repeat(IntPredicate)} and {@link Publisher#retry(BiIntPredicate)} @@ -116,7 +117,7 @@ private void tryRedo(TerminalNotification notification) { } catch (Throwable cause) { Throwable originalCause = notification.cause(); if (originalCause != null) { - cause.addSuppressed(originalCause); + addSuppressed(cause, originalCause); } subscriber.onError(cause); return; diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/RedoWhenPublisher.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/RedoWhenPublisher.java index 8b528d37c8..b61ff6e9da 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/RedoWhenPublisher.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/RedoWhenPublisher.java @@ -25,6 +25,7 @@ import java.util.function.IntFunction; import static io.servicetalk.concurrent.internal.TerminalNotification.complete; +import static io.servicetalk.utils.internal.ThrowableUtils.addSuppressed; import static java.util.Objects.requireNonNull; /** @@ -143,7 +144,7 @@ private void redoIfRequired(TerminalNotification terminalNotification) { } catch (Throwable cause) { Throwable originalCause = terminalNotification.cause(); if (originalCause != null) { - cause.addSuppressed(originalCause); + addSuppressed(cause, originalCause); } subscriber.onError(cause); return; diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/RetrySingle.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/RetrySingle.java index b39ec8cb4a..6d55652d3e 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/RetrySingle.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/RetrySingle.java @@ -21,6 +21,8 @@ import javax.annotation.Nullable; +import static io.servicetalk.utils.internal.ThrowableUtils.addSuppressed; + /** * A {@link Single} implementation as returned by {@link Single#retry(BiIntPredicate)}. * @@ -97,8 +99,7 @@ public void onError(Throwable t) { try { shouldRetry = retrySingle.shouldRetry.test(++retryCount, t); } catch (Throwable cause) { - cause.addSuppressed(t); - target.onError(cause); + target.onError(addSuppressed(cause, t)); return; } if (shouldRetry) { diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/RetryWhenSingle.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/RetryWhenSingle.java index 7b997a0dd7..805d615793 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/RetryWhenSingle.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/RetryWhenSingle.java @@ -22,6 +22,7 @@ import javax.annotation.Nullable; +import static io.servicetalk.utils.internal.ThrowableUtils.addSuppressed; import static java.util.Objects.requireNonNull; /** @@ -104,8 +105,7 @@ public void onError(Throwable t) { try { retryDecider = requireNonNull(retrySingle.shouldRetry.apply(++retryCount, t)); } catch (Throwable cause) { - cause.addSuppressed(t); - target.onError(cause); + target.onError(addSuppressed(cause, t)); return; } diff --git a/servicetalk-concurrent-api/src/testFixtures/java/io/servicetalk/concurrent/api/TestCompletable.java b/servicetalk-concurrent-api/src/testFixtures/java/io/servicetalk/concurrent/api/TestCompletable.java index badce3f177..71537878ac 100644 --- a/servicetalk-concurrent-api/src/testFixtures/java/io/servicetalk/concurrent/api/TestCompletable.java +++ b/servicetalk-concurrent-api/src/testFixtures/java/io/servicetalk/concurrent/api/TestCompletable.java @@ -31,6 +31,7 @@ import javax.annotation.Nullable; import static io.servicetalk.utils.internal.PlatformDependent.throwException; +import static io.servicetalk.utils.internal.ThrowableUtils.addSuppressed; import static java.util.Objects.requireNonNull; /** @@ -150,7 +151,7 @@ private Subscriber checkSubscriberAndExceptions() { final RuntimeException exception = new RuntimeException("Unexpected exception(s) encountered", exceptions.get(0)); for (int i = 1; i < exceptions.size(); i++) { - exception.addSuppressed(exceptions.get(i)); + addSuppressed(exception, exceptions.get(i)); } throw exception; } diff --git a/servicetalk-concurrent-api/src/testFixtures/java/io/servicetalk/concurrent/api/TestPublisher.java b/servicetalk-concurrent-api/src/testFixtures/java/io/servicetalk/concurrent/api/TestPublisher.java index 916ceb847c..e43dc65656 100644 --- a/servicetalk-concurrent-api/src/testFixtures/java/io/servicetalk/concurrent/api/TestPublisher.java +++ b/servicetalk-concurrent-api/src/testFixtures/java/io/servicetalk/concurrent/api/TestPublisher.java @@ -30,6 +30,7 @@ import javax.annotation.Nullable; import static io.servicetalk.utils.internal.PlatformDependent.throwException; +import static io.servicetalk.utils.internal.ThrowableUtils.addSuppressed; import static java.util.Objects.requireNonNull; /** @@ -176,7 +177,7 @@ private Subscriber checkSubscriberAndExceptions() { final RuntimeException exception = new RuntimeException("Unexpected exception(s) encountered", exceptions.get(0)); for (int i = 1; i < exceptions.size(); i++) { - exception.addSuppressed(exceptions.get(i)); + addSuppressed(exception, exceptions.get(i)); } throw exception; } diff --git a/servicetalk-concurrent-api/src/testFixtures/java/io/servicetalk/concurrent/api/TestSingle.java b/servicetalk-concurrent-api/src/testFixtures/java/io/servicetalk/concurrent/api/TestSingle.java index d16613b645..4d61626f6e 100644 --- a/servicetalk-concurrent-api/src/testFixtures/java/io/servicetalk/concurrent/api/TestSingle.java +++ b/servicetalk-concurrent-api/src/testFixtures/java/io/servicetalk/concurrent/api/TestSingle.java @@ -31,6 +31,7 @@ import static io.servicetalk.concurrent.test.internal.AwaitUtils.await; import static io.servicetalk.utils.internal.PlatformDependent.throwException; +import static io.servicetalk.utils.internal.ThrowableUtils.addSuppressed; import static java.util.Objects.requireNonNull; /** @@ -153,7 +154,7 @@ private Subscriber checkSubscriberAndExceptions() { final RuntimeException exception = new RuntimeException("Unexpected exception(s) encountered", exceptions.get(0)); for (int i = 1; i < exceptions.size(); i++) { - exception.addSuppressed(exceptions.get(i)); + addSuppressed(exception, exceptions.get(i)); } throw exception; } diff --git a/servicetalk-concurrent-internal/src/main/java/io/servicetalk/concurrent/internal/TerminalNotification.java b/servicetalk-concurrent-internal/src/main/java/io/servicetalk/concurrent/internal/TerminalNotification.java index fdd2a35de3..9d65f7c559 100644 --- a/servicetalk-concurrent-internal/src/main/java/io/servicetalk/concurrent/internal/TerminalNotification.java +++ b/servicetalk-concurrent-internal/src/main/java/io/servicetalk/concurrent/internal/TerminalNotification.java @@ -21,6 +21,7 @@ import java.util.Objects; import javax.annotation.Nullable; +import static io.servicetalk.utils.internal.ThrowableUtils.addSuppressed; import static java.util.Objects.requireNonNull; /** @@ -80,8 +81,7 @@ public void terminate(PublisherSource.Subscriber subscriber, Throwable additi subscriber.onError(additionalCause); } else { assert cause != null; - cause.addSuppressed(additionalCause); - subscriber.onError(cause); + subscriber.onError(addSuppressed(cause, additionalCause)); } } @@ -102,8 +102,7 @@ public void terminate(Subscriber subscriber, Throwable additionalCause) { subscriber.onError(additionalCause); } else { assert cause != null; - cause.addSuppressed(additionalCause); - subscriber.onError(cause); + subscriber.onError(addSuppressed(cause, additionalCause)); } } diff --git a/servicetalk-dns-discovery-netty/src/main/java/io/servicetalk/dns/discovery/netty/DefaultDnsClient.java b/servicetalk-dns-discovery-netty/src/main/java/io/servicetalk/dns/discovery/netty/DefaultDnsClient.java index 8e3e4ef7f2..c91f269af7 100644 --- a/servicetalk-dns-discovery-netty/src/main/java/io/servicetalk/dns/discovery/netty/DefaultDnsClient.java +++ b/servicetalk-dns-discovery-netty/src/main/java/io/servicetalk/dns/discovery/netty/DefaultDnsClient.java @@ -90,6 +90,7 @@ import static io.servicetalk.transport.netty.internal.BuilderUtils.datagramChannel; import static io.servicetalk.transport.netty.internal.BuilderUtils.socketChannel; import static io.servicetalk.transport.netty.internal.EventLoopAwareNettyIoExecutors.toEventLoopAwareNettyIoExecutor; +import static io.servicetalk.utils.internal.ThrowableUtils.addSuppressed; import static java.nio.ByteBuffer.wrap; import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; @@ -698,7 +699,7 @@ private void reportResolutionFailed(@Nullable final DnsResolutionObserver resolu try { resolutionObserver.resolutionFailed(cause); } catch (Throwable unexpected) { - unexpected.addSuppressed(cause); + addSuppressed(unexpected, cause); LOGGER.warn("Unexpected exception from {} while reporting DNS resolution failure", resolutionObserver, unexpected); } diff --git a/servicetalk-grpc-netty/src/test/java/io/servicetalk/grpc/netty/ProtocolCompatibilityTest.java b/servicetalk-grpc-netty/src/test/java/io/servicetalk/grpc/netty/ProtocolCompatibilityTest.java index 897be0c627..66cdfe088f 100644 --- a/servicetalk-grpc-netty/src/test/java/io/servicetalk/grpc/netty/ProtocolCompatibilityTest.java +++ b/servicetalk-grpc-netty/src/test/java/io/servicetalk/grpc/netty/ProtocolCompatibilityTest.java @@ -126,6 +126,7 @@ import static io.servicetalk.test.resources.DefaultTestCerts.serverPemHostname; import static io.servicetalk.transport.api.SslProvider.OPENSSL; import static io.servicetalk.transport.netty.internal.AddressUtils.localAddress; +import static io.servicetalk.utils.internal.ThrowableUtils.addSuppressed; import static java.time.Duration.ofMillis; import static java.util.Arrays.asList; import static java.util.concurrent.TimeUnit.NANOSECONDS; @@ -980,7 +981,7 @@ private static void closeAll(final AutoCloseable... acs) { if (re == null) { re = new RuntimeException("Failure(s) when closing: " + Arrays.toString(acs)); } - re.addSuppressed(t); + addSuppressed(re, t); } } diff --git a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/HttpDataSourceTransformations.java b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/HttpDataSourceTransformations.java index 95e7d9984f..84a86dae82 100644 --- a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/HttpDataSourceTransformations.java +++ b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/HttpDataSourceTransformations.java @@ -40,6 +40,7 @@ import static io.servicetalk.concurrent.api.Single.succeeded; import static io.servicetalk.concurrent.api.SourceAdapters.toSource; import static io.servicetalk.concurrent.internal.SubscriberUtils.checkDuplicateSubscription; +import static io.servicetalk.utils.internal.ThrowableUtils.addSuppressed; import static java.lang.Integer.MAX_VALUE; import static java.lang.System.nanoTime; import static java.util.Objects.requireNonNull; @@ -240,7 +241,7 @@ private boolean validateNext(@Nullable Object next) { try { iterator.close(); } catch (Throwable cause) { - e.addSuppressed(cause); + addSuppressed(e, cause); } throw e; } diff --git a/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/AbstractLifecycleObserverHttpFilter.java b/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/AbstractLifecycleObserverHttpFilter.java index 40e6183fb5..2deb50510d 100644 --- a/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/AbstractLifecycleObserverHttpFilter.java +++ b/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/AbstractLifecycleObserverHttpFilter.java @@ -49,6 +49,7 @@ import static io.servicetalk.concurrent.api.Single.defer; import static io.servicetalk.context.api.ContextMap.Key.newKey; +import static io.servicetalk.utils.internal.ThrowableUtils.addSuppressed; import static java.util.Objects.requireNonNull; abstract class AbstractLifecycleObserverHttpFilter implements HttpExecutionStrategyInfluencer { @@ -288,7 +289,7 @@ private static void safeReport(final Consumer onError, final Throwabl try { onError.accept(t); } catch (Throwable unexpected) { - unexpected.addSuppressed(t); + addSuppressed(unexpected, t); LOGGER.warn("Unexpected exception from {} while reporting a '{}' event", observer, eventName, unexpected); } } diff --git a/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/H2ClientParentConnectionContext.java b/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/H2ClientParentConnectionContext.java index cd3b7fd7b3..0f83332bc1 100644 --- a/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/H2ClientParentConnectionContext.java +++ b/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/H2ClientParentConnectionContext.java @@ -89,6 +89,7 @@ import static io.servicetalk.transport.netty.internal.ChannelCloseUtils.close; import static io.servicetalk.transport.netty.internal.ChannelSet.CHANNEL_CLOSEABLE_KEY; import static io.servicetalk.transport.netty.internal.CloseHandler.forNonPipelined; +import static io.servicetalk.utils.internal.ThrowableUtils.addSuppressed; import static java.util.Objects.requireNonNull; final class H2ClientParentConnectionContext extends H2ParentConnectionContext { @@ -375,7 +376,7 @@ private void childChannelActive(Future future, try { close(streamChannel, cause); } catch (Throwable unexpected) { - unexpected.addSuppressed(cause); + addSuppressed(unexpected, cause); LOGGER.warn("Unexpected exception while handling the original cause", unexpected); } } else { diff --git a/servicetalk-http-utils/src/main/java/io/servicetalk/http/utils/BeforeFinallyHttpOperator.java b/servicetalk-http-utils/src/main/java/io/servicetalk/http/utils/BeforeFinallyHttpOperator.java index 4f3cea2583..7ef0a1d959 100644 --- a/servicetalk-http-utils/src/main/java/io/servicetalk/http/utils/BeforeFinallyHttpOperator.java +++ b/servicetalk-http-utils/src/main/java/io/servicetalk/http/utils/BeforeFinallyHttpOperator.java @@ -32,6 +32,7 @@ import javax.annotation.Nullable; import static io.servicetalk.concurrent.api.SourceAdapters.toSource; +import static io.servicetalk.utils.internal.ThrowableUtils.addSuppressed; import static java.util.Objects.requireNonNull; import static java.util.concurrent.atomic.AtomicIntegerFieldUpdater.newUpdater; @@ -281,7 +282,7 @@ public void onError(final Throwable t) { beforeFinally.onError(t); } } catch (Throwable cause) { - t.addSuppressed(cause); + addSuppressed(t, cause); } subscriber.onError(t); return; @@ -298,7 +299,7 @@ public void onError(final Throwable t) { try { beforeFinally.onError(t); } catch (Throwable cause) { - t.addSuppressed(cause); + addSuppressed(t, cause); } try { subscriber.onError(t); @@ -398,7 +399,7 @@ public void onError(final Throwable t) { return; } } catch (Throwable cause) { - t.addSuppressed(cause); + addSuppressed(t, cause); } subscriber.onError(t); } diff --git a/servicetalk-serialization-api/build.gradle b/servicetalk-serialization-api/build.gradle index 6e563cd0b9..e6f9526997 100644 --- a/servicetalk-serialization-api/build.gradle +++ b/servicetalk-serialization-api/build.gradle @@ -26,6 +26,7 @@ dependencies { implementation project(":servicetalk-annotations") implementation project(":servicetalk-concurrent-api-internal") implementation project(":servicetalk-concurrent-internal") + implementation project(":servicetalk-utils-internal") implementation "com.google.code.findbugs:jsr305:$jsr305Version" testImplementation testFixtures(project(":servicetalk-concurrent-api")) diff --git a/servicetalk-serialization-api/src/main/java/io/servicetalk/serialization/api/DefaultSerializer.java b/servicetalk-serialization-api/src/main/java/io/servicetalk/serialization/api/DefaultSerializer.java index f19a1955e2..f2d5c1f56b 100644 --- a/servicetalk-serialization-api/src/main/java/io/servicetalk/serialization/api/DefaultSerializer.java +++ b/servicetalk-serialization-api/src/main/java/io/servicetalk/serialization/api/DefaultSerializer.java @@ -35,6 +35,7 @@ import javax.annotation.Nullable; import static io.servicetalk.concurrent.api.SourceAdapters.toSource; +import static io.servicetalk.utils.internal.ThrowableUtils.addSuppressed; import static java.lang.Integer.MAX_VALUE; import static java.lang.Math.max; import static java.lang.Math.min; @@ -326,7 +327,7 @@ private static CloseableIterable deserializeAndClose(final S source, try { deSerializer.close(); } catch (SerializationException e) { - throwable.addSuppressed(e); + addSuppressed(throwable, e); } throw throwable; } @@ -352,7 +353,7 @@ private static void closeIterator(CloseableIterator iterator, @Nullable Seria iterator.close(); // May throw in case of incomplete accumulated data } catch (Exception e) { if (cause != null) { - cause.addSuppressed(e); + addSuppressed(cause, e); throw cause; } if (e instanceof SerializationException) { diff --git a/servicetalk-test-resources/build.gradle b/servicetalk-test-resources/build.gradle index 06a26b6486..e58bbb6319 100644 --- a/servicetalk-test-resources/build.gradle +++ b/servicetalk-test-resources/build.gradle @@ -19,11 +19,12 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") - implementation project(":servicetalk-annotations") - api "org.apache.logging.log4j:log4j-core:$log4jVersion" api "org.apache.logging.log4j:log4j-slf4j-impl:$log4jVersion" api "org.hamcrest:hamcrest:$hamcrestVersion" + implementation project(":servicetalk-annotations") + implementation project(":servicetalk-utils-internal") + testImplementation "org.junit.jupiter:junit-jupiter-api" } diff --git a/servicetalk-test-resources/src/main/java/io/servicetalk/test/resources/TestUtils.java b/servicetalk-test-resources/src/main/java/io/servicetalk/test/resources/TestUtils.java index 0c1158d1bf..c153bded15 100644 --- a/servicetalk-test-resources/src/main/java/io/servicetalk/test/resources/TestUtils.java +++ b/servicetalk-test-resources/src/main/java/io/servicetalk/test/resources/TestUtils.java @@ -21,6 +21,7 @@ import java.util.Queue; +import static io.servicetalk.utils.internal.ThrowableUtils.addSuppressed; import static java.lang.Integer.min; /** @@ -57,7 +58,7 @@ public static void assertNoAsyncErrors(final String message, final Queue Date: Wed, 11 May 2022 18:21:01 -0700 Subject: [PATCH 11/40] Release 0.42.10 --- docs/antora.yml | 2 +- docs/generation/site-remote.yml | 20 +++++++++---------- docs/modules/ROOT/nav.adoc | 2 +- gradle.properties | 2 +- servicetalk-client-api/docs/antora.yml | 2 +- .../docs/modules/ROOT/nav.adoc | 2 +- servicetalk-concurrent-api/docs/antora.yml | 2 +- .../docs/modules/ROOT/nav.adoc | 2 +- .../docs/antora.yml | 2 +- .../docs/modules/ROOT/nav.adoc | 2 +- .../docs/antora.yml | 2 +- .../docs/modules/ROOT/nav.adoc | 2 +- servicetalk-examples/docs/antora.yml | 2 +- .../docs/modules/ROOT/nav.adoc | 2 +- servicetalk-grpc-api/docs/antora.yml | 2 +- .../docs/modules/ROOT/nav.adoc | 2 +- servicetalk-http-api/docs/antora.yml | 2 +- .../docs/modules/ROOT/nav.adoc | 2 +- .../docs/antora.yml | 2 +- .../docs/modules/ROOT/nav.adoc | 2 +- .../docs/antora.yml | 2 +- .../docs/modules/ROOT/nav.adoc | 2 +- servicetalk-loadbalancer/docs/antora.yml | 2 +- .../docs/modules/ROOT/nav.adoc | 2 +- 24 files changed, 33 insertions(+), 33 deletions(-) diff --git a/docs/antora.yml b/docs/antora.yml index 00a61d3a1b..894b4930d6 100644 --- a/docs/antora.yml +++ b/docs/antora.yml @@ -16,6 +16,6 @@ name: servicetalk title: ServiceTalk -version: SNAPSHOT +version: '0.42' nav: - modules/ROOT/nav.adoc diff --git a/docs/generation/site-remote.yml b/docs/generation/site-remote.yml index f541a569a5..356654c566 100644 --- a/docs/generation/site-remote.yml +++ b/docs/generation/site-remote.yml @@ -30,43 +30,43 @@ content: sources: - url: https://github.com/apple/servicetalk.git branches: main - tags: [0.19.0, 0.20.0, 0.21.0, 0.22.0, 0.23.0, 0.24.0, 0.25.0, 0.26.0, 0.27.0, 0.28.0, 0.29.0, 0.30.0, 0.31.0, 0.32.0, 0.33.0, 0.34.0, 0.35.0, 0.36.0, 0.37.0, 0.38.0, 0.39.0, 0.40.0, 0.41.14, 0.42.2] + tags: [0.19.0, 0.20.0, 0.21.0, 0.22.0, 0.23.0, 0.24.0, 0.25.0, 0.26.0, 0.27.0, 0.28.0, 0.29.0, 0.30.0, 0.31.0, 0.32.0, 0.33.0, 0.34.0, 0.35.0, 0.36.0, 0.37.0, 0.38.0, 0.39.0, 0.40.0, 0.41.14, 0.42.10] start_path: docs - url: https://github.com/apple/servicetalk.git branches: main - tags: [0.19.0, 0.20.0, 0.21.0, 0.22.0, 0.23.0, 0.24.0, 0.25.0, 0.26.0, 0.27.0, 0.28.0, 0.29.0, 0.30.0, 0.31.0, 0.32.0, 0.33.0, 0.34.0, 0.35.0, 0.36.0, 0.37.0, 0.38.0, 0.39.0, 0.40.0, 0.41.14, 0.42.2] + tags: [0.19.0, 0.20.0, 0.21.0, 0.22.0, 0.23.0, 0.24.0, 0.25.0, 0.26.0, 0.27.0, 0.28.0, 0.29.0, 0.30.0, 0.31.0, 0.32.0, 0.33.0, 0.34.0, 0.35.0, 0.36.0, 0.37.0, 0.38.0, 0.39.0, 0.40.0, 0.41.14, 0.42.10] start_path: servicetalk-examples/docs - url: https://github.com/apple/servicetalk.git branches: main - tags: [0.19.0, 0.20.0, 0.21.0, 0.22.0, 0.23.0, 0.24.0, 0.25.0, 0.26.0, 0.27.0, 0.28.0, 0.29.0, 0.30.0, 0.31.0, 0.32.0, 0.33.0, 0.34.0, 0.35.0, 0.36.0, 0.37.0, 0.38.0, 0.39.0, 0.40.0, 0.41.14, 0.42.2] + tags: [0.19.0, 0.20.0, 0.21.0, 0.22.0, 0.23.0, 0.24.0, 0.25.0, 0.26.0, 0.27.0, 0.28.0, 0.29.0, 0.30.0, 0.31.0, 0.32.0, 0.33.0, 0.34.0, 0.35.0, 0.36.0, 0.37.0, 0.38.0, 0.39.0, 0.40.0, 0.41.14, 0.42.10] start_path: servicetalk-http-api/docs - url: https://github.com/apple/servicetalk.git branches: main - tags: [0.19.0, 0.20.0, 0.21.0, 0.22.0, 0.23.0, 0.24.0, 0.25.0, 0.26.0, 0.27.0, 0.28.0, 0.29.0, 0.30.0, 0.31.0, 0.32.0, 0.33.0, 0.34.0, 0.35.0, 0.36.0, 0.37.0, 0.38.0, 0.39.0, 0.40.0, 0.41.14, 0.42.2] + tags: [0.19.0, 0.20.0, 0.21.0, 0.22.0, 0.23.0, 0.24.0, 0.25.0, 0.26.0, 0.27.0, 0.28.0, 0.29.0, 0.30.0, 0.31.0, 0.32.0, 0.33.0, 0.34.0, 0.35.0, 0.36.0, 0.37.0, 0.38.0, 0.39.0, 0.40.0, 0.41.14, 0.42.10] start_path: servicetalk-http-router-jersey/docs - url: https://github.com/apple/servicetalk.git branches: main - tags: [0.19.0, 0.20.0, 0.21.0, 0.22.0, 0.23.0, 0.24.0, 0.25.0, 0.26.0, 0.27.0, 0.28.0, 0.29.0, 0.30.0, 0.31.0, 0.32.0, 0.33.0, 0.34.0, 0.35.0, 0.36.0, 0.37.0, 0.38.0, 0.39.0, 0.40.0, 0.41.14, 0.42.2] + tags: [0.19.0, 0.20.0, 0.21.0, 0.22.0, 0.23.0, 0.24.0, 0.25.0, 0.26.0, 0.27.0, 0.28.0, 0.29.0, 0.30.0, 0.31.0, 0.32.0, 0.33.0, 0.34.0, 0.35.0, 0.36.0, 0.37.0, 0.38.0, 0.39.0, 0.40.0, 0.41.14, 0.42.10] start_path: servicetalk-http-security-jersey/docs - url: https://github.com/apple/servicetalk.git branches: main - tags: [0.19.0, 0.20.0, 0.21.0, 0.22.0, 0.23.0, 0.24.0, 0.25.0, 0.26.0, 0.27.0, 0.28.0, 0.29.0, 0.30.0, 0.31.0, 0.32.0, 0.33.0, 0.34.0, 0.35.0, 0.36.0, 0.37.0, 0.38.0, 0.39.0, 0.40.0, 0.41.14, 0.42.2] + tags: [0.19.0, 0.20.0, 0.21.0, 0.22.0, 0.23.0, 0.24.0, 0.25.0, 0.26.0, 0.27.0, 0.28.0, 0.29.0, 0.30.0, 0.31.0, 0.32.0, 0.33.0, 0.34.0, 0.35.0, 0.36.0, 0.37.0, 0.38.0, 0.39.0, 0.40.0, 0.41.14, 0.42.10] start_path: servicetalk-concurrent-api/docs - url: https://github.com/apple/servicetalk.git branches: main - tags: [0.19.0, 0.20.0, 0.21.0, 0.22.0, 0.23.0, 0.24.0, 0.25.0, 0.26.0, 0.27.0, 0.28.0, 0.29.0, 0.30.0, 0.31.0, 0.32.0, 0.33.0, 0.34.0, 0.35.0, 0.36.0, 0.37.0, 0.38.0, 0.39.0, 0.40.0, 0.41.14, 0.42.2] + tags: [0.19.0, 0.20.0, 0.21.0, 0.22.0, 0.23.0, 0.24.0, 0.25.0, 0.26.0, 0.27.0, 0.28.0, 0.29.0, 0.30.0, 0.31.0, 0.32.0, 0.33.0, 0.34.0, 0.35.0, 0.36.0, 0.37.0, 0.38.0, 0.39.0, 0.40.0, 0.41.14, 0.42.10] start_path: servicetalk-data-jackson-jersey/docs - url: https://github.com/apple/servicetalk.git branches: main - tags: [0.19.0, 0.20.0, 0.21.0, 0.22.0, 0.23.0, 0.24.0, 0.25.0, 0.26.0, 0.27.0, 0.28.0, 0.29.0, 0.30.0, 0.31.0, 0.32.0, 0.33.0, 0.34.0, 0.35.0, 0.36.0, 0.37.0, 0.38.0, 0.39.0, 0.40.0, 0.41.14, 0.42.2] + tags: [0.19.0, 0.20.0, 0.21.0, 0.22.0, 0.23.0, 0.24.0, 0.25.0, 0.26.0, 0.27.0, 0.28.0, 0.29.0, 0.30.0, 0.31.0, 0.32.0, 0.33.0, 0.34.0, 0.35.0, 0.36.0, 0.37.0, 0.38.0, 0.39.0, 0.40.0, 0.41.14, 0.42.10] start_path: servicetalk-grpc-api/docs - url: https://github.com/apple/servicetalk.git branches: main - tags: [0.20.0, 0.21.0, 0.22.0, 0.23.0, 0.24.0, 0.25.0, 0.26.0, 0.27.0, 0.28.0, 0.29.0, 0.30.0, 0.31.0, 0.32.0, 0.33.0, 0.34.0, 0.35.0, 0.36.0, 0.37.0, 0.38.0, 0.39.0, 0.40.0, 0.41.14, 0.42.2] + tags: [0.20.0, 0.21.0, 0.22.0, 0.23.0, 0.24.0, 0.25.0, 0.26.0, 0.27.0, 0.28.0, 0.29.0, 0.30.0, 0.31.0, 0.32.0, 0.33.0, 0.34.0, 0.35.0, 0.36.0, 0.37.0, 0.38.0, 0.39.0, 0.40.0, 0.41.14, 0.42.10] start_path: servicetalk-loadbalancer/docs - url: https://github.com/apple/servicetalk.git branches: main - tags: [0.25.0, 0.26.0, 0.27.0, 0.28.0, 0.29.0, 0.30.0, 0.31.0, 0.32.0, 0.33.0, 0.34.0, 0.35.0, 0.36.0, 0.37.0, 0.38.0, 0.39.0, 0.40.0, 0.41.14, 0.42.2] + tags: [0.25.0, 0.26.0, 0.27.0, 0.28.0, 0.29.0, 0.30.0, 0.31.0, 0.32.0, 0.33.0, 0.34.0, 0.35.0, 0.36.0, 0.37.0, 0.38.0, 0.39.0, 0.40.0, 0.41.14, 0.42.10] start_path: servicetalk-client-api/docs asciidoc: attributes: diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index 0afba89ac4..bb8528f4e8 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -1,5 +1,5 @@ ifndef::page-version[] -:page-version: SNAPSHOT +:page-version: 0.42 endif::[] include::{page-version}@servicetalk::partial$nav-versioned.adoc[] diff --git a/gradle.properties b/gradle.properties index 88d7953d34..a1b8a21083 100644 --- a/gradle.properties +++ b/gradle.properties @@ -22,7 +22,7 @@ org.gradle.jvmargs=-Xms2g -Xmx4g -dsa -da -ea:io.servicetalk... -XX:+HeapDumpOnO # project metadata used for publications group=io.servicetalk -version=0.42.10-SNAPSHOT +version=0.42.10 scmHost=github.com scmPath=apple/servicetalk issueManagementUrl=https://github.com/apple/servicetalk/issues diff --git a/servicetalk-client-api/docs/antora.yml b/servicetalk-client-api/docs/antora.yml index 6522f97515..efc15ff236 100644 --- a/servicetalk-client-api/docs/antora.yml +++ b/servicetalk-client-api/docs/antora.yml @@ -16,6 +16,6 @@ name: servicetalk-client-api title: Client API -version: SNAPSHOT +version: '0.42' nav: - modules/ROOT/nav.adoc diff --git a/servicetalk-client-api/docs/modules/ROOT/nav.adoc b/servicetalk-client-api/docs/modules/ROOT/nav.adoc index 0afba89ac4..bb8528f4e8 100644 --- a/servicetalk-client-api/docs/modules/ROOT/nav.adoc +++ b/servicetalk-client-api/docs/modules/ROOT/nav.adoc @@ -1,5 +1,5 @@ ifndef::page-version[] -:page-version: SNAPSHOT +:page-version: 0.42 endif::[] include::{page-version}@servicetalk::partial$nav-versioned.adoc[] diff --git a/servicetalk-concurrent-api/docs/antora.yml b/servicetalk-concurrent-api/docs/antora.yml index 71dcd1cef2..b28d71dc68 100644 --- a/servicetalk-concurrent-api/docs/antora.yml +++ b/servicetalk-concurrent-api/docs/antora.yml @@ -16,6 +16,6 @@ name: servicetalk-concurrent-api title: Concurrent API -version: SNAPSHOT +version: '0.42' nav: - modules/ROOT/nav.adoc diff --git a/servicetalk-concurrent-api/docs/modules/ROOT/nav.adoc b/servicetalk-concurrent-api/docs/modules/ROOT/nav.adoc index 0afba89ac4..bb8528f4e8 100644 --- a/servicetalk-concurrent-api/docs/modules/ROOT/nav.adoc +++ b/servicetalk-concurrent-api/docs/modules/ROOT/nav.adoc @@ -1,5 +1,5 @@ ifndef::page-version[] -:page-version: SNAPSHOT +:page-version: 0.42 endif::[] include::{page-version}@servicetalk::partial$nav-versioned.adoc[] diff --git a/servicetalk-data-jackson-jersey/docs/antora.yml b/servicetalk-data-jackson-jersey/docs/antora.yml index 9734c0b9ba..a3d24c2463 100644 --- a/servicetalk-data-jackson-jersey/docs/antora.yml +++ b/servicetalk-data-jackson-jersey/docs/antora.yml @@ -16,6 +16,6 @@ name: servicetalk-data-jackson-jersey title: JSON (Jackson) -version: SNAPSHOT +version: '0.42' nav: - modules/ROOT/nav.adoc diff --git a/servicetalk-data-jackson-jersey/docs/modules/ROOT/nav.adoc b/servicetalk-data-jackson-jersey/docs/modules/ROOT/nav.adoc index 0afba89ac4..bb8528f4e8 100644 --- a/servicetalk-data-jackson-jersey/docs/modules/ROOT/nav.adoc +++ b/servicetalk-data-jackson-jersey/docs/modules/ROOT/nav.adoc @@ -1,5 +1,5 @@ ifndef::page-version[] -:page-version: SNAPSHOT +:page-version: 0.42 endif::[] include::{page-version}@servicetalk::partial$nav-versioned.adoc[] diff --git a/servicetalk-data-protobuf-jersey/docs/antora.yml b/servicetalk-data-protobuf-jersey/docs/antora.yml index ca4b011d91..f8b901792c 100644 --- a/servicetalk-data-protobuf-jersey/docs/antora.yml +++ b/servicetalk-data-protobuf-jersey/docs/antora.yml @@ -16,6 +16,6 @@ name: servicetalk-data-protobuf-jersey title: Protobuf -version: SNAPSHOT +version: '0.42' nav: - modules/ROOT/nav.adoc diff --git a/servicetalk-data-protobuf-jersey/docs/modules/ROOT/nav.adoc b/servicetalk-data-protobuf-jersey/docs/modules/ROOT/nav.adoc index 0afba89ac4..bb8528f4e8 100644 --- a/servicetalk-data-protobuf-jersey/docs/modules/ROOT/nav.adoc +++ b/servicetalk-data-protobuf-jersey/docs/modules/ROOT/nav.adoc @@ -1,5 +1,5 @@ ifndef::page-version[] -:page-version: SNAPSHOT +:page-version: 0.42 endif::[] include::{page-version}@servicetalk::partial$nav-versioned.adoc[] diff --git a/servicetalk-examples/docs/antora.yml b/servicetalk-examples/docs/antora.yml index 9371528ccc..6cdf50dbed 100644 --- a/servicetalk-examples/docs/antora.yml +++ b/servicetalk-examples/docs/antora.yml @@ -16,6 +16,6 @@ name: servicetalk-examples title: Examples -version: SNAPSHOT +version: '0.42' nav: - modules/ROOT/nav.adoc diff --git a/servicetalk-examples/docs/modules/ROOT/nav.adoc b/servicetalk-examples/docs/modules/ROOT/nav.adoc index 0afba89ac4..bb8528f4e8 100644 --- a/servicetalk-examples/docs/modules/ROOT/nav.adoc +++ b/servicetalk-examples/docs/modules/ROOT/nav.adoc @@ -1,5 +1,5 @@ ifndef::page-version[] -:page-version: SNAPSHOT +:page-version: 0.42 endif::[] include::{page-version}@servicetalk::partial$nav-versioned.adoc[] diff --git a/servicetalk-grpc-api/docs/antora.yml b/servicetalk-grpc-api/docs/antora.yml index c96cd2d20f..aff1ab7c9d 100644 --- a/servicetalk-grpc-api/docs/antora.yml +++ b/servicetalk-grpc-api/docs/antora.yml @@ -16,6 +16,6 @@ name: servicetalk-grpc-api title: gRPC -version: SNAPSHOT +version: '0.42' nav: - modules/ROOT/nav.adoc diff --git a/servicetalk-grpc-api/docs/modules/ROOT/nav.adoc b/servicetalk-grpc-api/docs/modules/ROOT/nav.adoc index 0afba89ac4..bb8528f4e8 100644 --- a/servicetalk-grpc-api/docs/modules/ROOT/nav.adoc +++ b/servicetalk-grpc-api/docs/modules/ROOT/nav.adoc @@ -1,5 +1,5 @@ ifndef::page-version[] -:page-version: SNAPSHOT +:page-version: 0.42 endif::[] include::{page-version}@servicetalk::partial$nav-versioned.adoc[] diff --git a/servicetalk-http-api/docs/antora.yml b/servicetalk-http-api/docs/antora.yml index 96121d6cf9..a2b075c3b9 100644 --- a/servicetalk-http-api/docs/antora.yml +++ b/servicetalk-http-api/docs/antora.yml @@ -16,6 +16,6 @@ name: servicetalk-http-api title: HTTP -version: SNAPSHOT +version: '0.42' nav: - modules/ROOT/nav.adoc diff --git a/servicetalk-http-api/docs/modules/ROOT/nav.adoc b/servicetalk-http-api/docs/modules/ROOT/nav.adoc index 0afba89ac4..bb8528f4e8 100644 --- a/servicetalk-http-api/docs/modules/ROOT/nav.adoc +++ b/servicetalk-http-api/docs/modules/ROOT/nav.adoc @@ -1,5 +1,5 @@ ifndef::page-version[] -:page-version: SNAPSHOT +:page-version: 0.42 endif::[] include::{page-version}@servicetalk::partial$nav-versioned.adoc[] diff --git a/servicetalk-http-router-jersey/docs/antora.yml b/servicetalk-http-router-jersey/docs/antora.yml index c4c118acdb..f92e95c6bc 100644 --- a/servicetalk-http-router-jersey/docs/antora.yml +++ b/servicetalk-http-router-jersey/docs/antora.yml @@ -16,6 +16,6 @@ name: servicetalk-http-router-jersey title: JAX-RS Router (Jersey) -version: SNAPSHOT +version: '0.42' nav: - modules/ROOT/nav.adoc diff --git a/servicetalk-http-router-jersey/docs/modules/ROOT/nav.adoc b/servicetalk-http-router-jersey/docs/modules/ROOT/nav.adoc index 0afba89ac4..bb8528f4e8 100644 --- a/servicetalk-http-router-jersey/docs/modules/ROOT/nav.adoc +++ b/servicetalk-http-router-jersey/docs/modules/ROOT/nav.adoc @@ -1,5 +1,5 @@ ifndef::page-version[] -:page-version: SNAPSHOT +:page-version: 0.42 endif::[] include::{page-version}@servicetalk::partial$nav-versioned.adoc[] diff --git a/servicetalk-http-security-jersey/docs/antora.yml b/servicetalk-http-security-jersey/docs/antora.yml index 8574785341..1cffbf8112 100644 --- a/servicetalk-http-security-jersey/docs/antora.yml +++ b/servicetalk-http-security-jersey/docs/antora.yml @@ -16,6 +16,6 @@ name: servicetalk-http-security-jersey title: Security -version: SNAPSHOT +version: '0.42' nav: - modules/ROOT/nav.adoc diff --git a/servicetalk-http-security-jersey/docs/modules/ROOT/nav.adoc b/servicetalk-http-security-jersey/docs/modules/ROOT/nav.adoc index 0afba89ac4..bb8528f4e8 100644 --- a/servicetalk-http-security-jersey/docs/modules/ROOT/nav.adoc +++ b/servicetalk-http-security-jersey/docs/modules/ROOT/nav.adoc @@ -1,5 +1,5 @@ ifndef::page-version[] -:page-version: SNAPSHOT +:page-version: 0.42 endif::[] include::{page-version}@servicetalk::partial$nav-versioned.adoc[] diff --git a/servicetalk-loadbalancer/docs/antora.yml b/servicetalk-loadbalancer/docs/antora.yml index 3e34638348..e0e2c6c216 100644 --- a/servicetalk-loadbalancer/docs/antora.yml +++ b/servicetalk-loadbalancer/docs/antora.yml @@ -16,6 +16,6 @@ name: servicetalk-loadbalancer title: Load balancing -version: SNAPSHOT +version: '0.42' nav: - modules/ROOT/nav.adoc diff --git a/servicetalk-loadbalancer/docs/modules/ROOT/nav.adoc b/servicetalk-loadbalancer/docs/modules/ROOT/nav.adoc index 0afba89ac4..bb8528f4e8 100644 --- a/servicetalk-loadbalancer/docs/modules/ROOT/nav.adoc +++ b/servicetalk-loadbalancer/docs/modules/ROOT/nav.adoc @@ -1,5 +1,5 @@ ifndef::page-version[] -:page-version: SNAPSHOT +:page-version: 0.42 endif::[] include::{page-version}@servicetalk::partial$nav-versioned.adoc[] From 11dd16a4c97a2d70f8ef0052c5b4b82aecea1321 Mon Sep 17 00:00:00 2001 From: Mike Duigou Date: Wed, 11 May 2022 18:21:03 -0700 Subject: [PATCH 12/40] Preparing for 0.42.11-SNAPSHOT development --- docs/antora.yml | 2 +- docs/modules/ROOT/nav.adoc | 2 +- gradle.properties | 2 +- servicetalk-client-api/docs/antora.yml | 2 +- servicetalk-client-api/docs/modules/ROOT/nav.adoc | 2 +- servicetalk-concurrent-api/docs/antora.yml | 2 +- servicetalk-concurrent-api/docs/modules/ROOT/nav.adoc | 2 +- servicetalk-data-jackson-jersey/docs/antora.yml | 2 +- servicetalk-data-jackson-jersey/docs/modules/ROOT/nav.adoc | 2 +- servicetalk-data-protobuf-jersey/docs/antora.yml | 2 +- servicetalk-data-protobuf-jersey/docs/modules/ROOT/nav.adoc | 2 +- servicetalk-examples/docs/antora.yml | 2 +- servicetalk-examples/docs/modules/ROOT/nav.adoc | 2 +- servicetalk-examples/grpc/helloworld/pom.xml | 2 +- servicetalk-grpc-api/docs/antora.yml | 2 +- servicetalk-grpc-api/docs/modules/ROOT/nav.adoc | 2 +- servicetalk-http-api/docs/antora.yml | 2 +- servicetalk-http-api/docs/modules/ROOT/nav.adoc | 2 +- servicetalk-http-router-jersey/docs/antora.yml | 2 +- servicetalk-http-router-jersey/docs/modules/ROOT/nav.adoc | 2 +- servicetalk-http-security-jersey/docs/antora.yml | 2 +- servicetalk-http-security-jersey/docs/modules/ROOT/nav.adoc | 2 +- servicetalk-loadbalancer/docs/antora.yml | 2 +- servicetalk-loadbalancer/docs/modules/ROOT/nav.adoc | 2 +- 24 files changed, 24 insertions(+), 24 deletions(-) diff --git a/docs/antora.yml b/docs/antora.yml index 894b4930d6..00a61d3a1b 100644 --- a/docs/antora.yml +++ b/docs/antora.yml @@ -16,6 +16,6 @@ name: servicetalk title: ServiceTalk -version: '0.42' +version: SNAPSHOT nav: - modules/ROOT/nav.adoc diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index bb8528f4e8..0afba89ac4 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -1,5 +1,5 @@ ifndef::page-version[] -:page-version: 0.42 +:page-version: SNAPSHOT endif::[] include::{page-version}@servicetalk::partial$nav-versioned.adoc[] diff --git a/gradle.properties b/gradle.properties index a1b8a21083..1c6153aab6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -22,7 +22,7 @@ org.gradle.jvmargs=-Xms2g -Xmx4g -dsa -da -ea:io.servicetalk... -XX:+HeapDumpOnO # project metadata used for publications group=io.servicetalk -version=0.42.10 +version=0.42.11-SNAPSHOT scmHost=github.com scmPath=apple/servicetalk issueManagementUrl=https://github.com/apple/servicetalk/issues diff --git a/servicetalk-client-api/docs/antora.yml b/servicetalk-client-api/docs/antora.yml index efc15ff236..6522f97515 100644 --- a/servicetalk-client-api/docs/antora.yml +++ b/servicetalk-client-api/docs/antora.yml @@ -16,6 +16,6 @@ name: servicetalk-client-api title: Client API -version: '0.42' +version: SNAPSHOT nav: - modules/ROOT/nav.adoc diff --git a/servicetalk-client-api/docs/modules/ROOT/nav.adoc b/servicetalk-client-api/docs/modules/ROOT/nav.adoc index bb8528f4e8..0afba89ac4 100644 --- a/servicetalk-client-api/docs/modules/ROOT/nav.adoc +++ b/servicetalk-client-api/docs/modules/ROOT/nav.adoc @@ -1,5 +1,5 @@ ifndef::page-version[] -:page-version: 0.42 +:page-version: SNAPSHOT endif::[] include::{page-version}@servicetalk::partial$nav-versioned.adoc[] diff --git a/servicetalk-concurrent-api/docs/antora.yml b/servicetalk-concurrent-api/docs/antora.yml index b28d71dc68..71dcd1cef2 100644 --- a/servicetalk-concurrent-api/docs/antora.yml +++ b/servicetalk-concurrent-api/docs/antora.yml @@ -16,6 +16,6 @@ name: servicetalk-concurrent-api title: Concurrent API -version: '0.42' +version: SNAPSHOT nav: - modules/ROOT/nav.adoc diff --git a/servicetalk-concurrent-api/docs/modules/ROOT/nav.adoc b/servicetalk-concurrent-api/docs/modules/ROOT/nav.adoc index bb8528f4e8..0afba89ac4 100644 --- a/servicetalk-concurrent-api/docs/modules/ROOT/nav.adoc +++ b/servicetalk-concurrent-api/docs/modules/ROOT/nav.adoc @@ -1,5 +1,5 @@ ifndef::page-version[] -:page-version: 0.42 +:page-version: SNAPSHOT endif::[] include::{page-version}@servicetalk::partial$nav-versioned.adoc[] diff --git a/servicetalk-data-jackson-jersey/docs/antora.yml b/servicetalk-data-jackson-jersey/docs/antora.yml index a3d24c2463..9734c0b9ba 100644 --- a/servicetalk-data-jackson-jersey/docs/antora.yml +++ b/servicetalk-data-jackson-jersey/docs/antora.yml @@ -16,6 +16,6 @@ name: servicetalk-data-jackson-jersey title: JSON (Jackson) -version: '0.42' +version: SNAPSHOT nav: - modules/ROOT/nav.adoc diff --git a/servicetalk-data-jackson-jersey/docs/modules/ROOT/nav.adoc b/servicetalk-data-jackson-jersey/docs/modules/ROOT/nav.adoc index bb8528f4e8..0afba89ac4 100644 --- a/servicetalk-data-jackson-jersey/docs/modules/ROOT/nav.adoc +++ b/servicetalk-data-jackson-jersey/docs/modules/ROOT/nav.adoc @@ -1,5 +1,5 @@ ifndef::page-version[] -:page-version: 0.42 +:page-version: SNAPSHOT endif::[] include::{page-version}@servicetalk::partial$nav-versioned.adoc[] diff --git a/servicetalk-data-protobuf-jersey/docs/antora.yml b/servicetalk-data-protobuf-jersey/docs/antora.yml index f8b901792c..ca4b011d91 100644 --- a/servicetalk-data-protobuf-jersey/docs/antora.yml +++ b/servicetalk-data-protobuf-jersey/docs/antora.yml @@ -16,6 +16,6 @@ name: servicetalk-data-protobuf-jersey title: Protobuf -version: '0.42' +version: SNAPSHOT nav: - modules/ROOT/nav.adoc diff --git a/servicetalk-data-protobuf-jersey/docs/modules/ROOT/nav.adoc b/servicetalk-data-protobuf-jersey/docs/modules/ROOT/nav.adoc index bb8528f4e8..0afba89ac4 100644 --- a/servicetalk-data-protobuf-jersey/docs/modules/ROOT/nav.adoc +++ b/servicetalk-data-protobuf-jersey/docs/modules/ROOT/nav.adoc @@ -1,5 +1,5 @@ ifndef::page-version[] -:page-version: 0.42 +:page-version: SNAPSHOT endif::[] include::{page-version}@servicetalk::partial$nav-versioned.adoc[] diff --git a/servicetalk-examples/docs/antora.yml b/servicetalk-examples/docs/antora.yml index 6cdf50dbed..9371528ccc 100644 --- a/servicetalk-examples/docs/antora.yml +++ b/servicetalk-examples/docs/antora.yml @@ -16,6 +16,6 @@ name: servicetalk-examples title: Examples -version: '0.42' +version: SNAPSHOT nav: - modules/ROOT/nav.adoc diff --git a/servicetalk-examples/docs/modules/ROOT/nav.adoc b/servicetalk-examples/docs/modules/ROOT/nav.adoc index bb8528f4e8..0afba89ac4 100644 --- a/servicetalk-examples/docs/modules/ROOT/nav.adoc +++ b/servicetalk-examples/docs/modules/ROOT/nav.adoc @@ -1,5 +1,5 @@ ifndef::page-version[] -:page-version: 0.42 +:page-version: SNAPSHOT endif::[] include::{page-version}@servicetalk::partial$nav-versioned.adoc[] diff --git a/servicetalk-examples/grpc/helloworld/pom.xml b/servicetalk-examples/grpc/helloworld/pom.xml index 9406c0df65..e8a42cdb87 100644 --- a/servicetalk-examples/grpc/helloworld/pom.xml +++ b/servicetalk-examples/grpc/helloworld/pom.xml @@ -10,7 +10,7 @@ - 0.42.0 + 0.42.10 0.6.1 3.19.2 1.6.0 diff --git a/servicetalk-grpc-api/docs/antora.yml b/servicetalk-grpc-api/docs/antora.yml index aff1ab7c9d..c96cd2d20f 100644 --- a/servicetalk-grpc-api/docs/antora.yml +++ b/servicetalk-grpc-api/docs/antora.yml @@ -16,6 +16,6 @@ name: servicetalk-grpc-api title: gRPC -version: '0.42' +version: SNAPSHOT nav: - modules/ROOT/nav.adoc diff --git a/servicetalk-grpc-api/docs/modules/ROOT/nav.adoc b/servicetalk-grpc-api/docs/modules/ROOT/nav.adoc index bb8528f4e8..0afba89ac4 100644 --- a/servicetalk-grpc-api/docs/modules/ROOT/nav.adoc +++ b/servicetalk-grpc-api/docs/modules/ROOT/nav.adoc @@ -1,5 +1,5 @@ ifndef::page-version[] -:page-version: 0.42 +:page-version: SNAPSHOT endif::[] include::{page-version}@servicetalk::partial$nav-versioned.adoc[] diff --git a/servicetalk-http-api/docs/antora.yml b/servicetalk-http-api/docs/antora.yml index a2b075c3b9..96121d6cf9 100644 --- a/servicetalk-http-api/docs/antora.yml +++ b/servicetalk-http-api/docs/antora.yml @@ -16,6 +16,6 @@ name: servicetalk-http-api title: HTTP -version: '0.42' +version: SNAPSHOT nav: - modules/ROOT/nav.adoc diff --git a/servicetalk-http-api/docs/modules/ROOT/nav.adoc b/servicetalk-http-api/docs/modules/ROOT/nav.adoc index bb8528f4e8..0afba89ac4 100644 --- a/servicetalk-http-api/docs/modules/ROOT/nav.adoc +++ b/servicetalk-http-api/docs/modules/ROOT/nav.adoc @@ -1,5 +1,5 @@ ifndef::page-version[] -:page-version: 0.42 +:page-version: SNAPSHOT endif::[] include::{page-version}@servicetalk::partial$nav-versioned.adoc[] diff --git a/servicetalk-http-router-jersey/docs/antora.yml b/servicetalk-http-router-jersey/docs/antora.yml index f92e95c6bc..c4c118acdb 100644 --- a/servicetalk-http-router-jersey/docs/antora.yml +++ b/servicetalk-http-router-jersey/docs/antora.yml @@ -16,6 +16,6 @@ name: servicetalk-http-router-jersey title: JAX-RS Router (Jersey) -version: '0.42' +version: SNAPSHOT nav: - modules/ROOT/nav.adoc diff --git a/servicetalk-http-router-jersey/docs/modules/ROOT/nav.adoc b/servicetalk-http-router-jersey/docs/modules/ROOT/nav.adoc index bb8528f4e8..0afba89ac4 100644 --- a/servicetalk-http-router-jersey/docs/modules/ROOT/nav.adoc +++ b/servicetalk-http-router-jersey/docs/modules/ROOT/nav.adoc @@ -1,5 +1,5 @@ ifndef::page-version[] -:page-version: 0.42 +:page-version: SNAPSHOT endif::[] include::{page-version}@servicetalk::partial$nav-versioned.adoc[] diff --git a/servicetalk-http-security-jersey/docs/antora.yml b/servicetalk-http-security-jersey/docs/antora.yml index 1cffbf8112..8574785341 100644 --- a/servicetalk-http-security-jersey/docs/antora.yml +++ b/servicetalk-http-security-jersey/docs/antora.yml @@ -16,6 +16,6 @@ name: servicetalk-http-security-jersey title: Security -version: '0.42' +version: SNAPSHOT nav: - modules/ROOT/nav.adoc diff --git a/servicetalk-http-security-jersey/docs/modules/ROOT/nav.adoc b/servicetalk-http-security-jersey/docs/modules/ROOT/nav.adoc index bb8528f4e8..0afba89ac4 100644 --- a/servicetalk-http-security-jersey/docs/modules/ROOT/nav.adoc +++ b/servicetalk-http-security-jersey/docs/modules/ROOT/nav.adoc @@ -1,5 +1,5 @@ ifndef::page-version[] -:page-version: 0.42 +:page-version: SNAPSHOT endif::[] include::{page-version}@servicetalk::partial$nav-versioned.adoc[] diff --git a/servicetalk-loadbalancer/docs/antora.yml b/servicetalk-loadbalancer/docs/antora.yml index e0e2c6c216..3e34638348 100644 --- a/servicetalk-loadbalancer/docs/antora.yml +++ b/servicetalk-loadbalancer/docs/antora.yml @@ -16,6 +16,6 @@ name: servicetalk-loadbalancer title: Load balancing -version: '0.42' +version: SNAPSHOT nav: - modules/ROOT/nav.adoc diff --git a/servicetalk-loadbalancer/docs/modules/ROOT/nav.adoc b/servicetalk-loadbalancer/docs/modules/ROOT/nav.adoc index bb8528f4e8..0afba89ac4 100644 --- a/servicetalk-loadbalancer/docs/modules/ROOT/nav.adoc +++ b/servicetalk-loadbalancer/docs/modules/ROOT/nav.adoc @@ -1,5 +1,5 @@ ifndef::page-version[] -:page-version: 0.42 +:page-version: SNAPSHOT endif::[] include::{page-version}@servicetalk::partial$nav-versioned.adoc[] From 64f2716f740b543be37388ce79d636abcc4d427d Mon Sep 17 00:00:00 2001 From: Scott Mitchell Date: Thu, 12 May 2022 14:43:35 -0700 Subject: [PATCH 13/40] Reduce log level in RoundRobinLoadBalancer (#2213) Motivation: RoundRobinLoadBalancer logs at the warn level if it takes a host out of rotation due to exceeding the consecutive failure threshold. The failure maybe retried and/or captured in metrics/logs by the application and may not necessarily justify a warn level log from the framework. Modifications: - Adjust log level to debug when below the failure threshold, and info when crossing the threshold. Note the log level is also info when the host is connected to again and taken out of the penalty box. --- .../io/servicetalk/loadbalancer/RoundRobinLoadBalancer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/servicetalk-loadbalancer/src/main/java/io/servicetalk/loadbalancer/RoundRobinLoadBalancer.java b/servicetalk-loadbalancer/src/main/java/io/servicetalk/loadbalancer/RoundRobinLoadBalancer.java index 5e8abdaa02..52a5e88865 100644 --- a/servicetalk-loadbalancer/src/main/java/io/servicetalk/loadbalancer/RoundRobinLoadBalancer.java +++ b/servicetalk-loadbalancer/src/main/java/io/servicetalk/loadbalancer/RoundRobinLoadBalancer.java @@ -579,7 +579,7 @@ void markUnhealthy(final Throwable cause, final ConnectionFactory healthCheck = new HealthCheck<>(connectionFactory, this, cause); final ConnState nextState = new ConnState(previous.connections, healthCheck); if (connStateUpdater.compareAndSet(this, previous, nextState)) { - LOGGER.warn("Load balancer for {}: failed to open a new connection to the host on address {} " + + LOGGER.info("Load balancer for {}: failed to open a new connection to the host on address {} " + "{} time(s) in a row. Error counting threshold reached, marking this host as " + "UNHEALTHY for the selection algorithm and triggering background health-checking.", targetResource, address, healthCheckConfig.failedThreshold, cause); From 407a90d7273584a4011d1048ed8900c7d17ade57 Mon Sep 17 00:00:00 2001 From: Idel Pivnitskiy Date: Fri, 13 May 2022 16:33:48 -0500 Subject: [PATCH 14/40] Add `mavenCentral()` repository if no repositories are configured (#2215) Motivation: After some environmental changes (possibly #2184), some PRs fail to resolve dependencies if `mavenCentral()` is not defined in `build.gradle`. Modifications: - Add `mavenCentral()` if no repositories are configured; Result: Successful respolution of dependencies, see #2208. --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index 53be93a869..62741cb0c7 100644 --- a/build.gradle +++ b/build.gradle @@ -22,6 +22,7 @@ if (!repositories) { } } repositories { + mavenCentral() maven { url "https://plugins.gradle.org/m2/" } } } From 1290f952c0bb57499f931e362ad769866fa29f7f Mon Sep 17 00:00:00 2001 From: Idel Pivnitskiy Date: Fri, 13 May 2022 18:28:23 -0500 Subject: [PATCH 15/40] Update netty-incubator-transport-native-io_uring 0.0.13 -> 0.0.14 (#2208) --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 1c6153aab6..2a1f855b94 100644 --- a/gradle.properties +++ b/gradle.properties @@ -30,7 +30,7 @@ ciManagementUrl=https://github.com/apple/servicetalk/actions # dependency versions nettyVersion=4.1.77.Final -nettyIoUringVersion=0.0.13.Final +nettyIoUringVersion=0.0.14.Final jsr305Version=3.0.2 From 48a0c54b99ede30b04c75b43b98e12ff095ff4af Mon Sep 17 00:00:00 2001 From: Idel Pivnitskiy Date: Fri, 13 May 2022 18:29:39 -0500 Subject: [PATCH 16/40] Use `servicetalk-grpc-protoc-all` for pom.xml (#2214) Motivation: `build.gradle` for grpc example uses `servicetalk-grpc-protoc-all` artifact, but `pom.xml` uses `servicetalk-grpc-protoc`. After #2209, maven example does not work anymore: servicetalk-grpc-protoc_out: ServiceTalk code generation failed: java.lang.NoClassDefFoundError: com/squareup/javapoet/ClassName Modifications: - Use `all` to let maven use an uber jar; Result: Maven build works for grpc example. Related: https://github.com/servicetalk/examples/pull/1 --- servicetalk-examples/grpc/helloworld/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/servicetalk-examples/grpc/helloworld/pom.xml b/servicetalk-examples/grpc/helloworld/pom.xml index e8a42cdb87..27ea9d7279 100644 --- a/servicetalk-examples/grpc/helloworld/pom.xml +++ b/servicetalk-examples/grpc/helloworld/pom.xml @@ -54,6 +54,7 @@ io.servicetalk servicetalk-grpc-protoc ${servicetalk.version} + all io.servicetalk.grpc.protoc.Main From bff337833db9f590628987dc9f6f6eb06e2248b8 Mon Sep 17 00:00:00 2001 From: Mike Duigou Date: Mon, 16 May 2022 11:56:12 -0700 Subject: [PATCH 17/40] Add dependencies BOM (#2210) * Add dependencies BOM Motivation: The current ServiceTalk BOM file includes only ServiceTalk modules and does not include version information for the external dependencies referenced by ServiceTalk. This information can be found transitively but it is beneficial to be explicitly include it all in a BOM file. Modifications: Add an additional BOM `servicetalk-dependencies` which includes both ServiceTalk modules and BOMs and versions for external dependencies. Result: An additional ServiceTalk BOM which can improve dependency version resolution by explicitly identifying the preferred and tested versions of external components which ServiceTalk utilizes. --- servicetalk-bom/build.gradle | 9 +- servicetalk-dependencies/build.gradle | 123 ++++++++++++++++++++ servicetalk-opentracing-log4j2/build.gradle | 1 + servicetalk-test-resources/README.adoc | 2 +- servicetalk-test-resources/build.gradle | 9 +- settings.gradle | 1 + 6 files changed, 137 insertions(+), 8 deletions(-) create mode 100644 servicetalk-dependencies/build.gradle diff --git a/servicetalk-bom/build.gradle b/servicetalk-bom/build.gradle index 466898b3be..8ca61118d4 100644 --- a/servicetalk-bom/build.gradle +++ b/servicetalk-bom/build.gradle @@ -17,9 +17,12 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-core" apply plugin: "java-platform" -rootProject.subprojects.findAll { !it.name.contains("bom") && !it.name.contains("examples") && +description="ServiceTalk BOM that includes all modules" + +rootProject.subprojects.findAll { !it.name.endsWith("-bom") && !it.name.endsWith("-dependencies") && + !it.name.contains("examples") && !it.name.equals("grpc") && !it.name.equals("http") }.each { - dependencies.constraints.add("api", it) + dependencies.constraints.add(it.name.endsWith("-internal") ? "runtime" : "api", it ) } // Keep publishing and signing configuration in sync with ServiceTalkLibraryPlugin.groovy from @@ -31,7 +34,7 @@ publishing { from components.javaPlatform pom { name = project.name - description = 'A networking framework that evolves with your application' + description = project.description url = 'https://servicetalk.io' licenses { license { diff --git a/servicetalk-dependencies/build.gradle b/servicetalk-dependencies/build.gradle new file mode 100644 index 0000000000..f80433f724 --- /dev/null +++ b/servicetalk-dependencies/build.gradle @@ -0,0 +1,123 @@ +/* + * Copyright © 2018-2019 Apple Inc. and the ServiceTalk project authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-core" +apply plugin: "java-platform" + +description = "ServiceTalk BOM that includes direct dependencies" + +javaPlatform { + allowDependencies() +} + +dependencies { + api platform(project(":servicetalk-bom")) + api platform("io.netty:netty-bom:${nettyVersion}") + api platform("org.glassfish.jersey:jersey-bom:$jerseyVersion") + + constraints { + // Use `api` only for dependencies whose types appear in ServiceTalk API. + api "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" + api "com.google.api.grpc:proto-google-common-protos:$protoGoogleCommonProtosVersion" + api "com.google.protobuf:protobuf-java:$protobufVersion" + api "io.opentracing:opentracing-api:$openTracingVersion" + api "io.zipkin.reporter2:zipkin-reporter:$zipkinReporterVersion" + // `spi` and `core` types exposed in `log4j2-mdc-utils` + api "org.apache.logging.log4j:log4j-core:$log4jVersion" + api "jakarta.ws.rs:jakarta.ws.rs-api:$jaxRsVersion" + // Matchers are exposed by `servicetalk-test-resources` + api "org.hamcrest:hamcrest:$hamcrestVersion" + api "org.reactivestreams:reactive-streams:$reactiveStreamsVersion" + // Use `runtime` for dependencies which are used for implementation + runtime "com.google.code.findbugs:jsr305:$jsr305Version" + runtime "com.google.protobuf:protobuf-java-util:$protobufVersion" + runtime "com.sun.activation:jakarta.activation:$javaxActivationVersion" + runtime "com.sun.xml.bind:jaxb-core:$javaxJaxbCoreVersion" + runtime "com.sun.xml.bind:jaxb-impl:$javaxJaxbImplVersion" + runtime "jakarta.xml.bind:jakarta.xml.bind-api:$javaxJaxbApiVersion" + runtime "org.apache.logging.log4j:log4j-slf4j-impl:$log4jVersion" + runtime "org.jctools:jctools-core:$jcToolsVersion" + runtime "org.openjdk.jmh:jmh-core:$jmhCoreVersion" + runtime "org.slf4j:slf4j-api:$slf4jVersion" + } +} + +// Keep publishing and signing configuration in sync with ServiceTalkLibraryPlugin.groovy from +// servicetalk-gradle-plugin-internal +publishing { + publications { + mavenJava(MavenPublication) { + // publish POM + from components.javaPlatform + pom { + name = project.name + description = project.description + url = 'https://servicetalk.io' + licenses { + license { + name = 'The Apache License, Version 2.0' + url = 'http://www.apache.org/licenses/LICENSE-2.0.txt' + } + } + developers { + developer { + id = 'servicetalk-project-authors' + name = 'ServiceTalk project authors' + email = 'servicetalk-oss@group.apple.com' + } + } + scm { + connection = "scm:git:git://${scmHost}/${scmPath}.git" + developerConnection = "scm:git:ssh://${scmHost}:${scmPath}.git" + url = "https://${scmHost}/${scmPath}" + } + issueManagement { + system = 'ServiceTalk Issues' + url = "${issueManagementUrl}" + } + ciManagement { + system = 'ServiceTalk CI' + url = "${ciManagementUrl}" + } + } + } + } + + if (!repositories) { + repositories { + maven { + name = "sonatype" + def releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2" + def snapshotsRepoUrl = "https://oss.sonatype.org/content/repositories/snapshots" + url = project.isReleaseBuild ? releasesRepoUrl : snapshotsRepoUrl + credentials { + username = System.getenv("SONATYPE_USER") + password = System.getenv("SONATYPE_TOKEN") + } + } + } + } +} + +if (!!findProperty("signingKey") && !!findProperty("signingPassword")) { + pluginManager.apply("signing") + signing { + def signingKey = findProperty("signingKey") + def signingPassword = findProperty("signingPassword") + useInMemoryPgpKeys(signingKey, signingPassword) + sign publishing.publications.mavenJava + } +} diff --git a/servicetalk-opentracing-log4j2/build.gradle b/servicetalk-opentracing-log4j2/build.gradle index 807ec2ffd6..e8a6cb5992 100644 --- a/servicetalk-opentracing-log4j2/build.gradle +++ b/servicetalk-opentracing-log4j2/build.gradle @@ -28,6 +28,7 @@ dependencies { implementation project(":servicetalk-opentracing-asynccontext") implementation "com.google.code.findbugs:jsr305:$jsr305Version" implementation "org.apache.logging.log4j:log4j-api:$log4jVersion" + implementation "org.apache.logging.log4j:log4j-core:$log4jVersion" implementation "org.slf4j:slf4j-api:$slf4jVersion" testImplementation testFixtures(project(":servicetalk-log4j2-mdc-utils")) diff --git a/servicetalk-test-resources/README.adoc b/servicetalk-test-resources/README.adoc index 9c7045c355..335d839300 100644 --- a/servicetalk-test-resources/README.adoc +++ b/servicetalk-test-resources/README.adoc @@ -20,7 +20,7 @@ This module provides internal common resources to be used for ServiceTalk tests. The useful resources provided are: * Certificates and Keys -* Log4J configuration file +* Log4J configuration file (and Log4J runtime dependencies) This module should be included as a dependency in other ServiceTalk modules as: diff --git a/servicetalk-test-resources/build.gradle b/servicetalk-test-resources/build.gradle index e58bbb6319..1130ac62a1 100644 --- a/servicetalk-test-resources/build.gradle +++ b/servicetalk-test-resources/build.gradle @@ -19,12 +19,13 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") - api "org.apache.logging.log4j:log4j-core:$log4jVersion" - api "org.apache.logging.log4j:log4j-slf4j-impl:$log4jVersion" - api "org.hamcrest:hamcrest:$hamcrestVersion" - implementation project(":servicetalk-annotations") implementation project(":servicetalk-utils-internal") + api "org.hamcrest:hamcrest:$hamcrestVersion" + + implementation "org.apache.logging.log4j:log4j-core:$log4jVersion" + implementation "org.apache.logging.log4j:log4j-slf4j-impl:$log4jVersion" + testImplementation "org.junit.jupiter:junit-jupiter-api" } diff --git a/settings.gradle b/settings.gradle index 1952486853..6aeb46e390 100644 --- a/settings.gradle +++ b/settings.gradle @@ -36,6 +36,7 @@ include "servicetalk-annotations", "servicetalk-data-jackson-jersey", "servicetalk-data-protobuf-jersey", "servicetalk-data-protobuf", + "servicetalk-dependencies", "servicetalk-dns-discovery-netty", "servicetalk-encoding-api", "servicetalk-encoding-api-internal", From 8127bde8b4a48d72a7a01a46fac679b0be854017 Mon Sep 17 00:00:00 2001 From: Scott Mitchell Date: Tue, 17 May 2022 07:42:53 -0700 Subject: [PATCH 18/40] Add unit test for gRPC over h1, negotiated by TLS+ALPN (#2216) Motivation: ServiceTalk can do gRPC over HTTP/1.x, and it can negotiate protocols with TLS via ALPN. This isn't expected to be commonly used in practice but is possible given the layering of transports below protocol. --- .../io/servicetalk/grpc/netty/GrpcOverH1.java | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 servicetalk-grpc-netty/src/test/java/io/servicetalk/grpc/netty/GrpcOverH1.java diff --git a/servicetalk-grpc-netty/src/test/java/io/servicetalk/grpc/netty/GrpcOverH1.java b/servicetalk-grpc-netty/src/test/java/io/servicetalk/grpc/netty/GrpcOverH1.java new file mode 100644 index 0000000000..6d2953a3e0 --- /dev/null +++ b/servicetalk-grpc-netty/src/test/java/io/servicetalk/grpc/netty/GrpcOverH1.java @@ -0,0 +1,85 @@ +/* + * Copyright © 2022 Apple Inc. and the ServiceTalk project authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.servicetalk.grpc.netty; + +import io.servicetalk.http.api.HttpProtocolConfig; +import io.servicetalk.test.resources.DefaultTestCerts; +import io.servicetalk.transport.api.ClientSslConfigBuilder; +import io.servicetalk.transport.api.ServerContext; +import io.servicetalk.transport.api.ServerSslConfigBuilder; + +import io.grpc.examples.helloworld.Greeter; +import io.grpc.examples.helloworld.Greeter.BlockingGreeterClient; +import io.grpc.examples.helloworld.HelloReply; +import io.grpc.examples.helloworld.HelloRequest; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +import static io.servicetalk.concurrent.api.Single.succeeded; +import static io.servicetalk.grpc.netty.GrpcClients.forResolvedAddress; +import static io.servicetalk.grpc.netty.GrpcServers.forAddress; +import static io.servicetalk.http.netty.HttpProtocolConfigs.h1Default; +import static io.servicetalk.http.netty.HttpProtocolConfigs.h2Default; +import static io.servicetalk.test.resources.DefaultTestCerts.serverPemHostname; +import static io.servicetalk.transport.netty.internal.AddressUtils.localAddress; +import static org.junit.jupiter.api.Assertions.assertEquals; + +final class GrpcOverH1 { + private static final HttpProtocolConfig[] H1 = new HttpProtocolConfig[] {h1Default()}; + private static final HttpProtocolConfig[] H1H2 = new HttpProtocolConfig[] {h1Default(), h2Default()}; + private static final HttpProtocolConfig[] H2H1 = new HttpProtocolConfig[] {h2Default(), h1Default()}; + + private enum ProtocolTestMode { + ServerH1_ClientH1(H1, H1), + ServerH1_ClientH1H2(H1, H1H2), + ServerH1_ClientH2H1(H1, H2H1), + ServerH1H2_ClientH1(H1H2, H1), + ServerH2H1_ClientH1(H2H1, H1); + + final HttpProtocolConfig[] serverConfigs; + final HttpProtocolConfig[] clientConfigs; + + ProtocolTestMode(HttpProtocolConfig[] serverConfigs, HttpProtocolConfig[] clientConfigs) { + this.serverConfigs = serverConfigs; + this.clientConfigs = clientConfigs; + } + } + + @ParameterizedTest + @EnumSource(ProtocolTestMode.class) + void tlsNegotiated(ProtocolTestMode testMode) throws Exception { + String greetingPrefix = "Hello "; + String name = "foo"; + String expectedResponse = greetingPrefix + name; + try (ServerContext serverContext = forAddress(localAddress(0)) + .initializeHttp(builder -> builder + .sslConfig(new ServerSslConfigBuilder(DefaultTestCerts::loadServerPem, + DefaultTestCerts::loadServerKey).build()) + .protocols(testMode.serverConfigs)) + .listenAndAwait((Greeter.GreeterService) (ctx, request) -> + succeeded(HelloReply.newBuilder().setMessage(greetingPrefix + request.getName()).build())); + BlockingGreeterClient client = forResolvedAddress(serverContext.listenAddress()) + .initializeHttp(builder -> builder + .sslConfig(new ClientSslConfigBuilder(DefaultTestCerts::loadServerCAPem) + .peerHost(serverPemHostname()) + .build()) + .protocols(testMode.clientConfigs)) + .buildBlocking(new Greeter.ClientFactory())) { + assertEquals(expectedResponse, + client.sayHello(HelloRequest.newBuilder().setName(name).build()).getMessage()); + } + } +} From 05fbfa23a7d9b997449a026cee949f17d5ba9cab Mon Sep 17 00:00:00 2001 From: Mike Duigou Date: Tue, 17 May 2022 10:19:16 -0700 Subject: [PATCH 19/40] Use more external dependency BOM files (#2218) Motivation: Whenever possible, external dependencies should be imported through their BOM files for optimal management of versioning and transitive dependencies. Modifications: Add additional BOM files for Jackson, protobuf, Log4J and Jersey. Result: Improve resolution of external dependencies. --- servicetalk-dependencies/build.gradle | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/servicetalk-dependencies/build.gradle b/servicetalk-dependencies/build.gradle index f80433f724..e04b6caff7 100644 --- a/servicetalk-dependencies/build.gradle +++ b/servicetalk-dependencies/build.gradle @@ -26,29 +26,25 @@ javaPlatform { dependencies { api platform(project(":servicetalk-bom")) api platform("io.netty:netty-bom:${nettyVersion}") - api platform("org.glassfish.jersey:jersey-bom:$jerseyVersion") + api platform("com.fasterxml.jackson:jackson-bom:${jacksonVersion}") + api platform("com.google.protobuf:protobuf-bom:${protobufVersion}") + api platform("org.apache.logging.log4j:log4j-bom:${log4jVersion}") + api platform("org.glassfish.jersey:jersey-bom:${jerseyVersion}") constraints { - // Use `api` only for dependencies whose types appear in ServiceTalk API. - api "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" api "com.google.api.grpc:proto-google-common-protos:$protoGoogleCommonProtosVersion" - api "com.google.protobuf:protobuf-java:$protobufVersion" api "io.opentracing:opentracing-api:$openTracingVersion" api "io.zipkin.reporter2:zipkin-reporter:$zipkinReporterVersion" - // `spi` and `core` types exposed in `log4j2-mdc-utils` - api "org.apache.logging.log4j:log4j-core:$log4jVersion" api "jakarta.ws.rs:jakarta.ws.rs-api:$jaxRsVersion" // Matchers are exposed by `servicetalk-test-resources` api "org.hamcrest:hamcrest:$hamcrestVersion" api "org.reactivestreams:reactive-streams:$reactiveStreamsVersion" - // Use `runtime` for dependencies which are used for implementation + // Use `runtime` for dependencies which are used ONLY at runtime runtime "com.google.code.findbugs:jsr305:$jsr305Version" - runtime "com.google.protobuf:protobuf-java-util:$protobufVersion" runtime "com.sun.activation:jakarta.activation:$javaxActivationVersion" runtime "com.sun.xml.bind:jaxb-core:$javaxJaxbCoreVersion" runtime "com.sun.xml.bind:jaxb-impl:$javaxJaxbImplVersion" runtime "jakarta.xml.bind:jakarta.xml.bind-api:$javaxJaxbApiVersion" - runtime "org.apache.logging.log4j:log4j-slf4j-impl:$log4jVersion" runtime "org.jctools:jctools-core:$jcToolsVersion" runtime "org.openjdk.jmh:jmh-core:$jmhCoreVersion" runtime "org.slf4j:slf4j-api:$slf4jVersion" From 0f0f86eb27464afac9ecc3b27fe1a2269c9a4b67 Mon Sep 17 00:00:00 2001 From: Mike Duigou Date: Tue, 17 May 2022 15:42:36 -0700 Subject: [PATCH 20/40] Use `servicetalk-dependencies` BOM internally (#2217) Motivation: The new `dependencies` BOM introduced in #2210 can be used to improve the management of external dependencies by reducing use of explicit versions within the module `build.gradle` files. Modification: Use `dependencies` BOM for every module which includes `api` or `implementation` external dependencies. The BOM is imported as `api` platform only in cases where the external dependency is also imported `api`. `implementation` platform is used in cases where the external dependencies are only `implementation` dependencies themselves. The Jackson-BOM is no longer used because of issues with how it is versioned and our desire for a narrower dependency on `jackson-databind` only. Result: Fewer explicit version specifications and better managed dependency versioning. --- servicetalk-annotations/build.gradle | 4 +++- servicetalk-benchmarks/build.gradle | 8 +++++--- servicetalk-buffer-api/build.gradle | 3 ++- servicetalk-buffer-netty/build.gradle | 6 +++--- servicetalk-client-api-internal/build.gradle | 5 +++-- servicetalk-client-api/build.gradle | 5 +++-- .../build.gradle | 5 +++-- servicetalk-concurrent-api-test/build.gradle | 3 ++- servicetalk-concurrent-api/build.gradle | 5 +++-- servicetalk-concurrent-internal/build.gradle | 5 +++-- servicetalk-concurrent-jdkflow/build.gradle | 5 +++-- .../build.gradle | 5 +++-- .../build.gradle | 3 ++- servicetalk-concurrent/build.gradle | 3 ++- servicetalk-context-api/build.gradle | 3 ++- servicetalk-data-jackson-jersey/build.gradle | 8 ++++---- servicetalk-data-jackson/build.gradle | 5 +++-- servicetalk-data-protobuf-jersey/build.gradle | 10 +++++----- servicetalk-data-protobuf/build.gradle | 5 +++-- servicetalk-dependencies/build.gradle | 18 ++++++++++-------- servicetalk-dns-discovery-netty/build.gradle | 6 +++--- servicetalk-encoding-api-internal/build.gradle | 3 ++- servicetalk-encoding-api/build.gradle | 5 +++-- servicetalk-encoding-netty/build.gradle | 6 +++--- servicetalk-grpc-api/build.gradle | 7 ++++--- servicetalk-grpc-internal/build.gradle | 3 ++- servicetalk-grpc-netty/build.gradle | 7 ++++--- servicetalk-grpc-protobuf/build.gradle | 7 ++++--- servicetalk-grpc-protoc/build.gradle | 3 ++- servicetalk-grpc-utils/build.gradle | 3 ++- servicetalk-http-api/build.gradle | 5 +++-- servicetalk-http-netty/build.gradle | 6 ++++-- .../build.gradle | 6 +++--- servicetalk-http-router-jersey/build.gradle | 17 +++++++++-------- servicetalk-http-router-predicate/build.gradle | 3 ++- servicetalk-http-security-jersey/build.gradle | 6 +++--- servicetalk-http-utils/build.gradle | 5 +++-- servicetalk-loadbalancer/build.gradle | 6 ++++-- servicetalk-log4j2-mdc-utils/build.gradle | 15 ++++++++++----- servicetalk-log4j2-mdc/build.gradle | 3 ++- .../build.gradle | 4 +++- servicetalk-oio-api-internal/build.gradle | 6 ++++-- servicetalk-oio-api/build.gradle | 3 ++- .../build.gradle | 3 ++- servicetalk-opentracing-http/build.gradle | 9 +++++---- .../build.gradle | 6 ++++-- servicetalk-opentracing-inmemory/build.gradle | 5 +++-- servicetalk-opentracing-internal/build.gradle | 6 ++++-- servicetalk-opentracing-log4j2/build.gradle | 8 ++++---- .../build.gradle | 8 ++++---- servicetalk-router-api/build.gradle | 4 +++- servicetalk-router-utils-internal/build.gradle | 5 +++-- servicetalk-serialization-api/build.gradle | 3 ++- servicetalk-serializer-api/build.gradle | 4 +++- servicetalk-serializer-utils/build.gradle | 3 ++- servicetalk-tcp-netty-internal/build.gradle | 6 ++++-- servicetalk-test-resources/build.gradle | 6 ++---- servicetalk-transport-api/build.gradle | 5 +++-- .../build.gradle | 6 +++--- servicetalk-transport-netty/build.gradle | 4 ++-- servicetalk-utils-internal/build.gradle | 7 ++++--- 61 files changed, 205 insertions(+), 142 deletions(-) diff --git a/servicetalk-annotations/build.gradle b/servicetalk-annotations/build.gradle index 019f2b5748..47bca10683 100644 --- a/servicetalk-annotations/build.gradle +++ b/servicetalk-annotations/build.gradle @@ -17,5 +17,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation platform(project(":servicetalk-dependencies")) + + implementation "com.google.code.findbugs:jsr305" } diff --git a/servicetalk-benchmarks/build.gradle b/servicetalk-benchmarks/build.gradle index f996359ba5..640bbee964 100644 --- a/servicetalk-benchmarks/build.gradle +++ b/servicetalk-benchmarks/build.gradle @@ -22,6 +22,8 @@ plugins { apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) + implementation project(":servicetalk-annotations") implementation project(":servicetalk-buffer-netty") implementation project(":servicetalk-concurrent-api") @@ -30,9 +32,9 @@ dependencies { implementation project(":servicetalk-http-netty") implementation project(":servicetalk-transport-netty-internal") implementation project(":servicetalk-loadbalancer") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" - implementation "io.netty:netty-codec-http:$nettyVersion" - implementation "org.openjdk.jmh:jmh-core:$jmhCoreVersion" + implementation "com.google.code.findbugs:jsr305" + implementation "io.netty:netty-codec-http" + implementation "org.openjdk.jmh:jmh-core" testImplementation testFixtures(project(":servicetalk-concurrent-internal")) testImplementation project(":servicetalk-concurrent-internal") diff --git a/servicetalk-buffer-api/build.gradle b/servicetalk-buffer-api/build.gradle index 6c3aefa6a8..acdb038286 100644 --- a/servicetalk-buffer-api/build.gradle +++ b/servicetalk-buffer-api/build.gradle @@ -17,11 +17,12 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") implementation project(":servicetalk-annotations") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "com.google.code.findbugs:jsr305" testImplementation "org.junit.jupiter:junit-jupiter-api" testImplementation "org.junit.jupiter:junit-jupiter-params" diff --git a/servicetalk-buffer-netty/build.gradle b/servicetalk-buffer-netty/build.gradle index bca2a6a143..b52fc9445e 100644 --- a/servicetalk-buffer-netty/build.gradle +++ b/servicetalk-buffer-netty/build.gradle @@ -17,7 +17,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { - api platform("io.netty:netty-bom:$nettyVersion") + api platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-buffer-api") @@ -25,8 +25,8 @@ dependencies { implementation project(":servicetalk-annotations") implementation project(":servicetalk-utils-internal") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" - implementation "org.slf4j:slf4j-api:$slf4jVersion" + implementation "com.google.code.findbugs:jsr305" + implementation "org.slf4j:slf4j-api" testImplementation project(":servicetalk-test-resources") testImplementation "org.junit.jupiter:junit-jupiter-api" diff --git a/servicetalk-client-api-internal/build.gradle b/servicetalk-client-api-internal/build.gradle index 547104413e..a3da8f7ea7 100644 --- a/servicetalk-client-api-internal/build.gradle +++ b/servicetalk-client-api-internal/build.gradle @@ -17,6 +17,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-client-api") @@ -25,8 +26,8 @@ dependencies { implementation project(":servicetalk-annotations") implementation project(":servicetalk-concurrent-api-internal") implementation project(":servicetalk-concurrent-internal") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" - implementation "org.slf4j:slf4j-api:$slf4jVersion" + implementation "com.google.code.findbugs:jsr305" + implementation "org.slf4j:slf4j-api" testImplementation testFixtures(project(":servicetalk-concurrent-api")) testImplementation testFixtures(project(":servicetalk-concurrent-internal")) diff --git a/servicetalk-client-api/build.gradle b/servicetalk-client-api/build.gradle index a58b1ed263..630f4b9f77 100644 --- a/servicetalk-client-api/build.gradle +++ b/servicetalk-client-api/build.gradle @@ -17,6 +17,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + api platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-concurrent-api") @@ -25,8 +26,8 @@ dependencies { implementation project(":servicetalk-annotations") implementation project(":servicetalk-concurrent-api-internal") implementation project(":servicetalk-concurrent-internal") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" - implementation "org.slf4j:slf4j-api:$slf4jVersion" + implementation "com.google.code.findbugs:jsr305" + implementation "org.slf4j:slf4j-api" testImplementation testFixtures(project(":servicetalk-concurrent-api")) testImplementation testFixtures(project(":servicetalk-concurrent-internal")) diff --git a/servicetalk-concurrent-api-internal/build.gradle b/servicetalk-concurrent-api-internal/build.gradle index 4739e46687..ad73bc6e8b 100644 --- a/servicetalk-concurrent-api-internal/build.gradle +++ b/servicetalk-concurrent-api-internal/build.gradle @@ -17,6 +17,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-concurrent-api") @@ -27,8 +28,8 @@ dependencies { implementation project(":servicetalk-concurrent-api") implementation project(":servicetalk-concurrent-internal") implementation project(":servicetalk-utils-internal") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" - implementation "org.slf4j:slf4j-api:$slf4jVersion" + implementation "com.google.code.findbugs:jsr305" + implementation "org.slf4j:slf4j-api" testImplementation testFixtures(project(":servicetalk-concurrent-api")) testImplementation testFixtures(project(":servicetalk-concurrent-internal")) diff --git a/servicetalk-concurrent-api-test/build.gradle b/servicetalk-concurrent-api-test/build.gradle index 8cda2d7a99..a606d03441 100644 --- a/servicetalk-concurrent-api-test/build.gradle +++ b/servicetalk-concurrent-api-test/build.gradle @@ -17,6 +17,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-concurrent-api") @@ -25,7 +26,7 @@ dependencies { implementation project(":servicetalk-concurrent-internal") implementation project(":servicetalk-concurrent-test-internal") implementation project(":servicetalk-utils-internal") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "com.google.code.findbugs:jsr305" testImplementation testFixtures(project(":servicetalk-concurrent-internal")) testImplementation testFixtures(project(":servicetalk-concurrent-api")) diff --git a/servicetalk-concurrent-api/build.gradle b/servicetalk-concurrent-api/build.gradle index daa2d078dc..9a50545254 100644 --- a/servicetalk-concurrent-api/build.gradle +++ b/servicetalk-concurrent-api/build.gradle @@ -17,6 +17,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + api platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") testFixturesImplementation platform("org.junit:junit-bom:$junit5Version") @@ -26,8 +27,8 @@ dependencies { implementation project(":servicetalk-annotations") implementation project(":servicetalk-concurrent-internal") implementation project(":servicetalk-utils-internal") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" - implementation "org.slf4j:slf4j-api:$slf4jVersion" + implementation "com.google.code.findbugs:jsr305" + implementation "org.slf4j:slf4j-api" testImplementation testFixtures(project(":servicetalk-concurrent-internal")) testImplementation project(":servicetalk-concurrent-test-internal") diff --git a/servicetalk-concurrent-internal/build.gradle b/servicetalk-concurrent-internal/build.gradle index 2488ccf759..2dc39ba8d4 100644 --- a/servicetalk-concurrent-internal/build.gradle +++ b/servicetalk-concurrent-internal/build.gradle @@ -17,6 +17,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") testFixturesImplementation platform("org.junit:junit-bom:$junit5Version") @@ -25,8 +26,8 @@ dependencies { implementation project(":servicetalk-annotations") implementation project(":servicetalk-utils-internal") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" - implementation "org.slf4j:slf4j-api:$slf4jVersion" + implementation "com.google.code.findbugs:jsr305" + implementation "org.slf4j:slf4j-api" testImplementation project(":servicetalk-test-resources") testImplementation "org.junit.jupiter:junit-jupiter-api" diff --git a/servicetalk-concurrent-jdkflow/build.gradle b/servicetalk-concurrent-jdkflow/build.gradle index 17c7721e24..cb4a36b64f 100644 --- a/servicetalk-concurrent-jdkflow/build.gradle +++ b/servicetalk-concurrent-jdkflow/build.gradle @@ -30,13 +30,14 @@ compileJava { } dependencies { + implementation platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-concurrent-api") implementation project(":servicetalk-annotations") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" - implementation "org.slf4j:slf4j-api:$slf4jVersion" + implementation "com.google.code.findbugs:jsr305" + implementation "org.slf4j:slf4j-api" testImplementation testFixtures(project(":servicetalk-concurrent-api")) testImplementation testFixtures(project(":servicetalk-concurrent-internal")) diff --git a/servicetalk-concurrent-reactivestreams/build.gradle b/servicetalk-concurrent-reactivestreams/build.gradle index ee6ef5ca97..09a2ba698a 100644 --- a/servicetalk-concurrent-reactivestreams/build.gradle +++ b/servicetalk-concurrent-reactivestreams/build.gradle @@ -17,6 +17,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-concurrent-api") @@ -25,8 +26,8 @@ dependencies { implementation project(":servicetalk-annotations") implementation project(":servicetalk-serializer-utils") implementation project(":servicetalk-buffer-netty") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" - implementation "org.slf4j:slf4j-api:$slf4jVersion" + implementation "com.google.code.findbugs:jsr305" + implementation "org.slf4j:slf4j-api" testImplementation testFixtures(project(":servicetalk-concurrent-api")) testImplementation testFixtures(project(":servicetalk-concurrent-internal")) diff --git a/servicetalk-concurrent-test-internal/build.gradle b/servicetalk-concurrent-test-internal/build.gradle index f3b2f199e5..800f7d779d 100644 --- a/servicetalk-concurrent-test-internal/build.gradle +++ b/servicetalk-concurrent-test-internal/build.gradle @@ -17,6 +17,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + api platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-concurrent") @@ -24,7 +25,7 @@ dependencies { implementation project(":servicetalk-annotations") implementation project(":servicetalk-concurrent-internal") implementation project(":servicetalk-utils-internal") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "com.google.code.findbugs:jsr305" testImplementation testFixtures(project(":servicetalk-concurrent-internal")) testImplementation project(":servicetalk-test-resources") diff --git a/servicetalk-concurrent/build.gradle b/servicetalk-concurrent/build.gradle index 7c7c870cd6..b94d03fc2f 100644 --- a/servicetalk-concurrent/build.gradle +++ b/servicetalk-concurrent/build.gradle @@ -17,7 +17,8 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + api platform(project(":servicetalk-dependencies")) implementation project(":servicetalk-annotations") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "com.google.code.findbugs:jsr305" } diff --git a/servicetalk-context-api/build.gradle b/servicetalk-context-api/build.gradle index 654666c57f..724d75dd06 100644 --- a/servicetalk-context-api/build.gradle +++ b/servicetalk-context-api/build.gradle @@ -17,7 +17,8 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + api platform(project(":servicetalk-dependencies")) implementation project(":servicetalk-annotations") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "com.google.code.findbugs:jsr305" } diff --git a/servicetalk-data-jackson-jersey/build.gradle b/servicetalk-data-jackson-jersey/build.gradle index 781a4448fc..e8ea11ea1a 100644 --- a/servicetalk-data-jackson-jersey/build.gradle +++ b/servicetalk-data-jackson-jersey/build.gradle @@ -17,12 +17,12 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { - implementation platform("org.glassfish.jersey:jersey-bom:$jerseyVersion") + api platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.glassfish.jersey:jersey-bom:$jerseyVersion") testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-data-jackson") - api "jakarta.ws.rs:jakarta.ws.rs-api:$jaxRsVersion" // MediaType, Feature + api "jakarta.ws.rs:jakarta.ws.rs-api" // MediaType, Feature api "org.glassfish.jersey.core:jersey-common" // AutoDiscoverable implementation project(":servicetalk-annotations") @@ -34,9 +34,9 @@ dependencies { implementation project(":servicetalk-http-router-jersey-internal") implementation project(":servicetalk-http-utils") implementation project(":servicetalk-transport-netty") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "com.google.code.findbugs:jsr305" implementation "org.glassfish.jersey.core:jersey-server" - implementation "org.slf4j:slf4j-api:$slf4jVersion" + implementation "org.slf4j:slf4j-api" testImplementation testFixtures(project(":servicetalk-concurrent-api")) testImplementation testFixtures(project(":servicetalk-concurrent-internal")) diff --git a/servicetalk-data-jackson/build.gradle b/servicetalk-data-jackson/build.gradle index 8bb4514147..7ce7ca11af 100644 --- a/servicetalk-data-jackson/build.gradle +++ b/servicetalk-data-jackson/build.gradle @@ -17,17 +17,18 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + api platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-serialization-api") api project(":servicetalk-serializer-api") - api "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" + api "com.fasterxml.jackson.core:jackson-databind" implementation project(":servicetalk-annotations") implementation project(":servicetalk-concurrent-api-internal") implementation project(":servicetalk-concurrent-internal") implementation project(":servicetalk-utils-internal") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "com.google.code.findbugs:jsr305" testImplementation testFixtures(project(":servicetalk-concurrent-api")) testImplementation testFixtures(project(":servicetalk-concurrent-internal")) diff --git a/servicetalk-data-protobuf-jersey/build.gradle b/servicetalk-data-protobuf-jersey/build.gradle index 9b02b274ad..7594a868d6 100644 --- a/servicetalk-data-protobuf-jersey/build.gradle +++ b/servicetalk-data-protobuf-jersey/build.gradle @@ -24,11 +24,11 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" apply plugin: "com.google.protobuf" dependencies { - implementation platform("org.glassfish.jersey:jersey-bom:$jerseyVersion") + api platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.glassfish.jersey:jersey-bom:$jerseyVersion") testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") - api "jakarta.ws.rs:jakarta.ws.rs-api:$jaxRsVersion" // MediaType, Feature + api "jakarta.ws.rs:jakarta.ws.rs-api" // MediaType, Feature api "org.glassfish.jersey.core:jersey-common" // AutoDiscoverable implementation project(":servicetalk-annotations") @@ -41,10 +41,10 @@ dependencies { implementation project(":servicetalk-http-router-jersey-internal") implementation project(":servicetalk-http-utils") implementation project(":servicetalk-transport-netty") - implementation "com.google.protobuf:protobuf-java:$protobufVersion" - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "com.google.protobuf:protobuf-java" + implementation "com.google.code.findbugs:jsr305" implementation "org.glassfish.jersey.core:jersey-server" - implementation "org.slf4j:slf4j-api:$slf4jVersion" + implementation "org.slf4j:slf4j-api" testImplementation testFixtures(project(":servicetalk-concurrent-api")) testImplementation testFixtures(project(":servicetalk-concurrent-internal")) diff --git a/servicetalk-data-protobuf/build.gradle b/servicetalk-data-protobuf/build.gradle index f2e9ed9c99..62cdd8b163 100644 --- a/servicetalk-data-protobuf/build.gradle +++ b/servicetalk-data-protobuf/build.gradle @@ -26,19 +26,20 @@ apply plugin: "com.google.protobuf" ideaModule.dependsOn "generateTestProto" dependencies { + api platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-buffer-api") api project(":servicetalk-concurrent-api") api project(":servicetalk-serializer-api") - api "com.google.protobuf:protobuf-java:$protobufVersion" + api "com.google.protobuf:protobuf-java" implementation project(":servicetalk-annotations") implementation project(":servicetalk-concurrent-api-internal") implementation project(":servicetalk-concurrent-internal") implementation project(":servicetalk-serialization-api") implementation project(":servicetalk-serializer-utils") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "com.google.code.findbugs:jsr305" testImplementation testFixtures(project(":servicetalk-concurrent-api")) testImplementation testFixtures(project(":servicetalk-concurrent-internal")) diff --git a/servicetalk-dependencies/build.gradle b/servicetalk-dependencies/build.gradle index e04b6caff7..141d12cba6 100644 --- a/servicetalk-dependencies/build.gradle +++ b/servicetalk-dependencies/build.gradle @@ -26,28 +26,30 @@ javaPlatform { dependencies { api platform(project(":servicetalk-bom")) api platform("io.netty:netty-bom:${nettyVersion}") - api platform("com.fasterxml.jackson:jackson-bom:${jacksonVersion}") api platform("com.google.protobuf:protobuf-bom:${protobufVersion}") api platform("org.apache.logging.log4j:log4j-bom:${log4jVersion}") api platform("org.glassfish.jersey:jersey-bom:${jerseyVersion}") constraints { + // We don't use the jackson-bom because we want to target specifically jackson-databind + api "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" api "com.google.api.grpc:proto-google-common-protos:$protoGoogleCommonProtosVersion" + api "com.google.code.findbugs:jsr305:$jsr305Version" + api "com.sun.activation:jakarta.activation:$javaxActivationVersion" + api "com.sun.xml.bind:jaxb-core:$javaxJaxbCoreVersion" api "io.opentracing:opentracing-api:$openTracingVersion" api "io.zipkin.reporter2:zipkin-reporter:$zipkinReporterVersion" api "jakarta.ws.rs:jakarta.ws.rs-api:$jaxRsVersion" + api "jakarta.xml.bind:jakarta.xml.bind-api:$javaxJaxbApiVersion" // Matchers are exposed by `servicetalk-test-resources` api "org.hamcrest:hamcrest:$hamcrestVersion" + api "org.jctools:jctools-core:$jcToolsVersion" + api "org.openjdk.jmh:jmh-core:$jmhCoreVersion" api "org.reactivestreams:reactive-streams:$reactiveStreamsVersion" + api "org.slf4j:slf4j-api:$slf4jVersion" + // Use `runtime` for dependencies which are used ONLY at runtime - runtime "com.google.code.findbugs:jsr305:$jsr305Version" - runtime "com.sun.activation:jakarta.activation:$javaxActivationVersion" - runtime "com.sun.xml.bind:jaxb-core:$javaxJaxbCoreVersion" runtime "com.sun.xml.bind:jaxb-impl:$javaxJaxbImplVersion" - runtime "jakarta.xml.bind:jakarta.xml.bind-api:$javaxJaxbApiVersion" - runtime "org.jctools:jctools-core:$jcToolsVersion" - runtime "org.openjdk.jmh:jmh-core:$jmhCoreVersion" - runtime "org.slf4j:slf4j-api:$slf4jVersion" } } diff --git a/servicetalk-dns-discovery-netty/build.gradle b/servicetalk-dns-discovery-netty/build.gradle index 4202b56bb3..f04355762b 100644 --- a/servicetalk-dns-discovery-netty/build.gradle +++ b/servicetalk-dns-discovery-netty/build.gradle @@ -17,7 +17,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { - implementation platform("io.netty:netty-bom:$nettyVersion") + implementation platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-client-api") @@ -29,9 +29,9 @@ dependencies { implementation project(":servicetalk-transport-netty") implementation project(":servicetalk-transport-netty-internal") implementation project(":servicetalk-utils-internal") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "com.google.code.findbugs:jsr305" implementation "io.netty:netty-resolver-dns" - implementation "org.slf4j:slf4j-api:$slf4jVersion" + implementation "org.slf4j:slf4j-api" runtimeOnly( group:"io.netty", name:"netty-resolver-dns-native-macos", classifier:"osx-x86_64") runtimeOnly( group:"io.netty", name:"netty-resolver-dns-native-macos", classifier:"osx-aarch_64") diff --git a/servicetalk-encoding-api-internal/build.gradle b/servicetalk-encoding-api-internal/build.gradle index bc982b07e9..eeeb8ce237 100644 --- a/servicetalk-encoding-api-internal/build.gradle +++ b/servicetalk-encoding-api-internal/build.gradle @@ -17,8 +17,9 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) api project(":servicetalk-encoding-api") implementation project(":servicetalk-annotations") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "com.google.code.findbugs:jsr305" } diff --git a/servicetalk-encoding-api/build.gradle b/servicetalk-encoding-api/build.gradle index 574825c2d4..0f3c3f114c 100644 --- a/servicetalk-encoding-api/build.gradle +++ b/servicetalk-encoding-api/build.gradle @@ -17,6 +17,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-buffer-api") @@ -25,8 +26,8 @@ dependencies { implementation project(":servicetalk-annotations") implementation project(":servicetalk-concurrent-internal") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" - implementation "org.slf4j:slf4j-api:$slf4jVersion" + implementation "com.google.code.findbugs:jsr305" + implementation "org.slf4j:slf4j-api" testImplementation "org.junit.jupiter:junit-jupiter-api" testImplementation "org.junit.jupiter:junit-jupiter-params" diff --git a/servicetalk-encoding-netty/build.gradle b/servicetalk-encoding-netty/build.gradle index fbf8a40e08..7c2aaa9362 100644 --- a/servicetalk-encoding-netty/build.gradle +++ b/servicetalk-encoding-netty/build.gradle @@ -17,7 +17,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { - implementation platform("io.netty:netty-bom:$nettyVersion") + implementation platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-encoding-api") @@ -26,8 +26,8 @@ dependencies { implementation project(":servicetalk-buffer-netty") implementation project(":servicetalk-concurrent-internal") implementation "io.netty:netty-codec" - implementation "com.google.code.findbugs:jsr305:$jsr305Version" - implementation "org.slf4j:slf4j-api:$slf4jVersion" + implementation "com.google.code.findbugs:jsr305" + implementation "org.slf4j:slf4j-api" testImplementation testFixtures(project(":servicetalk-concurrent-internal")) testImplementation "org.junit.jupiter:junit-jupiter-api" diff --git a/servicetalk-grpc-api/build.gradle b/servicetalk-grpc-api/build.gradle index 668c2b8666..51fc22681c 100644 --- a/servicetalk-grpc-api/build.gradle +++ b/servicetalk-grpc-api/build.gradle @@ -17,6 +17,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + api platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-concurrent-api") @@ -35,9 +36,9 @@ dependencies { implementation project(":servicetalk-grpc-internal") implementation project(":servicetalk-oio-api-internal") implementation project(":servicetalk-serializer-utils") - implementation "org.slf4j:slf4j-api:$slf4jVersion" - implementation "com.google.code.findbugs:jsr305:$jsr305Version" - implementation "com.google.protobuf:protobuf-java:$protobufVersion" + implementation "com.google.code.findbugs:jsr305" + implementation "com.google.protobuf:protobuf-java" + implementation "org.slf4j:slf4j-api" testImplementation project(":servicetalk-test-resources") testImplementation "org.junit.jupiter:junit-jupiter-api" diff --git a/servicetalk-grpc-internal/build.gradle b/servicetalk-grpc-internal/build.gradle index 04d5ef2ece..9468afbd50 100644 --- a/servicetalk-grpc-internal/build.gradle +++ b/servicetalk-grpc-internal/build.gradle @@ -17,13 +17,14 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-http-api") implementation project(":servicetalk-annotations") implementation project(":servicetalk-utils-internal") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "com.google.code.findbugs:jsr305" testImplementation project(":servicetalk-test-resources") testImplementation "org.junit.jupiter:junit-jupiter-api" diff --git a/servicetalk-grpc-netty/build.gradle b/servicetalk-grpc-netty/build.gradle index a550a433e0..24cf052f61 100644 --- a/servicetalk-grpc-netty/build.gradle +++ b/servicetalk-grpc-netty/build.gradle @@ -24,6 +24,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" apply plugin: "com.google.protobuf" dependencies { + implementation platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") testImplementation enforcedPlatform("io.grpc:grpc-bom:$grpcVersion") @@ -37,9 +38,9 @@ dependencies { implementation project(":servicetalk-transport-netty-internal") implementation project(":servicetalk-utils-internal") implementation project(":servicetalk-concurrent-internal") - implementation "org.slf4j:slf4j-api:$slf4jVersion" - implementation "com.google.code.findbugs:jsr305:$jsr305Version" - implementation "com.google.protobuf:protobuf-java:$protobufVersion" + implementation "org.slf4j:slf4j-api" + implementation "com.google.code.findbugs:jsr305" + implementation "com.google.protobuf:protobuf-java" testImplementation testFixtures(project(":servicetalk-concurrent-api")) testImplementation testFixtures(project(":servicetalk-concurrent-internal")) diff --git a/servicetalk-grpc-protobuf/build.gradle b/servicetalk-grpc-protobuf/build.gradle index ccb1b68042..b3a0d618e7 100644 --- a/servicetalk-grpc-protobuf/build.gradle +++ b/servicetalk-grpc-protobuf/build.gradle @@ -26,10 +26,11 @@ apply plugin: "com.google.protobuf" ideaModule.dependsOn "generateTestProto" dependencies { + api platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-grpc-api") - api "com.google.protobuf:protobuf-java:$protobufVersion" + api "com.google.protobuf:protobuf-java" api "com.google.api.grpc:proto-google-common-protos:$protoGoogleCommonProtosVersion" implementation project(":servicetalk-annotations") @@ -37,8 +38,8 @@ dependencies { implementation project(":servicetalk-serializer-api") implementation project(":servicetalk-data-protobuf") implementation project(":servicetalk-serializer-utils") - implementation "org.slf4j:slf4j-api:$slf4jVersion" - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "org.slf4j:slf4j-api" + implementation "com.google.code.findbugs:jsr305" testImplementation project(":servicetalk-test-resources") testImplementation "org.junit.jupiter:junit-jupiter-api" diff --git a/servicetalk-grpc-protoc/build.gradle b/servicetalk-grpc-protoc/build.gradle index fbfea22680..754d88292f 100644 --- a/servicetalk-grpc-protoc/build.gradle +++ b/servicetalk-grpc-protoc/build.gradle @@ -22,6 +22,7 @@ plugins { apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") implementation project(":servicetalk-annotations") @@ -29,7 +30,7 @@ dependencies { // Needed for the generated classes api project(":servicetalk-data-protobuf") - compileOnly "com.google.code.findbugs:jsr305:$jsr305Version" + compileOnly "com.google.code.findbugs:jsr305" compileOnly "com.squareup:javapoet:$javaPoetVersion" testImplementation project(":servicetalk-grpc-api") diff --git a/servicetalk-grpc-utils/build.gradle b/servicetalk-grpc-utils/build.gradle index 3597ad6641..50c07e28b9 100644 --- a/servicetalk-grpc-utils/build.gradle +++ b/servicetalk-grpc-utils/build.gradle @@ -17,10 +17,11 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) api project(":servicetalk-grpc-api") implementation project(":servicetalk-annotations") implementation project(":servicetalk-logging-slf4j-internal") implementation project(":servicetalk-utils-internal") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "com.google.code.findbugs:jsr305" } diff --git a/servicetalk-http-api/build.gradle b/servicetalk-http-api/build.gradle index bf4e36b147..6614ee67c2 100644 --- a/servicetalk-http-api/build.gradle +++ b/servicetalk-http-api/build.gradle @@ -17,6 +17,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") testFixturesImplementation platform("org.junit:junit-bom:$junit5Version") @@ -39,8 +40,8 @@ dependencies { implementation project(":servicetalk-serializer-utils") implementation project(":servicetalk-utils-internal") implementation project(":servicetalk-oio-api-internal") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" - implementation "org.slf4j:slf4j-api:$slf4jVersion" + implementation "com.google.code.findbugs:jsr305" + implementation "org.slf4j:slf4j-api" testImplementation testFixtures(project(":servicetalk-concurrent-api")) testImplementation testFixtures(project(":servicetalk-concurrent-internal")) diff --git a/servicetalk-http-netty/build.gradle b/servicetalk-http-netty/build.gradle index 7aa43e8222..4021f2b881 100644 --- a/servicetalk-http-netty/build.gradle +++ b/servicetalk-http-netty/build.gradle @@ -17,6 +17,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) implementation platform("io.netty:netty-bom:$nettyVersion") testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") @@ -36,10 +37,10 @@ dependencies { implementation project(":servicetalk-transport-netty") implementation project(":servicetalk-transport-netty-internal") implementation project(":servicetalk-utils-internal") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "com.google.code.findbugs:jsr305" implementation "io.netty:netty-codec-http" implementation "io.netty:netty-codec-http2" - implementation "org.slf4j:slf4j-api:$slf4jVersion" + implementation "org.slf4j:slf4j-api" testImplementation testFixtures(project(":servicetalk-buffer-api")) testImplementation testFixtures(project(":servicetalk-concurrent-api")) @@ -68,4 +69,5 @@ dependencies { testFixturesImplementation project(":servicetalk-http-utils") testFixturesImplementation project(":servicetalk-test-resources") testFixturesImplementation "org.hamcrest:hamcrest:$hamcrestVersion" + testFixturesRuntimeOnly "org.apache.logging.log4j:log4j-slf4j-impl:$log4jVersion" } diff --git a/servicetalk-http-router-jersey-internal/build.gradle b/servicetalk-http-router-jersey-internal/build.gradle index 982a52b21d..dc956d13bb 100644 --- a/servicetalk-http-router-jersey-internal/build.gradle +++ b/servicetalk-http-router-jersey-internal/build.gradle @@ -17,15 +17,15 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { - implementation platform("org.glassfish.jersey:jersey-bom:$jerseyVersion") + api platform(project(":servicetalk-dependencies")) api project(":servicetalk-http-api") - api "jakarta.ws.rs:jakarta.ws.rs-api:$jaxRsVersion" + api "jakarta.ws.rs:jakarta.ws.rs-api" implementation project(":servicetalk-annotations") implementation project(":servicetalk-concurrent-api-internal") implementation project(":servicetalk-concurrent-internal") implementation project(":servicetalk-http-utils") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "com.google.code.findbugs:jsr305" implementation "org.glassfish.jersey.core:jersey-common" } diff --git a/servicetalk-http-router-jersey/build.gradle b/servicetalk-http-router-jersey/build.gradle index 9ea140360c..0012a162d7 100644 --- a/servicetalk-http-router-jersey/build.gradle +++ b/servicetalk-http-router-jersey/build.gradle @@ -17,14 +17,14 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { - implementation platform("org.glassfish.jersey:jersey-bom:$jerseyVersion") + api platform(project(":servicetalk-dependencies")) testFixturesImplementation platform("org.glassfish.jersey:jersey-bom:$jerseyVersion") testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") testFixturesImplementation platform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-http-api") api project(":servicetalk-router-api") - api "jakarta.ws.rs:jakarta.ws.rs-api:$jaxRsVersion" + api "jakarta.ws.rs:jakarta.ws.rs-api" implementation project(":servicetalk-annotations") implementation project(":servicetalk-concurrent-api-internal") @@ -33,13 +33,14 @@ dependencies { implementation project(":servicetalk-http-router-jersey-internal") implementation project(":servicetalk-http-utils") implementation project(":servicetalk-router-utils-internal") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" - implementation "com.sun.activation:jakarta.activation:$javaxActivationVersion" - implementation "com.sun.xml.bind:jaxb-core:$javaxJaxbCoreVersion" - implementation "com.sun.xml.bind:jaxb-impl:$javaxJaxbImplVersion" - implementation "jakarta.xml.bind:jakarta.xml.bind-api:$javaxJaxbApiVersion" + implementation "com.google.code.findbugs:jsr305" + implementation "com.sun.activation:jakarta.activation" + implementation "com.sun.xml.bind:jaxb-core" + implementation "jakarta.xml.bind:jakarta.xml.bind-api" implementation "org.glassfish.jersey.core:jersey-server" - implementation "org.slf4j:slf4j-api:$slf4jVersion" + implementation "org.slf4j:slf4j-api" + + runtimeOnly "com.sun.xml.bind:jaxb-impl" testImplementation "org.junit.jupiter:junit-jupiter-api" testImplementation "org.mockito:mockito-core:$mockitoCoreVersion" diff --git a/servicetalk-http-router-predicate/build.gradle b/servicetalk-http-router-predicate/build.gradle index 43d3258231..8911b8da0e 100644 --- a/servicetalk-http-router-predicate/build.gradle +++ b/servicetalk-http-router-predicate/build.gradle @@ -17,12 +17,13 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-http-api") implementation project(":servicetalk-annotations") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "com.google.code.findbugs:jsr305" testImplementation testFixtures(project(":servicetalk-concurrent-api")) testImplementation testFixtures(project(":servicetalk-concurrent-internal")) diff --git a/servicetalk-http-security-jersey/build.gradle b/servicetalk-http-security-jersey/build.gradle index 200a9e7304..34df9ee1af 100644 --- a/servicetalk-http-security-jersey/build.gradle +++ b/servicetalk-http-security-jersey/build.gradle @@ -17,15 +17,15 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { - implementation platform("org.glassfish.jersey:jersey-bom:$jerseyVersion") + api platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.glassfish.jersey:jersey-bom:$jerseyVersion") testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") - api "jakarta.ws.rs:jakarta.ws.rs-api:$jaxRsVersion" + api "jakarta.ws.rs:jakarta.ws.rs-api" implementation project(":servicetalk-annotations") implementation project(":servicetalk-concurrent-api") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "com.google.code.findbugs:jsr305" implementation "org.glassfish.jersey.core:jersey-common" testImplementation testFixtures(project(":servicetalk-concurrent-internal")) diff --git a/servicetalk-http-utils/build.gradle b/servicetalk-http-utils/build.gradle index 92618b5dfd..a66ff6215c 100644 --- a/servicetalk-http-utils/build.gradle +++ b/servicetalk-http-utils/build.gradle @@ -17,6 +17,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-concurrent-api") @@ -27,8 +28,8 @@ dependencies { implementation project(":servicetalk-concurrent-internal") implementation project(":servicetalk-logging-slf4j-internal") implementation project(":servicetalk-utils-internal") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" - implementation "org.slf4j:slf4j-api:$slf4jVersion" + implementation "com.google.code.findbugs:jsr305" + implementation "org.slf4j:slf4j-api" testImplementation testFixtures(project(":servicetalk-buffer-api")) testImplementation testFixtures(project(":servicetalk-concurrent-api")) diff --git a/servicetalk-loadbalancer/build.gradle b/servicetalk-loadbalancer/build.gradle index 242fb58c13..049cd6b6b4 100644 --- a/servicetalk-loadbalancer/build.gradle +++ b/servicetalk-loadbalancer/build.gradle @@ -17,6 +17,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-client-api") @@ -26,14 +27,15 @@ dependencies { implementation project(":servicetalk-concurrent-api-internal") implementation project(":servicetalk-concurrent-internal") implementation project(":servicetalk-client-api-internal") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" - implementation "org.slf4j:slf4j-api:$slf4jVersion" + implementation "com.google.code.findbugs:jsr305" + implementation "org.slf4j:slf4j-api" testImplementation testFixtures(project(":servicetalk-concurrent-api")) testImplementation testFixtures(project(":servicetalk-concurrent-internal")) testImplementation project(":servicetalk-concurrent-test-internal") testImplementation project(":servicetalk-test-resources") testImplementation "org.junit.jupiter:junit-jupiter-api" + testImplementation "org.apache.logging.log4j:log4j-core" testImplementation "org.hamcrest:hamcrest:$hamcrestVersion" testImplementation "org.mockito:mockito-core:$mockitoCoreVersion" } diff --git a/servicetalk-log4j2-mdc-utils/build.gradle b/servicetalk-log4j2-mdc-utils/build.gradle index 18c2639eff..b081399464 100644 --- a/servicetalk-log4j2-mdc-utils/build.gradle +++ b/servicetalk-log4j2-mdc-utils/build.gradle @@ -17,23 +17,28 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + api platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") + testFixturesImplementation enforcedPlatform(project(":servicetalk-dependencies")) - api "org.apache.logging.log4j:log4j-core:$log4jVersion" + api "org.apache.logging.log4j:log4j-api" implementation project(":servicetalk-annotations") implementation project(":servicetalk-concurrent-api") implementation project(":servicetalk-concurrent-internal") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "com.google.code.findbugs:jsr305" + implementation "org.apache.logging.log4j:log4j-core" testImplementation project(":servicetalk-test-resources") testImplementation "org.junit.jupiter:junit-jupiter-api" testImplementation "org.slf4j:slf4j-api:$slf4jVersion" testImplementation "org.hamcrest:hamcrest:$hamcrestVersion" - testFixturesImplementation "com.google.code.findbugs:jsr305:$jsr305Version" - testFixturesImplementation "org.apache.logging.log4j:log4j-slf4j-impl:$log4jVersion" - testFixturesImplementation "org.hamcrest:hamcrest:$hamcrestVersion" + testFixturesImplementation "com.google.code.findbugs:jsr305" + testFixturesImplementation "org.apache.logging.log4j:log4j-core" + testFixturesImplementation "org.hamcrest:hamcrest" + testFixturesImplementation "org.slf4j:slf4j-api:$slf4jVersion" + testFixturesRuntimeOnly "org.apache.logging.log4j:log4j-slf4j-impl" } test { diff --git a/servicetalk-log4j2-mdc/build.gradle b/servicetalk-log4j2-mdc/build.gradle index 9a148975fe..cfdb04a164 100644 --- a/servicetalk-log4j2-mdc/build.gradle +++ b/servicetalk-log4j2-mdc/build.gradle @@ -17,11 +17,12 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") implementation project(":servicetalk-annotations") implementation project(":servicetalk-log4j2-mdc-utils") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "com.google.code.findbugs:jsr305" testImplementation "org.junit.jupiter:junit-jupiter-api" testImplementation "org.hamcrest:hamcrest:$hamcrestVersion" diff --git a/servicetalk-logging-slf4j-internal/build.gradle b/servicetalk-logging-slf4j-internal/build.gradle index 66ae7a6bd8..dd72ae81fd 100644 --- a/servicetalk-logging-slf4j-internal/build.gradle +++ b/servicetalk-logging-slf4j-internal/build.gradle @@ -17,8 +17,10 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) + api project(":servicetalk-logging-api") implementation project(":servicetalk-annotations") - implementation "org.slf4j:slf4j-api:$slf4jVersion" + implementation "org.slf4j:slf4j-api" } diff --git a/servicetalk-oio-api-internal/build.gradle b/servicetalk-oio-api-internal/build.gradle index f4067f637c..52ca1f4f0c 100644 --- a/servicetalk-oio-api-internal/build.gradle +++ b/servicetalk-oio-api-internal/build.gradle @@ -17,9 +17,11 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) + api project(":servicetalk-oio-api") implementation project(":servicetalk-annotations") - implementation "org.slf4j:slf4j-api:$slf4jVersion" - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "org.slf4j:slf4j-api" + implementation "com.google.code.findbugs:jsr305" } diff --git a/servicetalk-oio-api/build.gradle b/servicetalk-oio-api/build.gradle index 294c156d5c..baf0b1dbd7 100644 --- a/servicetalk-oio-api/build.gradle +++ b/servicetalk-oio-api/build.gradle @@ -17,7 +17,8 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) implementation project(":servicetalk-annotations") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "com.google.code.findbugs:jsr305" } diff --git a/servicetalk-opentracing-asynccontext/build.gradle b/servicetalk-opentracing-asynccontext/build.gradle index 465af5051e..3357b860fc 100644 --- a/servicetalk-opentracing-asynccontext/build.gradle +++ b/servicetalk-opentracing-asynccontext/build.gradle @@ -17,13 +17,14 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-opentracing-inmemory") implementation project(":servicetalk-annotations") implementation project(":servicetalk-concurrent-api") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "com.google.code.findbugs:jsr305" testImplementation project(":servicetalk-test-resources") testImplementation "org.junit.jupiter:junit-jupiter-api" diff --git a/servicetalk-opentracing-http/build.gradle b/servicetalk-opentracing-http/build.gradle index 4614b51037..31372283c5 100644 --- a/servicetalk-opentracing-http/build.gradle +++ b/servicetalk-opentracing-http/build.gradle @@ -17,18 +17,19 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + api platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-http-api") - api "io.opentracing:opentracing-api:$openTracingVersion" + api "io.opentracing:opentracing-api" implementation project(":servicetalk-annotations") implementation project(":servicetalk-http-utils") implementation project(":servicetalk-opentracing-inmemory") implementation project(":servicetalk-opentracing-inmemory-api") implementation project(":servicetalk-opentracing-internal") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" - implementation "org.slf4j:slf4j-api:$slf4jVersion" + implementation "com.google.code.findbugs:jsr305" + implementation "org.slf4j:slf4j-api" testImplementation testFixtures(project(":servicetalk-concurrent-api")) testImplementation testFixtures(project(":servicetalk-concurrent-internal")) @@ -41,10 +42,10 @@ dependencies { testImplementation project(":servicetalk-opentracing-asynccontext") testImplementation project(":servicetalk-test-resources") testImplementation project(":servicetalk-opentracing-log4j2") - testImplementation "org.apache.logging.log4j:log4j-slf4j-impl:$log4jVersion" testImplementation "org.apache.logging.log4j:log4j-core:$log4jVersion" testImplementation "org.hamcrest:hamcrest:$hamcrestVersion" testImplementation "org.junit.jupiter:junit-jupiter-api" testImplementation "org.mockito:mockito-core:$mockitoCoreVersion" testImplementation "org.mockito:mockito-junit-jupiter:$mockitoCoreVersion" + testRuntimeOnly "org.apache.logging.log4j:log4j-slf4j-impl:$log4jVersion" } diff --git a/servicetalk-opentracing-inmemory-api/build.gradle b/servicetalk-opentracing-inmemory-api/build.gradle index d9de542016..59ca131b35 100644 --- a/servicetalk-opentracing-inmemory-api/build.gradle +++ b/servicetalk-opentracing-inmemory-api/build.gradle @@ -17,10 +17,12 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + api platform(project(":servicetalk-dependencies")) + api "io.opentracing:opentracing-api:$openTracingVersion" implementation project(":servicetalk-annotations") implementation project(":servicetalk-opentracing-internal") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" - implementation "org.slf4j:slf4j-api:$slf4jVersion" + implementation "com.google.code.findbugs:jsr305" + implementation "org.slf4j:slf4j-api" } diff --git a/servicetalk-opentracing-inmemory/build.gradle b/servicetalk-opentracing-inmemory/build.gradle index 78d9875346..8c4bae1c54 100644 --- a/servicetalk-opentracing-inmemory/build.gradle +++ b/servicetalk-opentracing-inmemory/build.gradle @@ -17,6 +17,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-opentracing-inmemory-api") @@ -26,8 +27,8 @@ dependencies { implementation project(":servicetalk-buffer-api") implementation project(":servicetalk-opentracing-internal") implementation project(":servicetalk-utils-internal") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" - implementation "org.slf4j:slf4j-api:$slf4jVersion" + implementation "com.google.code.findbugs:jsr305" + implementation "org.slf4j:slf4j-api" testImplementation "org.junit.jupiter:junit-jupiter-api" testImplementation "org.mockito:mockito-core:$mockitoCoreVersion" diff --git a/servicetalk-opentracing-internal/build.gradle b/servicetalk-opentracing-internal/build.gradle index 9e500a3f79..c82647517b 100644 --- a/servicetalk-opentracing-internal/build.gradle +++ b/servicetalk-opentracing-internal/build.gradle @@ -17,7 +17,9 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) + implementation project(":servicetalk-annotations") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" - implementation "org.slf4j:slf4j-api:$slf4jVersion" + implementation "com.google.code.findbugs:jsr305" + implementation "org.slf4j:slf4j-api" } diff --git a/servicetalk-opentracing-log4j2/build.gradle b/servicetalk-opentracing-log4j2/build.gradle index e8a6cb5992..7ceb58188e 100644 --- a/servicetalk-opentracing-log4j2/build.gradle +++ b/servicetalk-opentracing-log4j2/build.gradle @@ -17,6 +17,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-log4j2-mdc-utils") @@ -26,10 +27,9 @@ dependencies { implementation project(":servicetalk-opentracing-inmemory-api") implementation project(":servicetalk-opentracing-internal") implementation project(":servicetalk-opentracing-asynccontext") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" - implementation "org.apache.logging.log4j:log4j-api:$log4jVersion" - implementation "org.apache.logging.log4j:log4j-core:$log4jVersion" - implementation "org.slf4j:slf4j-api:$slf4jVersion" + implementation "com.google.code.findbugs:jsr305" + implementation "org.apache.logging.log4j:log4j-core" + implementation "org.slf4j:slf4j-api" testImplementation testFixtures(project(":servicetalk-log4j2-mdc-utils")) testImplementation "org.junit.jupiter:junit-jupiter-api" diff --git a/servicetalk-opentracing-zipkin-publisher/build.gradle b/servicetalk-opentracing-zipkin-publisher/build.gradle index 5e5165308b..17b1f81edb 100644 --- a/servicetalk-opentracing-zipkin-publisher/build.gradle +++ b/servicetalk-opentracing-zipkin-publisher/build.gradle @@ -17,6 +17,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + api platform(project(":servicetalk-dependencies")) implementation platform("io.netty:netty-bom:$nettyVersion") testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") @@ -25,18 +26,17 @@ dependencies { api project(":servicetalk-logging-api") api project(":servicetalk-http-api") api project(":servicetalk-transport-api") - - api "io.zipkin.reporter2:zipkin-reporter:$zipkinReporterVersion" + api "io.zipkin.reporter2:zipkin-reporter" implementation project(":servicetalk-annotations") implementation project(":servicetalk-transport-netty-internal") implementation project(":servicetalk-concurrent-api-internal") implementation project(":servicetalk-concurrent-internal") implementation project(":servicetalk-logging-slf4j-internal") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "com.google.code.findbugs:jsr305" implementation "io.netty:netty-codec" implementation "io.netty:netty-transport" - implementation "org.slf4j:slf4j-api:$slf4jVersion" + implementation "org.slf4j:slf4j-api" testImplementation testFixtures(project(":servicetalk-concurrent-api")) testImplementation testFixtures(project(":servicetalk-concurrent-internal")) diff --git a/servicetalk-router-api/build.gradle b/servicetalk-router-api/build.gradle index 7a73b3cd28..6afe230a23 100644 --- a/servicetalk-router-api/build.gradle +++ b/servicetalk-router-api/build.gradle @@ -17,6 +17,8 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) + implementation project(":servicetalk-annotations") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "com.google.code.findbugs:jsr305" } diff --git a/servicetalk-router-utils-internal/build.gradle b/servicetalk-router-utils-internal/build.gradle index 572de2bdb3..6d5ef5e489 100644 --- a/servicetalk-router-utils-internal/build.gradle +++ b/servicetalk-router-utils-internal/build.gradle @@ -17,10 +17,11 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) + implementation project(":servicetalk-annotations") implementation project(":servicetalk-concurrent-api") implementation project(":servicetalk-router-api") implementation project(":servicetalk-transport-api") - - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "com.google.code.findbugs:jsr305" } diff --git a/servicetalk-serialization-api/build.gradle b/servicetalk-serialization-api/build.gradle index e6f9526997..cd770950a3 100644 --- a/servicetalk-serialization-api/build.gradle +++ b/servicetalk-serialization-api/build.gradle @@ -17,6 +17,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-buffer-api") @@ -27,7 +28,7 @@ dependencies { implementation project(":servicetalk-concurrent-api-internal") implementation project(":servicetalk-concurrent-internal") implementation project(":servicetalk-utils-internal") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "com.google.code.findbugs:jsr305" testImplementation testFixtures(project(":servicetalk-concurrent-api")) testImplementation testFixtures(project(":servicetalk-concurrent-internal")) diff --git a/servicetalk-serializer-api/build.gradle b/servicetalk-serializer-api/build.gradle index 16d60f0b59..6f9efdd0ec 100644 --- a/servicetalk-serializer-api/build.gradle +++ b/servicetalk-serializer-api/build.gradle @@ -17,6 +17,8 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) + api project(":servicetalk-buffer-api") api project(":servicetalk-concurrent-api") api project(":servicetalk-oio-api") @@ -24,5 +26,5 @@ dependencies { implementation project(":servicetalk-annotations") implementation project(":servicetalk-concurrent-api-internal") implementation project(":servicetalk-oio-api-internal") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "com.google.code.findbugs:jsr305" } diff --git a/servicetalk-serializer-utils/build.gradle b/servicetalk-serializer-utils/build.gradle index 04bcc6bc30..24172e2550 100644 --- a/servicetalk-serializer-utils/build.gradle +++ b/servicetalk-serializer-utils/build.gradle @@ -17,6 +17,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-serializer-api") @@ -25,7 +26,7 @@ dependencies { implementation project(":servicetalk-annotations") implementation project(":servicetalk-concurrent-internal") implementation project(":servicetalk-utils-internal") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "com.google.code.findbugs:jsr305" testImplementation testFixtures(project(":servicetalk-concurrent-api")) testImplementation testFixtures(project(":servicetalk-concurrent-internal")) diff --git a/servicetalk-tcp-netty-internal/build.gradle b/servicetalk-tcp-netty-internal/build.gradle index 7721e88e4f..45b107e7fe 100644 --- a/servicetalk-tcp-netty-internal/build.gradle +++ b/servicetalk-tcp-netty-internal/build.gradle @@ -17,6 +17,8 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) + testImplementation enforcedPlatform("io.netty:netty-bom:$nettyVersion") testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") testFixturesImplementation platform("io.netty:netty-bom:$nettyVersion") @@ -32,8 +34,8 @@ dependencies { implementation project(":servicetalk-concurrent-internal") implementation project(":servicetalk-logging-slf4j-internal") implementation project(":servicetalk-transport-netty") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" - implementation "org.slf4j:slf4j-api:$slf4jVersion" + implementation "com.google.code.findbugs:jsr305" + implementation "org.slf4j:slf4j-api" testImplementation testFixtures(project(":servicetalk-concurrent-api")) testImplementation testFixtures(project(":servicetalk-concurrent-internal")) diff --git a/servicetalk-test-resources/build.gradle b/servicetalk-test-resources/build.gradle index 1130ac62a1..67e045dff9 100644 --- a/servicetalk-test-resources/build.gradle +++ b/servicetalk-test-resources/build.gradle @@ -17,15 +17,13 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + api platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") implementation project(":servicetalk-annotations") implementation project(":servicetalk-utils-internal") - api "org.hamcrest:hamcrest:$hamcrestVersion" - - implementation "org.apache.logging.log4j:log4j-core:$log4jVersion" - implementation "org.apache.logging.log4j:log4j-slf4j-impl:$log4jVersion" + api "org.hamcrest:hamcrest" testImplementation "org.junit.jupiter:junit-jupiter-api" } diff --git a/servicetalk-transport-api/build.gradle b/servicetalk-transport-api/build.gradle index 3c356805d7..7a76b38573 100644 --- a/servicetalk-transport-api/build.gradle +++ b/servicetalk-transport-api/build.gradle @@ -17,6 +17,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-buffer-api") @@ -25,8 +26,8 @@ dependencies { implementation project(":servicetalk-annotations") implementation project(":servicetalk-concurrent-internal") implementation project(":servicetalk-utils-internal") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" - implementation "org.slf4j:slf4j-api:$slf4jVersion" + implementation "com.google.code.findbugs:jsr305" + implementation "org.slf4j:slf4j-api" testImplementation testFixtures(project(":servicetalk-concurrent-api")) testImplementation testFixtures(project(":servicetalk-concurrent-internal")) diff --git a/servicetalk-transport-netty-internal/build.gradle b/servicetalk-transport-netty-internal/build.gradle index 39ef0cd5de..b1a109c789 100644 --- a/servicetalk-transport-netty-internal/build.gradle +++ b/servicetalk-transport-netty-internal/build.gradle @@ -17,7 +17,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { - api platform("io.netty:netty-bom:$nettyVersion") + api platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") testFixturesImplementation platform("org.junit:junit-bom:$junit5Version") @@ -32,7 +32,7 @@ dependencies { implementation project(":servicetalk-concurrent-internal") implementation project(":servicetalk-logging-slf4j-internal") implementation project(":servicetalk-utils-internal") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "com.google.code.findbugs:jsr305" implementation "io.netty:netty-transport-native-epoll" runtimeOnly( group:"io.netty", name:"netty-transport-native-epoll", classifier:"linux-x86_64") runtimeOnly( group:"io.netty", name:"netty-transport-native-epoll", classifier:"linux-aarch_64") @@ -46,7 +46,7 @@ dependencies { runtimeOnly( group:"io.netty", name:"netty-tcnative-boringssl-static", classifier:"linux-aarch_64") runtimeOnly( group:"io.netty", name:"netty-tcnative-boringssl-static", classifier:"osx-x86_64") runtimeOnly( group:"io.netty", name:"netty-tcnative-boringssl-static", classifier:"osx-aarch_64") - implementation "org.slf4j:slf4j-api:$slf4jVersion" + implementation "org.slf4j:slf4j-api" testImplementation testFixtures(project(":servicetalk-concurrent-api")) testImplementation testFixtures(project(":servicetalk-concurrent-internal")) diff --git a/servicetalk-transport-netty/build.gradle b/servicetalk-transport-netty/build.gradle index 8b09819b43..d1062349e3 100644 --- a/servicetalk-transport-netty/build.gradle +++ b/servicetalk-transport-netty/build.gradle @@ -17,7 +17,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { - implementation platform("io.netty:netty-bom:$nettyVersion") + implementation platform(project(":servicetalk-dependencies")) api project(":servicetalk-concurrent-api") api project(":servicetalk-transport-api") @@ -25,6 +25,6 @@ dependencies { implementation project(":servicetalk-annotations") implementation project(":servicetalk-concurrent-internal") implementation project(":servicetalk-transport-netty-internal") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" + implementation "com.google.code.findbugs:jsr305" implementation "io.netty:netty-common" } diff --git a/servicetalk-utils-internal/build.gradle b/servicetalk-utils-internal/build.gradle index 4ef1ae5ec0..f8454eaa8f 100644 --- a/servicetalk-utils-internal/build.gradle +++ b/servicetalk-utils-internal/build.gradle @@ -17,13 +17,14 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { + implementation platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") implementation project(":servicetalk-annotations") implementation project(":servicetalk-buffer-api") - implementation "com.google.code.findbugs:jsr305:$jsr305Version" - implementation "org.jctools:jctools-core:$jcToolsVersion" - implementation "org.slf4j:slf4j-api:$slf4jVersion" + implementation "com.google.code.findbugs:jsr305" + implementation "org.jctools:jctools-core" + implementation "org.slf4j:slf4j-api" testImplementation "org.junit.jupiter:junit-jupiter-api" testImplementation "org.hamcrest:hamcrest:$hamcrestVersion" From c0b80c08f6a1396c9c42e656495a5442948cf5ff Mon Sep 17 00:00:00 2001 From: Thomas Kountis Date: Fri, 20 May 2022 09:59:55 -0700 Subject: [PATCH 21/40] Clear async-context inside RRLB health checking (#2220) Motivation: Health checking is an indefinite process (for as long as the host is present), and relying on async-context can lead to misbehavior with code storing stuff in it. Modification: Upon subscribing for the health-check process, we clear async-context. Result: No state maintained in async-context for the lifetime of health-checking. --- .../io/servicetalk/loadbalancer/RoundRobinLoadBalancer.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/servicetalk-loadbalancer/src/main/java/io/servicetalk/loadbalancer/RoundRobinLoadBalancer.java b/servicetalk-loadbalancer/src/main/java/io/servicetalk/loadbalancer/RoundRobinLoadBalancer.java index 52a5e88865..42d41e9998 100644 --- a/servicetalk-loadbalancer/src/main/java/io/servicetalk/loadbalancer/RoundRobinLoadBalancer.java +++ b/servicetalk-loadbalancer/src/main/java/io/servicetalk/loadbalancer/RoundRobinLoadBalancer.java @@ -25,6 +25,7 @@ import io.servicetalk.concurrent.PublisherSource.Subscriber; import io.servicetalk.concurrent.PublisherSource.Subscription; import io.servicetalk.concurrent.api.AsyncCloseable; +import io.servicetalk.concurrent.api.AsyncContext; import io.servicetalk.concurrent.api.Completable; import io.servicetalk.concurrent.api.CompositeCloseable; import io.servicetalk.concurrent.api.Executor; @@ -777,6 +778,8 @@ public void schedule(final Throwable originalCause) { host.healthCheckConfig.healthCheckInterval, host.healthCheckConfig.executor) .apply(0, originalCause) + // Remove any state from async context + .beforeOnSubscribe(__ -> AsyncContext.clear()) .concat(connectionFactory.newConnection(host.address, null, null) // There is no risk for StackOverflowError because result of each connection // attempt will be invoked on IoExecutor as a new task. From 49e3525dc8016cf91b222d105c5307328bf864da Mon Sep 17 00:00:00 2001 From: Idel Pivnitskiy Date: Fri, 20 May 2022 18:12:10 -0500 Subject: [PATCH 22/40] Make `HostHeaderHttpRequesterFilter` public (#2212) Motivation: Users may have a need to set the `Host` header with a different value than they used to create a client. For these cases, it's convenient to reuse existing filter instead of writing their own. Modifications: - Move `HostHeaderHttpRequesterFilter` from `http-netty` to `http-utils` and make it `public`; - Disable `DefaultSingleAddressHttpClientBuilder.addHostHeaderFallbackFilter` when `HostHeaderHttpRequesterFilter` is added manually; - Move `NetUtils` from `http-api` to `utils-internal` module to share with other modules outside `http-api`, rename it to `NetworkUtils`; - Add `NetworkUtilsTests`; - Replace all usages of `io.netty.util.NetUtil.isValidIpV*Address` with `io.servicetalk.utils.internal.NetworkUtils.isValidIpV*Address`; Result: Users can use `HostHeaderHttpRequesterFilter` to set the `Host` header and move it anywhere in the filter chain. --- .../io/servicetalk/http/api/HeaderUtils.java | 4 +- .../api/SingleAddressHttpClientBuilder.java | 2 +- ...DefaultSingleAddressHttpClientBuilder.java | 17 +- .../http/netty/HttpClientConfig.java | 4 +- .../HostHeaderHttpRequesterFilterTest.java | 5 +- ...irectingClientAndConnectionFilterTest.java | 1 + .../utils}/HostHeaderHttpRequesterFilter.java | 17 +- .../netty/internal/BuilderUtils.java | 6 +- .../utils/internal/NetworkUtils.java | 23 +- .../utils/internal/NetworkUtilsTest.java | 447 ++++++++++++++++++ 10 files changed, 498 insertions(+), 28 deletions(-) rename {servicetalk-http-netty/src/main/java/io/servicetalk/http/netty => servicetalk-http-utils/src/main/java/io/servicetalk/http/utils}/HostHeaderHttpRequesterFilter.java (84%) rename servicetalk-http-api/src/main/java/io/servicetalk/http/api/NetUtils.java => servicetalk-utils-internal/src/main/java/io/servicetalk/utils/internal/NetworkUtils.java (91%) create mode 100644 servicetalk-utils-internal/src/test/java/io/servicetalk/utils/internal/NetworkUtilsTest.java diff --git a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/HeaderUtils.java b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/HeaderUtils.java index f35419fb64..bc4de628d8 100644 --- a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/HeaderUtils.java +++ b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/HeaderUtils.java @@ -46,12 +46,12 @@ import static io.servicetalk.http.api.HttpHeaderNames.TRANSFER_ENCODING; import static io.servicetalk.http.api.HttpHeaderNames.VARY; import static io.servicetalk.http.api.HttpHeaderValues.CHUNKED; -import static io.servicetalk.http.api.NetUtils.isValidIpV4Address; -import static io.servicetalk.http.api.NetUtils.isValidIpV6Address; import static io.servicetalk.http.api.UriUtils.TCHAR_HMASK; import static io.servicetalk.http.api.UriUtils.TCHAR_LMASK; import static io.servicetalk.http.api.UriUtils.isBitSet; import static io.servicetalk.utils.internal.CharsetUtils.standardCharsets; +import static io.servicetalk.utils.internal.NetworkUtils.isValidIpV4Address; +import static io.servicetalk.utils.internal.NetworkUtils.isValidIpV6Address; import static java.lang.Math.min; import static java.lang.System.lineSeparator; import static java.nio.charset.StandardCharsets.UTF_8; diff --git a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/SingleAddressHttpClientBuilder.java b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/SingleAddressHttpClientBuilder.java index 368d3bf111..b7cbcd3e85 100644 --- a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/SingleAddressHttpClientBuilder.java +++ b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/SingleAddressHttpClientBuilder.java @@ -94,7 +94,7 @@ SingleAddressHttpClientBuilder enableWireLogging(String loggerName, SingleAddressHttpClientBuilder protocols(HttpProtocolConfig... protocols); /** - * Configures automatically setting {@code Host} headers by inferring from the address or {@link HttpMetaData}. + * Configures automatically setting {@code Host} headers by inferring from the address. *

* When {@code false} is passed, this setting disables the default filter such that no {@code Host} header will be * manipulated. diff --git a/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/DefaultSingleAddressHttpClientBuilder.java b/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/DefaultSingleAddressHttpClientBuilder.java index ea1f4e2aca..9c2c394e10 100644 --- a/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/DefaultSingleAddressHttpClientBuilder.java +++ b/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/DefaultSingleAddressHttpClientBuilder.java @@ -45,6 +45,7 @@ import io.servicetalk.http.api.StreamingHttpConnectionFilterFactory; import io.servicetalk.http.api.StreamingHttpRequest; import io.servicetalk.http.api.StreamingHttpRequestResponseFactory; +import io.servicetalk.http.utils.HostHeaderHttpRequesterFilter; import io.servicetalk.logging.api.LogLevel; import io.servicetalk.transport.api.ClientSslConfig; import io.servicetalk.transport.api.ExecutionStrategy; @@ -448,13 +449,22 @@ public DefaultSingleAddressHttpClientBuilder appendConnectionFilter( requireNonNull(factory); connectionFilterFactory = appendConnectionFilter(connectionFilterFactory, factory); strategyComputation.add(factory); + ifHostHeaderHttpRequesterFilter(factory); return this; } @Override public DefaultSingleAddressHttpClientBuilder appendConnectionFilter( final Predicate predicate, final StreamingHttpConnectionFilterFactory factory) { - return appendConnectionFilter(toConditionalConnectionFilterFactory(predicate, factory)); + appendConnectionFilter(toConditionalConnectionFilterFactory(predicate, factory)); + ifHostHeaderHttpRequesterFilter(factory); + return this; + } + + private void ifHostHeaderHttpRequesterFilter(final Object filter) { + if (filter instanceof HostHeaderHttpRequesterFilter) { + addHostHeaderFallbackFilter = false; + } } // Use another method to keep final references and avoid StackOverflowError @@ -491,7 +501,9 @@ public DefaultSingleAddressHttpClientBuilder appendClientFilter( ensureSingleRetryFilter(); retryingHttpRequesterFilter = (RetryingHttpRequesterFilter) factory; } - return appendClientFilter(toConditionalClientFilterFactory(predicate, factory)); + appendClientFilter(toConditionalClientFilterFactory(predicate, factory)); + ifHostHeaderHttpRequesterFilter(factory); + return this; } private void ensureSingleRetryFilter() { @@ -518,6 +530,7 @@ public DefaultSingleAddressHttpClientBuilder appendClientFilter( } clientFilterFactory = appendFilter(clientFilterFactory, factory); strategyComputation.add(factory); + ifHostHeaderHttpRequesterFilter(factory); return this; } diff --git a/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/HttpClientConfig.java b/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/HttpClientConfig.java index 842ece52fb..a6efeec79e 100644 --- a/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/HttpClientConfig.java +++ b/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/HttpClientConfig.java @@ -22,9 +22,9 @@ import java.util.List; import javax.annotation.Nullable; -import static io.netty.util.NetUtil.isValidIpV4Address; -import static io.netty.util.NetUtil.isValidIpV6Address; import static io.servicetalk.http.netty.HttpServerConfig.httpAlpnProtocols; +import static io.servicetalk.utils.internal.NetworkUtils.isValidIpV4Address; +import static io.servicetalk.utils.internal.NetworkUtils.isValidIpV6Address; final class HttpClientConfig { diff --git a/servicetalk-http-netty/src/test/java/io/servicetalk/http/netty/HostHeaderHttpRequesterFilterTest.java b/servicetalk-http-netty/src/test/java/io/servicetalk/http/netty/HostHeaderHttpRequesterFilterTest.java index 8bec182469..8a731e214f 100644 --- a/servicetalk-http-netty/src/test/java/io/servicetalk/http/netty/HostHeaderHttpRequesterFilterTest.java +++ b/servicetalk-http-netty/src/test/java/io/servicetalk/http/netty/HostHeaderHttpRequesterFilterTest.java @@ -22,6 +22,7 @@ import io.servicetalk.http.api.HttpRequest; import io.servicetalk.http.api.HttpResponse; import io.servicetalk.http.api.ReservedBlockingHttpConnection; +import io.servicetalk.http.utils.HostHeaderHttpRequesterFilter; import io.servicetalk.transport.api.ServerContext; import org.junit.jupiter.params.ParameterizedTest; @@ -128,7 +129,6 @@ void clientBuilderAppendClientFilter(HttpVersionConfig httpVersionConfig) throws try (ServerContext context = buildServer(); BlockingHttpClient client = forSingleAddress(serverHostAndPort(context)) .protocols(httpVersionConfig.config()) - .hostHeaderFallback(false) // turn off the default .appendClientFilter(new HostHeaderHttpRequesterFilter("foo.bar:-1")) .buildBlocking()) { assertResponse(client, null, "foo.bar:-1"); @@ -142,7 +142,6 @@ void clientBuilderAppendConnectionFilter(HttpVersionConfig httpVersionConfig) th try (ServerContext context = buildServer(); BlockingHttpClient client = forSingleAddress(serverHostAndPort(context)) .protocols(httpVersionConfig.config()) - .hostHeaderFallback(false) // turn off the default .appendConnectionFilter(new HostHeaderHttpRequesterFilter("foo.bar:-1")) .buildBlocking()) { assertResponse(client, null, "foo.bar:-1"); @@ -156,7 +155,6 @@ void reserveConnection(HttpVersionConfig httpVersionConfig) throws Exception { try (ServerContext context = buildServer(); BlockingHttpClient client = HttpClients.forResolvedAddress(serverHostAndPort(context)) .protocols(httpVersionConfig.config()) - .hostHeaderFallback(false) // turn off the default .appendConnectionFilter(new HostHeaderHttpRequesterFilter("foo.bar:-1")) .buildBlocking(); ReservedBlockingHttpConnection conn = client.reserveConnection(client.get("/"))) { @@ -172,7 +170,6 @@ void clientBuilderAppendClientFilterExplicitHostHeader(HttpVersionConfig httpVer try (ServerContext context = buildServer(); BlockingHttpClient client = forSingleAddress(serverHostAndPort(context)) .protocols(httpVersionConfig.config()) - .hostHeaderFallback(false) // turn off the default .appendClientFilter(new HostHeaderHttpRequesterFilter("foo.bar:-1")) .buildBlocking()) { assertResponse(client, "bar.only:-1", "bar.only:-1"); diff --git a/servicetalk-http-netty/src/test/java/io/servicetalk/http/netty/RedirectingClientAndConnectionFilterTest.java b/servicetalk-http-netty/src/test/java/io/servicetalk/http/netty/RedirectingClientAndConnectionFilterTest.java index 0b897a3d4e..3e355ee60b 100644 --- a/servicetalk-http-netty/src/test/java/io/servicetalk/http/netty/RedirectingClientAndConnectionFilterTest.java +++ b/servicetalk-http-netty/src/test/java/io/servicetalk/http/netty/RedirectingClientAndConnectionFilterTest.java @@ -22,6 +22,7 @@ import io.servicetalk.http.api.HttpRequest; import io.servicetalk.http.api.HttpResponse; import io.servicetalk.http.netty.ConditionalFilterFactory.FilterFactory; +import io.servicetalk.http.utils.HostHeaderHttpRequesterFilter; import io.servicetalk.http.utils.RedirectingHttpRequesterFilter; import io.servicetalk.transport.api.HostAndPort; diff --git a/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/HostHeaderHttpRequesterFilter.java b/servicetalk-http-utils/src/main/java/io/servicetalk/http/utils/HostHeaderHttpRequesterFilter.java similarity index 84% rename from servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/HostHeaderHttpRequesterFilter.java rename to servicetalk-http-utils/src/main/java/io/servicetalk/http/utils/HostHeaderHttpRequesterFilter.java index ccb3596d5b..43dc3bf0e5 100644 --- a/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/HostHeaderHttpRequesterFilter.java +++ b/servicetalk-http-utils/src/main/java/io/servicetalk/http/utils/HostHeaderHttpRequesterFilter.java @@ -1,5 +1,5 @@ /* - * Copyright © 2018-2021 Apple Inc. and the ServiceTalk project authors + * Copyright © 2018-2022 Apple Inc. and the ServiceTalk project authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.servicetalk.http.netty; +package io.servicetalk.http.utils; import io.servicetalk.concurrent.api.Single; import io.servicetalk.http.api.FilterableStreamingHttpClient; @@ -21,6 +21,7 @@ import io.servicetalk.http.api.HttpExecutionStrategies; import io.servicetalk.http.api.HttpExecutionStrategy; import io.servicetalk.http.api.HttpHeaderNames; +import io.servicetalk.http.api.HttpRequestMetaData; import io.servicetalk.http.api.StreamingHttpClientFilter; import io.servicetalk.http.api.StreamingHttpClientFilterFactory; import io.servicetalk.http.api.StreamingHttpConnectionFilter; @@ -29,24 +30,26 @@ import io.servicetalk.http.api.StreamingHttpRequester; import io.servicetalk.http.api.StreamingHttpResponse; -import static io.netty.util.NetUtil.isValidIpV6Address; import static io.servicetalk.buffer.api.CharSequences.newAsciiString; import static io.servicetalk.concurrent.api.Single.defer; import static io.servicetalk.http.api.HttpHeaderNames.HOST; import static io.servicetalk.http.api.HttpProtocolVersion.HTTP_1_0; +import static io.servicetalk.utils.internal.NetworkUtils.isValidIpV6Address; /** - * A filter which will apply a fallback value for the {@link HttpHeaderNames#HOST} header if one is not present. + * A filter which will set a {@link HttpHeaderNames#HOST} header with the fallback value if the header is not already + * present in {@link HttpRequestMetaData}. */ -final class HostHeaderHttpRequesterFilter implements StreamingHttpClientFilterFactory, - StreamingHttpConnectionFilterFactory { +public final class HostHeaderHttpRequesterFilter implements StreamingHttpClientFilterFactory, + StreamingHttpConnectionFilterFactory { private final CharSequence fallbackHost; /** * Create a new instance. + * * @param fallbackHost The address to use as a fallback if a {@link HttpHeaderNames#HOST} header is not present. */ - HostHeaderHttpRequesterFilter(CharSequence fallbackHost) { + public HostHeaderHttpRequesterFilter(CharSequence fallbackHost) { this.fallbackHost = newAsciiString(isValidIpV6Address(fallbackHost) && fallbackHost.charAt(0) != '[' ? "[" + fallbackHost + "]" : fallbackHost.toString()); } diff --git a/servicetalk-transport-netty-internal/src/main/java/io/servicetalk/transport/netty/internal/BuilderUtils.java b/servicetalk-transport-netty-internal/src/main/java/io/servicetalk/transport/netty/internal/BuilderUtils.java index dacfeac5a4..a51e6d1c10 100644 --- a/servicetalk-transport-netty-internal/src/main/java/io/servicetalk/transport/netty/internal/BuilderUtils.java +++ b/servicetalk-transport-netty-internal/src/main/java/io/servicetalk/transport/netty/internal/BuilderUtils.java @@ -39,7 +39,6 @@ import io.netty.incubator.channel.uring.IOUringDatagramChannel; import io.netty.incubator.channel.uring.IOUringServerSocketChannel; import io.netty.incubator.channel.uring.IOUringSocketChannel; -import io.netty.util.NetUtil; import java.io.Closeable; import java.io.IOException; @@ -51,6 +50,7 @@ import javax.annotation.Nullable; import static io.netty.util.NetUtil.createByteArrayFromIpAddressString; +import static io.netty.util.NetUtil.toAddressString; import static io.servicetalk.transport.netty.internal.NativeTransportUtils.useEpoll; import static io.servicetalk.transport.netty.internal.NativeTransportUtils.useIoUring; import static io.servicetalk.transport.netty.internal.NativeTransportUtils.useKQueue; @@ -203,9 +203,9 @@ public static String formatCanonicalAddress(SocketAddress address) { if (inetAddress == null) { return address.toString(); } else if (inetAddress instanceof Inet6Address) { - return '[' + NetUtil.toAddressString(inetAddress) + "]:" + inetSocketAddress.getPort(); + return '[' + toAddressString(inetAddress) + "]:" + inetSocketAddress.getPort(); } else { - return NetUtil.toAddressString(inetAddress) + ':' + inetSocketAddress.getPort(); + return toAddressString(inetAddress) + ':' + inetSocketAddress.getPort(); } } return address.toString(); diff --git a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/NetUtils.java b/servicetalk-utils-internal/src/main/java/io/servicetalk/utils/internal/NetworkUtils.java similarity index 91% rename from servicetalk-http-api/src/main/java/io/servicetalk/http/api/NetUtils.java rename to servicetalk-utils-internal/src/main/java/io/servicetalk/utils/internal/NetworkUtils.java index 551588a512..8b801126df 100644 --- a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/NetUtils.java +++ b/servicetalk-utils-internal/src/main/java/io/servicetalk/utils/internal/NetworkUtils.java @@ -1,5 +1,5 @@ /* - * Copyright © 2018, 2021 Apple Inc. and the ServiceTalk project authors + * Copyright © 2018, 2021-2022 Apple Inc. and the ServiceTalk project authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,29 +28,37 @@ * License for the specific language governing permissions and limitations * under the License. */ -package io.servicetalk.http.api; +package io.servicetalk.utils.internal; import static io.servicetalk.buffer.api.CharSequences.indexOf; -final class NetUtils { +/** + * Network-related utilities. + *

+ * This class borrowed some of its methods from + * NetUtil class + * which was part of Netty. + */ +public final class NetworkUtils { - private NetUtils() { + private NetworkUtils() { // no instances } /** * Takes a string and parses it to see if it is a valid IPV4 address. * + * @param ip the IP-address to validate * @return true, if the string represents an IPV4 address in dotted notation, false otherwise. */ - static boolean isValidIpV4Address(final CharSequence ip) { + public static boolean isValidIpV4Address(final CharSequence ip) { return isValidIpV4Address(ip, 0, ip.length()); } private static boolean isValidIpV4Address(final CharSequence ip, int from, int toExclusive) { int len = toExclusive - from; int i; - return len <= 15 && len > 7 && + return len <= 15 && len >= 7 && (i = indexOf(ip, '.', from + 1)) > 0 && isValidIpV4Word(ip, from, i) && (i = indexOf(ip, '.', from = i + 2)) > 0 && isValidIpV4Word(ip, from - 1, i) && (i = indexOf(ip, '.', from = i + 2)) > 0 && isValidIpV4Word(ip, from - 1, i) && @@ -60,9 +68,10 @@ private static boolean isValidIpV4Address(final CharSequence ip, int from, int t /** * Takes a string and parses it to see if it is a valid IPV6 address. * + * @param ip the IP-address to validate * @return true, if the string represents an IPV6 address */ - static boolean isValidIpV6Address(final CharSequence ip) { + public static boolean isValidIpV6Address(final CharSequence ip) { int end = ip.length(); if (end < 2) { return false; diff --git a/servicetalk-utils-internal/src/test/java/io/servicetalk/utils/internal/NetworkUtilsTest.java b/servicetalk-utils-internal/src/test/java/io/servicetalk/utils/internal/NetworkUtilsTest.java new file mode 100644 index 0000000000..0ad1442e91 --- /dev/null +++ b/servicetalk-utils-internal/src/test/java/io/servicetalk/utils/internal/NetworkUtilsTest.java @@ -0,0 +1,447 @@ +/* + * Copyright © 2022 Apple Inc. and the ServiceTalk project authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * Copyright 2012 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.servicetalk.utils.internal; + +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static io.servicetalk.utils.internal.NetworkUtils.isValidIpV4Address; +import static io.servicetalk.utils.internal.NetworkUtils.isValidIpV6Address; +import static java.util.Arrays.asList; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@SuppressWarnings("PMD.AvoidUsingHardCodedIP") +class NetworkUtilsTest { + + private static final List validIpV4Hosts = asList( + "192.168.1.0", + "10.255.255.254", + "172.18.5.4", + "0.0.0.0", + "127.0.0.1", + "255.255.255.255", + "1.2.3.4"); + + private static final List invalidIpV4Hosts = asList( + "Garbage", + "1.256.3.4", + "256.0.0.1", + "1.1.1.1.1", + "x.255.255.255", + "0.1:0.0", + "0.1.0.0:", + "127.0.0.", + "1.2..4", + "192.0.1", + "192.0.1.1.1", + "192.0.1.a", + "19a.0.1.1", + "a.0.1.1", + ".0.1.1", + "127.0.0", + "192.0.1.256", + "0.0.200.259", + "1.1.-1.1", + "1.1. 1.1", + "1.1.1.1 ", + "1.1.+1.1", + "0.0x1.0.255", + "0.01x.0.255", + "0.x01.0.255", + "0.-.0.0", + "0..0.0", + "0.A.0.0", + "0.1111.0.0", + "..."); + + private static final List validIpV6Hosts = asList( + "::ffff:5.6.7.8", + "fdf8:f53b:82e4::53", + "fe80::200:5aee:feaa:20a2", + "2001::1", + "2001:0000:4136:e378:8000:63bf:3fff:fdd2", + "2001:0002:6c::430", + "2001:10:240:ab::a", + "2002:cb0a:3cdd:1::1", + "2001:db8:8:4::2", + "ff01:0:0:0:0:0:0:2", + "[fdf8:f53b:82e4::53]", + "[fe80::200:5aee:feaa:20a2]", + "[2001::1]", + "[2001:0000:4136:e378:8000:63bf:3fff:fdd2]", + "0:1:2:3:4:5:6:789a", + "0:1:2:3::f", + "0:0:0:0:0:0:10.0.0.1", + "0:0:0:0:0::10.0.0.1", + "0:0:0:0::10.0.0.1", + "::0:0:0:0:0:10.0.0.1", + "0::0:0:0:0:10.0.0.1", + "0:0::0:0:0:10.0.0.1", + "0:0:0::0:0:10.0.0.1", + "0:0:0:0::0:10.0.0.1", + "0:0:0:0:0:ffff:10.0.0.1", + "::ffff:192.168.0.1", + // Test if various interface names after the percent sign are recognized. + "[::1%1]", + "[::1%eth0]", + "[::1%%]", + "0:0:0:0:0:ffff:10.0.0.1%", + "0:0:0:0:0:ffff:10.0.0.1%1", + "[0:0:0:0:0:ffff:10.0.0.1%1]", + "[0:0:0:0:0::10.0.0.1%1]", + "[::0:0:0:0:ffff:10.0.0.1%1]", + "::0:0:0:0:ffff:10.0.0.1%1", + "::1%1", + "::1%eth0", + "::1%%", + // Tests with leading or trailing compression + "0:0:0:0:0:0:0::", + "0:0:0:0:0:0::", + "0:0:0:0:0::", + "0:0:0:0::", + "0:0:0::", + "0:0::", + "0::", + "::", + "::0", + "::0:0", + "::0:0:0", + "::0:0:0:0", + "::0:0:0:0:0", + "::0:0:0:0:0:0", + "::0:0:0:0:0:0:0"); + + private static final List invalidIpV6Hosts = asList( + // Test method with garbage. + "Obvious Garbage", + // Test method with preferred style, too many : + "0:1:2:3:4:5:6:7:8", + // Test method with preferred style, not enough : + "0:1:2:3:4:5:6", + // Test method with preferred style, bad digits. + "0:1:2:3:4:5:6:x", + // Test method with preferred style, adjacent : + "0:1:2:3:4:5:6::7", + // Too many : separators trailing + "0:1:2:3:4:5:6:7::", + // Too many : separators leading + "::0:1:2:3:4:5:6:7", + // Too many : separators trailing + "1:2:3:4:5:6:7:", + // Too many : separators leading + ":1:2:3:4:5:6:7", + // Compression with : separators trailing + "0:1:2:3:4:5::7:", + "0:1:2:3:4::7:", + "0:1:2:3::7:", + "0:1:2::7:", + "0:1::7:", + "0::7:", + // Compression at start with : separators trailing + "::0:1:2:3:4:5:7:", + "::0:1:2:3:4:7:", + "::0:1:2:3:7:", + "::0:1:2:7:", + "::0:1:7:", + "::7:", + // The : separators leading and trailing + ":1:2:3:4:5:6:7:", + ":1:2:3:4:5:6:", + ":1:2:3:4:5:", + ":1:2:3:4:", + ":1:2:3:", + ":1:2:", + ":1:", + // Compression with : separators leading + ":1::2:3:4:5:6:7", + ":1::3:4:5:6:7", + ":1::4:5:6:7", + ":1::5:6:7", + ":1::6:7", + ":1::7", + ":1:2:3:4:5:6::7", + ":1:3:4:5:6::7", + ":1:4:5:6::7", + ":1:5:6::7", + ":1:6::7", + ":1::", + // Compression trailing with : separators leading + ":1:2:3:4:5:6:7::", + ":1:3:4:5:6:7::", + ":1:4:5:6:7::", + ":1:5:6:7::", + ":1:6:7::", + ":1:7::", + // Double compression + "1::2:3:4:5:6::", + "::1:2:3:4:5::6", + "::1:2:3:4:5:6::", + "::1:2:3:4:5::", + "::1:2:3:4::", + "::1:2:3::", + "::1:2::", + "::0::", + "12::0::12", + // Too many : separators leading 0 + "0::1:2:3:4:5:6:7", + // Test method with preferred style, too many digits. + "0:1:2:3:4:5:6:789abcdef", + // Test method with compressed style, bad digits. + "0:1:2:3::x", + // Test method with compressed style, too many adjacent : + "0:1:2:::3", + // Test method with compressed style, too many digits. + "0:1:2:3::abcde", + // Test method with compressed style, not enough : + "0:1", + // Test method with ipv4 style, bad ipv6 digits. + "0:0:0:0:0:x:10.0.0.1", + // Test method with ipv4 style, bad ipv4 digits. + "0:0:0:0:0:0:10.0.0.x", + // Test method with ipv4 style, too many ipv6 digits. + "0:0:0:0:0:00000:10.0.0.1", + // Test method with ipv4 style, too many : + "0:0:0:0:0:0:0:10.0.0.1", + // Test method with ipv4 style, not enough : + "0:0:0:0:0:10.0.0.1", + // Test method with ipv4 style, too many . + "0:0:0:0:0:0:10.0.0.0.1", + // Test method with ipv4 style, not enough . + "0:0:0:0:0:0:10.0.1", + // Test method with ipv4 style, adjacent . + "0:0:0:0:0:0:10..0.0.1", + // Test method with ipv4 style, leading . + "0:0:0:0:0:0:.0.0.1", + // Test method with ipv4 style, leading . + "0:0:0:0:0:0:.10.0.0.1", + // Test method with ipv4 style, trailing . + "0:0:0:0:0:0:10.0.0.", + // Test method with ipv4 style, trailing . + "0:0:0:0:0:0:10.0.0.1.", + // Test method with compressed ipv4 style, bad ipv6 digits. + "::fffx:192.168.0.1", + // Test method with compressed ipv4 style, bad ipv4 digits. + "::ffff:192.168.0.x", + // Test method with compressed ipv4 style, too many adjacent : + ":::ffff:192.168.0.1", + // Test method with compressed ipv4 style, too many ipv6 digits. + "::fffff:192.168.0.1", + // Test method with compressed ipv4 style, too many ipv4 digits. + "::ffff:1923.168.0.1", + // Test method with compressed ipv4 style, not enough : + ":ffff:192.168.0.1", + // Test method with compressed ipv4 style, too many . + "::ffff:192.168.0.1.2", + // Test method with compressed ipv4 style, not enough . + "::ffff:192.168.0", + // Test method with compressed ipv4 style, adjacent . + "::ffff:192.168..0.1", + // Test method, bad ipv6 digits. + "x:0:0:0:0:0:10.0.0.1", + // Test method, bad ipv4 digits. + "0:0:0:0:0:0:x.0.0.1", + // Test method, too many ipv6 digits. + "00000:0:0:0:0:0:10.0.0.1", + // Test method, too many ipv4 digits. + "0:0:0:0:0:0:10.0.0.1000", + // Test method, too many : + "0:0:0:0:0:0:0:10.0.0.1", + // Test method, not enough : + "0:0:0:0:0:10.0.0.1", + // Test method, out of order trailing : + "0:0:0:0:0:10.0.0.1:", + // Test method, out of order leading : + ":0:0:0:0:0:10.0.0.1", + // Test method, out of order leading : + "0:0:0:0::10.0.0.1:", + // Test method, out of order trailing : + ":0:0:0:0::10.0.0.1", + // Test method, too many . + "0:0:0:0:0:0:10.0.0.0.1", + // Test method, not enough . + "0:0:0:0:0:0:10.0.1", + // Test method, adjacent . + "0:0:0:0:0:0:10.0.0..1", + // Empty contents + "", + // Invalid single compression + ":", + ":::", + // Trailing : (max number of : = 8) + "2001:0:4136:e378:8000:63bf:3fff:fdd2:", + // Leading : (max number of : = 8) + ":aaaa:bbbb:cccc:dddd:eeee:ffff:1111:2222", + // Invalid character + "1234:2345:3456:4567:5678:6789::X890", + // Trailing . in IPv4 + "::ffff:255.255.255.255.", + // To many characters in IPv4 + "::ffff:0.0.1111.0", + // Test method, adjacent . + "::ffff:0.0..0", + // Not enough IPv4 entries trailing . + "::ffff:127.0.0.", + // Invalid trailing IPv4 character + "::ffff:127.0.0.a", + // Invalid leading IPv4 character + "::ffff:a.0.0.1", + // Invalid middle IPv4 character + "::ffff:127.a.0.1", + // Invalid middle IPv4 character + "::ffff:127.0.a.1", + // Not enough IPv4 entries no trailing . + "::ffff:1.2.4", + // Extra IPv4 entry + "::ffff:192.168.0.1.255", + // Not enough IPv6 content + ":ffff:192.168.0.1.255", + // Intermixed IPv4 and IPv6 symbols + "::ffff:255.255:255.255.", + // Invalid IPv4 mapped address - invalid ipv4 separator + "0:0:0::0:0:00f.0.0.1", + // Invalid IPv4 mapped address - not enough f's + "0:0:0:0:0:fff:1.0.0.1", + // Invalid IPv4 mapped address - not IPv4 mapped, not IPv4 compatible + "0:0:0:0:0:ff00:1.0.0.1", + // Invalid IPv4 mapped address - not IPv4 mapped, not IPv4 compatible + "0:0:0:0:0:ff:1.0.0.1", + // Invalid IPv4 mapped address - too many f's + "0:0:0:0:0:fffff:1.0.0.1", + // Invalid IPv4 mapped address - too many bytes (too many 0's) + "0:0:0:0:0:0:ffff:1.0.0.1", + // Invalid IPv4 mapped address - too many bytes (too many 0's) + "::0:0:0:0:0:ffff:1.0.0.1", + // Invalid IPv4 mapped address - too many bytes (too many 0's) + "0:0:0:0:0:0::1.0.0.1", + // Invalid IPv4 mapped address - too many bytes (too many 0's) + "0:0:0:0:0:00000:1.0.0.1", + // Invalid IPv4 mapped address - too few bytes (not enough 0's) + "0:0:0:0:ffff:1.0.0.1", + // Invalid IPv4 mapped address - too few bytes (not enough 0's) + "ffff:192.168.0.1", + // Invalid IPv4 mapped address - 0's after the mapped ffff indicator + "0:0:0:0:0:ffff::10.0.0.1", + // Invalid IPv4 mapped address - 0's after the mapped ffff indicator + "0:0:0:0:ffff::10.0.0.1", + // Invalid IPv4 mapped address - 0's after the mapped ffff indicator + "0:0:0:ffff::10.0.0.1", + // Invalid IPv4 mapped address - 0's after the mapped ffff indicator + "0:0:ffff::10.0.0.1", + // Invalid IPv4 mapped address - 0's after the mapped ffff indicator + "0:ffff::10.0.0.1", + // Invalid IPv4 mapped address - 0's after the mapped ffff indicator + "ffff::10.0.0.1", + // Invalid IPv4 mapped address - not all 0's before the mapped separator + "1:0:0:0:0:ffff:10.0.0.1", + // Address that is similar to IPv4 mapped, but is invalid + "0:0:0:0:ffff:ffff:1.0.0.1", + // Valid number of separators, but invalid IPv4 format + "::1:2:3:4:5:6.7.8.9", + // Too many digits + "0:0:0:0:0:0:ffff:10.0.0.1", + // Invalid IPv4 format + ":1.2.3.4", + // Invalid IPv4 format + "::.2.3.4", + // Invalid IPv4 format + "::ffff:0.1.2."); + + @Test + void testIsValidIpV4Address() { + for (String host : validIpV4Hosts) { + assertTrue(isValidIpV4Address(host), host); + } + for (String host : invalidIpV4Hosts) { + assertFalse(isValidIpV4Address(host), host); + } + } + + @Test + void testIsValidIpV6Address() { + for (String host : validIpV6Hosts) { + assertTrue(isValidIpV6Address(host), host); + if (host.charAt(0) != '[' && !host.contains("%")) { + String hostMod = '[' + host + ']'; + assertTrue(isValidIpV6Address(hostMod), hostMod); + + hostMod = host + '%'; + assertTrue(isValidIpV6Address(hostMod), hostMod); + + hostMod = host + "%eth1"; + assertTrue(isValidIpV6Address(hostMod), hostMod); + + hostMod = '[' + host + "%]"; + assertTrue(isValidIpV6Address(hostMod), hostMod); + + hostMod = '[' + host + "%1]"; + assertTrue(isValidIpV6Address(hostMod), hostMod); + + hostMod = '[' + host + "]%"; + assertFalse(isValidIpV6Address(hostMod), hostMod); + + hostMod = '[' + host + "]%1"; + assertFalse(isValidIpV6Address(hostMod), hostMod); + } + } + for (String host : invalidIpV6Hosts) { + assertFalse(isValidIpV6Address(host), host); + + String hostMod = '[' + host + ']'; + assertFalse(isValidIpV6Address(hostMod), hostMod); + + hostMod = host + '%'; + assertFalse(isValidIpV6Address(hostMod), hostMod); + + hostMod = host + "%eth1"; + assertFalse(isValidIpV6Address(hostMod), hostMod); + + hostMod = '[' + host + "%]"; + assertFalse(isValidIpV6Address(hostMod), hostMod); + + hostMod = '[' + host + "%1]"; + assertFalse(isValidIpV6Address(hostMod), hostMod); + + hostMod = '[' + host + "]%"; + assertFalse(isValidIpV6Address(hostMod), hostMod); + + hostMod = '[' + host + "]%1"; + assertFalse(isValidIpV6Address(hostMod), hostMod); + + hostMod = host + ']'; + assertFalse(isValidIpV6Address(hostMod), hostMod); + + hostMod = '[' + host; + assertFalse(isValidIpV6Address(hostMod), hostMod); + } + } +} From 44ae20ae1c25d428f8c897a15ea33f5cb4d81f7e Mon Sep 17 00:00:00 2001 From: Scott Mitchell Date: Mon, 23 May 2022 07:21:52 -0700 Subject: [PATCH 23/40] CompletableConcatWithCompletablesTest.testSourceSuccessReentrant timeout (#2223) Motivation: This test intentionally runs a large number if iterations to ensure reentry doesn't OOME. However it may take longer to complete. Modifications: - Increase test timeout from default 10s to 30s. Result: Fixes https://github.com/apple/servicetalk/issues/1947 --- .../api/completable/CompletableConcatWithCompletablesTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/servicetalk-concurrent-api/src/test/java/io/servicetalk/concurrent/api/completable/CompletableConcatWithCompletablesTest.java b/servicetalk-concurrent-api/src/test/java/io/servicetalk/concurrent/api/completable/CompletableConcatWithCompletablesTest.java index 840516ab59..4c8002c4ec 100644 --- a/servicetalk-concurrent-api/src/test/java/io/servicetalk/concurrent/api/completable/CompletableConcatWithCompletablesTest.java +++ b/servicetalk-concurrent-api/src/test/java/io/servicetalk/concurrent/api/completable/CompletableConcatWithCompletablesTest.java @@ -23,6 +23,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.mockito.stubbing.Answer; @@ -86,6 +87,7 @@ void testSourceSuccessNextSuccess(int num) { @ParameterizedTest @ValueSource(ints = {1, 2, 10000}) + @Timeout(30) void testSourceSuccessReentrant(int num) { Completable[] mockCompletables = new Completable[num]; for (int i = 0; i < mockCompletables.length; ++i) { From b952931b2d97d4c8ea4331e118b658bd37a11e7b Mon Sep 17 00:00:00 2001 From: Thomas Kountis Date: Mon, 23 May 2022 14:46:19 -0700 Subject: [PATCH 24/40] Support Completable from a Callable (#2225) Motivation New Completable adapter from a Callable implementation. Modification New API to support this adaptor along with modification on the pre-existing fromRunnable to re-use this new Callable approach and minimize duplication. Result Richer API --- ...pletable.java => CallableCompletable.java} | 16 +++++++------ .../concurrent/api/Completable.java | 23 ++++++++++++++++++- .../BlockingStreamingToStreamingService.java | 13 +++++++---- 3 files changed, 40 insertions(+), 12 deletions(-) rename servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/{RunnableCompletable.java => CallableCompletable.java} (82%) diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/RunnableCompletable.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/CallableCompletable.java similarity index 82% rename from servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/RunnableCompletable.java rename to servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/CallableCompletable.java index b396b7ff8c..cb94698b0a 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/RunnableCompletable.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/CallableCompletable.java @@ -1,5 +1,5 @@ /* - * Copyright © 2019, 2021 Apple Inc. and the ServiceTalk project authors + * Copyright © 2019, 2021-2022 Apple Inc. and the ServiceTalk project authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,17 +17,19 @@ import io.servicetalk.concurrent.internal.ThreadInterruptingCancellable; +import java.util.concurrent.Callable; + import static io.servicetalk.concurrent.internal.SubscriberUtils.handleExceptionFromOnSubscribe; import static io.servicetalk.concurrent.internal.SubscriberUtils.safeOnComplete; import static io.servicetalk.concurrent.internal.SubscriberUtils.safeOnError; import static java.lang.Thread.currentThread; import static java.util.Objects.requireNonNull; -final class RunnableCompletable extends AbstractSynchronousCompletable { - private final Runnable runnable; +final class CallableCompletable extends AbstractSynchronousCompletable { + private final Callable callable; - RunnableCompletable(final Runnable runnable) { - this.runnable = requireNonNull(runnable); + CallableCompletable(final Callable callable) { + this.callable = requireNonNull(callable); } @Override @@ -41,14 +43,14 @@ void doSubscribe(final Subscriber subscriber) { } try { - runnable.run(); + callable.call(); } catch (Throwable cause) { cancellable.setDone(cause); safeOnError(subscriber, cause); return; } // It is safe to set this outside the scope of the try/catch above because we don't do any blocking - // operations which may be interrupted between the completion of the blockingHttpService call and + // operations which may be interrupted between the completion of the Callable call and // here. cancellable.setDone(); safeOnComplete(subscriber); diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/Completable.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/Completable.java index 41c506f93c..2637d02788 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/Completable.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/Completable.java @@ -25,6 +25,7 @@ import org.slf4j.LoggerFactory; import java.time.Duration; +import java.util.concurrent.Callable; import java.util.concurrent.CompletionStage; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; @@ -1793,7 +1794,27 @@ public static Completable completed() { * @return A new {@code Completable}. */ public static Completable fromRunnable(final Runnable runnable) { - return new RunnableCompletable(runnable); + return new CallableCompletable(() -> { + runnable.run(); + return null; + }); + } + + /** + * Creates a {@link Completable} which when subscribed will invoke {@link Callable#call()} on the passed + * {@link Callable} and emit the value returned by that invocation from the returned {@link Completable}. Any error + * emitted by the {@link Callable} will terminate the returned {@link Completable} with the same error. + *

+ * Blocking inside {@link Callable#call()} will in turn block the subscribe call to the returned + * {@link Completable}. + * If this behavior is undesirable then the returned {@link Completable} should be offloaded using + * {@link #subscribeOn(io.servicetalk.concurrent.Executor)} which offloads the subscribe call. + * + * @param callable {@link Callable} which is invoked before completion. + * @return A new {@code Completable}. + */ + public static Completable fromCallable(final Callable callable) { + return new CallableCompletable(callable); } /** diff --git a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/BlockingStreamingToStreamingService.java b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/BlockingStreamingToStreamingService.java index 856ee008f6..d4557806b2 100644 --- a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/BlockingStreamingToStreamingService.java +++ b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/BlockingStreamingToStreamingService.java @@ -1,5 +1,5 @@ /* - * Copyright © 2018-2019, 2021 Apple Inc. and the ServiceTalk project authors + * Copyright © 2018-2019, 2021-2022 Apple Inc. and the ServiceTalk project authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,7 +32,6 @@ import static io.servicetalk.concurrent.api.SourceAdapters.fromSource; import static io.servicetalk.concurrent.internal.SubscriberUtils.handleExceptionFromOnSubscribe; import static io.servicetalk.concurrent.internal.SubscriberUtils.safeOnError; -import static io.servicetalk.http.api.BlockingUtils.blockingToCompletable; import static io.servicetalk.http.api.DefaultHttpExecutionStrategy.OFFLOAD_RECEIVE_META_STRATEGY; import static io.servicetalk.http.api.DefaultPayloadInfo.forTransportReceive; import static io.servicetalk.http.api.HeaderUtils.hasContentLength; @@ -154,12 +153,18 @@ public void cancel() { @Override public Completable closeAsync() { - return blockingToCompletable(original::close); + return Completable.fromCallable(() -> { + original.close(); + return null; + }); } @Override public Completable closeAsyncGracefully() { - return blockingToCompletable(original::closeGracefully); + return Completable.fromCallable(() -> { + original.closeGracefully(); + return null; + }); } private static final class BufferHttpPayloadWriter implements HttpPayloadWriter { From ed9d36087cf5934b5dae6847870bb6cb37650bc6 Mon Sep 17 00:00:00 2001 From: Thomas Kountis Date: Mon, 23 May 2022 15:38:21 -0700 Subject: [PATCH 25/40] Shared BlockingUtils in concurrent api internal (#2185) Motivation: BlockingUtils offer useful functionality that could be used outside the http package. Modifications: Moved BlockingUtils to concurrent-api-internal Result: Shared utilities among modules. --- .../api/internal}/BlockingUtils.java | 65 ++++++++++--------- .../http/api/BlockingRequestUtils.java | 32 +++++++++ .../http/api/BlockingToStreamingService.java | 13 ++-- .../http/api/HttpServerBuilder.java | 2 +- ...reamingHttpClientToBlockingHttpClient.java | 6 +- ...tpClientToBlockingStreamingHttpClient.java | 2 +- ...ttpConnectionToBlockingHttpConnection.java | 2 +- ...tionToBlockingStreamingHttpConnection.java | 2 +- ...amingHttpServiceToBlockingHttpService.java | 2 +- ...ServiceToBlockingStreamingHttpService.java | 2 +- 10 files changed, 85 insertions(+), 43 deletions(-) rename {servicetalk-http-api/src/main/java/io/servicetalk/http/api => servicetalk-concurrent-api-internal/src/main/java/io/servicetalk/concurrent/api/internal}/BlockingUtils.java (54%) create mode 100644 servicetalk-http-api/src/main/java/io/servicetalk/http/api/BlockingRequestUtils.java diff --git a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/BlockingUtils.java b/servicetalk-concurrent-api-internal/src/main/java/io/servicetalk/concurrent/api/internal/BlockingUtils.java similarity index 54% rename from servicetalk-http-api/src/main/java/io/servicetalk/http/api/BlockingUtils.java rename to servicetalk-concurrent-api-internal/src/main/java/io/servicetalk/concurrent/api/internal/BlockingUtils.java index 7de99630b8..8cf982ae19 100644 --- a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/BlockingUtils.java +++ b/servicetalk-concurrent-api-internal/src/main/java/io/servicetalk/concurrent/api/internal/BlockingUtils.java @@ -1,5 +1,5 @@ /* - * Copyright © 2018 Apple Inc. and the ServiceTalk project authors + * Copyright © 2022 Apple Inc. and the ServiceTalk project authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.servicetalk.http.api; +package io.servicetalk.concurrent.api.internal; import io.servicetalk.concurrent.api.Completable; import io.servicetalk.concurrent.api.Single; @@ -21,32 +21,28 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; -import static io.servicetalk.concurrent.api.Completable.fromRunnable; import static io.servicetalk.utils.internal.PlatformDependent.throwException; -final class BlockingUtils { +/** + * Common utility functions to unwrap {@link ExecutionException} from async operations. + */ +public final class BlockingUtils { private BlockingUtils() { // no instances } - interface RunnableCheckedException { - void run() throws Exception; - - default void runUnchecked() { - try { - run(); - } catch (Exception e) { - throwException(e); - } - } - } - - static Completable blockingToCompletable(RunnableCheckedException r) { - return fromRunnable(r::runUnchecked); - } - - static T futureGetCancelOnInterrupt(Future future) throws Exception { + /** + * Completes a {@link Future} by invoking {@link Future#get()}. + * Any occurred {@link Exception} will be converted to unchecked, and {@link ExecutionException}s will be unwrapped. + * Upon interruption, the {@link Future} is cancelled. + * + * @param future The future to operate on. + * @param The type of the result. + * @return The result of the future. + * @throws Exception InterrupedException upon interruption or unchecked exceptions for any other exception. + */ + public static T futureGetCancelOnInterrupt(Future future) throws Exception { try { return future.get(); } catch (InterruptedException e) { @@ -58,14 +54,16 @@ static T futureGetCancelOnInterrupt(Future future) throws Exception { } } - static HttpResponse request(final StreamingHttpRequester requester, final HttpRequest request) throws Exception { - // It is assumed that users will always apply timeouts at the StreamingHttpService layer (e.g. via filter). So - // we don't apply any explicit timeout here and just wait forever. - return blockingInvocation(requester.request(request.toStreamingRequest()) - .flatMap(response -> response.toResponse().shareContextOnSubscribe())); - } - - static T blockingInvocation(Single source) throws Exception { + /** + * Subscribes a {@link Single} immediately and awaits result. + * Any occurred {@link Exception} will be converted to unchecked, and {@link ExecutionException}s will be unwrapped. + * + * @param source The {@link Single} to operate on. + * @param The type of the result. + * @return The result of the single. + * @throws Exception InterrupedException upon interruption or unchecked exceptions for any other exception. + */ + public static T blockingInvocation(Single source) throws Exception { // It is assumed that users will always apply timeouts at the StreamingHttpService layer (e.g. via filter). So // we don't apply any explicit timeout here and just wait forever. try { @@ -75,7 +73,14 @@ static T blockingInvocation(Single source) throws Exception { } } - static void blockingInvocation(Completable source) throws Exception { + /** + * Subscribes a {@link Completable} immediately and awaits result. + * Any occurred {@link Exception} will be converted to unchecked, and {@link ExecutionException}s will be unwrapped. + * + * @param source The {@link Completable} to operate on. + * @throws Exception unchecked exceptions for any exception that occurs. + */ + public static void blockingInvocation(Completable source) throws Exception { // It is assumed that users will always apply timeouts at the StreamingHttpService layer (e.g. via filter). So // we don't apply any explicit timeout here and just wait forever. try { diff --git a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/BlockingRequestUtils.java b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/BlockingRequestUtils.java new file mode 100644 index 0000000000..55179cb75c --- /dev/null +++ b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/BlockingRequestUtils.java @@ -0,0 +1,32 @@ +/* + * Copyright © 2018, 2022 Apple Inc. and the ServiceTalk project authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.servicetalk.http.api; + +import static io.servicetalk.concurrent.api.internal.BlockingUtils.blockingInvocation; + +final class BlockingRequestUtils { + + private BlockingRequestUtils() { + // no instances + } + + static HttpResponse request(final StreamingHttpRequester requester, final HttpRequest request) throws Exception { + // It is assumed that users will always apply timeouts at the StreamingHttpService layer (e.g. via filter). So + // we don't apply any explicit timeout here and just wait forever. + return blockingInvocation(requester.request(request.toStreamingRequest()) + .flatMap(response -> response.toResponse().shareContextOnSubscribe())); + } +} diff --git a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/BlockingToStreamingService.java b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/BlockingToStreamingService.java index 78f2d66e57..05fcbfe53e 100644 --- a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/BlockingToStreamingService.java +++ b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/BlockingToStreamingService.java @@ -1,5 +1,5 @@ /* - * Copyright © 2018 Apple Inc. and the ServiceTalk project authors + * Copyright © 2018, 2022 Apple Inc. and the ServiceTalk project authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,6 @@ import io.servicetalk.concurrent.api.Single; import static io.servicetalk.concurrent.api.Single.fromCallable; -import static io.servicetalk.http.api.BlockingUtils.blockingToCompletable; import static io.servicetalk.http.api.DefaultHttpExecutionStrategy.OFFLOAD_RECEIVE_DATA_STRATEGY; import static io.servicetalk.http.api.HttpExecutionStrategies.defaultStrategy; import static java.util.Objects.requireNonNull; @@ -43,11 +42,17 @@ public Single handle(final HttpServiceContext ctx, @Override public Completable closeAsync() { - return blockingToCompletable(original::close); + return Completable.fromCallable(() -> { + original.close(); + return null; + }); } @Override public Completable closeAsyncGracefully() { - return blockingToCompletable(original::closeGracefully); + return Completable.fromCallable(() -> { + original.closeGracefully(); + return null; + }); } } diff --git a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/HttpServerBuilder.java b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/HttpServerBuilder.java index 5848a140cc..d43ac554dc 100644 --- a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/HttpServerBuilder.java +++ b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/HttpServerBuilder.java @@ -35,7 +35,7 @@ import java.util.function.BooleanSupplier; import java.util.function.Predicate; -import static io.servicetalk.http.api.BlockingUtils.blockingInvocation; +import static io.servicetalk.concurrent.api.internal.BlockingUtils.blockingInvocation; /** * A builder for building HTTP Servers. diff --git a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/StreamingHttpClientToBlockingHttpClient.java b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/StreamingHttpClientToBlockingHttpClient.java index b670ed8c8a..dce3340fa8 100644 --- a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/StreamingHttpClientToBlockingHttpClient.java +++ b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/StreamingHttpClientToBlockingHttpClient.java @@ -17,7 +17,7 @@ import io.servicetalk.concurrent.BlockingIterable; -import static io.servicetalk.http.api.BlockingUtils.blockingInvocation; +import static io.servicetalk.concurrent.api.internal.BlockingUtils.blockingInvocation; import static io.servicetalk.http.api.HttpContextKeys.HTTP_EXECUTION_STRATEGY_KEY; import static io.servicetalk.http.api.HttpExecutionStrategies.defaultStrategy; import static io.servicetalk.http.api.RequestResponseFactories.toAggregated; @@ -59,7 +59,7 @@ public StreamingHttpClient asStreamingClient() { @Override public HttpResponse request(final HttpRequest request) throws Exception { request.context().putIfAbsent(HTTP_EXECUTION_STRATEGY_KEY, strategy); - return BlockingUtils.request(client, request); + return BlockingRequestUtils.request(client, request); } @Override @@ -146,7 +146,7 @@ public BlockingIterable transportEventIterable(final HttpEventK @Override public HttpResponse request(final HttpRequest request) throws Exception { - return BlockingUtils.request(connection, request); + return BlockingRequestUtils.request(connection, request); } @Override diff --git a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/StreamingHttpClientToBlockingStreamingHttpClient.java b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/StreamingHttpClientToBlockingStreamingHttpClient.java index a55b971893..7841b60032 100644 --- a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/StreamingHttpClientToBlockingStreamingHttpClient.java +++ b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/StreamingHttpClientToBlockingStreamingHttpClient.java @@ -17,7 +17,7 @@ import io.servicetalk.concurrent.BlockingIterable; -import static io.servicetalk.http.api.BlockingUtils.blockingInvocation; +import static io.servicetalk.concurrent.api.internal.BlockingUtils.blockingInvocation; import static io.servicetalk.http.api.HttpContextKeys.HTTP_EXECUTION_STRATEGY_KEY; import static io.servicetalk.http.api.HttpExecutionStrategies.defaultStrategy; import static io.servicetalk.http.api.RequestResponseFactories.toBlockingStreaming; diff --git a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/StreamingHttpConnectionToBlockingHttpConnection.java b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/StreamingHttpConnectionToBlockingHttpConnection.java index 8156283d55..d50fb5e704 100644 --- a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/StreamingHttpConnectionToBlockingHttpConnection.java +++ b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/StreamingHttpConnectionToBlockingHttpConnection.java @@ -66,7 +66,7 @@ public StreamingHttpConnection asStreamingConnection() { @Override public HttpResponse request(final HttpRequest request) throws Exception { - return BlockingUtils.request(connection, request); + return BlockingRequestUtils.request(connection, request); } @Override diff --git a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/StreamingHttpConnectionToBlockingStreamingHttpConnection.java b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/StreamingHttpConnectionToBlockingStreamingHttpConnection.java index 5642affa1f..6733846bed 100644 --- a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/StreamingHttpConnectionToBlockingStreamingHttpConnection.java +++ b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/StreamingHttpConnectionToBlockingStreamingHttpConnection.java @@ -17,7 +17,7 @@ import io.servicetalk.concurrent.BlockingIterable; -import static io.servicetalk.http.api.BlockingUtils.blockingInvocation; +import static io.servicetalk.concurrent.api.internal.BlockingUtils.blockingInvocation; import static io.servicetalk.http.api.DefaultHttpExecutionStrategy.OFFLOAD_SEND_EVENT_STRATEGY; import static io.servicetalk.http.api.HttpExecutionStrategies.defaultStrategy; import static io.servicetalk.http.api.RequestResponseFactories.toBlockingStreaming; diff --git a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/StreamingHttpServiceToBlockingHttpService.java b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/StreamingHttpServiceToBlockingHttpService.java index e1c60442f3..e83f890059 100644 --- a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/StreamingHttpServiceToBlockingHttpService.java +++ b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/StreamingHttpServiceToBlockingHttpService.java @@ -15,7 +15,7 @@ */ package io.servicetalk.http.api; -import static io.servicetalk.http.api.BlockingUtils.futureGetCancelOnInterrupt; +import static io.servicetalk.concurrent.api.internal.BlockingUtils.futureGetCancelOnInterrupt; import static java.util.Objects.requireNonNull; final class StreamingHttpServiceToBlockingHttpService implements BlockingHttpService { diff --git a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/StreamingHttpServiceToBlockingStreamingHttpService.java b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/StreamingHttpServiceToBlockingStreamingHttpService.java index 6653277d93..addeade44f 100644 --- a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/StreamingHttpServiceToBlockingStreamingHttpService.java +++ b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/StreamingHttpServiceToBlockingStreamingHttpService.java @@ -29,7 +29,7 @@ import javax.annotation.Nullable; import static io.servicetalk.concurrent.api.SourceAdapters.toSource; -import static io.servicetalk.http.api.BlockingUtils.futureGetCancelOnInterrupt; +import static io.servicetalk.concurrent.api.internal.BlockingUtils.futureGetCancelOnInterrupt; import static io.servicetalk.utils.internal.PlatformDependent.throwException; import static java.util.Objects.requireNonNull; From cda273e02b3e4768a4b9cb77292f100b3f5adacf Mon Sep 17 00:00:00 2001 From: Mike Duigou Date: Tue, 24 May 2022 10:48:57 -0700 Subject: [PATCH 26/40] Use `servicetalk-dependencies` for tests (#2219) Motivation: Some of the dependencies imported for tests can use the `servicetalk-dependencies` BOM introduced in #2210. Modifications: Import `servicetalk-dependencies` for test configurations Result: Better management of test dependencies. --- servicetalk-concurrent-api/build.gradle | 10 ++++++---- servicetalk-concurrent-internal/build.gradle | 5 +++-- servicetalk-concurrent-reactivestreams/build.gradle | 2 +- servicetalk-http-api/build.gradle | 3 ++- servicetalk-http-netty/build.gradle | 3 ++- servicetalk-http-router-jersey/build.gradle | 2 +- servicetalk-log4j2-mdc-utils/build.gradle | 9 +++++---- servicetalk-opentracing-asynccontext/build.gradle | 5 +++-- servicetalk-opentracing-http/build.gradle | 6 ++++-- servicetalk-opentracing-log4j2/build.gradle | 7 ++++--- servicetalk-serializer-utils/build.gradle | 4 ++-- servicetalk-tcp-netty-internal/build.gradle | 8 ++++---- servicetalk-transport-netty-internal/build.gradle | 3 ++- 13 files changed, 39 insertions(+), 28 deletions(-) diff --git a/servicetalk-concurrent-api/build.gradle b/servicetalk-concurrent-api/build.gradle index 9a50545254..73ea04c318 100644 --- a/servicetalk-concurrent-api/build.gradle +++ b/servicetalk-concurrent-api/build.gradle @@ -18,7 +18,9 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { api platform(project(":servicetalk-dependencies")) + testImplementation enforcedPlatform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") + testFixturesImplementation platform(project(":servicetalk-dependencies")) testFixturesImplementation platform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-concurrent") @@ -35,15 +37,15 @@ dependencies { testImplementation project(":servicetalk-test-resources") testImplementation "org.junit.jupiter:junit-jupiter-api" testImplementation "org.junit.jupiter:junit-jupiter-params" - testImplementation "org.hamcrest:hamcrest:$hamcrestVersion" + testImplementation "org.hamcrest:hamcrest" testImplementation "org.mockito:mockito-core:$mockitoCoreVersion" testFixturesImplementation testFixtures(project(":servicetalk-concurrent-internal")) testFixturesImplementation project(":servicetalk-utils-internal") testFixturesImplementation project(":servicetalk-concurrent-test-internal") - testFixturesImplementation "com.google.code.findbugs:jsr305:$jsr305Version" + testFixturesImplementation "com.google.code.findbugs:jsr305" testFixturesImplementation "org.junit.jupiter:junit-jupiter-api" - testFixturesImplementation "org.hamcrest:hamcrest:$hamcrestVersion" + testFixturesImplementation "org.hamcrest:hamcrest" testFixturesImplementation "org.mockito:mockito-core:$mockitoCoreVersion" - testFixturesImplementation "org.slf4j:slf4j-api:$slf4jVersion" + testFixturesImplementation "org.slf4j:slf4j-api" } diff --git a/servicetalk-concurrent-internal/build.gradle b/servicetalk-concurrent-internal/build.gradle index 2dc39ba8d4..e558b9c576 100644 --- a/servicetalk-concurrent-internal/build.gradle +++ b/servicetalk-concurrent-internal/build.gradle @@ -19,6 +19,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { implementation platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") + testFixturesImplementation platform(project(":servicetalk-dependencies")) testFixturesImplementation platform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-concurrent") @@ -36,6 +37,6 @@ dependencies { testFixturesImplementation project(":servicetalk-annotations") testFixturesImplementation "org.junit.jupiter:junit-jupiter-api" - testFixturesImplementation "com.google.code.findbugs:jsr305:$jsr305Version" - testFixturesImplementation "org.slf4j:slf4j-api:$slf4jVersion" + testFixturesImplementation "com.google.code.findbugs:jsr305" + testFixturesImplementation "org.slf4j:slf4j-api" } diff --git a/servicetalk-concurrent-reactivestreams/build.gradle b/servicetalk-concurrent-reactivestreams/build.gradle index 09a2ba698a..4b01051596 100644 --- a/servicetalk-concurrent-reactivestreams/build.gradle +++ b/servicetalk-concurrent-reactivestreams/build.gradle @@ -21,7 +21,7 @@ dependencies { testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-concurrent-api") - api "org.reactivestreams:reactive-streams:$reactiveStreamsVersion" + api "org.reactivestreams:reactive-streams" implementation project(":servicetalk-annotations") implementation project(":servicetalk-serializer-utils") diff --git a/servicetalk-http-api/build.gradle b/servicetalk-http-api/build.gradle index 6614ee67c2..463ce8bd5b 100644 --- a/servicetalk-http-api/build.gradle +++ b/servicetalk-http-api/build.gradle @@ -19,6 +19,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { implementation platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") + testFixturesImplementation platform(project(":servicetalk-dependencies")) testFixturesImplementation platform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-buffer-api") @@ -59,7 +60,7 @@ dependencies { testFixturesImplementation testFixtures(project(":servicetalk-concurrent-internal")) testFixturesImplementation testFixtures(project(":servicetalk-transport-netty-internal")) testFixturesImplementation project(":servicetalk-buffer-netty") - testFixturesImplementation "com.google.code.findbugs:jsr305:$jsr305Version" + testFixturesImplementation "com.google.code.findbugs:jsr305" testFixturesImplementation "org.junit.jupiter:junit-jupiter-api" testFixturesImplementation "org.junit.jupiter:junit-jupiter-params" testFixturesImplementation "org.hamcrest:hamcrest:$hamcrestVersion" diff --git a/servicetalk-http-netty/build.gradle b/servicetalk-http-netty/build.gradle index 4021f2b881..df0ca3b80a 100644 --- a/servicetalk-http-netty/build.gradle +++ b/servicetalk-http-netty/build.gradle @@ -18,8 +18,9 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { implementation platform(project(":servicetalk-dependencies")) - implementation platform("io.netty:netty-bom:$nettyVersion") + testImplementation enforcedPlatform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") + testFixturesImplementation platform(project(":servicetalk-dependencies")) api project(":servicetalk-concurrent-api") api project(":servicetalk-logging-api") diff --git a/servicetalk-http-router-jersey/build.gradle b/servicetalk-http-router-jersey/build.gradle index 0012a162d7..7b4f7cdff3 100644 --- a/servicetalk-http-router-jersey/build.gradle +++ b/servicetalk-http-router-jersey/build.gradle @@ -18,8 +18,8 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { api platform(project(":servicetalk-dependencies")) - testFixturesImplementation platform("org.glassfish.jersey:jersey-bom:$jerseyVersion") testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") + testFixturesImplementation platform(project(":servicetalk-dependencies")) testFixturesImplementation platform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-http-api") diff --git a/servicetalk-log4j2-mdc-utils/build.gradle b/servicetalk-log4j2-mdc-utils/build.gradle index b081399464..8a9e22b48a 100644 --- a/servicetalk-log4j2-mdc-utils/build.gradle +++ b/servicetalk-log4j2-mdc-utils/build.gradle @@ -18,8 +18,9 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { api platform(project(":servicetalk-dependencies")) + testImplementation enforcedPlatform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") - testFixturesImplementation enforcedPlatform(project(":servicetalk-dependencies")) + testFixturesImplementation platform(project(":servicetalk-dependencies")) api "org.apache.logging.log4j:log4j-api" @@ -31,13 +32,13 @@ dependencies { testImplementation project(":servicetalk-test-resources") testImplementation "org.junit.jupiter:junit-jupiter-api" - testImplementation "org.slf4j:slf4j-api:$slf4jVersion" - testImplementation "org.hamcrest:hamcrest:$hamcrestVersion" + testImplementation "org.slf4j:slf4j-api" + testImplementation "org.hamcrest:hamcrest" testFixturesImplementation "com.google.code.findbugs:jsr305" testFixturesImplementation "org.apache.logging.log4j:log4j-core" testFixturesImplementation "org.hamcrest:hamcrest" - testFixturesImplementation "org.slf4j:slf4j-api:$slf4jVersion" + testFixturesImplementation "org.slf4j:slf4j-api" testFixturesRuntimeOnly "org.apache.logging.log4j:log4j-slf4j-impl" } diff --git a/servicetalk-opentracing-asynccontext/build.gradle b/servicetalk-opentracing-asynccontext/build.gradle index 3357b860fc..69164a62e3 100644 --- a/servicetalk-opentracing-asynccontext/build.gradle +++ b/servicetalk-opentracing-asynccontext/build.gradle @@ -18,6 +18,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { implementation platform(project(":servicetalk-dependencies")) + testImplementation enforcedPlatform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-opentracing-inmemory") @@ -28,8 +29,8 @@ dependencies { testImplementation project(":servicetalk-test-resources") testImplementation "org.junit.jupiter:junit-jupiter-api" - testImplementation "org.slf4j:slf4j-api:$slf4jVersion" - testImplementation "org.hamcrest:hamcrest:$hamcrestVersion" + testImplementation "org.slf4j:slf4j-api" + testImplementation "org.hamcrest:hamcrest" testImplementation "org.mockito:mockito-core:$mockitoCoreVersion" testImplementation "org.mockito:mockito-junit-jupiter:$mockitoCoreVersion" } diff --git a/servicetalk-opentracing-http/build.gradle b/servicetalk-opentracing-http/build.gradle index 31372283c5..58485c2bda 100644 --- a/servicetalk-opentracing-http/build.gradle +++ b/servicetalk-opentracing-http/build.gradle @@ -18,7 +18,9 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { api platform(project(":servicetalk-dependencies")) + testImplementation enforcedPlatform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") + testRuntimeOnly enforcedPlatform(project(":servicetalk-dependencies")) api project(":servicetalk-http-api") api "io.opentracing:opentracing-api" @@ -42,10 +44,10 @@ dependencies { testImplementation project(":servicetalk-opentracing-asynccontext") testImplementation project(":servicetalk-test-resources") testImplementation project(":servicetalk-opentracing-log4j2") - testImplementation "org.apache.logging.log4j:log4j-core:$log4jVersion" + testImplementation "org.apache.logging.log4j:log4j-core" testImplementation "org.hamcrest:hamcrest:$hamcrestVersion" testImplementation "org.junit.jupiter:junit-jupiter-api" testImplementation "org.mockito:mockito-core:$mockitoCoreVersion" testImplementation "org.mockito:mockito-junit-jupiter:$mockitoCoreVersion" - testRuntimeOnly "org.apache.logging.log4j:log4j-slf4j-impl:$log4jVersion" + testRuntimeOnly "org.apache.logging.log4j:log4j-slf4j-impl" } diff --git a/servicetalk-opentracing-log4j2/build.gradle b/servicetalk-opentracing-log4j2/build.gradle index 7ceb58188e..cef8c640ff 100644 --- a/servicetalk-opentracing-log4j2/build.gradle +++ b/servicetalk-opentracing-log4j2/build.gradle @@ -18,6 +18,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { implementation platform(project(":servicetalk-dependencies")) + testImplementation enforcedPlatform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-log4j2-mdc-utils") @@ -33,7 +34,7 @@ dependencies { testImplementation testFixtures(project(":servicetalk-log4j2-mdc-utils")) testImplementation "org.junit.jupiter:junit-jupiter-api" - testImplementation "org.hamcrest:hamcrest:$hamcrestVersion" - testImplementation "org.apache.logging.log4j:log4j-slf4j-impl:$log4jVersion" - testImplementation "org.apache.logging.log4j:log4j-core:$log4jVersion" + testImplementation "org.hamcrest:hamcrest" + testImplementation "org.apache.logging.log4j:log4j-core" + testImplementation "org.apache.logging.log4j:log4j-slf4j-impl" } diff --git a/servicetalk-serializer-utils/build.gradle b/servicetalk-serializer-utils/build.gradle index 24172e2550..eb6822f79d 100644 --- a/servicetalk-serializer-utils/build.gradle +++ b/servicetalk-serializer-utils/build.gradle @@ -32,9 +32,9 @@ dependencies { testImplementation testFixtures(project(":servicetalk-concurrent-internal")) testImplementation project(":servicetalk-concurrent-test-internal") testImplementation project(":servicetalk-buffer-netty") - testImplementation "com.google.protobuf:protobuf-java:$protobufVersion" + testImplementation "com.google.protobuf:protobuf-java" testImplementation "org.junit.jupiter:junit-jupiter-api" testImplementation "org.junit.jupiter:junit-jupiter-params" - testImplementation "org.hamcrest:hamcrest:$hamcrestVersion" + testImplementation "org.hamcrest:hamcrest" testImplementation "org.mockito:mockito-core:$mockitoCoreVersion" } diff --git a/servicetalk-tcp-netty-internal/build.gradle b/servicetalk-tcp-netty-internal/build.gradle index 45b107e7fe..04203d6276 100644 --- a/servicetalk-tcp-netty-internal/build.gradle +++ b/servicetalk-tcp-netty-internal/build.gradle @@ -19,9 +19,9 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { implementation platform(project(":servicetalk-dependencies")) - testImplementation enforcedPlatform("io.netty:netty-bom:$nettyVersion") + testImplementation enforcedPlatform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") - testFixturesImplementation platform("io.netty:netty-bom:$nettyVersion") + testFixturesImplementation platform(project(":servicetalk-dependencies")) testFixturesImplementation platform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-client-api") @@ -48,7 +48,7 @@ dependencies { testFixturesImplementation testFixtures(project(":servicetalk-concurrent-api")) testFixturesImplementation testFixtures(project(":servicetalk-transport-netty-internal")) - testFixturesImplementation "com.google.code.findbugs:jsr305:$jsr305Version" + testFixturesImplementation "com.google.code.findbugs:jsr305" testFixturesImplementation "io.netty:netty-transport-native-epoll" testFixturesRuntimeOnly( group:"io.netty", name:"netty-transport-native-epoll", classifier:"linux-x86_64") testFixturesRuntimeOnly( group:"io.netty", name:"netty-transport-native-epoll", classifier:"linux-aarch_64") @@ -58,5 +58,5 @@ dependencies { testFixturesImplementation "org.junit.jupiter:junit-jupiter-api" testFixturesImplementation "org.hamcrest:hamcrest:$hamcrestVersion" testFixturesImplementation "org.mockito:mockito-core:$mockitoCoreVersion" - testFixturesImplementation "org.slf4j:slf4j-api:$slf4jVersion" + testFixturesImplementation "org.slf4j:slf4j-api" } diff --git a/servicetalk-transport-netty-internal/build.gradle b/servicetalk-transport-netty-internal/build.gradle index b1a109c789..284d2647fe 100644 --- a/servicetalk-transport-netty-internal/build.gradle +++ b/servicetalk-transport-netty-internal/build.gradle @@ -19,6 +19,7 @@ apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library" dependencies { api platform(project(":servicetalk-dependencies")) testImplementation enforcedPlatform("org.junit:junit-bom:$junit5Version") + testFixturesImplementation platform(project(":servicetalk-dependencies")) testFixturesImplementation platform("org.junit:junit-bom:$junit5Version") api project(":servicetalk-buffer-netty") @@ -61,7 +62,7 @@ dependencies { testFixturesImplementation project(":servicetalk-utils-internal") testFixturesImplementation "io.netty.incubator:netty-incubator-transport-native-io_uring:$nettyIoUringVersion" - testFixturesImplementation "com.google.code.findbugs:jsr305:$jsr305Version" + testFixturesImplementation "com.google.code.findbugs:jsr305" testFixturesImplementation "org.junit.jupiter:junit-jupiter-api" testFixturesImplementation "org.hamcrest:hamcrest:$hamcrestVersion" testFixturesImplementation "org.mockito:mockito-core:$mockitoCoreVersion" From 83fd27c34595718a11785f9de156ed6fb3f1ed2a Mon Sep 17 00:00:00 2001 From: Scott Mitchell Date: Thu, 26 May 2022 21:04:09 -0700 Subject: [PATCH 27/40] Update spotbugs 4.6.0 -> 4.7.0 (#2222) --- .../gradle/spotbugs/test-exclusions.xml | 26 ++ .../gradle/spotbugs/test-exclusions.xml | 22 ++ .../gradle/spotbugs/test-exclusions.xml | 8 + .../gradle/spotbugs/main-exclusions.xml | 26 ++ .../gradle/spotbugs/test-exclusions.xml | 12 + .../gradle/spotbugs/main-exclusions.xml | 26 ++ .../gradle/spotbugs/test-exclusions.xml | 22 ++ .../gradle/spotbugs/main-exclusions.xml | 41 ++++ .../gradle/spotbugs/test-exclusions.xml | 12 + .../spotbugs/testFixtures-exclusions.xml | 5 + .../concurrent/api/CopyOnWriteContextMap.java | 4 +- .../api/CopyOnWriteExecutorPluginSet.java | 2 +- .../concurrent/api/TestCompletableTest.java | 2 +- .../concurrent/api/TestPublisherTest.java | 2 +- .../concurrent/api/TestSingleTest.java | 2 +- .../concurrent/api/TestCompletable.java | 4 +- .../concurrent/api/TestPublisher.java | 4 +- .../concurrent/api/TestSingle.java | 2 +- .../gradle/spotbugs/main-exclusions.xml | 31 +++ .../gradle/spotbugs/test-exclusions.xml | 4 + .../gradle/spotbugs/test-exclusions.xml | 26 ++ .../gradle/spotbugs/test-exclusions.xml | 26 ++ .../gradle/spotbugs/test-exclusions.xml | 22 ++ .../gradle/spotbugs/main-exclusions.xml | 28 +++ .../gradle/spotbugs/test-exclusions.xml | 26 ++ .../gradle/spotbugs/test-exclusions.xml | 4 + .../gradle/spotbugs/test-exclusions.xml | 8 + .../gradle/spotbugs/test-exclusions.xml | 8 + .../gradle/spotbugs/main-exclusions.xml | 15 ++ .../gradle/spotbugs/test-exclusions.xml | 12 + .../dns/discovery/netty/TestDnsServer.java | 2 +- .../gradle/spotbugs/test-exclusions.xml | 26 ++ .../gradle/plugin/internal/Versions.groovy | 2 +- .../gradle/spotbugs/main-exclusions.xml | 66 ++++- .../gradle/spotbugs/test-exclusions.xml | 26 ++ .../gradle/spotbugs/main-exclusions.xml | 23 ++ .../gradle/spotbugs/test-exclusions.xml | 23 ++ .../{GrpcOverH1.java => GrpcOverH1Test.java} | 2 +- .../gradle/spotbugs/main-exclusions.xml | 227 +++++++++++++++++- .../gradle/spotbugs/test-exclusions.xml | 8 + .../spotbugs/testFixtures-exclusions.xml | 8 + .../gradle/spotbugs/main-exclusions.xml | 79 +++++- .../gradle/spotbugs/test-exclusions.xml | 16 ++ .../spotbugs/testFixtures-exclusions.xml | 22 ++ .../gradle/spotbugs/main-exclusions.xml | 6 + .../spotbugs/testFixtures-exclusions.xml | 15 ++ .../gradle/spotbugs/test-exclusions.xml | 8 + .../gradle/spotbugs/test-exclusions.xml | 4 + .../gradle/spotbugs/test-exclusions.xml | 8 + .../gradle/spotbugs/test-exclusions.xml | 12 + .../gradle/spotbugs/test-exclusions.xml | 22 ++ .../gradle/spotbugs/test-exclusions.xml | 8 + .../gradle/spotbugs/main-exclusions.xml | 23 ++ .../gradle/spotbugs/main-exclusions.xml | 27 +++ .../gradle/spotbugs/test-exclusions.xml | 4 + .../gradle/spotbugs/main-exclusions.xml | 6 + .../gradle/spotbugs/test-exclusions.xml | 8 + .../gradle/spotbugs/main-exclusions.xml | 10 +- .../gradle/spotbugs/test-exclusions.xml | 11 + .../gradle/spotbugs/test-exclusions.xml | 26 ++ .../gradle/spotbugs/main-exclusions.xml | 11 + .../gradle/spotbugs/test-exclusions.xml | 12 + .../spotbugs/testFixtures-exclusions.xml | 23 ++ .../gradle/spotbugs/test-exclusions.xml | 22 ++ .../gradle/spotbugs/main-exclusions.xml | 26 ++ .../gradle/spotbugs/test-exclusions.xml | 4 + .../gradle/spotbugs/main-exclusions.xml | 50 ++++ .../gradle/spotbugs/test-exclusions.xml | 8 + .../spotbugs/testFixtures-exclusions.xml | 12 + .../gradle/spotbugs/main-exclusions.xml | 18 ++ .../gradle/spotbugs/test-exclusions.xml | 4 + 71 files changed, 1331 insertions(+), 19 deletions(-) create mode 100644 servicetalk-buffer-api/gradle/spotbugs/test-exclusions.xml create mode 100644 servicetalk-client-api-internal/gradle/spotbugs/test-exclusions.xml create mode 100644 servicetalk-concurrent-api-internal/gradle/spotbugs/main-exclusions.xml create mode 100644 servicetalk-concurrent-api-test/gradle/spotbugs/main-exclusions.xml create mode 100644 servicetalk-concurrent-api-test/gradle/spotbugs/test-exclusions.xml create mode 100644 servicetalk-concurrent-jdkflow/gradle/spotbugs/test-exclusions.xml create mode 100644 servicetalk-concurrent-reactivestreams/gradle/spotbugs/test-exclusions.xml create mode 100644 servicetalk-concurrent-test-internal/gradle/spotbugs/test-exclusions.xml create mode 100644 servicetalk-concurrent/gradle/spotbugs/main-exclusions.xml create mode 100644 servicetalk-data-jackson-jersey/gradle/spotbugs/test-exclusions.xml create mode 100644 servicetalk-encoding-netty/gradle/spotbugs/test-exclusions.xml create mode 100644 servicetalk-grpc-health/gradle/spotbugs/test-exclusions.xml create mode 100644 servicetalk-grpc-netty/gradle/spotbugs/main-exclusions.xml rename servicetalk-grpc-netty/src/test/java/io/servicetalk/grpc/netty/{GrpcOverH1.java => GrpcOverH1Test.java} (99%) create mode 100644 servicetalk-http-netty/gradle/spotbugs/testFixtures-exclusions.xml create mode 100644 servicetalk-log4j2-mdc-utils/gradle/spotbugs/test-exclusions.xml create mode 100644 servicetalk-opentracing-inmemory-api/gradle/spotbugs/main-exclusions.xml create mode 100644 servicetalk-opentracing-inmemory/gradle/spotbugs/main-exclusions.xml create mode 100644 servicetalk-serializer-utils/gradle/spotbugs/test-exclusions.xml create mode 100644 servicetalk-tcp-netty-internal/gradle/spotbugs/testFixtures-exclusions.xml create mode 100644 servicetalk-test-resources/gradle/spotbugs/test-exclusions.xml create mode 100644 servicetalk-transport-api/gradle/spotbugs/main-exclusions.xml diff --git a/servicetalk-buffer-api/gradle/spotbugs/test-exclusions.xml b/servicetalk-buffer-api/gradle/spotbugs/test-exclusions.xml new file mode 100644 index 0000000000..500404e766 --- /dev/null +++ b/servicetalk-buffer-api/gradle/spotbugs/test-exclusions.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + diff --git a/servicetalk-client-api-internal/gradle/spotbugs/test-exclusions.xml b/servicetalk-client-api-internal/gradle/spotbugs/test-exclusions.xml new file mode 100644 index 0000000000..e88990d20f --- /dev/null +++ b/servicetalk-client-api-internal/gradle/spotbugs/test-exclusions.xml @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/servicetalk-client-api/gradle/spotbugs/test-exclusions.xml b/servicetalk-client-api/gradle/spotbugs/test-exclusions.xml index a10553e0a3..8bd196c0d1 100644 --- a/servicetalk-client-api/gradle/spotbugs/test-exclusions.xml +++ b/servicetalk-client-api/gradle/spotbugs/test-exclusions.xml @@ -20,4 +20,12 @@ + + + + + + + + diff --git a/servicetalk-concurrent-api-internal/gradle/spotbugs/main-exclusions.xml b/servicetalk-concurrent-api-internal/gradle/spotbugs/main-exclusions.xml new file mode 100644 index 0000000000..04c77edbcb --- /dev/null +++ b/servicetalk-concurrent-api-internal/gradle/spotbugs/main-exclusions.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + diff --git a/servicetalk-concurrent-api-internal/gradle/spotbugs/test-exclusions.xml b/servicetalk-concurrent-api-internal/gradle/spotbugs/test-exclusions.xml index 9b52a096a8..1428faac7f 100644 --- a/servicetalk-concurrent-api-internal/gradle/spotbugs/test-exclusions.xml +++ b/servicetalk-concurrent-api-internal/gradle/spotbugs/test-exclusions.xml @@ -25,4 +25,16 @@ + + + + + + + + + + + + diff --git a/servicetalk-concurrent-api-test/gradle/spotbugs/main-exclusions.xml b/servicetalk-concurrent-api-test/gradle/spotbugs/main-exclusions.xml new file mode 100644 index 0000000000..ecdcfb05c6 --- /dev/null +++ b/servicetalk-concurrent-api-test/gradle/spotbugs/main-exclusions.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + diff --git a/servicetalk-concurrent-api-test/gradle/spotbugs/test-exclusions.xml b/servicetalk-concurrent-api-test/gradle/spotbugs/test-exclusions.xml new file mode 100644 index 0000000000..e61ee2b6da --- /dev/null +++ b/servicetalk-concurrent-api-test/gradle/spotbugs/test-exclusions.xml @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/servicetalk-concurrent-api/gradle/spotbugs/main-exclusions.xml b/servicetalk-concurrent-api/gradle/spotbugs/main-exclusions.xml index 8100435296..972aa5f78a 100644 --- a/servicetalk-concurrent-api/gradle/spotbugs/main-exclusions.xml +++ b/servicetalk-concurrent-api/gradle/spotbugs/main-exclusions.xml @@ -57,4 +57,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/servicetalk-concurrent-api/gradle/spotbugs/test-exclusions.xml b/servicetalk-concurrent-api/gradle/spotbugs/test-exclusions.xml index fe13580606..a2bfeb6fba 100644 --- a/servicetalk-concurrent-api/gradle/spotbugs/test-exclusions.xml +++ b/servicetalk-concurrent-api/gradle/spotbugs/test-exclusions.xml @@ -51,4 +51,16 @@ + + + + + + + + + + + + diff --git a/servicetalk-concurrent-api/gradle/spotbugs/testFixtures-exclusions.xml b/servicetalk-concurrent-api/gradle/spotbugs/testFixtures-exclusions.xml index 5777964d26..32c2415d81 100644 --- a/servicetalk-concurrent-api/gradle/spotbugs/testFixtures-exclusions.xml +++ b/servicetalk-concurrent-api/gradle/spotbugs/testFixtures-exclusions.xml @@ -21,4 +21,9 @@ + + + + + diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/CopyOnWriteContextMap.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/CopyOnWriteContextMap.java index 6bcd5dc2d9..53aef60c01 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/CopyOnWriteContextMap.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/CopyOnWriteContextMap.java @@ -2712,7 +2712,7 @@ private CopyContextMap removeBelowSeven(int i) { (Key) context[8], context[9], (Key) context[10], context[11]); default: - throw new RuntimeException("Programming error, unable to remove a key at index=" + i); + throw new IllegalStateException("Programming error, unable to remove a key at index=" + i); } } @@ -2838,7 +2838,7 @@ private CopyContextMap removeBelowSeven(final GrowableIntArray indexesToRemove) default: break; } - throw new RuntimeException("Programming error, unable to reduce from " + size() + " to " + + throw new IllegalStateException("Programming error, unable to reduce from " + size() + " to " + (size() - indexesToRemove.count())); } diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/CopyOnWriteExecutorPluginSet.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/CopyOnWriteExecutorPluginSet.java index d08d5ee291..3d5e47c18e 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/CopyOnWriteExecutorPluginSet.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/CopyOnWriteExecutorPluginSet.java @@ -175,7 +175,7 @@ public CopyOnWriteSet remove(final ExecutorPlugin plugin) { case 2: return new TwoExecutorPluginSet(plugins[0], plugins[1]); default: - throw new RuntimeException("programming error. i: " + i); + throw new IllegalStateException("programming error. i: " + i); } } ExecutorPlugin[] newArray = new ExecutorPlugin[plugins.length - 1]; diff --git a/servicetalk-concurrent-api/src/test/java/io/servicetalk/concurrent/api/TestCompletableTest.java b/servicetalk-concurrent-api/src/test/java/io/servicetalk/concurrent/api/TestCompletableTest.java index d58a5704a1..5ef63bebcf 100644 --- a/servicetalk-concurrent-api/src/test/java/io/servicetalk/concurrent/api/TestCompletableTest.java +++ b/servicetalk-concurrent-api/src/test/java/io/servicetalk/concurrent/api/TestCompletableTest.java @@ -49,7 +49,7 @@ void testNonResubscribeableCompletable() { source.subscribe(subscriber2); - Exception e = assertThrows(RuntimeException.class, () -> source.onComplete()); + AssertionError e = assertThrows(AssertionError.class, () -> source.onComplete()); assertEquals("Unexpected exception(s) encountered", e.getMessage()); assertThat(e.getCause(), allOf(instanceOf(IllegalStateException.class), hasProperty("message", startsWith("Duplicate subscriber")))); diff --git a/servicetalk-concurrent-api/src/test/java/io/servicetalk/concurrent/api/TestPublisherTest.java b/servicetalk-concurrent-api/src/test/java/io/servicetalk/concurrent/api/TestPublisherTest.java index ed6fa36b48..891ef8e890 100644 --- a/servicetalk-concurrent-api/src/test/java/io/servicetalk/concurrent/api/TestPublisherTest.java +++ b/servicetalk-concurrent-api/src/test/java/io/servicetalk/concurrent/api/TestPublisherTest.java @@ -59,7 +59,7 @@ void testNonResubscribeablePublisher() { source.subscribe(subscriber2); - Exception e = assertThrows(RuntimeException.class, () -> source.onComplete()); + AssertionError e = assertThrows(AssertionError.class, () -> source.onComplete()); assertEquals("Unexpected exception(s) encountered", e.getMessage()); assertThat(e.getCause(), allOf(instanceOf(IllegalStateException.class), hasProperty("message", diff --git a/servicetalk-concurrent-api/src/test/java/io/servicetalk/concurrent/api/TestSingleTest.java b/servicetalk-concurrent-api/src/test/java/io/servicetalk/concurrent/api/TestSingleTest.java index 53235cfe90..9946f1b79b 100644 --- a/servicetalk-concurrent-api/src/test/java/io/servicetalk/concurrent/api/TestSingleTest.java +++ b/servicetalk-concurrent-api/src/test/java/io/servicetalk/concurrent/api/TestSingleTest.java @@ -47,7 +47,7 @@ void testNonResubscribeableSingle() { source.subscribe(subscriber2); - Exception e = assertThrows(RuntimeException.class, () -> source.onSuccess("b")); + AssertionError e = assertThrows(AssertionError.class, () -> source.onSuccess("b")); assertEquals("Unexpected exception(s) encountered", e.getMessage()); assertThat(e.getCause(), allOf(instanceOf(IllegalStateException.class), hasProperty("message", diff --git a/servicetalk-concurrent-api/src/testFixtures/java/io/servicetalk/concurrent/api/TestCompletable.java b/servicetalk-concurrent-api/src/testFixtures/java/io/servicetalk/concurrent/api/TestCompletable.java index 71537878ac..b28d6e5394 100644 --- a/servicetalk-concurrent-api/src/testFixtures/java/io/servicetalk/concurrent/api/TestCompletable.java +++ b/servicetalk-concurrent-api/src/testFixtures/java/io/servicetalk/concurrent/api/TestCompletable.java @@ -148,7 +148,7 @@ public void onError(final Throwable t) { private Subscriber checkSubscriberAndExceptions() { if (!exceptions.isEmpty()) { - final RuntimeException exception = new RuntimeException("Unexpected exception(s) encountered", + final AssertionError exception = new AssertionError("Unexpected exception(s) encountered", exceptions.get(0)); for (int i = 1; i < exceptions.size(); i++) { addSuppressed(exception, exceptions.get(i)); @@ -353,7 +353,7 @@ private Subscriber waitForSubscriber() { Thread.currentThread().interrupt(); return throwException(e); } catch (ExecutionException e) { - throw new RuntimeException(e); + return throwException(e); } } } diff --git a/servicetalk-concurrent-api/src/testFixtures/java/io/servicetalk/concurrent/api/TestPublisher.java b/servicetalk-concurrent-api/src/testFixtures/java/io/servicetalk/concurrent/api/TestPublisher.java index e43dc65656..ef19774bdd 100644 --- a/servicetalk-concurrent-api/src/testFixtures/java/io/servicetalk/concurrent/api/TestPublisher.java +++ b/servicetalk-concurrent-api/src/testFixtures/java/io/servicetalk/concurrent/api/TestPublisher.java @@ -174,7 +174,7 @@ public void onError(final Throwable t) { private Subscriber checkSubscriberAndExceptions() { if (!exceptions.isEmpty()) { - final RuntimeException exception = new RuntimeException("Unexpected exception(s) encountered", + final AssertionError exception = new AssertionError("Unexpected exception(s) encountered", exceptions.get(0)); for (int i = 1; i < exceptions.size(); i++) { addSuppressed(exception, exceptions.get(i)); @@ -422,7 +422,7 @@ private Subscriber waitForSubscriber() { Thread.currentThread().interrupt(); return throwException(e); } catch (ExecutionException e) { - throw new RuntimeException(e); + return throwException(e); } } } diff --git a/servicetalk-concurrent-api/src/testFixtures/java/io/servicetalk/concurrent/api/TestSingle.java b/servicetalk-concurrent-api/src/testFixtures/java/io/servicetalk/concurrent/api/TestSingle.java index 4d61626f6e..d4d8abb8a6 100644 --- a/servicetalk-concurrent-api/src/testFixtures/java/io/servicetalk/concurrent/api/TestSingle.java +++ b/servicetalk-concurrent-api/src/testFixtures/java/io/servicetalk/concurrent/api/TestSingle.java @@ -151,7 +151,7 @@ public void onError(final Throwable t) { private Subscriber checkSubscriberAndExceptions() { if (!exceptions.isEmpty()) { - final RuntimeException exception = new RuntimeException("Unexpected exception(s) encountered", + final AssertionError exception = new AssertionError("Unexpected exception(s) encountered", exceptions.get(0)); for (int i = 1; i < exceptions.size(); i++) { addSuppressed(exception, exceptions.get(i)); diff --git a/servicetalk-concurrent-internal/gradle/spotbugs/main-exclusions.xml b/servicetalk-concurrent-internal/gradle/spotbugs/main-exclusions.xml index deed4d6c10..8880bc393a 100644 --- a/servicetalk-concurrent-internal/gradle/spotbugs/main-exclusions.xml +++ b/servicetalk-concurrent-internal/gradle/spotbugs/main-exclusions.xml @@ -27,4 +27,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/servicetalk-concurrent-internal/gradle/spotbugs/test-exclusions.xml b/servicetalk-concurrent-internal/gradle/spotbugs/test-exclusions.xml index 9b52a096a8..13abd228e8 100644 --- a/servicetalk-concurrent-internal/gradle/spotbugs/test-exclusions.xml +++ b/servicetalk-concurrent-internal/gradle/spotbugs/test-exclusions.xml @@ -25,4 +25,8 @@ + + + + diff --git a/servicetalk-concurrent-jdkflow/gradle/spotbugs/test-exclusions.xml b/servicetalk-concurrent-jdkflow/gradle/spotbugs/test-exclusions.xml new file mode 100644 index 0000000000..500404e766 --- /dev/null +++ b/servicetalk-concurrent-jdkflow/gradle/spotbugs/test-exclusions.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + diff --git a/servicetalk-concurrent-reactivestreams/gradle/spotbugs/test-exclusions.xml b/servicetalk-concurrent-reactivestreams/gradle/spotbugs/test-exclusions.xml new file mode 100644 index 0000000000..500404e766 --- /dev/null +++ b/servicetalk-concurrent-reactivestreams/gradle/spotbugs/test-exclusions.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + diff --git a/servicetalk-concurrent-test-internal/gradle/spotbugs/test-exclusions.xml b/servicetalk-concurrent-test-internal/gradle/spotbugs/test-exclusions.xml new file mode 100644 index 0000000000..e61ee2b6da --- /dev/null +++ b/servicetalk-concurrent-test-internal/gradle/spotbugs/test-exclusions.xml @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/servicetalk-concurrent/gradle/spotbugs/main-exclusions.xml b/servicetalk-concurrent/gradle/spotbugs/main-exclusions.xml new file mode 100644 index 0000000000..9b7ccdaa72 --- /dev/null +++ b/servicetalk-concurrent/gradle/spotbugs/main-exclusions.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + diff --git a/servicetalk-data-jackson-jersey/gradle/spotbugs/test-exclusions.xml b/servicetalk-data-jackson-jersey/gradle/spotbugs/test-exclusions.xml new file mode 100644 index 0000000000..500404e766 --- /dev/null +++ b/servicetalk-data-jackson-jersey/gradle/spotbugs/test-exclusions.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + diff --git a/servicetalk-data-jackson/gradle/spotbugs/test-exclusions.xml b/servicetalk-data-jackson/gradle/spotbugs/test-exclusions.xml index 1e109e57b4..90c20cf9ca 100644 --- a/servicetalk-data-jackson/gradle/spotbugs/test-exclusions.xml +++ b/servicetalk-data-jackson/gradle/spotbugs/test-exclusions.xml @@ -28,4 +28,8 @@ + + + + diff --git a/servicetalk-data-protobuf-jersey/gradle/spotbugs/test-exclusions.xml b/servicetalk-data-protobuf-jersey/gradle/spotbugs/test-exclusions.xml index 3c332a5d3a..cfe45ee004 100644 --- a/servicetalk-data-protobuf-jersey/gradle/spotbugs/test-exclusions.xml +++ b/servicetalk-data-protobuf-jersey/gradle/spotbugs/test-exclusions.xml @@ -23,4 +23,12 @@ + + + + + + + + diff --git a/servicetalk-data-protobuf/gradle/spotbugs/test-exclusions.xml b/servicetalk-data-protobuf/gradle/spotbugs/test-exclusions.xml index a36fb3866a..f8fbdb0df4 100644 --- a/servicetalk-data-protobuf/gradle/spotbugs/test-exclusions.xml +++ b/servicetalk-data-protobuf/gradle/spotbugs/test-exclusions.xml @@ -19,4 +19,12 @@ + + + + + + + + diff --git a/servicetalk-dns-discovery-netty/gradle/spotbugs/main-exclusions.xml b/servicetalk-dns-discovery-netty/gradle/spotbugs/main-exclusions.xml index 5b43ffe555..e91650cbbd 100644 --- a/servicetalk-dns-discovery-netty/gradle/spotbugs/main-exclusions.xml +++ b/servicetalk-dns-discovery-netty/gradle/spotbugs/main-exclusions.xml @@ -21,4 +21,19 @@ + + + + + + + + + + + + + + + diff --git a/servicetalk-dns-discovery-netty/gradle/spotbugs/test-exclusions.xml b/servicetalk-dns-discovery-netty/gradle/spotbugs/test-exclusions.xml index f3b96891a1..bdabf555ea 100644 --- a/servicetalk-dns-discovery-netty/gradle/spotbugs/test-exclusions.xml +++ b/servicetalk-dns-discovery-netty/gradle/spotbugs/test-exclusions.xml @@ -31,4 +31,16 @@ + + + + + + + + + + + + diff --git a/servicetalk-dns-discovery-netty/src/test/java/io/servicetalk/dns/discovery/netty/TestDnsServer.java b/servicetalk-dns-discovery-netty/src/test/java/io/servicetalk/dns/discovery/netty/TestDnsServer.java index 83cdff0ace..ef29379d35 100644 --- a/servicetalk-dns-discovery-netty/src/test/java/io/servicetalk/dns/discovery/netty/TestDnsServer.java +++ b/servicetalk-dns-discovery-netty/src/test/java/io/servicetalk/dns/discovery/netty/TestDnsServer.java @@ -142,7 +142,7 @@ protected void putResourceRecordData(IoBuffer ioBuffer, ResourceRecord resourceR try { bytes = InetAddress.getByName(resourceRecord.get(DnsAttribute.IP_ADDRESS)).getAddress(); } catch (UnknownHostException e) { - throw new RuntimeException(e); + throw new IllegalStateException(e); } ioBuffer.put(bytes); } diff --git a/servicetalk-encoding-netty/gradle/spotbugs/test-exclusions.xml b/servicetalk-encoding-netty/gradle/spotbugs/test-exclusions.xml new file mode 100644 index 0000000000..500404e766 --- /dev/null +++ b/servicetalk-encoding-netty/gradle/spotbugs/test-exclusions.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + diff --git a/servicetalk-gradle-plugin-internal/src/main/groovy/io/servicetalk/gradle/plugin/internal/Versions.groovy b/servicetalk-gradle-plugin-internal/src/main/groovy/io/servicetalk/gradle/plugin/internal/Versions.groovy index a767e44404..66aa2162bf 100644 --- a/servicetalk-gradle-plugin-internal/src/main/groovy/io/servicetalk/gradle/plugin/internal/Versions.groovy +++ b/servicetalk-gradle-plugin-internal/src/main/groovy/io/servicetalk/gradle/plugin/internal/Versions.groovy @@ -22,7 +22,7 @@ import static org.gradle.api.JavaVersion.VERSION_1_8 final class Versions { static final String CHECKSTYLE_VERSION = "9.2" static final String PMD_VERSION = "6.41.0" - static final String SPOTBUGS_VERSION = "4.6.0" + static final String SPOTBUGS_VERSION = "4.7.0" static final String PITEST_VERSION = "1.7.3" static final String PITEST_JUNIT5_PLUGIN_VERSION = "0.15" static final JavaVersion TARGET_VERSION = VERSION_1_8 diff --git a/servicetalk-grpc-api/gradle/spotbugs/main-exclusions.xml b/servicetalk-grpc-api/gradle/spotbugs/main-exclusions.xml index 233d5bd41b..4ad373bbb4 100644 --- a/servicetalk-grpc-api/gradle/spotbugs/main-exclusions.xml +++ b/servicetalk-grpc-api/gradle/spotbugs/main-exclusions.xml @@ -1,6 +1,6 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/servicetalk-grpc-health/gradle/spotbugs/test-exclusions.xml b/servicetalk-grpc-health/gradle/spotbugs/test-exclusions.xml new file mode 100644 index 0000000000..500404e766 --- /dev/null +++ b/servicetalk-grpc-health/gradle/spotbugs/test-exclusions.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + diff --git a/servicetalk-grpc-netty/gradle/spotbugs/main-exclusions.xml b/servicetalk-grpc-netty/gradle/spotbugs/main-exclusions.xml new file mode 100644 index 0000000000..c14fe30e7f --- /dev/null +++ b/servicetalk-grpc-netty/gradle/spotbugs/main-exclusions.xml @@ -0,0 +1,23 @@ + + + + + + + + + diff --git a/servicetalk-grpc-netty/gradle/spotbugs/test-exclusions.xml b/servicetalk-grpc-netty/gradle/spotbugs/test-exclusions.xml index ba3e5587c4..a396334e69 100644 --- a/servicetalk-grpc-netty/gradle/spotbugs/test-exclusions.xml +++ b/servicetalk-grpc-netty/gradle/spotbugs/test-exclusions.xml @@ -50,4 +50,27 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/servicetalk-grpc-netty/src/test/java/io/servicetalk/grpc/netty/GrpcOverH1.java b/servicetalk-grpc-netty/src/test/java/io/servicetalk/grpc/netty/GrpcOverH1Test.java similarity index 99% rename from servicetalk-grpc-netty/src/test/java/io/servicetalk/grpc/netty/GrpcOverH1.java rename to servicetalk-grpc-netty/src/test/java/io/servicetalk/grpc/netty/GrpcOverH1Test.java index 6d2953a3e0..98e2d4ecb3 100644 --- a/servicetalk-grpc-netty/src/test/java/io/servicetalk/grpc/netty/GrpcOverH1.java +++ b/servicetalk-grpc-netty/src/test/java/io/servicetalk/grpc/netty/GrpcOverH1Test.java @@ -37,7 +37,7 @@ import static io.servicetalk.transport.netty.internal.AddressUtils.localAddress; import static org.junit.jupiter.api.Assertions.assertEquals; -final class GrpcOverH1 { +final class GrpcOverH1Test { private static final HttpProtocolConfig[] H1 = new HttpProtocolConfig[] {h1Default()}; private static final HttpProtocolConfig[] H1H2 = new HttpProtocolConfig[] {h1Default(), h2Default()}; private static final HttpProtocolConfig[] H2H1 = new HttpProtocolConfig[] {h2Default(), h1Default()}; diff --git a/servicetalk-http-api/gradle/spotbugs/main-exclusions.xml b/servicetalk-http-api/gradle/spotbugs/main-exclusions.xml index 28a2683dbd..3955ff0ab2 100644 --- a/servicetalk-http-api/gradle/spotbugs/main-exclusions.xml +++ b/servicetalk-http-api/gradle/spotbugs/main-exclusions.xml @@ -1,6 +1,6 @@ + + + + + + diff --git a/servicetalk-http-router-jersey/gradle/spotbugs/main-exclusions.xml b/servicetalk-http-router-jersey/gradle/spotbugs/main-exclusions.xml index ecb248b288..3773d0e990 100644 --- a/servicetalk-http-router-jersey/gradle/spotbugs/main-exclusions.xml +++ b/servicetalk-http-router-jersey/gradle/spotbugs/main-exclusions.xml @@ -54,4 +54,10 @@ + + + + + + diff --git a/servicetalk-http-router-jersey/gradle/spotbugs/testFixtures-exclusions.xml b/servicetalk-http-router-jersey/gradle/spotbugs/testFixtures-exclusions.xml index 9a8321c91b..e1b5d6cb5f 100644 --- a/servicetalk-http-router-jersey/gradle/spotbugs/testFixtures-exclusions.xml +++ b/servicetalk-http-router-jersey/gradle/spotbugs/testFixtures-exclusions.xml @@ -26,4 +26,19 @@ + + + + + + + + + + + + + + + diff --git a/servicetalk-http-router-predicate/gradle/spotbugs/test-exclusions.xml b/servicetalk-http-router-predicate/gradle/spotbugs/test-exclusions.xml index c15803210a..2993fc6e20 100644 --- a/servicetalk-http-router-predicate/gradle/spotbugs/test-exclusions.xml +++ b/servicetalk-http-router-predicate/gradle/spotbugs/test-exclusions.xml @@ -20,6 +20,14 @@ + + + + + + + + diff --git a/servicetalk-http-security-jersey/gradle/spotbugs/test-exclusions.xml b/servicetalk-http-security-jersey/gradle/spotbugs/test-exclusions.xml index a10553e0a3..af0f601b22 100644 --- a/servicetalk-http-security-jersey/gradle/spotbugs/test-exclusions.xml +++ b/servicetalk-http-security-jersey/gradle/spotbugs/test-exclusions.xml @@ -20,4 +20,8 @@ + + + + diff --git a/servicetalk-http-utils/gradle/spotbugs/test-exclusions.xml b/servicetalk-http-utils/gradle/spotbugs/test-exclusions.xml index e6ff4dd154..63083a5d63 100644 --- a/servicetalk-http-utils/gradle/spotbugs/test-exclusions.xml +++ b/servicetalk-http-utils/gradle/spotbugs/test-exclusions.xml @@ -26,4 +26,12 @@ + + + + + + + + diff --git a/servicetalk-loadbalancer/gradle/spotbugs/test-exclusions.xml b/servicetalk-loadbalancer/gradle/spotbugs/test-exclusions.xml index a10553e0a3..7e276c24b9 100644 --- a/servicetalk-loadbalancer/gradle/spotbugs/test-exclusions.xml +++ b/servicetalk-loadbalancer/gradle/spotbugs/test-exclusions.xml @@ -20,4 +20,16 @@ + + + + + + + + + + + + diff --git a/servicetalk-log4j2-mdc-utils/gradle/spotbugs/test-exclusions.xml b/servicetalk-log4j2-mdc-utils/gradle/spotbugs/test-exclusions.xml new file mode 100644 index 0000000000..e88990d20f --- /dev/null +++ b/servicetalk-log4j2-mdc-utils/gradle/spotbugs/test-exclusions.xml @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/servicetalk-opentracing-http/gradle/spotbugs/test-exclusions.xml b/servicetalk-opentracing-http/gradle/spotbugs/test-exclusions.xml index ee5b9f746d..e9e343d01c 100644 --- a/servicetalk-opentracing-http/gradle/spotbugs/test-exclusions.xml +++ b/servicetalk-opentracing-http/gradle/spotbugs/test-exclusions.xml @@ -26,4 +26,12 @@ + + + + + + + + diff --git a/servicetalk-opentracing-inmemory-api/gradle/spotbugs/main-exclusions.xml b/servicetalk-opentracing-inmemory-api/gradle/spotbugs/main-exclusions.xml new file mode 100644 index 0000000000..0acee33f30 --- /dev/null +++ b/servicetalk-opentracing-inmemory-api/gradle/spotbugs/main-exclusions.xml @@ -0,0 +1,23 @@ + + + + + + + + + diff --git a/servicetalk-opentracing-inmemory/gradle/spotbugs/main-exclusions.xml b/servicetalk-opentracing-inmemory/gradle/spotbugs/main-exclusions.xml new file mode 100644 index 0000000000..324f6cde08 --- /dev/null +++ b/servicetalk-opentracing-inmemory/gradle/spotbugs/main-exclusions.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + diff --git a/servicetalk-opentracing-log4j2/gradle/spotbugs/test-exclusions.xml b/servicetalk-opentracing-log4j2/gradle/spotbugs/test-exclusions.xml index c6e27b6320..b75808c0fa 100644 --- a/servicetalk-opentracing-log4j2/gradle/spotbugs/test-exclusions.xml +++ b/servicetalk-opentracing-log4j2/gradle/spotbugs/test-exclusions.xml @@ -20,4 +20,8 @@ + + + + diff --git a/servicetalk-opentracing-zipkin-publisher/gradle/spotbugs/main-exclusions.xml b/servicetalk-opentracing-zipkin-publisher/gradle/spotbugs/main-exclusions.xml index 8aa484e8a7..2c526f31be 100644 --- a/servicetalk-opentracing-zipkin-publisher/gradle/spotbugs/main-exclusions.xml +++ b/servicetalk-opentracing-zipkin-publisher/gradle/spotbugs/main-exclusions.xml @@ -31,4 +31,10 @@ + + + + + + diff --git a/servicetalk-opentracing-zipkin-publisher/gradle/spotbugs/test-exclusions.xml b/servicetalk-opentracing-zipkin-publisher/gradle/spotbugs/test-exclusions.xml index a10553e0a3..8bd196c0d1 100644 --- a/servicetalk-opentracing-zipkin-publisher/gradle/spotbugs/test-exclusions.xml +++ b/servicetalk-opentracing-zipkin-publisher/gradle/spotbugs/test-exclusions.xml @@ -20,4 +20,12 @@ + + + + + + + + diff --git a/servicetalk-serialization-api/gradle/spotbugs/main-exclusions.xml b/servicetalk-serialization-api/gradle/spotbugs/main-exclusions.xml index a664a9d333..b42531fd9c 100644 --- a/servicetalk-serialization-api/gradle/spotbugs/main-exclusions.xml +++ b/servicetalk-serialization-api/gradle/spotbugs/main-exclusions.xml @@ -1,6 +1,6 @@ + + + + + + + + + + diff --git a/servicetalk-tcp-netty-internal/gradle/spotbugs/main-exclusions.xml b/servicetalk-tcp-netty-internal/gradle/spotbugs/main-exclusions.xml index 90454d89ce..a2134f331e 100644 --- a/servicetalk-tcp-netty-internal/gradle/spotbugs/main-exclusions.xml +++ b/servicetalk-tcp-netty-internal/gradle/spotbugs/main-exclusions.xml @@ -43,4 +43,15 @@ + + + + + + + + + + + diff --git a/servicetalk-tcp-netty-internal/gradle/spotbugs/test-exclusions.xml b/servicetalk-tcp-netty-internal/gradle/spotbugs/test-exclusions.xml index e354904679..8b23240e08 100644 --- a/servicetalk-tcp-netty-internal/gradle/spotbugs/test-exclusions.xml +++ b/servicetalk-tcp-netty-internal/gradle/spotbugs/test-exclusions.xml @@ -25,4 +25,16 @@ + + + + + + + + + + + + diff --git a/servicetalk-tcp-netty-internal/gradle/spotbugs/testFixtures-exclusions.xml b/servicetalk-tcp-netty-internal/gradle/spotbugs/testFixtures-exclusions.xml new file mode 100644 index 0000000000..bf969114ae --- /dev/null +++ b/servicetalk-tcp-netty-internal/gradle/spotbugs/testFixtures-exclusions.xml @@ -0,0 +1,23 @@ + + + + + + + + + diff --git a/servicetalk-test-resources/gradle/spotbugs/test-exclusions.xml b/servicetalk-test-resources/gradle/spotbugs/test-exclusions.xml new file mode 100644 index 0000000000..e88990d20f --- /dev/null +++ b/servicetalk-test-resources/gradle/spotbugs/test-exclusions.xml @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/servicetalk-transport-api/gradle/spotbugs/main-exclusions.xml b/servicetalk-transport-api/gradle/spotbugs/main-exclusions.xml new file mode 100644 index 0000000000..79849a65af --- /dev/null +++ b/servicetalk-transport-api/gradle/spotbugs/main-exclusions.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + diff --git a/servicetalk-transport-api/gradle/spotbugs/test-exclusions.xml b/servicetalk-transport-api/gradle/spotbugs/test-exclusions.xml index a10553e0a3..af0f601b22 100644 --- a/servicetalk-transport-api/gradle/spotbugs/test-exclusions.xml +++ b/servicetalk-transport-api/gradle/spotbugs/test-exclusions.xml @@ -20,4 +20,8 @@ + + + + diff --git a/servicetalk-transport-netty-internal/gradle/spotbugs/main-exclusions.xml b/servicetalk-transport-netty-internal/gradle/spotbugs/main-exclusions.xml index b639b98d82..10b5cd9b5b 100644 --- a/servicetalk-transport-netty-internal/gradle/spotbugs/main-exclusions.xml +++ b/servicetalk-transport-netty-internal/gradle/spotbugs/main-exclusions.xml @@ -47,4 +47,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/servicetalk-transport-netty-internal/gradle/spotbugs/test-exclusions.xml b/servicetalk-transport-netty-internal/gradle/spotbugs/test-exclusions.xml index f0ea3ac96c..757beb5705 100644 --- a/servicetalk-transport-netty-internal/gradle/spotbugs/test-exclusions.xml +++ b/servicetalk-transport-netty-internal/gradle/spotbugs/test-exclusions.xml @@ -30,4 +30,12 @@ + + + + + + + + diff --git a/servicetalk-transport-netty-internal/gradle/spotbugs/testFixtures-exclusions.xml b/servicetalk-transport-netty-internal/gradle/spotbugs/testFixtures-exclusions.xml index fa0ae5a8b1..e981cb7803 100644 --- a/servicetalk-transport-netty-internal/gradle/spotbugs/testFixtures-exclusions.xml +++ b/servicetalk-transport-netty-internal/gradle/spotbugs/testFixtures-exclusions.xml @@ -27,4 +27,16 @@ + + + + + + + + + + + + diff --git a/servicetalk-utils-internal/gradle/spotbugs/main-exclusions.xml b/servicetalk-utils-internal/gradle/spotbugs/main-exclusions.xml index 62c39d7d92..0c49c01781 100644 --- a/servicetalk-utils-internal/gradle/spotbugs/main-exclusions.xml +++ b/servicetalk-utils-internal/gradle/spotbugs/main-exclusions.xml @@ -21,4 +21,22 @@ + + + + + + + + + + + + + + + + + + diff --git a/servicetalk-utils-internal/gradle/spotbugs/test-exclusions.xml b/servicetalk-utils-internal/gradle/spotbugs/test-exclusions.xml index 76d8981054..aa1140c766 100644 --- a/servicetalk-utils-internal/gradle/spotbugs/test-exclusions.xml +++ b/servicetalk-utils-internal/gradle/spotbugs/test-exclusions.xml @@ -20,4 +20,8 @@ + + + + From 05a015c7cc20db25cd886d037cfd87bdd2d70eb7 Mon Sep 17 00:00:00 2001 From: Scott Mitchell Date: Thu, 26 May 2022 21:23:58 -0700 Subject: [PATCH 28/40] gRPC improve error status for non-200 h2 response status (#2221) Motivation: ServiceTalk currently assumes the response status is 200 when decoding into gRPC. This means we will fail during checking the content-type or during deserialization if an error is return from a middle proxy with a different encoding type. We can provide more informative gRPC error codes if we validate the h2 response status. --- .../servicetalk/grpc/api/GrpcStatusCode.java | 27 +++++- .../io/servicetalk/grpc/api/GrpcUtils.java | 52 ++++++++++- .../HttpResponseUponGrpcRequestTest.java | 4 +- .../grpc/netty/ProtocolCompatibilityTest.java | 91 +++++++++++++++++-- 4 files changed, 156 insertions(+), 18 deletions(-) diff --git a/servicetalk-grpc-api/src/main/java/io/servicetalk/grpc/api/GrpcStatusCode.java b/servicetalk-grpc-api/src/main/java/io/servicetalk/grpc/api/GrpcStatusCode.java index cf50d65465..99beca234f 100644 --- a/servicetalk-grpc-api/src/main/java/io/servicetalk/grpc/api/GrpcStatusCode.java +++ b/servicetalk-grpc-api/src/main/java/io/servicetalk/grpc/api/GrpcStatusCode.java @@ -40,17 +40,34 @@ public enum GrpcStatusCode { NOT_FOUND(5), /** Some entity that we attempted to create already exists. */ ALREADY_EXISTS(6), - /** Permission denied for a particular client. Different from {@link #UNAUTHENTICATED}. */ + /** + * Permission denied for a particular client. Must not be used for the following cases: + *

    + *
  • rejections caused by exhausting some resource (use {@link #RESOURCE_EXHAUSTED} instead)
  • + *
  • the caller cannot be identified (use {@link #UNAUTHENTICATED} instead)
  • + *
+ */ PERMISSION_DENIED(7), /** Resource exhausted. */ RESOURCE_EXHAUSTED(8), - /** The action cannot be executed on the current system state. Client should not retry.. */ + /** The action cannot be executed on the current system state. Client should not retry. */ FAILED_PRECONDITION(9), - /** Aborted, typically due to a concurrency issue (think CAS). Client may retry the whole sequence.. */ + /** Aborted, typically due to a concurrency issue (think CAS). Client may retry the whole sequence. */ ABORTED(10), - /** Used for range errors. */ + /** + * Used for range errors (e.g. seeking or reading past end of file.) + *

+ * Unlike {@link #INVALID_ARGUMENT}, this error indicates a problem that may be fixed if the system state changes. + * For example, a 32-bit file system will generate {@link #INVALID_ARGUMENT} if asked to read at an offset that is + * not in the range [0,2^32-1], but it will generate OUT_OF_RANGE if asked to read from an offset past the current + * file size. + *

+ * There is a fair bit of overlap with {@link #FAILED_PRECONDITION}. This error is more specific and recommended + * in scenarios when callers who are iterating through a space can easily look for an OUT_OF_RANGE error to detect + * when they are done. + */ OUT_OF_RANGE(11), - /** Unimplemented action. */ + /** The method/operation is not implemented/supported. */ UNIMPLEMENTED(12), /** Internal invariant violated. */ INTERNAL(13), diff --git a/servicetalk-grpc-api/src/main/java/io/servicetalk/grpc/api/GrpcUtils.java b/servicetalk-grpc-api/src/main/java/io/servicetalk/grpc/api/GrpcUtils.java index f5a2c150f0..8644e1e19e 100644 --- a/servicetalk-grpc-api/src/main/java/io/servicetalk/grpc/api/GrpcUtils.java +++ b/servicetalk-grpc-api/src/main/java/io/servicetalk/grpc/api/GrpcUtils.java @@ -35,6 +35,7 @@ import io.servicetalk.http.api.HttpResponse; import io.servicetalk.http.api.HttpResponseFactory; import io.servicetalk.http.api.HttpResponseMetaData; +import io.servicetalk.http.api.HttpResponseStatus; import io.servicetalk.http.api.HttpSerializer; import io.servicetalk.http.api.StatelessTrailersTransformer; import io.servicetalk.http.api.StreamingHttpResponse; @@ -77,7 +78,11 @@ import static io.servicetalk.grpc.api.GrpcHeaderValues.SERVICETALK_USER_AGENT; import static io.servicetalk.grpc.api.GrpcStatusCode.CANCELLED; import static io.servicetalk.grpc.api.GrpcStatusCode.DEADLINE_EXCEEDED; -import static io.servicetalk.grpc.api.GrpcStatusCode.INTERNAL; +import static io.servicetalk.grpc.api.GrpcStatusCode.FAILED_PRECONDITION; +import static io.servicetalk.grpc.api.GrpcStatusCode.INVALID_ARGUMENT; +import static io.servicetalk.grpc.api.GrpcStatusCode.PERMISSION_DENIED; +import static io.servicetalk.grpc.api.GrpcStatusCode.UNAUTHENTICATED; +import static io.servicetalk.grpc.api.GrpcStatusCode.UNAVAILABLE; import static io.servicetalk.grpc.api.GrpcStatusCode.UNIMPLEMENTED; import static io.servicetalk.grpc.api.GrpcStatusCode.UNKNOWN; import static io.servicetalk.grpc.api.GrpcStatusCode.fromHttp2ErrorCode; @@ -89,6 +94,19 @@ import static io.servicetalk.http.api.HttpHeaderNames.USER_AGENT; import static io.servicetalk.http.api.HttpHeaderValues.TRAILERS; import static io.servicetalk.http.api.HttpRequestMethod.POST; +import static io.servicetalk.http.api.HttpResponseStatus.BAD_GATEWAY; +import static io.servicetalk.http.api.HttpResponseStatus.EXPECTATION_FAILED; +import static io.servicetalk.http.api.HttpResponseStatus.FORBIDDEN; +import static io.servicetalk.http.api.HttpResponseStatus.GATEWAY_TIMEOUT; +import static io.servicetalk.http.api.HttpResponseStatus.NOT_FOUND; +import static io.servicetalk.http.api.HttpResponseStatus.NOT_IMPLEMENTED; +import static io.servicetalk.http.api.HttpResponseStatus.OK; +import static io.servicetalk.http.api.HttpResponseStatus.PRECONDITION_FAILED; +import static io.servicetalk.http.api.HttpResponseStatus.REQUEST_TIMEOUT; +import static io.servicetalk.http.api.HttpResponseStatus.SERVICE_UNAVAILABLE; +import static io.servicetalk.http.api.HttpResponseStatus.StatusClass.CLIENT_ERROR_4XX; +import static io.servicetalk.http.api.HttpResponseStatus.TOO_MANY_REQUESTS; +import static io.servicetalk.http.api.HttpResponseStatus.UNAUTHORIZED; import static java.lang.String.valueOf; import static java.util.Collections.emptyList; import static java.util.Objects.requireNonNull; @@ -263,10 +281,39 @@ static GrpcStatusException toGrpcException(Throwable cause) { : new GrpcStatusException(toGrpcStatus(cause), () -> null); } + private static void validateStatusCode(HttpResponseStatus status) { + final int statusCode = status.code(); + if (statusCode == OK.code()) { + return; + } + final GrpcStatusCode grpcStatusCode; + if (statusCode == BAD_GATEWAY.code() || statusCode == SERVICE_UNAVAILABLE.code() || + statusCode == GATEWAY_TIMEOUT.code() || statusCode == TOO_MANY_REQUESTS.code()) { + grpcStatusCode = UNAVAILABLE; + } else if (statusCode == UNAUTHORIZED.code()) { + grpcStatusCode = UNAUTHENTICATED; + } else if (statusCode == FORBIDDEN.code()) { + grpcStatusCode = PERMISSION_DENIED; + } else if (statusCode == NOT_FOUND.code() || statusCode == NOT_IMPLEMENTED.code()) { + grpcStatusCode = UNIMPLEMENTED; + } else if (statusCode == REQUEST_TIMEOUT.code()) { + grpcStatusCode = DEADLINE_EXCEEDED; + } else if (statusCode == PRECONDITION_FAILED.code() || statusCode == EXPECTATION_FAILED.code()) { + grpcStatusCode = FAILED_PRECONDITION; + } else if (CLIENT_ERROR_4XX.contains(statusCode)) { + grpcStatusCode = INVALID_ARGUMENT; + } else { + grpcStatusCode = UNKNOWN; + } + throw GrpcStatusException.of(Status.newBuilder().setCode(grpcStatusCode.value()) + .setMessage("HTTP status code: " + status).build()); + } + static Publisher validateResponseAndGetPayload(final StreamingHttpResponse response, final CharSequence expectedContentType, final BufferAllocator allocator, final GrpcStreamingDeserializer deserializer) { + validateStatusCode(response.status()); // gRPC protocol requires 200, don't look further if this check fails. // In case of an empty response, gRPC-server may return only one HEADER frame with endStream=true. Our // HTTP1-based implementation translates them into response headers so we need to look for a grpc-status in both // headers and trailers. Since this is streaming response and we have the headers now, we check for the @@ -293,6 +340,7 @@ static Resp validateResponseAndGetPayload(final HttpResponse response, final CharSequence expectedContentType, final BufferAllocator allocator, final GrpcDeserializer deserializer) { + validateStatusCode(response.status()); // gRPC protocol requires 200, don't look further if this check fails. // In case of an empty response, gRPC-server may return only one HEADER frame with endStream=true. Our // HTTP1-based implementation translates them into response headers so we need to look for a grpc-status in both // headers and trailers. @@ -320,7 +368,7 @@ static void validateContentType(HttpHeaders headers, CharSequence expectedConten if (!contentEqualsIgnoreCase(requestContentType, expectedContentType) && (requestContentType == null || !regionMatches(requestContentType, true, 0, APPLICATION_GRPC, 0, APPLICATION_GRPC.length()))) { - throw GrpcStatusException.of(Status.newBuilder().setCode(INTERNAL.value()) + throw GrpcStatusException.of(Status.newBuilder().setCode(UNKNOWN.value()) .setMessage("invalid content-type: " + requestContentType).build()); } } diff --git a/servicetalk-grpc-netty/src/test/java/io/servicetalk/grpc/netty/HttpResponseUponGrpcRequestTest.java b/servicetalk-grpc-netty/src/test/java/io/servicetalk/grpc/netty/HttpResponseUponGrpcRequestTest.java index 6ec8aeee2d..b717b88ec2 100644 --- a/servicetalk-grpc-netty/src/test/java/io/servicetalk/grpc/netty/HttpResponseUponGrpcRequestTest.java +++ b/servicetalk-grpc-netty/src/test/java/io/servicetalk/grpc/netty/HttpResponseUponGrpcRequestTest.java @@ -49,7 +49,7 @@ final class HttpResponseUponGrpcRequestTest { ServerContext serverContext = HttpServers.forAddress(localAddress(0)) .protocols(h2Default()) .listenAndAwait((ctx, request, responseFactory) -> - succeeded(responseFactory.badRequest().payloadBody(responsePayload, textSerializerUtf8()))); + succeeded(responseFactory.ok().payloadBody(responsePayload, textSerializerUtf8()))); client = GrpcClients.forAddress(serverHostAndPort(serverContext)) .buildBlocking(new TesterProto.Tester.ClientFactory()); @@ -111,7 +111,7 @@ private static void assertThrowsGrpcStatusException(Executable executable) { } private static void assertGrpcStatusException(GrpcStatusException grpcStatusException) { - assertThat(grpcStatusException.status().code(), is(GrpcStatusCode.INTERNAL)); + assertThat(grpcStatusException.status().code(), is(GrpcStatusCode.UNKNOWN)); String description = grpcStatusException.status().description(); assertThat(description, notNullValue()); assertThat(description, containsString("invalid content-type: text/plain;")); diff --git a/servicetalk-grpc-netty/src/test/java/io/servicetalk/grpc/netty/ProtocolCompatibilityTest.java b/servicetalk-grpc-netty/src/test/java/io/servicetalk/grpc/netty/ProtocolCompatibilityTest.java index 66cdfe088f..804b25f45a 100644 --- a/servicetalk-grpc-netty/src/test/java/io/servicetalk/grpc/netty/ProtocolCompatibilityTest.java +++ b/servicetalk-grpc-netty/src/test/java/io/servicetalk/grpc/netty/ProtocolCompatibilityTest.java @@ -15,6 +15,7 @@ */ package io.servicetalk.grpc.netty; +import io.servicetalk.buffer.api.Buffer; import io.servicetalk.concurrent.BlockingIterable; import io.servicetalk.concurrent.PublisherSource; import io.servicetalk.concurrent.SingleSource.Processor; @@ -51,7 +52,9 @@ import io.servicetalk.grpc.netty.CompatProto.Compat.ServiceFactory; import io.servicetalk.grpc.netty.CompatProto.RequestContainer.CompatRequest; import io.servicetalk.grpc.netty.CompatProto.ResponseContainer.CompatResponse; +import io.servicetalk.http.api.HttpResponseStatus; import io.servicetalk.http.api.HttpServerBuilder; +import io.servicetalk.http.api.HttpServerContext; import io.servicetalk.http.api.HttpServiceContext; import io.servicetalk.http.api.SingleAddressHttpClientBuilder; import io.servicetalk.http.api.StreamingHttpClient; @@ -69,6 +72,7 @@ import com.google.protobuf.Any; import com.google.protobuf.InvalidProtocolBufferException; +import com.google.rpc.Code; import io.grpc.Codec; import io.grpc.Compressor; import io.grpc.CompressorRegistry; @@ -85,6 +89,7 @@ import io.grpc.stub.StreamObserver; import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.CsvSource; @@ -116,11 +121,22 @@ import static io.servicetalk.concurrent.api.SourceAdapters.fromSource; import static io.servicetalk.concurrent.internal.TestTimeoutConstants.DEFAULT_TIMEOUT_SECONDS; import static io.servicetalk.grpc.api.GrpcExecutionStrategies.defaultStrategy; -import static io.servicetalk.grpc.api.GrpcExecutionStrategies.offloadNever; +import static io.servicetalk.grpc.api.GrpcExecutionStrategy.from; import static io.servicetalk.grpc.api.GrpcStatusCode.CANCELLED; import static io.servicetalk.grpc.api.GrpcStatusCode.DEADLINE_EXCEEDED; +import static io.servicetalk.grpc.api.GrpcStatusCode.FAILED_PRECONDITION; +import static io.servicetalk.grpc.api.GrpcStatusCode.INTERNAL; +import static io.servicetalk.grpc.api.GrpcStatusCode.INVALID_ARGUMENT; +import static io.servicetalk.grpc.api.GrpcStatusCode.UNKNOWN; import static io.servicetalk.grpc.internal.DeadlineUtils.GRPC_TIMEOUT_HEADER_KEY; -import static io.servicetalk.http.netty.HttpProtocolConfigs.h2; +import static io.servicetalk.http.api.HttpExecutionStrategies.offloadNone; +import static io.servicetalk.http.api.HttpResponseStatus.BAD_REQUEST; +import static io.servicetalk.http.api.HttpResponseStatus.EXPECTATION_FAILED; +import static io.servicetalk.http.api.HttpResponseStatus.PRECONDITION_FAILED; +import static io.servicetalk.http.api.HttpResponseStatus.REQUEST_HEADER_FIELDS_TOO_LARGE; +import static io.servicetalk.http.api.HttpResponseStatus.REQUEST_TIMEOUT; +import static io.servicetalk.http.api.HttpResponseStatus.StatusClass.CLIENT_ERROR_4XX; +import static io.servicetalk.http.netty.HttpProtocolConfigs.h2Default; import static io.servicetalk.test.resources.DefaultTestCerts.loadServerKey; import static io.servicetalk.test.resources.DefaultTestCerts.loadServerPem; import static io.servicetalk.test.resources.DefaultTestCerts.serverPemHostname; @@ -132,6 +148,7 @@ import static java.util.concurrent.TimeUnit.NANOSECONDS; import static java.util.concurrent.TimeUnit.SECONDS; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -404,7 +421,7 @@ void grpcJavaToServiceTalkErrorInResponseNoOffload(final boolean ssl, final String compression) throws Exception { final TestServerContext server = serviceTalkServer(ErrorMode.SIMPLE_IN_RESPONSE, ssl, - offloadNever(), compression, null); + from(offloadNone()), compression, null); final CompatClient client = grpcJavaClient(server.listenAddress(), compression, ssl, null); testGrpcError(client, server, false, streaming, compression); } @@ -458,7 +475,7 @@ void grpcJavaToServiceTalkErrorWithStatusInResponseNoOffloads( final boolean streaming, final String compression) throws Exception { final TestServerContext server = serviceTalkServer(ErrorMode.STATUS_IN_RESPONSE, ssl, - offloadNever(), compression, null); + from(offloadNone()), compression, null); final CompatClient client = grpcJavaClient(server.listenAddress(), compression, ssl, null); testGrpcError(client, server, true, streaming, compression); } @@ -485,6 +502,62 @@ void grpcJavaToServiceTalkBlocking( testRequestResponse(client, server, streaming, compression); } + @Test + void clientH2ReturnStatus() throws Exception { + try (HttpServerContext server = HttpServers.forAddress(localAddress(0)) + .protocols(h2Default()) + .listenBlockingAndAwait((ctx, request, responseFactory) -> { + byte meta = request.payloadBody().readByte(); + if (meta != 0) { + throw new IllegalArgumentException("compression not supported"); + } + int length = request.payloadBody().readInt(); + if (request.payloadBody().readableBytes() != length) { + throw new IllegalArgumentException("payload body length incomplete: " + length); + } + CompatRequest compatRequest = CompatRequest.parser().parseFrom( + Buffer.asInputStream(request.payloadBody())); + return responseFactory.newResponse(HttpResponseStatus.of(compatRequest.getId(), "foo")) + .payloadBody(ctx.executionContext().bufferAllocator().fromAscii("error")); + }); + CompatClient grpcJavaClient = grpcJavaClient(server.listenAddress(), null, false, null); + CompatClient stClient = serviceTalkClient(server.listenAddress(), false, null, null)) { + for (int httpCode = 100; httpCode < 999; ++httpCode) { + CompatRequest request = CompatRequest.newBuilder().setId(httpCode).build(); + int grpcJavaCode = Code.OK.getNumber(); + int stCode = GrpcStatusCode.OK.value(); + try { + grpcJavaClient.scalarCall(request).toFuture().get(); + } catch (ExecutionException e) { + grpcJavaCode = ((StatusRuntimeException) e.getCause()).getStatus().getCode().value(); + } + try { + stClient.scalarCall(request).toFuture().get(); + } catch (ExecutionException e) { + stCode = ((GrpcStatusException) e.getCause()).status().code().value(); + } + if (httpCode < 200) { + // grpc-java maps 1xx responses to error code INTERNAL, we currently map to UNKNOWN. The test server + // isn't following the http protocol by returning only a 1xx response and each framework catches + // this exception differently internally. + assertThat("h2 response code: " + httpCode, stCode, equalTo(UNKNOWN.value())); + assertThat("h2 response code: " + httpCode, grpcJavaCode, equalTo(INTERNAL.value())); + } else if (httpCode == REQUEST_TIMEOUT.code()) { + assertThat("h2 response code: " + httpCode, stCode, equalTo(DEADLINE_EXCEEDED.value())); + assertThat("h2 response code: " + httpCode, grpcJavaCode, equalTo(UNKNOWN.value())); + } else if (httpCode == PRECONDITION_FAILED.code() || httpCode == EXPECTATION_FAILED.code()) { + assertThat("h2 response code: " + httpCode, stCode, equalTo(FAILED_PRECONDITION.value())); + assertThat("h2 response code: " + httpCode, grpcJavaCode, equalTo(UNKNOWN.value())); + } else if (stCode != grpcJavaCode && CLIENT_ERROR_4XX.contains(httpCode)) { + assertThat("h2 response code: " + httpCode, stCode, equalTo(INVALID_ARGUMENT.value())); + assertThat("h2 response code: " + httpCode, grpcJavaCode, equalTo( + httpCode == BAD_REQUEST.code() || httpCode == REQUEST_HEADER_FIELDS_TOO_LARGE.code() ? + INTERNAL.value() : UNKNOWN.value())); + } + } + } + } + @ParameterizedTest @MethodSource("sslStreamingAndCompressionParams") void grpcJavaToServiceTalkBlockingError(final boolean ssl, @@ -603,7 +676,7 @@ void timeoutMidRequest(boolean stClient, boolean stServer, boolean clientInitiat Duration serverTimeout = clientInitiatedTimeout ? null : DEFAULT_DEADLINE; BlockingQueue serverErrorQueue = new ArrayBlockingQueue<>(16); final TestServerContext server = stServer ? - serviceTalkServer(ErrorMode.NONE, false, offloadNever(), null, null, serverErrorQueue) : + serviceTalkServer(ErrorMode.NONE, false, from(offloadNone()), null, null, serverErrorQueue) : grpcJavaServer(ErrorMode.NONE, false, null); try (ServerContext proxyCtx = buildTimeoutProxy(server.listenAddress(), serverTimeout, false)) { final CompatClient client = stClient ? @@ -633,8 +706,8 @@ void timeoutMidRequest(boolean stClient, boolean stServer, boolean clientInitiat private static ServerContext buildTimeoutProxy(SocketAddress serverAddress, @Nullable Duration forcedTimeout, boolean ssl) throws Exception { HttpServerBuilder proxyBuilder = HttpServers.forAddress(localAddress(0)) - .executionStrategy(offloadNever()) - .protocols(h2().build()); + .executionStrategy(from(offloadNone())) + .protocols(h2Default()); if (ssl) { proxyBuilder.sslConfig(new ServerSslConfigBuilder(DefaultTestCerts::loadServerPem, DefaultTestCerts::loadServerKey).build()); @@ -651,8 +724,8 @@ private static final class RemoveTimeoutHeaderProxy implements StreamingHttpServ boolean ssl) { SingleAddressHttpClientBuilder builder = HttpClients.forResolvedAddress((InetSocketAddress) serverAddress) - .executionStrategy(offloadNever()) - .protocols(h2().build()); + .executionStrategy(from(offloadNone())) + .protocols(h2Default()); if (ssl) { builder.sslConfig(new ClientSslConfigBuilder(DefaultTestCerts::loadServerCAPem) .peerHost(serverPemHostname()).build()); From fc53573c2cf34c16af5463d6125ccf4be4d66648 Mon Sep 17 00:00:00 2001 From: Idel Pivnitskiy Date: Fri, 27 May 2022 13:11:03 -0500 Subject: [PATCH 29/40] Log the cause why native transport libs are not loaded (#2226) Motivation: The cause is logged only when users explicitly set `-Dio.servicetalk.transport.netty.requireNativeLibs=true`. Logging cause in all cases simplifies debugging of the issue. Modifications: - Include the cause in `NativeTransportUtils` log message; Result: Users see the root cause why native libs are not loaded. --- .../transport/netty/internal/NativeTransportUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/servicetalk-transport-netty-internal/src/main/java/io/servicetalk/transport/netty/internal/NativeTransportUtils.java b/servicetalk-transport-netty-internal/src/main/java/io/servicetalk/transport/netty/internal/NativeTransportUtils.java index 3b6039859c..31100278f1 100644 --- a/servicetalk-transport-netty-internal/src/main/java/io/servicetalk/transport/netty/internal/NativeTransportUtils.java +++ b/servicetalk-transport-netty-internal/src/main/java/io/servicetalk/transport/netty/internal/NativeTransportUtils.java @@ -93,7 +93,7 @@ private static void reactOnUnavailability(final String transport, final String o "running with native libraries. Consider using \"-D{}=true\" to fail application initialization " + "without native libraries. If this is intentional, let netty know about it using \"-D{}=true\". " + "For more information, see https://netty.io/wiki/native-transports.html", - transport, os, normalizedArch(), REQUIRE_NATIVE_LIBS_NAME, NETTY_NO_NATIVE_NAME); + transport, os, normalizedArch(), REQUIRE_NATIVE_LIBS_NAME, NETTY_NO_NATIVE_NAME, cause); } } From 931ffe4edd6436148dade509aaf0bc27f1e92fa4 Mon Sep 17 00:00:00 2001 From: Mike Duigou Date: Fri, 27 May 2022 11:24:47 -0700 Subject: [PATCH 30/40] Additional test of expected server offloading (#2227) Motivation: When a `StreamingHttpService` is converted to another API flavor the expected offloading points change. Modifications: Add a test that verifies that converted HTTP services have the expected offloading. Result: Additional test coverage. --- ...ttpServerDefaultExecutionStrategyTest.java | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 servicetalk-http-netty/src/test/java/io/servicetalk/http/netty/HttpServerDefaultExecutionStrategyTest.java diff --git a/servicetalk-http-netty/src/test/java/io/servicetalk/http/netty/HttpServerDefaultExecutionStrategyTest.java b/servicetalk-http-netty/src/test/java/io/servicetalk/http/netty/HttpServerDefaultExecutionStrategyTest.java new file mode 100644 index 0000000000..2453867716 --- /dev/null +++ b/servicetalk-http-netty/src/test/java/io/servicetalk/http/netty/HttpServerDefaultExecutionStrategyTest.java @@ -0,0 +1,103 @@ +/* + * Copyright © 2022 Apple Inc. and the ServiceTalk project authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.servicetalk.http.netty; + +import io.servicetalk.concurrent.api.Single; +import io.servicetalk.http.api.BlockingHttpService; +import io.servicetalk.http.api.BlockingStreamingHttpService; +import io.servicetalk.http.api.HttpApiConversions; +import io.servicetalk.http.api.HttpExecutionStrategies; +import io.servicetalk.http.api.HttpExecutionStrategy; +import io.servicetalk.http.api.HttpService; +import io.servicetalk.http.api.HttpServiceContext; +import io.servicetalk.http.api.StreamingHttpRequest; +import io.servicetalk.http.api.StreamingHttpResponse; +import io.servicetalk.http.api.StreamingHttpResponseFactory; +import io.servicetalk.http.api.StreamingHttpService; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; + +import static io.servicetalk.concurrent.api.Publisher.from; +import static io.servicetalk.concurrent.api.Single.succeeded; +import static io.servicetalk.http.api.HttpExecutionStrategies.offloadAll; +import static io.servicetalk.http.api.HttpExecutionStrategies.offloadNone; +import static io.servicetalk.http.api.HttpSerializers.appSerializerUtf8FixLen; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class HttpServerDefaultExecutionStrategyTest { + + private static Stream services() { + return Stream.of(offloadNone(), + HttpExecutionStrategies.customStrategyBuilder().offloadSend().build(), + offloadAll()) + .map((HttpExecutionStrategy hes) -> new StreamingHttpService() { + @Override + public Single handle(final HttpServiceContext ctx, + final StreamingHttpRequest request, + final StreamingHttpResponseFactory responseFactory) { + return succeeded(responseFactory.ok() + .payloadBody(from("Hello World!"), appSerializerUtf8FixLen())); + } + + @Override + public HttpExecutionStrategy requiredOffloads() { + return hes; + } + + public String toString() { + return hes.toString(); + } + }) + .map(service -> Arguments.of(service)); + } + + @ParameterizedTest(name = "{displayName} {index}: service: {0}") + @MethodSource("services") + void testHttpService(StreamingHttpService streamingAsyncService) { + HttpService aggregateService = HttpApiConversions.toHttpService(streamingAsyncService); + HttpExecutionStrategy serviceStrategy = aggregateService.requiredOffloads(); + assertTrue(serviceStrategy.isSendOffloaded(), "Unexpected send strategy " + serviceStrategy); + assertFalse(serviceStrategy.isMetadataReceiveOffloaded(), "Unexpected meta strategy " + serviceStrategy); + assertTrue(serviceStrategy.isDataReceiveOffloaded(), "Unexpected read strategy " + serviceStrategy); + } + + @ParameterizedTest(name = "{displayName} {index}: service: {0}") + @MethodSource("services") + void testBlockingHttpService(StreamingHttpService streamingAsyncService) { + BlockingHttpService blockingHttpService = + HttpApiConversions.toBlockingHttpService(streamingAsyncService); + HttpExecutionStrategy serviceStrategy = blockingHttpService.requiredOffloads(); + assertFalse(serviceStrategy.isSendOffloaded(), "Unexpected send strategy " + serviceStrategy); + assertFalse(serviceStrategy.isMetadataReceiveOffloaded(), "Unexpected meta strategy " + serviceStrategy); + assertTrue(serviceStrategy.isDataReceiveOffloaded(), "Unexpected read strategy " + serviceStrategy); + } + + @ParameterizedTest(name = "{displayName} {index}: service: {0}") + @MethodSource("services") + void testBlockingStreamingHttpService(StreamingHttpService streamingAsyncService) { + BlockingStreamingHttpService blockingStreamingHttpService = + HttpApiConversions.toBlockingStreamingHttpService(streamingAsyncService); + HttpExecutionStrategy serviceStrategy = blockingStreamingHttpService.requiredOffloads(); + assertFalse(serviceStrategy.isSendOffloaded(), "Unexpected send strategy " + serviceStrategy); + assertTrue(serviceStrategy.isMetadataReceiveOffloaded(), "Unexpected meta strategy " + serviceStrategy); + assertFalse(serviceStrategy.isDataReceiveOffloaded(), "Unexpected read strategy " + serviceStrategy); + } +} From f41ce248b789ff416c508648f430ec44a2c72a24 Mon Sep 17 00:00:00 2001 From: Idel Pivnitskiy Date: Fri, 27 May 2022 14:47:54 -0500 Subject: [PATCH 31/40] Enhance logging for execution strategy computation (#2224) Motivation: Users should see when the resulting execution strategy is different from what they configured at the builder and should be able to debug the root cause. Modifications: - Log at `info` level when computed strategy adds more offloading to the custom strategy specified at the builder; - Add debug level logging for each computation step when changes are detected; Result: Users see when strategy changes after analyzing filters and are able to debug the cause. --- .../ClientStrategyInfluencerChainBuilder.java | 78 ++++++++++------- .../http/netty/DefaultHttpServerBuilder.java | 86 +++++++++++-------- ...DefaultSingleAddressHttpClientBuilder.java | 21 ++++- 3 files changed, 116 insertions(+), 69 deletions(-) diff --git a/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/ClientStrategyInfluencerChainBuilder.java b/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/ClientStrategyInfluencerChainBuilder.java index 783b302f47..57a433d385 100644 --- a/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/ClientStrategyInfluencerChainBuilder.java +++ b/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/ClientStrategyInfluencerChainBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright © 2019, 2021 Apple Inc. and the ServiceTalk project authors + * Copyright © 2019, 2021-2022 Apple Inc. and the ServiceTalk project authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -60,69 +60,63 @@ private ClientStrategyInfluencerChainBuilder(ClientStrategyInfluencerChainBuilde } void add(StreamingHttpClientFilterFactory clientFilter) { - add("filter", clientFilter, clientFilter.requiredOffloads()); + add(StreamingHttpClientFilterFactory.class, clientFilter, clientFilter.requiredOffloads()); } + @SuppressWarnings({"rawtypes", "unchecked"}) void add(HttpLoadBalancerFactory lb) { - add("load balancer", lb, lb.requiredOffloads()); + add(HttpLoadBalancerFactory.class, (HttpLoadBalancerFactory) lb, lb.requiredOffloads()); } - private void add(String purpose, ExecutionStrategyInfluencer influencer, HttpExecutionStrategy strategy) { + private > void add( + final Class clazz, final T influencer, HttpExecutionStrategy strategy) { if (offloadNever() == strategy) { - LOGGER.warn("{}#requiredOffloads() returns offloadNever(), which is unexpected. " + - "offloadNone() should be used instead. " + - "Making automatic adjustment, update the {} to avoid this warning.", - influencer, purpose); + offloadNeverWarning(clazz, influencer); strategy = offloadNone(); } if (defaultStrategy() == strategy) { - LOGGER.warn("{}#requiredOffloads() returns defaultStrategy(), which is unexpected. " + - "offloadAll() (safe default) or more appropriate custom strategy should be used instead." + - "Making automatic adjustment, update the {} to avoid this warning.", - influencer, purpose); + defaultStrategyWarning(clazz, influencer); strategy = offloadAll(); } - clientChain = null != clientChain ? clientChain.merge(strategy) : strategy; + @Nullable + final HttpExecutionStrategy clientChain = this.clientChain; + this.clientChain = null != clientChain ? clientChain.merge(strategy) : strategy; + logIfChanges(clazz, influencer, clientChain, this.clientChain); } void add(ConnectionFactoryFilter connectionFactoryFilter) { ExecutionStrategy filterOffloads = connectionFactoryFilter.requiredOffloads(); if (offloadNever() == filterOffloads) { - LOGGER.warn("{}#requiredOffloads() returns offloadNever(), which is unexpected. " + - "offloadNone() should be used instead. " + - "Making automatic adjustment, update the filter.", - connectionFactoryFilter); + offloadNeverWarning(ConnectionFactoryFilter.class, connectionFactoryFilter); filterOffloads = offloadNone(); } if (defaultStrategy() == filterOffloads) { - LOGGER.warn("{}#requiredOffloads() returns defaultStrategy(), which is unexpected. " + - "offloadAll() (safe default) or more appropriate custom strategy should be used instead." + - "Making automatic adjustment, consider updating the filter.", - connectionFactoryFilter); + defaultStrategyWarning(ConnectionFactoryFilter.class, connectionFactoryFilter); filterOffloads = offloadAll(); } - connFactoryChain = null != connFactoryChain ? + @Nullable + final ConnectAndHttpExecutionStrategy connFactoryChain = this.connFactoryChain; + this.connFactoryChain = null != connFactoryChain ? connFactoryChain.merge(filterOffloads) : ConnectAndHttpExecutionStrategy.from(filterOffloads); + logIfChanges(ConnectionFactoryFilter.class, connectionFactoryFilter, connFactoryChain, this.connFactoryChain); } void add(StreamingHttpConnectionFilterFactory connectionFilter) { HttpExecutionStrategy filterOffloads = connectionFilter.requiredOffloads(); if (offloadNever() == filterOffloads) { - LOGGER.warn("{}#requiredOffloads() returns offloadNever(), which is unexpected. " + - "offloadNone() should be used instead. " + - "Making automatic adjustment, consider updating the filter.", - connectionFilter); + offloadNeverWarning(StreamingHttpConnectionFilterFactory.class, connectionFilter); filterOffloads = offloadNone(); } if (defaultStrategy() == filterOffloads) { - LOGGER.warn("{}#requiredOffloads() returns defaultStrategy(), which is unexpected. " + - "offloadAll() (safe default) or more appropriate custom strategy should be used instead." + - "Making automatic adjustment, consider updating the filter.", - connectionFilter); + defaultStrategyWarning(StreamingHttpConnectionFilterFactory.class, connectionFilter); filterOffloads = offloadAll(); } if (filterOffloads.hasOffloads()) { - connFilterChain = null != connFilterChain ? connFilterChain.merge(filterOffloads) : filterOffloads; + @Nullable + final HttpExecutionStrategy connFilterChain = this.connFilterChain; + this.connFilterChain = null != connFilterChain ? connFilterChain.merge(filterOffloads) : filterOffloads; + logIfChanges(StreamingHttpConnectionFilterFactory.class, + connectionFilter, connFilterChain, this.connFilterChain); } } @@ -156,4 +150,26 @@ ExecutionStrategy buildForConnectionFactory() { ClientStrategyInfluencerChainBuilder copy() { return new ClientStrategyInfluencerChainBuilder(this); } + + private static > void offloadNeverWarning(final Class clazz, + final T influencer) { + LOGGER.warn("{}#requiredOffloads() returns offloadNever(), which is unexpected. offloadNone() should be used " + + "instead. Making automatic adjustment, update the {} to avoid this warning.", + influencer, clazz.getSimpleName()); + } + + private static > void defaultStrategyWarning(final Class clazz, + final T influencer) { + LOGGER.warn("{}#requiredOffloads() returns defaultStrategy(), which is unexpected. " + + "offloadAll() (safe default) or more appropriate custom strategy should be used instead." + + "Making automatic adjustment, update the {} to avoid this warning.", + influencer, clazz.getSimpleName()); + } + + private static > void logIfChanges(final Class clazz, + final T influencer, @Nullable final ExecutionStrategy before, @Nullable final ExecutionStrategy after) { + if (before != after) { + LOGGER.debug("{} '{}' changes execution strategy from '{}' to '{}'", clazz, influencer, before, after); + } + } } diff --git a/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/DefaultHttpServerBuilder.java b/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/DefaultHttpServerBuilder.java index 0c9b2f0e90..bc8403c7f0 100644 --- a/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/DefaultHttpServerBuilder.java +++ b/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/DefaultHttpServerBuilder.java @@ -25,6 +25,7 @@ import io.servicetalk.http.api.HttpExecutionContext; import io.servicetalk.http.api.HttpExecutionStrategies; import io.servicetalk.http.api.HttpExecutionStrategy; +import io.servicetalk.http.api.HttpExecutionStrategyInfluencer; import io.servicetalk.http.api.HttpHeaderNames; import io.servicetalk.http.api.HttpLifecycleObserver; import io.servicetalk.http.api.HttpProtocolConfig; @@ -40,7 +41,6 @@ import io.servicetalk.http.api.StreamingHttpServiceFilterFactory; import io.servicetalk.logging.api.LogLevel; import io.servicetalk.transport.api.ConnectionAcceptorFactory; -import io.servicetalk.transport.api.ExecutionStrategy; import io.servicetalk.transport.api.ExecutionStrategyInfluencer; import io.servicetalk.transport.api.IoExecutor; import io.servicetalk.transport.api.ServerSslConfig; @@ -92,7 +92,7 @@ final class DefaultHttpServerBuilder implements HttpServerBuilder { private static StreamingHttpServiceFilterFactory buildFactory(List filters) { return filters.stream() - .reduce((prev, filter) -> strategy -> prev.create(filter.create(strategy))) + .reduce((prev, filter) -> service -> prev.create(filter.create(service))) .orElse(StreamingHttpServiceFilter::new); // unfortunate that we need extra layer } @@ -105,11 +105,17 @@ private static StreamingHttpService buildService(Stream filters, - HttpExecutionStrategy defaultStrategy) { - return filters.stream() - .map(ExecutionStrategyInfluencer::requiredOffloads) - .map(HttpExecutionStrategy::from) - .reduce(defaultStrategy, HttpExecutionStrategy::merge); + HttpExecutionStrategy serviceStrategy) { + HttpExecutionStrategy current = serviceStrategy; + for (StreamingHttpServiceFilterFactory filter : filters) { + HttpExecutionStrategy next = current.merge(filter.requiredOffloads()); + if (current != next) { + LOGGER.debug("{} '{}' changes execution strategy from '{}' to '{}'", + StreamingHttpServiceFilterFactory.class, filter, current, next); + current = next; + } + } + return current; } private static T checkNonOffloading(String desc, HttpExecutionStrategy assumeStrategy, T obj) { @@ -122,15 +128,6 @@ private static T checkNonOffloading(String desc, HttpExecutionStrategy assum return obj; } - private static HttpExecutionStrategy requiredOffloads(Object anything, HttpExecutionStrategy defaultOffloads) { - if (anything instanceof ExecutionStrategyInfluencer) { - ExecutionStrategy requiredOffloads = ((ExecutionStrategyInfluencer) anything).requiredOffloads(); - return HttpExecutionStrategy.from(requiredOffloads); - } else { - return defaultOffloads; - } - } - @Override public HttpServerBuilder drainRequestPayloadBody(final boolean enable) { this.drainRequestPayloadBody = enable; @@ -257,22 +254,24 @@ public HttpServerBuilder bufferAllocator(final BufferAllocator allocator) { @Override public Single listen(final HttpService service) { - return listenForAdapter(toStreamingHttpService(service, computeServiceStrategy(service))); + return listenForAdapter(toStreamingHttpService(service, computeServiceStrategy(HttpService.class, service))); } @Override public Single listenStreaming(final StreamingHttpService service) { - return listenForService(service, computeServiceStrategy(service)); + return listenForService(service, computeServiceStrategy(StreamingHttpService.class, service)); } @Override public Single listenBlocking(final BlockingHttpService service) { - return listenForAdapter(toStreamingHttpService(service, computeServiceStrategy(service))); + return listenForAdapter(toStreamingHttpService(service, + computeServiceStrategy(BlockingHttpService.class, service))); } @Override public Single listenBlockingStreaming(final BlockingStreamingHttpService service) { - return listenForAdapter(toStreamingHttpService(service, computeServiceStrategy(service))); + return listenForAdapter(toStreamingHttpService(service, + computeServiceStrategy(BlockingStreamingHttpService.class, service))); } private HttpExecutionContext buildExecutionContext(final HttpExecutionStrategy strategy) { @@ -298,12 +297,12 @@ private Single listenForAdapter(HttpApiConversions.ServiceAda * * * @param rawService {@link StreamingHttpService} to use for the server. - * @param strategy the {@link HttpExecutionStrategy} to use for the service. + * @param computedStrategy the computed {@link HttpExecutionStrategy} to use for the service. * @return A {@link Single} that completes when the server is successfully started or terminates with an error if * the server could not be started. */ private Single listenForService(final StreamingHttpService rawService, - final HttpExecutionStrategy strategy) { + final HttpExecutionStrategy computedStrategy) { InfluencerConnectionAcceptor connectionAcceptor = connectionAcceptorFactory == null ? null : InfluencerConnectionAcceptor.withStrategy(connectionAcceptorFactory.create(ACCEPT_ALL), connectionAcceptorFactory.requiredOffloads()); @@ -313,28 +312,44 @@ private Single listenForService(final StreamingHttpService ra if (noOffloadServiceFilters.isEmpty()) { filteredService = serviceFilters.isEmpty() ? rawService : buildService(serviceFilters.stream(), rawService); - executionContext = buildExecutionContext(strategy); + executionContext = buildExecutionContext(computedStrategy); } else { Stream nonOffloadingFilters = noOffloadServiceFilters.stream(); - if (strategy.isRequestResponseOffloaded()) { - executionContext = buildExecutionContext(REQRESP_OFFLOADS.missing(strategy)); + if (computedStrategy.isRequestResponseOffloaded()) { + executionContext = buildExecutionContext(REQRESP_OFFLOADS.missing(computedStrategy)); BooleanSupplier shouldOffload = executionContext.ioExecutor().shouldOffloadSupplier(); // We are going to have to offload, even if just to the raw service OffloadingFilter offloadingFilter = - new OffloadingFilter(strategy, buildFactory(serviceFilters), shouldOffload); + new OffloadingFilter(computedStrategy, buildFactory(serviceFilters), shouldOffload); nonOffloadingFilters = Stream.concat(nonOffloadingFilters, Stream.of(offloadingFilter)); } else { // All the filters can be appended. nonOffloadingFilters = Stream.concat(nonOffloadingFilters, serviceFilters.stream()); - executionContext = buildExecutionContext(strategy); + executionContext = buildExecutionContext(computedStrategy); } filteredService = buildService(nonOffloadingFilters, rawService); } + final HttpExecutionStrategy builderStrategy = this.strategy; return doBind(executionContext, connectionAcceptor, filteredService) - .afterOnSuccess(serverContext -> LOGGER.debug("Server for address {} uses strategy {}", - serverContext.listenAddress(), strategy)); + .afterOnSuccess(serverContext -> { + if (builderStrategy != defaultStrategy() && + builderStrategy.missing(computedStrategy) != offloadNone()) { + LOGGER.info("Server for address {} created with the builder strategy {} but resulting " + + "computed strategy is {}. One of the filters or a final service enforce " + + "additional offloading. To find out what filter or service is " + + "it, enable debug level logging for {}.", serverContext.listenAddress(), + builderStrategy, computedStrategy, DefaultHttpServerBuilder.class); + } else if (builderStrategy == computedStrategy) { + LOGGER.debug("Server for address {} created with the execution strategy {}.", + serverContext.listenAddress(), computedStrategy); + } else { + LOGGER.debug("Server for address {} created with the builder strategy {}, " + + "resulting computed strategy is {}.", + serverContext.listenAddress(), builderStrategy, computedStrategy); + } + }); } private Single doBind(final HttpExecutionContext executionContext, @@ -357,11 +372,14 @@ private Single doBind(final HttpExecutionContext executionCon filteredService, drainRequestPayloadBody); } - private HttpExecutionStrategy computeServiceStrategy(Object service) { - HttpExecutionStrategy serviceStrategy = requiredOffloads(service, defaultStrategy()); - HttpExecutionStrategy filterStrategy = computeRequiredStrategy(serviceFilters, serviceStrategy); - return defaultStrategy() == strategy ? filterStrategy : - strategy.hasOffloads() ? strategy.merge(filterStrategy) : strategy; + private HttpExecutionStrategy computeServiceStrategy( + final Class clazz, final T service) { + final HttpExecutionStrategy serviceStrategy = service.requiredOffloads(); + LOGGER.debug("{} '{}' requires {} strategy.", clazz.getSimpleName(), service, serviceStrategy); + final HttpExecutionStrategy builderStrategy = this.strategy; + final HttpExecutionStrategy computedStrategy = computeRequiredStrategy(serviceFilters, serviceStrategy); + return defaultStrategy() == builderStrategy ? computedStrategy : + builderStrategy.hasOffloads() ? builderStrategy.merge(computedStrategy) : builderStrategy; } private static StreamingHttpService applyInternalFilters(StreamingHttpService service, diff --git a/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/DefaultSingleAddressHttpClientBuilder.java b/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/DefaultSingleAddressHttpClientBuilder.java index 9c2c394e10..66f0292944 100644 --- a/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/DefaultSingleAddressHttpClientBuilder.java +++ b/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/DefaultSingleAddressHttpClientBuilder.java @@ -69,6 +69,8 @@ import static io.servicetalk.concurrent.api.AsyncCloseables.newCompositeCloseable; import static io.servicetalk.concurrent.api.Processors.newCompletableProcessor; import static io.servicetalk.concurrent.api.RetryStrategies.retryWithConstantBackoffDeltaJitter; +import static io.servicetalk.http.api.HttpExecutionStrategies.defaultStrategy; +import static io.servicetalk.http.api.HttpExecutionStrategies.offloadNone; import static io.servicetalk.http.api.HttpProtocolVersion.HTTP_1_1; import static io.servicetalk.http.api.HttpProtocolVersion.HTTP_2_0; import static io.servicetalk.http.netty.AlpnIds.HTTP_2; @@ -234,7 +236,7 @@ private static StreamingHttpClient buildStreaming(final HttpClientBuildCo connectionFactoryStrategy = connectionFactoryStrategy.merge(proxy.requiredOffloads()); } - final HttpExecutionStrategy executionStrategy = executionContext.executionStrategy(); + final HttpExecutionStrategy builderStrategy = executionContext.executionStrategy(); // closed by the LoadBalancer final ConnectionFactory connectionFactory; final StreamingHttpRequestResponseFactory reqRespFactory = defaultReqRespFactory(roConfig, @@ -291,9 +293,20 @@ ctx.builder.connectionFilterFactory, new AlpnReqRespFactoryFunc( currClientFilterFactory = appendFilter(currClientFilterFactory, ctx.builder.retryingHttpRequesterFilter); } - HttpExecutionStrategy computedStrategy = ctx.builder.strategyComputation.buildForClient(executionStrategy); - LOGGER.debug("Client for {} created with base strategy {} → computed strategy {}", - targetAddress(ctx), executionStrategy, computedStrategy); + HttpExecutionStrategy computedStrategy = ctx.builder.strategyComputation.buildForClient(builderStrategy); + if (builderStrategy != defaultStrategy() && + builderStrategy.missing(computedStrategy) != offloadNone()) { + LOGGER.info("Client for {} created with the builder strategy {} but resulting computed strategy is " + + "{}. One of the filters enforces additional offloading. To find out what filter is " + + "it, enable debug level logging for {}.", targetAddress(ctx), builderStrategy, + computedStrategy, ClientStrategyInfluencerChainBuilder.class); + } else if (builderStrategy == computedStrategy) { + LOGGER.debug("Client for {} created with the execution strategy {}.", + targetAddress(ctx), computedStrategy); + } else { + LOGGER.debug("Client for {} created with the builder strategy {}, resulting computed strategy is {}.", + targetAddress(ctx), builderStrategy, computedStrategy); + } return new FilterableClientToClient(currClientFilterFactory != null ? currClientFilterFactory.create(lbClient, lb.eventStream(), ctx.sdStatus) : lbClient, computedStrategy); From 599b059ac2f30ef1eeb1081fddba49c3d29c5482 Mon Sep 17 00:00:00 2001 From: Scott Mitchell Date: Fri, 27 May 2022 14:03:36 -0700 Subject: [PATCH 32/40] Update protobuf 3.20.0 -> 3.21.0 (#2231) --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 2a1f855b94..6ee0a640fc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -55,7 +55,7 @@ zipkinReporterVersion=2.16.3 # gRPC protobufGradlePluginVersion=0.8.18 -protobufVersion=3.20.0 +protobufVersion=3.21.0 protoGoogleCommonProtosVersion=2.8.1 javaPoetVersion=1.13.0 shadowPluginVersion=7.1.1 From 9c4e932f014a8d450cb690b56f4069cb6aa50761 Mon Sep 17 00:00:00 2001 From: Scott Mitchell Date: Fri, 27 May 2022 15:41:14 -0700 Subject: [PATCH 33/40] Avoid direct usage of RuntimeException (#2228) Motivation: In some instances we use APIs that throw checked exceptions from methods without checked throws exception in the method signature. In some of these instances we wrap in a RuntimeException, however this doesn't provide any insight into the exception being thrown. Recent spotbugs warnings highlights these cases. Modifications: - DefaultExecutor to rethrow checked exception which is used internally to terminate async control flow - RequestResponseFactories factory methods to rethrow checked exceptions. - Zipkin UdpReporter report method to throw ClosedChannelException if already closed. --- .../gradle/spotbugs/main-exclusions.xml | 10 ---------- .../concurrent/api/DefaultExecutor.java | 3 ++- .../concurrent/api/FromIterablePublisher.java | 4 ++-- .../api/PublisherAsBlockingIterable.java | 6 ++---- .../api/PublisherConcatMapIterable.java | 4 ++-- .../gradle/spotbugs/main-exclusions.xml | 8 -------- .../internal/AbstractCloseableIterable.java | 4 +++- .../internal/AutoClosableUtils.java | 19 +++++++++++++++++++ .../gradle/spotbugs/main-exclusions.xml | 13 ------------- .../http/api/FormUrlEncodedSerializer.java | 2 +- .../http/api/RequestResponseFactories.java | 17 +++++------------ .../http/netty/NettyHttpServerTest.java | 9 +++------ .../gradle/spotbugs/main-exclusions.xml | 6 ------ .../publisher/reporter/UdpReporter.java | 3 ++- .../publisher/reporter/UdpReporterTest.java | 3 ++- .../DefaultSerializerDeserializationTest.java | 12 ++++++------ 16 files changed, 49 insertions(+), 74 deletions(-) diff --git a/servicetalk-concurrent-api/gradle/spotbugs/main-exclusions.xml b/servicetalk-concurrent-api/gradle/spotbugs/main-exclusions.xml index 972aa5f78a..8f37d389d4 100644 --- a/servicetalk-concurrent-api/gradle/spotbugs/main-exclusions.xml +++ b/servicetalk-concurrent-api/gradle/spotbugs/main-exclusions.xml @@ -83,19 +83,9 @@ - - - - - - - - - - diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/DefaultExecutor.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/DefaultExecutor.java index 3df3a6acf7..3e0112bcd5 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/DefaultExecutor.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/DefaultExecutor.java @@ -36,6 +36,7 @@ import javax.annotation.Nullable; import static io.servicetalk.concurrent.Cancellable.IGNORE_CANCEL; +import static io.servicetalk.utils.internal.PlatformDependent.throwException; import static java.lang.Thread.NORM_PRIORITY; import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; import static java.util.concurrent.TimeUnit.SECONDS; @@ -157,7 +158,7 @@ private static void shutdownExecutor(java.util.concurrent.Executor jdkExecutor) try { ((AutoCloseable) jdkExecutor).close(); } catch (Exception e) { - throw new RuntimeException("unexpected exception while closing executor: " + jdkExecutor, e); + throwException(e); } } } diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/FromIterablePublisher.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/FromIterablePublisher.java index f3c38fd6e0..81e5a28255 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/FromIterablePublisher.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/FromIterablePublisher.java @@ -21,7 +21,7 @@ import java.util.Iterator; import java.util.concurrent.TimeoutException; -import static io.servicetalk.concurrent.internal.AutoClosableUtils.closeAndReThrowUnchecked; +import static io.servicetalk.concurrent.internal.AutoClosableUtils.closeAndReThrow; import static io.servicetalk.concurrent.internal.FlowControlUtils.addWithOverflowProtection; import static io.servicetalk.concurrent.internal.SubscriberUtils.handleExceptionFromOnSubscribe; import static io.servicetalk.concurrent.internal.SubscriberUtils.isRequestNValid; @@ -113,7 +113,7 @@ public final void request(final long n) { public final void cancel() { cleanupForCancel(); if (iterator instanceof AutoCloseable) { - closeAndReThrowUnchecked((AutoCloseable) iterator); + closeAndReThrow((AutoCloseable) iterator); } } diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/PublisherAsBlockingIterable.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/PublisherAsBlockingIterable.java index 4ba4ba35ef..229470f018 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/PublisherAsBlockingIterable.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/PublisherAsBlockingIterable.java @@ -39,6 +39,7 @@ import static io.servicetalk.concurrent.api.SubscriberApiUtils.wrapNull; import static io.servicetalk.concurrent.internal.TerminalNotification.complete; import static io.servicetalk.concurrent.internal.TerminalNotification.error; +import static io.servicetalk.utils.internal.PlatformDependent.throwException; import static java.lang.Math.min; import static java.lang.Thread.currentThread; import static java.util.Objects.requireNonNull; @@ -255,10 +256,7 @@ private T processNext() { if (cause == null) { throw new NoSuchElementException(); } - if (cause instanceof RuntimeException) { - throw (RuntimeException) cause; - } - throw new RuntimeException(cause); + throwException(cause); } return unwrapNullUnchecked(signal); } diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/PublisherConcatMapIterable.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/PublisherConcatMapIterable.java index 4e7c1a9bfa..5bdabc1314 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/PublisherConcatMapIterable.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/PublisherConcatMapIterable.java @@ -26,7 +26,7 @@ import java.util.function.Function; import javax.annotation.Nullable; -import static io.servicetalk.concurrent.internal.AutoClosableUtils.closeAndReThrowUnchecked; +import static io.servicetalk.concurrent.internal.AutoClosableUtils.closeAndReThrow; import static io.servicetalk.concurrent.internal.ConcurrentUtils.releaseLock; import static io.servicetalk.concurrent.internal.ConcurrentUtils.tryAcquireLock; import static io.servicetalk.concurrent.internal.SubscriberUtils.checkDuplicateSubscription; @@ -161,7 +161,7 @@ private void doCancel() { private static void tryClose(final Iterator currentIterator) { if (currentIterator instanceof AutoCloseable) { - closeAndReThrowUnchecked(((AutoCloseable) currentIterator)); + closeAndReThrow(((AutoCloseable) currentIterator)); } } diff --git a/servicetalk-concurrent-internal/gradle/spotbugs/main-exclusions.xml b/servicetalk-concurrent-internal/gradle/spotbugs/main-exclusions.xml index 8880bc393a..55a4525fa4 100644 --- a/servicetalk-concurrent-internal/gradle/spotbugs/main-exclusions.xml +++ b/servicetalk-concurrent-internal/gradle/spotbugs/main-exclusions.xml @@ -37,14 +37,6 @@ - - - - - - - - diff --git a/servicetalk-concurrent-internal/src/main/java/io/servicetalk/concurrent/internal/AbstractCloseableIterable.java b/servicetalk-concurrent-internal/src/main/java/io/servicetalk/concurrent/internal/AbstractCloseableIterable.java index 5a43900f6b..5d01de53c0 100644 --- a/servicetalk-concurrent-internal/src/main/java/io/servicetalk/concurrent/internal/AbstractCloseableIterable.java +++ b/servicetalk-concurrent-internal/src/main/java/io/servicetalk/concurrent/internal/AbstractCloseableIterable.java @@ -21,6 +21,8 @@ import java.util.Iterator; import java.util.NoSuchElementException; +import static io.servicetalk.utils.internal.PlatformDependent.throwException; + /** * An abstract implementation of {@link CloseableIterable} that wraps an {@link Iterable}. * @@ -58,7 +60,7 @@ public boolean hasNext() { try { close(); } catch (Exception e) { - throw new RuntimeException(e); + throwException(e); } } return false; diff --git a/servicetalk-concurrent-internal/src/main/java/io/servicetalk/concurrent/internal/AutoClosableUtils.java b/servicetalk-concurrent-internal/src/main/java/io/servicetalk/concurrent/internal/AutoClosableUtils.java index 31720bc5fb..22705845b7 100644 --- a/servicetalk-concurrent-internal/src/main/java/io/servicetalk/concurrent/internal/AutoClosableUtils.java +++ b/servicetalk-concurrent-internal/src/main/java/io/servicetalk/concurrent/internal/AutoClosableUtils.java @@ -16,6 +16,9 @@ package io.servicetalk.concurrent.internal; import java.io.IOException; +import java.io.UncheckedIOException; + +import static io.servicetalk.utils.internal.PlatformDependent.throwException; /** * Utilities for {@link AutoCloseable}. @@ -28,15 +31,31 @@ private AutoClosableUtils() { /** * Call {@link AutoCloseable#close()} and re-throw any exceptions as an unchecked exception. * @param closeable The object to close. + * @deprecated Use {@link #closeAndReThrow(AutoCloseable)}. */ + @Deprecated public static void closeAndReThrowUnchecked(AutoCloseable closeable) { try { closeable.close(); + } catch (IOException e) { + throw new UncheckedIOException(e); } catch (Exception e) { throw new RuntimeException(e); } } + /** + * Call {@link AutoCloseable#close()} and re-throw any exception. + * @param closeable The object to close. + */ + public static void closeAndReThrow(AutoCloseable closeable) { + try { + closeable.close(); + } catch (Exception e) { + throwException(e); + } + } + /** * Call {@link AutoCloseable#close()} and re-throw any exceptions as a {@link IOException}. * @param closeable The object to close. diff --git a/servicetalk-http-api/gradle/spotbugs/main-exclusions.xml b/servicetalk-http-api/gradle/spotbugs/main-exclusions.xml index 3955ff0ab2..9d651fcfe6 100644 --- a/servicetalk-http-api/gradle/spotbugs/main-exclusions.xml +++ b/servicetalk-http-api/gradle/spotbugs/main-exclusions.xml @@ -244,11 +244,6 @@ - - - - - @@ -318,12 +313,4 @@ - - - - - - - - diff --git a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/FormUrlEncodedSerializer.java b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/FormUrlEncodedSerializer.java index c30ed42e96..43e7b2932a 100644 --- a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/FormUrlEncodedSerializer.java +++ b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/FormUrlEncodedSerializer.java @@ -134,7 +134,7 @@ private static byte[] urlEncode(final String value, Charset charset) { try { return URLEncoder.encode(value, charset.name()).getBytes(charset); } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); + throw new IllegalStateException("URLDecoder failed to find Charset: " + charset, e); } } } diff --git a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/RequestResponseFactories.java b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/RequestResponseFactories.java index 22dd3d7a55..3deb3ad4b9 100644 --- a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/RequestResponseFactories.java +++ b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/RequestResponseFactories.java @@ -18,7 +18,6 @@ import java.util.concurrent.ExecutionException; import static io.servicetalk.utils.internal.PlatformDependent.throwException; -import static java.lang.Thread.currentThread; final class RequestResponseFactories { @@ -123,26 +122,20 @@ public HttpResponse newResponse(final HttpResponseStatus status) { } private static HttpRequest newRequestBlocking(StreamingHttpRequestFactory requestFactory, - HttpRequestMethod method, String requestTarget) { + HttpRequestMethod method, String requestTarget) { try { return requestFactory.newRequest(method, requestTarget).toRequest().toFuture().get(); - } catch (InterruptedException e) { - currentThread().interrupt(); // Reset the interrupted flag. + } catch (InterruptedException | ExecutionException e) { return throwException(e); - } catch (ExecutionException e) { - throw new RuntimeException(e); } } private static HttpResponse newResponseBlocking(StreamingHttpResponseFactory responseFactory, - HttpResponseStatus status) { + HttpResponseStatus status) { try { return responseFactory.newResponse(status).toResponse().toFuture().get(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new RuntimeException(e); - } catch (ExecutionException e) { - throw new RuntimeException(e); + } catch (InterruptedException | ExecutionException e) { + return throwException(e); } } } diff --git a/servicetalk-http-netty/src/test/java/io/servicetalk/http/netty/NettyHttpServerTest.java b/servicetalk-http-netty/src/test/java/io/servicetalk/http/netty/NettyHttpServerTest.java index 1cff23fd94..b646f2e433 100644 --- a/servicetalk-http-netty/src/test/java/io/servicetalk/http/netty/NettyHttpServerTest.java +++ b/servicetalk-http-netty/src/test/java/io/servicetalk/http/netty/NettyHttpServerTest.java @@ -91,7 +91,6 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.Matchers.startsWith; -import static org.hamcrest.core.CombinableMatcher.either; import static org.hamcrest.core.IsInstanceOf.instanceOf; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -595,14 +594,12 @@ void testErrorBeforeRead(ExecutorSupplier clientExecutorSupplier, final BlockingIterator httpPayloadChunks = response.payloadBody().toIterable().iterator(); - Exception e = assertThrows(Exception.class, httpPayloadChunks::next); - assertThat(e, either(instanceOf(RuntimeException.class)).or(instanceOf(ExecutionException.class))); // Due to a race condition, the exception cause here can vary. // If the socket closure is delayed slightly // (for example, by delaying the Publisher.error(...) on the server) // then the client throws ClosedChannelException. However if the socket closure happens quickly enough, // the client throws NativeIoException (KQueue) or IOException (NIO). - assertThat(e.getCause(), instanceOf(IOException.class)); + assertThrows(IOException.class, httpPayloadChunks::next); } catch (Throwable cause) { // The server intentionally triggers an error when it writes, if this happens before all content is read // the client may fail to write the request due to premature connection closure. @@ -640,8 +637,8 @@ void testErrorDuringRead(ExecutorSupplier clientExecutorSupplier, sb.append(httpPayloadChunks.next().toString(US_ASCII)); } fail("Server should close upon receiving the request"); - } catch (RuntimeException wrapped) { // BlockingIterator wraps - assertClientTransportInboundClosed(wrapped.getCause()); + } catch (Throwable cause) { + assertClientTransportInboundClosed(cause); } assertEquals("Goodbyecruelworld!", sb.toString()); assertConnectionClosed(); diff --git a/servicetalk-opentracing-zipkin-publisher/gradle/spotbugs/main-exclusions.xml b/servicetalk-opentracing-zipkin-publisher/gradle/spotbugs/main-exclusions.xml index 2c526f31be..8aa484e8a7 100644 --- a/servicetalk-opentracing-zipkin-publisher/gradle/spotbugs/main-exclusions.xml +++ b/servicetalk-opentracing-zipkin-publisher/gradle/spotbugs/main-exclusions.xml @@ -31,10 +31,4 @@ - - - - - - diff --git a/servicetalk-opentracing-zipkin-publisher/src/main/java/io/servicetalk/opentracing/zipkin/publisher/reporter/UdpReporter.java b/servicetalk-opentracing-zipkin-publisher/src/main/java/io/servicetalk/opentracing/zipkin/publisher/reporter/UdpReporter.java index 5204822ad1..8cd41afebc 100644 --- a/servicetalk-opentracing-zipkin-publisher/src/main/java/io/servicetalk/opentracing/zipkin/publisher/reporter/UdpReporter.java +++ b/servicetalk-opentracing-zipkin-publisher/src/main/java/io/servicetalk/opentracing/zipkin/publisher/reporter/UdpReporter.java @@ -50,6 +50,7 @@ import javax.annotation.Nullable; import static io.netty.channel.ChannelOption.RCVBUF_ALLOCATOR; +import static io.netty.util.internal.PlatformDependent.throwException; import static io.servicetalk.concurrent.internal.FutureUtils.awaitTermination; import static io.servicetalk.transport.netty.internal.BuilderUtils.datagramChannel; import static io.servicetalk.transport.netty.internal.EventLoopAwareNettyIoExecutors.toEventLoopAwareNettyIoExecutor; @@ -215,7 +216,7 @@ public CheckResult check() { @Override public void report(final Span span) { if (!channel.isActive()) { - throw new RuntimeException(StacklessClosedChannelException.newInstance(this.getClass(), "report")); + throwException(StacklessClosedChannelException.newInstance(this.getClass(), "report")); } channel.writeAndFlush(span); } diff --git a/servicetalk-opentracing-zipkin-publisher/src/test/java/io/servicetalk/opentracing/zipkin/publisher/reporter/UdpReporterTest.java b/servicetalk-opentracing-zipkin-publisher/src/test/java/io/servicetalk/opentracing/zipkin/publisher/reporter/UdpReporterTest.java index 3c2b7f917a..cb3e839df7 100644 --- a/servicetalk-opentracing-zipkin-publisher/src/test/java/io/servicetalk/opentracing/zipkin/publisher/reporter/UdpReporterTest.java +++ b/servicetalk-opentracing-zipkin-publisher/src/test/java/io/servicetalk/opentracing/zipkin/publisher/reporter/UdpReporterTest.java @@ -35,6 +35,7 @@ import java.io.Closeable; import java.net.InetSocketAddress; +import java.nio.channels.ClosedChannelException; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingDeque; @@ -108,7 +109,7 @@ void reportAfterClose() throws Exception { assertThat("Unexpected check state.", reporter.check(), is(OK)); reporter.close(); assertThat("Unexpected check state.", reporter.check(), is(not(OK))); - assertThrows(RuntimeException.class, () -> reporter.report(newSpan("1")), + assertThrows(ClosedChannelException.class, () -> reporter.report(newSpan("1")), "Report post close accepted."); } } diff --git a/servicetalk-serialization-api/src/test/java/io/servicetalk/serialization/api/DefaultSerializerDeserializationTest.java b/servicetalk-serialization-api/src/test/java/io/servicetalk/serialization/api/DefaultSerializerDeserializationTest.java index 038edc49ad..b2f04e6127 100644 --- a/servicetalk-serialization-api/src/test/java/io/servicetalk/serialization/api/DefaultSerializerDeserializationTest.java +++ b/servicetalk-serialization-api/src/test/java/io/servicetalk/serialization/api/DefaultSerializerDeserializationTest.java @@ -256,8 +256,8 @@ void iterableCompletesWithLeftOverData() { try { iterator.hasNext(); Assertions.fail(); - } catch (RuntimeException re) { - assertThat("Unexpected exception.", re.getCause(), sameInstance(e)); + } catch (SerializationException se) { + assertThat(se, sameInstance(e)); } verify(deSerializer).close(); } @@ -308,8 +308,8 @@ void deserializeIncompleteAggregatedWithType() { try { deserialized.iterator().hasNext(); Assertions.fail(); - } catch (RuntimeException re) { - assertThat("Unexpected exception.", re.getCause(), sameInstance(e)); + } catch (SerializationException se) { + assertThat(se, sameInstance(e)); } verify(deSerializer).close(); } @@ -331,8 +331,8 @@ void deserializeIncompleteAggregatedWithTypeHolder() { try { deserialized.iterator().hasNext(); Assertions.fail(); - } catch (RuntimeException re) { - assertThat("Unexpected exception.", re.getCause(), sameInstance(e)); + } catch (SerializationException se) { + assertThat(se, sameInstance(e)); } verify(listDeSerializer).close(); } From e43761c8fcaf7d73b67b117bdeb69082d0f167a2 Mon Sep 17 00:00:00 2001 From: Dom Corvasce Date: Wed, 1 Jun 2022 20:21:29 +0200 Subject: [PATCH 34/40] Update `http` documentation links to `https` (#2232) Motivation: There are many links to external documentation and specifications contained in the ServiceTalk source code. Many of these links are currently `http` links where they could be `https` links. Modifications: Replace use of `http` URL with equivalent `https` URL. Result: Documentation refers to canonical `https` links where available. Co-authored-by: Dom Corvasce --- .gitignore | 2 +- .../concurrent/api/Completable.java | 54 ++--- .../servicetalk/concurrent/api/Executor.java | 4 +- .../servicetalk/concurrent/api/Publisher.java | 194 +++++++++--------- .../io/servicetalk/concurrent/api/Single.java | 78 +++---- .../grpc/routeguide/RouteSummaryBuilder.java | 2 +- .../http/uds/blocking/BlockingUdsClient.java | 2 +- .../http/uds/blocking/BlockingUdsServer.java | 2 +- .../http/api/RedirectConfigBuilder.java | 4 +- .../http/netty/HttpRequestEncoder.java | 2 +- .../netty/RetryingHttpRequesterFilter.java | 6 +- .../internal/ZipkinHeaderNames.java | 2 +- .../transport/api/DomainSocketAddress.java | 4 +- 13 files changed, 178 insertions(+), 178 deletions(-) diff --git a/.gitignore b/.gitignore index bf5f3a2f4c..854d653a60 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +# virtual machine crash logs, see https://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* # intellij diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/Completable.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/Completable.java index 2637d02788..887e87bcc0 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/Completable.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/Completable.java @@ -93,7 +93,7 @@ protected Completable() { } * } * @return A {@link Completable} which transform errors emitted on this {@link Completable} into a * {@link Subscriber#onComplete()} signal (e.g. swallows the error). - * @see ReactiveX catch operator. + * @see ReactiveX catch operator. */ public final Completable onErrorComplete() { return onErrorComplete(t -> true); @@ -117,7 +117,7 @@ public final Completable onErrorComplete() { * @param The {@link Throwable} type. * @return A {@link Completable} which transform errors emitted on this {@link Completable} which match {@code type} * into a {@link Subscriber#onComplete()} signal (e.g. swallows the error). - * @see ReactiveX catch operator. + * @see ReactiveX catch operator. */ public final Completable onErrorComplete(Class type) { return onErrorComplete(type::isInstance); @@ -141,7 +141,7 @@ public final Completable onErrorComplete(Class type) { * {@link Subscriber#onComplete()} signal. Returns {@code false} to propagate the error. * @return A {@link Completable} which transform errors emitted on this {@link Completable} which match * {@code predicate} into a {@link Subscriber#onComplete()} signal (e.g. swallows the error). - * @see ReactiveX catch operator. + * @see ReactiveX catch operator. */ public final Completable onErrorComplete(Predicate predicate) { return new OnErrorCompleteCompletable(this, predicate); @@ -160,7 +160,7 @@ public final Completable onErrorComplete(Predicate predicate) * } * @param mapper returns the error used to terminate the returned {@link Completable}. * @return A {@link Completable} which transform errors emitted on this {@link Completable} into a different error. - * @see ReactiveX catch operator. + * @see ReactiveX catch operator. */ public final Completable onErrorMap(Function mapper) { return onErrorMap(t -> true, mapper); @@ -185,7 +185,7 @@ public final Completable onErrorMap(Function The type of {@link Throwable} to transform. * @return A {@link Completable} which transform errors emitted on this {@link Completable} into a different error. - * @see ReactiveX catch operator. + * @see ReactiveX catch operator. */ public final Completable onErrorMap( Class type, Function mapper) { @@ -213,7 +213,7 @@ public final Completable onErrorMap( * {@code false} to propagate the original error. * @param mapper returns the error used to terminate the returned {@link Completable}. * @return A {@link Completable} which transform errors emitted on this {@link Completable} into a different error. - * @see ReactiveX catch operator. + * @see ReactiveX catch operator. */ public final Completable onErrorMap(Predicate predicate, Function mapper) { @@ -265,7 +265,7 @@ public final Completable onErrorResume(Function The type of {@link Throwable} to transform. * @return A {@link Completable} that recovers from an error from this {@code Publisher} by using another * {@link Completable} provided by the passed {@code nextFactory}. - * @see ReactiveX catch operator. + * @see ReactiveX catch operator. */ public final Completable onErrorResume( Class type, Function nextFactory) { @@ -298,7 +298,7 @@ public final Completable onErrorResume( * @param nextFactory Returns the next {@link Completable}, when this {@link Completable} emits an error. * @return A {@link Completable} that recovers from an error from this {@link Completable} by using another * {@link Completable} provided by the passed {@code nextFactory}. - * @see ReactiveX catch operator. + * @see ReactiveX catch operator. */ public final Completable onErrorResume(Predicate predicate, Function nextFactory) { @@ -466,7 +466,7 @@ public final Completable whenCancel(Runnable onCancel) { * @param unit The units for {@code duration}. * @return a new {@link Completable} that will mimic the signals of this {@link Completable} but will terminate with * a {@link TimeoutException} if time {@code duration} elapses before {@link Subscriber#onComplete()}. - * @see ReactiveX timeout operator. + * @see ReactiveX timeout operator. */ public final Completable timeout(long duration, TimeUnit unit) { return timeout(duration, unit, global()); @@ -486,7 +486,7 @@ public final Completable timeout(long duration, TimeUnit unit) { * notifications. * @return a new {@link Completable} that will mimic the signals of this {@link Completable} but will terminate with * a {@link TimeoutException} if time {@code duration} elapses before {@link Subscriber#onComplete()}. - * @see ReactiveX timeout operator. + * @see ReactiveX timeout operator. */ public final Completable timeout(long duration, TimeUnit unit, io.servicetalk.concurrent.Executor timeoutExecutor) { @@ -504,7 +504,7 @@ public final Completable timeout(long duration, TimeUnit unit, * @param duration The time duration which is allowed to elapse before {@link Subscriber#onComplete()}. * @return a new {@link Completable} that will mimic the signals of this {@link Completable} but will terminate with * a {@link TimeoutException} if time {@code duration} elapses before {@link Subscriber#onComplete()}. - * @see ReactiveX timeout operator. + * @see ReactiveX timeout operator. */ public final Completable timeout(Duration duration) { return timeout(duration, global()); @@ -523,7 +523,7 @@ public final Completable timeout(Duration duration) { * notifications. * @return a new {@link Completable} that will mimic the signals of this {@link Completable} but will terminate with * a {@link TimeoutException} if time {@code duration} elapses before {@link Subscriber#onComplete()}. - * @see ReactiveX timeout operator. + * @see ReactiveX timeout operator. */ public final Completable timeout(Duration duration, io.servicetalk.concurrent.Executor timeoutExecutor) { return new TimeoutCompletable(this, duration, timeoutExecutor); @@ -722,7 +722,7 @@ public final Completable merge(Iterable other) { * It terminates with an error when any one of this {@link Completable} or passed {@link Publisher} terminates with * an error. * - * @see ReactiveX merge operator. + * @see ReactiveX merge operator. */ public final Publisher merge(Publisher mergeWith) { return new CompletableMergeWithPublisher<>(this, mergeWith, false); @@ -761,7 +761,7 @@ public final Publisher merge(Publisher mergeWith) { * {@link Completable} and the passed {@link Publisher} terminate. If either terminates with an error then the * error will be propagated to the return value. * - * @see ReactiveX merge operator. + * @see ReactiveX merge operator. */ public final Publisher mergeDelayError(Publisher mergeWith) { return new CompletableMergeWithPublisher<>(this, mergeWith, true); @@ -922,7 +922,7 @@ public final Completable mergeDelayError(Iterable other) * @return A {@link Completable} that completes with this {@link Completable} or re-subscribes if an error is * emitted and if the passed {@link BiPredicate} returned {@code true}. * - * @see ReactiveX retry operator. + * @see ReactiveX retry operator. */ public final Completable retry(BiIntPredicate shouldRetry) { return toSingle().retry(shouldRetry).ignoreElement(); @@ -966,7 +966,7 @@ public final Completable retry(BiIntPredicate shouldRetry) { * @return A {@link Completable} that completes with this {@link Completable} or re-subscribes if an error is * emitted and {@link Completable} returned by {@link BiFunction} completes successfully. * - * @see ReactiveX retry operator. + * @see ReactiveX retry operator. */ public final Completable retryWhen(BiIntFunction retryWhen) { return toSingle().retryWhen(retryWhen).ignoreElement(); @@ -993,7 +993,7 @@ public final Completable retryWhen(BiIntFunctionReactiveX repeat operator. + * @see ReactiveX repeat operator. */ public final Publisher repeat(IntPredicate shouldRepeat) { return toSingle().repeat(shouldRepeat); @@ -1027,7 +1027,7 @@ public final Publisher repeat(IntPredicate shouldRepeat) { * re-subscribed when this {@link Completable} completes. * @return A {@link Completable} that completes after all re-subscriptions completes. * - * @see ReactiveX retry operator. + * @see ReactiveX retry operator. */ public final Publisher repeatWhen(IntFunction repeatWhen) { return toSingle().repeatWhen(repeatWhen); @@ -1233,7 +1233,7 @@ public final Completable beforeCancel(Runnable onCancel) { * * for Subscriptions/{@link Subscriber}s of the returned {@link Completable}. MUST NOT throw. * @return The new {@link Completable}. - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Completable beforeFinally(Runnable doFinally) { return beforeFinally(new RunnableTerminalSignalConsumer(doFinally)); @@ -1265,7 +1265,7 @@ public final Completable beforeFinally(Runnable doFinally) { * @param doFinally For each subscribe of the returned {@link Completable}, at most one method of this * {@link TerminalSignalConsumer} will be invoked. * @return The new {@link Completable}. - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Completable beforeFinally(TerminalSignalConsumer doFinally) { return new BeforeFinallyCompletable(this, doFinally); @@ -1399,7 +1399,7 @@ public final Completable afterCancel(Runnable onCancel) { * * for Subscriptions/{@link Subscriber}s of the returned {@link Completable}. MUST NOT throw. * @return The new {@link Completable}. - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Completable afterFinally(Runnable doFinally) { return afterFinally(new RunnableTerminalSignalConsumer(doFinally)); @@ -1431,7 +1431,7 @@ public final Completable afterFinally(Runnable doFinally) { * @param doFinally For each subscribe of the returned {@link Completable}, at most one method of this * {@link TerminalSignalConsumer} will be invoked. * @return The new {@link Completable}. - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Completable afterFinally(TerminalSignalConsumer doFinally) { return new AfterFinallyCompletable(this, doFinally); @@ -1651,7 +1651,7 @@ public final Completable shareContextOnSubscribe() { * @return A new {@link Completable} that terminates with the result (either success or error) of either this * {@link Completable} or the passed {@code other} {@link Completable}, whichever terminates first. Therefore the * result is said to be ambiguous relative to which source it originated from. - * @see ReactiveX amb operator. + * @see ReactiveX amb operator. */ public final Completable ambWith(final Completable other) { return toSingle().ambWith(other.toSingle()).ignoreElement(); @@ -2135,7 +2135,7 @@ public static Completable mergeAllDelayError(int maxConcurrency, Completable... * @return A new {@link Completable} that terminates with the result (either success or error) of whichever amongst * the passed {@code completables} that terminates first. Therefore the result is said to be * ambiguous relative to which source it originated from. - * @see ReactiveX amb operator. + * @see ReactiveX amb operator. */ public static Completable amb(final Completable... completables) { return Single.amb(stream(spliterator(completables), false) @@ -2159,7 +2159,7 @@ public static Completable amb(final Completable... completables) { * @return A new {@link Completable} that terminates with the result (either success or error) of whichever amongst * the passed {@code completables} that terminates first. Therefore the result is said to be * ambiguous relative to which source it originated from. - * @see ReactiveX amb operator. + * @see ReactiveX amb operator. */ public static Completable amb(final Iterable completables) { return Single.amb(stream(completables.spliterator(), false) @@ -2181,7 +2181,7 @@ public static Completable amb(final Iterable completables) { * @param completables {@link Completable}s which to subscribe to and race to propagate to the return value. * @return A new {@link Completable} that terminates with the result (either success or error) of whichever amongst * the passed {@code completables} that terminates first. - * @see ReactiveX amb operator. + * @see ReactiveX amb operator. */ public static Completable anyOf(final Completable... completables) { return amb(completables); @@ -2203,7 +2203,7 @@ public static Completable anyOf(final Completable... completables) { * @return A new {@link Completable} that terminates with the result (either success or error) of whichever amongst * the passed {@code completables} that terminates first. * that result. - * @see ReactiveX amb operator. + * @see ReactiveX amb operator. */ public static Completable anyOf(final Iterable completables) { return amb(completables); diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/Executor.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/Executor.java index eba19dc511..be74a27899 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/Executor.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/Executor.java @@ -35,7 +35,7 @@ public interface Executor extends io.servicetalk.concurrent.Executor, Listenable * @param delay The time duration which is allowed to elapse between subscribe and termination. * @param unit The units for {@code duration}. * @return a new {@link Completable} that will complete after the time duration expires. - * @see ReactiveX Timer. + * @see ReactiveX Timer. */ default Completable timer(long delay, TimeUnit unit) { return new TimerCompletable(delay, unit, this); @@ -46,7 +46,7 @@ default Completable timer(long delay, TimeUnit unit) { * @param delay The time duration which is allowed to elapse between subscribe and termination. * * @return a new {@link Completable} that will complete after the time duration expires. - * @see ReactiveX Timer. + * @see ReactiveX Timer. */ default Completable timer(Duration delay) { return new TimerCompletable(delay, this); diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/Publisher.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/Publisher.java index 6d4b2f9e9a..a7aff6eb88 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/Publisher.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/Publisher.java @@ -112,7 +112,7 @@ protected Publisher() { * @param Type of the items emitted by the returned {@link Publisher}. * @return A {@link Publisher} that transforms elements emitted by this {@link Publisher} into a different type. * - * @see ReactiveX map operator. + * @see ReactiveX map operator. */ public final Publisher map(Function mapper) { return new MapPublisher<>(this, mapper); @@ -155,7 +155,7 @@ public final Publisher cast(Class clazz) { * * @param predicate for the filter. * @return A {@link Publisher} that only emits the items that pass the {@code predicate}. - * @see ReactiveX filter operator. + * @see ReactiveX filter operator. */ public final Publisher filter(Predicate predicate) { return filter(() -> predicate); @@ -202,8 +202,8 @@ public final Publisher ofType(Class clazz) { * {@code true} the item is emitted to the returned {@link Publisher}. This {@link Predicate} is unique per * subscribe and may therefore keep state and can be used for example to track distinct signals. * @return A {@link Publisher} emits filtered signals observed by this {@link Publisher}. - * @see ReactiveX filter operator. - * @see ReactiveX distinct operator. + * @see ReactiveX filter operator. + * @see ReactiveX distinct operator. */ final Publisher filter(Supplier> filterSupplier) { return new FilterPublisher<>(this, filterSupplier); @@ -223,7 +223,7 @@ final Publisher filter(Supplier> filterSupplie * } * * @return A {@link Publisher} that emits distinct signals observed by this {@link Publisher}. - * @see ReactiveX distinct operator. + * @see ReactiveX distinct operator. */ public final Publisher distinct() { return filter(newDistinctSupplier()); @@ -249,7 +249,7 @@ public final Publisher distinct() { * {@link Subscriber#onNext(Object)} from this {@link Publisher}. * @param Type of the items emitted by the returned {@link Publisher}. * @return A {@link Publisher} that transforms elements emitted by this {@link Publisher} into a different type. - * @see ReactiveX scan operator. + * @see ReactiveX scan operator. */ public final Publisher scanWith(Supplier initial, BiFunction accumulator) { return new ScanWithPublisher<>(this, initial, accumulator); @@ -283,7 +283,7 @@ public final Publisher scanWith(Supplier initial, BiFunction Type of the items emitted by the returned {@link Publisher}. * @return A {@link Publisher} that transforms elements emitted by this {@link Publisher} into a different type. - * @see ReactiveX scan operator. + * @see ReactiveX scan operator. */ public final Publisher scanWith(Supplier> mapperSupplier) { return new ScanWithPublisher<>(this, mapperSupplier); @@ -325,7 +325,7 @@ public final Publisher scanWith(Supplier Type of the items emitted by the returned {@link Publisher}. * @return A {@link Publisher} that transforms elements emitted by this {@link Publisher} into a different type. - * @see ReactiveX scan operator. + * @see ReactiveX scan operator. */ public final Publisher scanWithLifetime( Supplier> mapperSupplier) { @@ -348,7 +348,7 @@ public final Publisher scanWithLifetime( * } * @return A {@link Publisher} which transform errors emitted on this {@link Publisher} into a * {@link Subscriber#onComplete()} signal (e.g. swallows the error). - * @see ReactiveX catch operator. + * @see ReactiveX catch operator. */ public final Publisher onErrorComplete() { return onErrorComplete(t -> true); @@ -374,7 +374,7 @@ public final Publisher onErrorComplete() { * @param The {@link Throwable} type. * @return A {@link Publisher} which transform errors emitted on this {@link Publisher} which match {@code type} * into a {@link Subscriber#onComplete()} signal (e.g. swallows the error). - * @see ReactiveX catch operator. + * @see ReactiveX catch operator. */ public final Publisher onErrorComplete(Class type) { return onErrorComplete(type::isInstance); @@ -400,7 +400,7 @@ public final Publisher onErrorComplete(Class type) { * {@link Subscriber#onComplete()} signal. Returns {@code false} to propagate the error. * @return A {@link Publisher} which transform errors emitted on this {@link Publisher} which match * {@code predicate} into a {@link Subscriber#onComplete()} signal (e.g. swallows the error). - * @see ReactiveX catch operator. + * @see ReactiveX catch operator. */ public final Publisher onErrorComplete(Predicate predicate) { return new OnErrorCompletePublisher<>(this, predicate); @@ -423,7 +423,7 @@ public final Publisher onErrorComplete(Predicate predicate * @param itemSupplier returns the element to emit to {@link Subscriber#onNext(Object)}. * @return A {@link Publisher} which transform errors emitted on this {@link Publisher} into * {@link Subscriber#onNext(Object)} then {@link Subscriber#onComplete()} signals (e.g. swallows the error). - * @see ReactiveX catch operator. + * @see ReactiveX catch operator. */ public final Publisher onErrorReturn(Function itemSupplier) { return onErrorReturn(t -> true, itemSupplier); @@ -451,7 +451,7 @@ public final Publisher onErrorReturn(Function * @param The type of {@link Throwable} to transform. * @return A {@link Publisher} which transform errors emitted on this {@link Publisher} into * {@link Subscriber#onNext(Object)} then {@link Subscriber#onComplete()} signals (e.g. swallows the error). - * @see ReactiveX catch operator. + * @see ReactiveX catch operator. */ public final Publisher onErrorReturn( Class type, Function itemSupplier) { @@ -483,7 +483,7 @@ public final Publisher onErrorReturn( * @param itemSupplier returns the element to emit to {@link Subscriber#onNext(Object)}. * @return A {@link Publisher} which transform errors emitted on this {@link Publisher} into * {@link Subscriber#onNext(Object)} then {@link Subscriber#onComplete()} signals (e.g. swallows the error). - * @see ReactiveX catch operator. + * @see ReactiveX catch operator. */ public final Publisher onErrorReturn(Predicate predicate, Function itemSupplier) { @@ -506,7 +506,7 @@ public final Publisher onErrorReturn(Predicate predicate, * } * @param mapper returns the error used to terminate the returned {@link Publisher}. * @return A {@link Publisher} which transform errors emitted on this {@link Publisher} into a different error. - * @see ReactiveX catch operator. + * @see ReactiveX catch operator. */ public final Publisher onErrorMap(Function mapper) { return onErrorMap(t -> true, mapper); @@ -533,7 +533,7 @@ public final Publisher onErrorMap(Function The type of {@link Throwable} to transform. * @return A {@link Publisher} which transform errors emitted on this {@link Publisher} into a different error. - * @see ReactiveX catch operator. + * @see ReactiveX catch operator. */ public final Publisher onErrorMap( Class type, Function mapper) { @@ -563,7 +563,7 @@ public final Publisher onErrorMap( * {@code false} to propagate the original error. * @param mapper returns the error used to terminate the returned {@link Publisher}. * @return A {@link Publisher} which transform errors emitted on this {@link Publisher} into a different error. - * @see ReactiveX catch operator. + * @see ReactiveX catch operator. */ public final Publisher onErrorMap(Predicate predicate, Function mapper) { @@ -589,7 +589,7 @@ public final Publisher onErrorMap(Predicate predicate, * @param nextFactory Returns the next {@link Publisher}, when this {@link Publisher} emits an error. * @return A {@link Publisher} that recovers from an error from this {@link Publisher} by using another * {@link Publisher} provided by the passed {@code nextFactory}. - * @see ReactiveX catch operator. + * @see ReactiveX catch operator. */ public final Publisher onErrorResume(Function> nextFactory) { return onErrorResume(t -> true, nextFactory); @@ -620,7 +620,7 @@ public final Publisher onErrorResume(Function The type of {@link Throwable} to transform. * @return A {@link Publisher} that recovers from an error from this {@link Publisher} by using another * {@link Publisher} provided by the passed {@code nextFactory}. - * @see ReactiveX catch operator. + * @see ReactiveX catch operator. */ public final Publisher onErrorResume( Class type, Function> nextFactory) { @@ -655,7 +655,7 @@ public final Publisher onErrorResume( * @param nextFactory Returns the next {@link Publisher}, when this {@link Publisher} emits an error. * @return A {@link Publisher} that recovers from an error from this {@link Publisher} by using another * {@link Publisher} provided by the passed {@code nextFactory}. - * @see ReactiveX catch operator. + * @see ReactiveX catch operator. */ public final Publisher onErrorResume(Predicate predicate, Function> nextFactory) { @@ -692,7 +692,7 @@ public final Publisher onErrorResume(Predicate predicate, * each mapped {@link Publisher}. * @param The type of mapped {@link Publisher}. * @return A new {@link Publisher} which flattens the emissions from all mapped {@link Publisher}s. - * @see ReactiveX flatMap operator. + * @see ReactiveX flatMap operator. */ public final Publisher flatMapMerge(Function> mapper) { return new PublisherFlatMapMerge<>(this, mapper, false); @@ -726,7 +726,7 @@ public final Publisher flatMapMerge(Function The type of mapped {@link Publisher}. * @return A new {@link Publisher} which flattens the emissions from all mapped {@link Publisher}s. - * @see ReactiveX flatMap operator. + * @see ReactiveX flatMap operator. */ public final Publisher flatMapMerge(Function> mapper, int maxConcurrency) { @@ -777,7 +777,7 @@ public final Publisher flatMapMerge(Function The type of mapped {@link Publisher}. * @return A new {@link Publisher} which flattens the emissions from all mapped {@link Publisher}s. - * @see ReactiveX flatMap operator. + * @see ReactiveX flatMap operator. */ public final Publisher flatMapMergeDelayError(Function> mapper) { return new PublisherFlatMapMerge<>(this, mapper, true); @@ -824,7 +824,7 @@ public final Publisher flatMapMergeDelayError(Function The type of mapped {@link Publisher}. * @return A new {@link Publisher} which flattens the emissions from all mapped {@link Publisher}s. - * @see ReactiveX flatMap operator. + * @see ReactiveX flatMap operator. */ public final Publisher flatMapMergeDelayError(Function> mapper, int maxConcurrency) { @@ -874,7 +874,7 @@ public final Publisher flatMapMergeDelayError(Function The type of mapped {@link Publisher}. * @return A new {@link Publisher} which flattens the emissions from all mapped {@link Publisher}s. - * @see ReactiveX flatMap operator. + * @see ReactiveX flatMap operator. */ public final Publisher flatMapMergeDelayError(Function> mapper, int maxConcurrency, int maxDelayedErrorsHint) { @@ -916,7 +916,7 @@ public final Publisher flatMapMergeDelayError(Function Type of items emitted by the returned {@link Publisher}. * @return A new {@link Publisher} that emits all items emitted by each single produced by {@code mapper}. * - * @see ReactiveX flatMap operator. + * @see ReactiveX flatMap operator. * @see #flatMapMergeSingle(Function, int) * @see #flatMapConcatSingle(Function) */ @@ -956,7 +956,7 @@ public final Publisher flatMapMergeSingle(Function Type of items emitted by the returned {@link Publisher}. * @return A new {@link Publisher} that emits all items emitted by each single produced by {@code mapper}. * - * @see ReactiveX flatMap operator. + * @see ReactiveX flatMap operator. * @see #flatMapConcatSingle(Function, int) */ public final Publisher flatMapMergeSingle(Function> mapper, @@ -1147,7 +1147,7 @@ public final Publisher flatMapMergeSingleDelayError( * @return A new {@link Completable} that terminates successfully if all the intermediate {@link Completable}s have * terminated successfully or any one of them has terminated with a failure. * - * @see ReactiveX flatMap operator. + * @see ReactiveX flatMap operator. * @see #flatMapCompletable(Function, int) * @see #flatMapCompletableDelayError(Function) */ @@ -1185,7 +1185,7 @@ public final Completable flatMapCompletable(FunctionReactiveX flatMap operator. + * @see ReactiveX flatMap operator. * @see #flatMapCompletable(Function) * @see #flatMapCompletableDelayError(Function, int) */ @@ -1231,7 +1231,7 @@ public final Completable flatMapCompletable(FunctionReactiveX flatMap operator. + * @see ReactiveX flatMap operator. * @see #flatMapMergeSingleDelayError(Function, int) */ public final Completable flatMapCompletableDelayError(Function mapper) { @@ -1274,7 +1274,7 @@ public final Completable flatMapCompletableDelayError(FunctionReactiveX flatMap operator. + * @see ReactiveX flatMap operator. * @see #flatMapMergeSingleDelayError(Function, int) */ public final Completable flatMapCompletableDelayError(Function mapper, @@ -1320,7 +1320,7 @@ public final Completable flatMapCompletableDelayError(FunctionReactiveX flatMap operator. + * @see ReactiveX flatMap operator. * @see #flatMapMergeSingleDelayError(Function, int) */ public final Completable flatMapCompletableDelayError(Function mapper, @@ -1358,7 +1358,7 @@ public final Completable flatMapCompletableDelayError(Function Type of items emitted by the returned {@link Publisher}. * @return A new {@link Publisher} that emits all items emitted by each single produced by {@code mapper}. * - * @see ReactiveX flatMap operator. + * @see ReactiveX flatMap operator. * @see #flatMapConcatSingle(Function, int) * @see #flatMapMergeSingle(Function) */ @@ -1394,7 +1394,7 @@ public final Publisher flatMapConcatSingle(Function Type of items emitted by the returned {@link Publisher}. * @return A new {@link Publisher} that emits all items emitted by each single produced by {@code mapper}. * - * @see ReactiveX flatMap operator. + * @see ReactiveX flatMap operator. * @see #flatMapMergeSingle(Function, int) */ public final Publisher flatMapConcatSingle(Function> mapper, @@ -1705,7 +1705,7 @@ public final Publisher whenFinally(TerminalSignalConsumer doFinally) { * returned {@link Publisher}. MUST NOT throw. * @return The new {@link Publisher}. * - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Publisher whenRequest(LongConsumer onRequest) { return beforeRequest(onRequest); @@ -1739,7 +1739,7 @@ public final Publisher whenCancel(Runnable onCancel) { * @param unit The units for {@code duration}. * @return a new {@link Publisher} that will mimic the signals of this {@link Publisher} but will terminate with a * {@link TimeoutException} if time {@code duration} elapses between {@link Subscriber#onNext(Object)} calls. - * @see ReactiveX timeout operator. + * @see ReactiveX timeout operator. * @see #timeout(long, TimeUnit, io.servicetalk.concurrent.Executor) */ public final Publisher timeout(long duration, TimeUnit unit) { @@ -1757,7 +1757,7 @@ public final Publisher timeout(long duration, TimeUnit unit) { * @param duration The time duration which is allowed to elapse between {@link Subscriber#onNext(Object)} calls. * @return a new {@link Publisher} that will mimic the signals of this {@link Publisher} but will terminate with a * {@link TimeoutException} if time {@code duration} elapses between {@link Subscriber#onNext(Object)} calls. - * @see ReactiveX timeout operator. + * @see ReactiveX timeout operator. * @see #timeout(long, TimeUnit, io.servicetalk.concurrent.Executor) */ public final Publisher timeout(Duration duration) { @@ -1778,7 +1778,7 @@ public final Publisher timeout(Duration duration) { * notifications. * @return a new {@link Publisher} that will mimic the signals of this {@link Publisher} but will terminate with a * {@link TimeoutException} if time {@code duration} elapses between {@link Subscriber#onNext(Object)} calls. - * @see ReactiveX timeout operator. + * @see ReactiveX timeout operator. */ public final Publisher timeout(long duration, TimeUnit unit, io.servicetalk.concurrent.Executor timeoutExecutor) { @@ -1798,7 +1798,7 @@ public final Publisher timeout(long duration, TimeUnit unit, * notifications. * @return a new {@link Publisher} that will mimic the signals of this {@link Publisher} but will terminate with a * {@link TimeoutException} if time {@code duration} elapses between {@link Subscriber#onNext(Object)} calls. - * @see ReactiveX timeout operator. + * @see ReactiveX timeout operator. */ public final Publisher timeout(Duration duration, io.servicetalk.concurrent.Executor timeoutExecutor) { return timeout(toNanos(duration), TimeUnit.NANOSECONDS, timeoutExecutor); @@ -1815,7 +1815,7 @@ public final Publisher timeout(Duration duration, io.servicetalk.concurrent.E * @param duration The time duration during which the Publisher must complete. * @return a new {@link Publisher} that will mimic the signals of this {@link Publisher} but will terminate with a * {@link TimeoutException} if time {@code duration} elapses between subscribe and termination. - * @see ReactiveX timeout operator. + * @see ReactiveX timeout operator. */ public final Publisher timeoutTerminal(Duration duration) { return timeoutTerminal(duration, global()); @@ -1834,7 +1834,7 @@ public final Publisher timeoutTerminal(Duration duration) { * notifications. * @return a new {@link Publisher} that will mimic the signals of this {@link Publisher} but will terminate with a * {@link TimeoutException} if time {@code duration} elapses between subscribe and termination. - * @see ReactiveX timeout operator. + * @see ReactiveX timeout operator. */ public final Publisher timeoutTerminal(Duration duration, io.servicetalk.concurrent.Executor timeoutExecutor) { return timeoutTerminal(toNanos(duration), TimeUnit.NANOSECONDS, timeoutExecutor); @@ -1852,7 +1852,7 @@ public final Publisher timeoutTerminal(Duration duration, io.servicetalk.conc * @param unit The units for {@code duration}. * @return a new {@link Publisher} that will mimic the signals of this {@link Publisher} but will terminate with a * {@link TimeoutException} if time {@code duration} elapses between subscribe and termination. - * @see ReactiveX timeout operator. + * @see ReactiveX timeout operator. */ public final Publisher timeoutTerminal(long duration, TimeUnit unit) { return timeoutTerminal(duration, unit, global()); @@ -1872,7 +1872,7 @@ public final Publisher timeoutTerminal(long duration, TimeUnit unit) { * notifications. * @return a new {@link Publisher} that will mimic the signals of this {@link Publisher} but will terminate with a * {@link TimeoutException} if time {@code duration} elapses between subscribe and termination. - * @see ReactiveX timeout operator. + * @see ReactiveX timeout operator. */ public final Publisher timeoutTerminal(long duration, TimeUnit unit, io.servicetalk.concurrent.Executor timeoutExecutor) { @@ -1895,7 +1895,7 @@ public final Publisher timeoutTerminal(long duration, TimeUnit unit, * successfully. * @return A {@link Publisher} that emits all items from this {@link Publisher} and {@code next} {@link Publisher}. * - * @see ReactiveX concat operator. + * @see ReactiveX concat operator. */ public final Publisher concat(Publisher next) { return new ConcatPublisher<>(this, next); @@ -1917,7 +1917,7 @@ public final Publisher concat(Publisher next) { * @return A {@link Publisher} that emits all items from this {@link Publisher} and the result of {@code next} * {@link Single}. * - * @see ReactiveX concat operator. + * @see ReactiveX concat operator. */ public final Publisher concat(Single next) { return new PublisherConcatWithSingle<>(this, next); @@ -1941,7 +1941,7 @@ public final Publisher concat(Single next) { * @return A {@link Publisher} that emits all items from this {@link Publisher} and then awaits successful * completion of {@code next} {@link Completable}. * - * @see ReactiveX concat operator. + * @see ReactiveX concat operator. */ public final Publisher concat(Completable next) { return new PublisherConcatWithCompletable<>(this, next); @@ -1987,7 +1987,7 @@ public final Publisher concat(Completable next) { * @return A {@link Publisher} that emits all items from this {@link Publisher} and re-subscribes if an error is * emitted if the passed {@link BiIntPredicate} returned {@code true}. * - * @see ReactiveX retry operator. + * @see ReactiveX retry operator. */ public final Publisher retry(BiIntPredicate shouldRetry) { return new RedoPublisher<>(this, @@ -2039,7 +2039,7 @@ public final Publisher retry(BiIntPredicate shouldRetry) { * @return A {@link Publisher} that emits all items from this {@link Publisher} and re-subscribes if an error is * emitted and {@link Completable} returned by {@link BiIntFunction} completes successfully. * - * @see ReactiveX retry operator. + * @see ReactiveX retry operator. */ public final Publisher retryWhen(BiIntFunction retryWhen) { return new RedoWhenPublisher<>(this, (retryCount, notification) -> { @@ -2073,7 +2073,7 @@ public final Publisher retryWhen(BiIntFunctionReactiveX repeat operator. + * @see ReactiveX repeat operator. */ public final Publisher repeat(IntPredicate shouldRepeat) { return new RedoPublisher<>(this, @@ -2113,7 +2113,7 @@ public final Publisher repeat(IntPredicate shouldRepeat) { * @return A {@link Publisher} that emits all items from this {@link Publisher} and re-subscribes if an error is * emitted and {@link Completable} returned by {@link IntFunction} completes successfully. * - * @see ReactiveX retry operator. + * @see ReactiveX retry operator. */ public final Publisher repeatWhen(IntFunction repeatWhen) { return new RedoWhenPublisher<>(this, (retryCount, notification) -> { @@ -2147,7 +2147,7 @@ public final Publisher repeatWhen(IntFunction repeatWh * @param numElements Number of elements to take. * @return A {@link Publisher} that emits at most {@code numElements} elements from {@code this} {@link Publisher}. * - * @see ReactiveX take operator. + * @see ReactiveX take operator. */ public final Publisher takeAtMost(long numElements) { return new TakeNPublisher<>(this, numElements); @@ -2175,7 +2175,7 @@ public final Publisher takeAtMost(long numElements) { * @return A {@link Publisher} that only emits the items as long as the {@link Predicate#test(Object)} method * returns {@code true}. * - * @see ReactiveX takeWhile operator. + * @see ReactiveX takeWhile operator. */ public final Publisher takeWhile(Predicate predicate) { return new TakeWhilePublisher<>(this, predicate); @@ -2200,7 +2200,7 @@ public final Publisher takeWhile(Predicate predicate) { * @param until {@link Completable}, termination of which, terminates the returned {@link Publisher}. * @return A {@link Publisher} that only emits the items till {@code until} {@link Completable} is completed. * - * @see ReactiveX takeUntil operator. + * @see ReactiveX takeUntil operator. */ public final Publisher takeUntil(Completable until) { return new TakeUntilPublisher<>(this, until); @@ -2252,7 +2252,7 @@ public final Publisher takeUntil(Completable until) { * @param Type of {@link GroupedPublisher} keys. * @return A {@link Publisher} that emits {@link GroupedPublisher}s for new {@code key}s as emitted by * {@code keySelector} {@link Function}. - * @see ReactiveX groupBy operator. + * @see ReactiveX groupBy operator. */ public final Publisher> groupBy(Function keySelector) { return groupBy(keySelector, 64); @@ -2307,7 +2307,7 @@ public final Publisher> groupBy(Function Type of {@link GroupedPublisher} keys. * @return A {@link Publisher} that emits {@link GroupedPublisher}s for new {@code key}s as emitted by * {@code keySelector} {@link Function}. - * @see ReactiveX groupBy operator. + * @see ReactiveX groupBy operator. */ public final Publisher> groupBy(Function keySelector, int queueLimit) { @@ -2365,7 +2365,7 @@ public final Publisher> groupBy(Function Type of {@link GroupedPublisher} keys. * @return A {@link Publisher} that emits {@link GroupedPublisher}s for new {@code key}s as emitted by * {@code keySelector} {@link Function}. - * @see ReactiveX groupBy operator. + * @see ReactiveX groupBy operator. */ public final Publisher> groupBy(Function keySelector, int queueLimit, int expectedGroupCountHint) { @@ -2530,7 +2530,7 @@ public final Publisher multicastToExactly(int expectedSubscribers, int queueL * subscribe to the return value. * @return a {@link Publisher} that subscribes a single time upstream but allows for multiple downstream * {@link Subscriber}s. Signals from upstream will be multicast to each downstream {@link Subscriber}. - * @see ReactiveX multicast operator + * @see ReactiveX multicast operator */ public final Publisher multicast(int minSubscribers) { return multicast(minSubscribers, true); @@ -2561,7 +2561,7 @@ public final Publisher multicast(int minSubscribers) { * all downstream {@link Subscriber}s cancel, and the upstream Subscription will stay valid until termination. * @return a {@link Publisher} that subscribes a single time upstream but allows for multiple downstream * {@link Subscriber}s. Signals from upstream will be multicast to each downstream {@link Subscriber}. - * @see ReactiveX multicast operator + * @see ReactiveX multicast operator */ public final Publisher multicast(int minSubscribers, boolean cancelUpstream) { return multicast(minSubscribers, 64, cancelUpstream); @@ -2591,7 +2591,7 @@ public final Publisher multicast(int minSubscribers, boolean cancelUpstream) * for unequal demand. * @return a {@link Publisher} that subscribes a single time upstream but allows for multiple downstream * {@link Subscriber}s. Signals from upstream will be multicast to each downstream {@link Subscriber}. - * @see ReactiveX multicast operator + * @see ReactiveX multicast operator */ public final Publisher multicast(int minSubscribers, int queueLimit) { return multicast(minSubscribers, queueLimit, true); @@ -2624,7 +2624,7 @@ public final Publisher multicast(int minSubscribers, int queueLimit) { * all downstream {@link Subscriber}s cancel, and the upstream Subscription will stay valid until termination. * @return a {@link Publisher} that subscribes a single time upstream but allows for multiple downstream * {@link Subscriber}s. Signals from upstream will be multicast to each downstream {@link Subscriber}. - * @see ReactiveX multicast operator + * @see ReactiveX multicast operator */ public final Publisher multicast(int minSubscribers, int queueLimit, boolean cancelUpstream) { return multicast(minSubscribers, queueLimit, cancelUpstream, t -> completed()); @@ -2661,7 +2661,7 @@ public final Publisher multicast(int minSubscribers, int queueLimit, boolean * * @return a {@link Publisher} that subscribes a single time upstream but allows for multiple downstream * {@link Subscriber}s. Signals from upstream will be multicast to each downstream {@link Subscriber}. - * @see ReactiveX multicast operator + * @see ReactiveX multicast operator */ public final Publisher multicast(int minSubscribers, int queueLimit, Function terminalResubscribe) { @@ -2702,7 +2702,7 @@ public final Publisher multicast(int minSubscribers, int queueLimit, * * @return a {@link Publisher} that subscribes a single time upstream but allows for multiple downstream * {@link Subscriber}s. Signals from upstream will be multicast to each downstream {@link Subscriber}. - * @see ReactiveX multicast operator + * @see ReactiveX multicast operator */ public final Publisher multicast(int minSubscribers, int queueLimit, boolean cancelUpstream, Function terminalResubscribe) { @@ -2745,7 +2745,7 @@ public final Publisher multicast(int minSubscribers, int queueLimit, boolean * @return a {@link Publisher} that buffers items from this {@link Publisher} and emit those buffers instead of the * individual items. * - * @see ReactiveX buffer operator. + * @see ReactiveX buffer operator. */ public final , B> Publisher buffer(final BufferStrategy strategy) { return new PublisherBuffer<>(this, strategy); @@ -2761,7 +2761,7 @@ public final , B> Publisher buffer(final BufferS * {@link Publisher}. MUST NOT throw. * @return The new {@link Publisher}. * - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Publisher beforeOnSubscribe(Consumer onSubscribe) { return beforeSubscriber(doOnSubscribeSupplier(onSubscribe)); @@ -2784,7 +2784,7 @@ public final Publisher beforeOnSubscribe(Consumer onSub * of the returned {@link Publisher}. MUST NOT throw. * @return The new {@link Publisher}. * - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Publisher beforeOnNext(Consumer onNext) { return beforeSubscriber(doOnNextSupplier(onNext)); @@ -2808,7 +2808,7 @@ public final Publisher beforeOnNext(Consumer onNext) { * {@link Subscriber}s of the returned {@link Publisher}. MUST NOT throw. * @return The new {@link Publisher}. * - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Publisher beforeOnError(Consumer onError) { return beforeSubscriber(doOnErrorSupplier(onError)); @@ -2829,7 +2829,7 @@ public final Publisher beforeOnError(Consumer onError) { * {@link Subscriber}s of the returned {@link Publisher}. MUST NOT throw. * @return The new {@link Publisher}. * - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Publisher beforeOnComplete(Runnable onComplete) { return beforeSubscriber(doOnCompleteSupplier(onComplete)); @@ -2843,7 +2843,7 @@ public final Publisher beforeOnComplete(Runnable onComplete) { * {@link Subscription}s of the returned {@link Publisher}. MUST NOT throw. * @return The new {@link Publisher}. * - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Publisher beforeRequest(LongConsumer onRequest) { return beforeSubscription(doOnRequestSupplier(onRequest)); @@ -2857,7 +2857,7 @@ public final Publisher beforeRequest(LongConsumer onRequest) { * {@link Subscription}s of the returned {@link Publisher}. MUST NOT throw. * @return The new {@link Publisher}. * - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Publisher beforeCancel(Runnable onCancel) { return beforeSubscription(doOnCancelSupplier(onCancel)); @@ -2891,7 +2891,7 @@ public final Publisher beforeCancel(Runnable onCancel) { * * for {@link Subscription}s/{@link Subscriber}s of the returned {@link Publisher}. MUST NOT throw. * @return The new {@link Publisher}. - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Publisher beforeFinally(Runnable doFinally) { return beforeFinally(new RunnableTerminalSignalConsumer(doFinally)); @@ -2923,7 +2923,7 @@ public final Publisher beforeFinally(Runnable doFinally) { * @param doFinally For each subscribe of the returned {@link Publisher}, at most one method of this * {@link TerminalSignalConsumer} will be invoked. * @return The new {@link Publisher}. - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Publisher beforeFinally(TerminalSignalConsumer doFinally) { return new BeforeFinallyPublisher<>(this, doFinally); @@ -2939,7 +2939,7 @@ public final Publisher beforeFinally(TerminalSignalConsumer doFinally) { * {@link Subscriber} methods MUST NOT throw. * @return The new {@link Publisher}. * - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Publisher beforeSubscriber(Supplier> subscriberSupplier) { return new BeforeSubscriberPublisher<>(this, subscriberSupplier); @@ -2955,7 +2955,7 @@ public final Publisher beforeSubscriber(SupplierMUST NOT throw. * @return The new {@link Publisher}. * - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Publisher beforeSubscription(Supplier subscriptionSupplier) { return new WhenSubscriptionPublisher<>(this, subscriptionSupplier, true); @@ -2971,7 +2971,7 @@ public final Publisher beforeSubscription(Supplier su * {@link Subscriber}s of the returned {@link Publisher}. MUST NOT throw. * @return The new {@link Publisher}. * - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Publisher afterOnSubscribe(Consumer onSubscribe) { return afterSubscriber(doOnSubscribeSupplier(onSubscribe)); @@ -2994,7 +2994,7 @@ public final Publisher afterOnSubscribe(Consumer onSubs * of the returned {@link Publisher}. MUST NOT throw. * @return The new {@link Publisher}. * - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Publisher afterOnNext(Consumer onNext) { return afterSubscriber(doOnNextSupplier(onNext)); @@ -3018,7 +3018,7 @@ public final Publisher afterOnNext(Consumer onNext) { * {@link Subscriber}s of the returned {@link Publisher}. MUST NOT throw. * @return The new {@link Publisher}. * - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Publisher afterOnError(Consumer onError) { return afterSubscriber(doOnErrorSupplier(onError)); @@ -3039,7 +3039,7 @@ public final Publisher afterOnError(Consumer onError) { * {@link Subscriber}s of the returned {@link Publisher}. MUST NOT throw. * @return The new {@link Publisher}. * - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Publisher afterOnComplete(Runnable onComplete) { return afterSubscriber(doOnCompleteSupplier(onComplete)); @@ -3053,7 +3053,7 @@ public final Publisher afterOnComplete(Runnable onComplete) { * {@link Subscription}s of the returned {@link Publisher}. MUST NOT throw. * @return The new {@link Publisher}. * - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Publisher afterRequest(LongConsumer onRequest) { return afterSubscription(doOnRequestSupplier(onRequest)); @@ -3067,7 +3067,7 @@ public final Publisher afterRequest(LongConsumer onRequest) { * of the returned {@link Publisher}. MUST NOT throw. * @return The new {@link Publisher}. * - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Publisher afterCancel(Runnable onCancel) { return afterSubscription(doOnCancelSupplier(onCancel)); @@ -3101,7 +3101,7 @@ public final Publisher afterCancel(Runnable onCancel) { * * for {@link Subscription}s/{@link Subscriber}s of the returned {@link Publisher}. MUST NOT throw. * @return The new {@link Publisher}. - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Publisher afterFinally(Runnable doFinally) { return afterFinally(new RunnableTerminalSignalConsumer(doFinally)); @@ -3133,7 +3133,7 @@ public final Publisher afterFinally(Runnable doFinally) { * @param doFinally For each subscribe of the returned {@link Publisher}, at most one method of this * {@link TerminalSignalConsumer} will be invoked. * @return The new {@link Publisher}. - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Publisher afterFinally(TerminalSignalConsumer doFinally) { return new AfterFinallyPublisher<>(this, doFinally); @@ -3149,7 +3149,7 @@ public final Publisher afterFinally(TerminalSignalConsumer doFinally) { * {@link Subscriber} methods MUST NOT throw. * @return The new {@link Publisher}. * - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Publisher afterSubscriber(Supplier> subscriberSupplier) { return new AfterSubscriberPublisher<>(this, subscriberSupplier); @@ -3179,7 +3179,7 @@ public final Publisher whenSubscriber(SupplierMUST NOT throw. * @return The new {@link Publisher}. * - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Publisher afterSubscription(Supplier subscriptionSupplier) { return new WhenSubscriptionPublisher<>(this, subscriptionSupplier, false); @@ -3195,7 +3195,7 @@ public final Publisher afterSubscription(Supplier sub * {@link Subscription} methods MUST NOT throw. * @return The new {@link Publisher}. * - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Publisher whenSubscription(Supplier subscriptionSupplier) { return beforeSubscription(subscriptionSupplier); @@ -3436,7 +3436,7 @@ public final Publisher liftAsync(PublisherOperatorReactiveX first operator. + * @see ReactiveX first operator. */ public final Single firstOrElse(Supplier defaultValueSupplier) { return new PubToSingleFirstOrElse<>(this, defaultValueSupplier); @@ -3463,7 +3463,7 @@ public final Single firstOrError() { * * @return A {@link Completable} that mirrors the terminal signal from this {@code Publisher}. * - * @see + * @see * ReactiveX ignoreElements operator. */ public final Completable ignoreElements() { @@ -3492,7 +3492,7 @@ public final Completable completableOrError() { * @return A {@link Single} that completes with the single {@code result} or any error emitted by the source * {@link Publisher}. * - * @see ReactiveX reduce operator. + * @see ReactiveX reduce operator. */ public final Single collect(Supplier resultFactory, BiFunction collector) { @@ -3750,7 +3750,7 @@ protected void subscribeInternal(Subscriber subscriber) { * @return A new {@link Publisher} that emits {@code value} to its {@link Subscriber} and then * {@link Subscriber#onComplete()}. * - * @see ReactiveX just operator. + * @see ReactiveX just operator. */ public static Publisher from(@Nullable T value) { return new FromSingleItemPublisher<>(value); @@ -3767,7 +3767,7 @@ public static Publisher from(@Nullable T value) { * @return A new {@link Publisher} that emits {@code v1} and {@code v2} to its {@link Subscriber} and then * {@link Subscriber#onComplete()}. * - * @see ReactiveX just operator. + * @see ReactiveX just operator. */ public static Publisher from(@Nullable T v1, @Nullable T v2) { return new FromNPublisher<>(v1, v2); @@ -3785,7 +3785,7 @@ public static Publisher from(@Nullable T v1, @Nullable T v2) { * @return A new {@link Publisher} that emits {@code v1}, {@code v2}, and {@code v3} to its {@link Subscriber} and * then {@link Subscriber#onComplete()}. * - * @see ReactiveX just operator. + * @see ReactiveX just operator. */ public static Publisher from(@Nullable T v1, @Nullable T v2, @Nullable T v3) { return new FromNPublisher<>(v1, v2, v3); @@ -3801,7 +3801,7 @@ public static Publisher from(@Nullable T v1, @Nullable T v2, @Nullable T * @return A new {@link Publisher} that emits all {@code values} to its {@link Subscriber} and then * {@link Subscriber#onComplete()}. * - * @see ReactiveX from operator. + * @see ReactiveX from operator. */ @SafeVarargs public static Publisher from(T... values) { @@ -3909,7 +3909,7 @@ public static Publisher fromInputStream(InputStream stream, int readChun * @param end The end of the range (exclusive). * @return a new {@link Publisher} that when subscribed will emit all {@link Integer}s within the range of * [{@code begin}, {@code end}). - * @see Range. + * @see Range. */ public static Publisher range(int begin, int end) { return new RangeIntPublisher(begin, end); @@ -3923,7 +3923,7 @@ public static Publisher range(int begin, int end) { * @param stride The amount to increment in between each signal. * @return a new {@link Publisher} that when subscribed will emit all {@link Integer}s within the range of * [{@code begin}, {@code end}) with an increment of {@code stride} between each signal. - * @see Range. + * @see Range. */ public static Publisher range(int begin, int end, int stride) { return new RangeIntPublisher(begin, end, stride); @@ -3937,7 +3937,7 @@ public static Publisher range(int begin, int end, int stride) { * @return A new {@link Publisher} that completes when subscribed without emitting any item to its * {@link Subscriber}. * - * @see ReactiveX empty operator. + * @see ReactiveX empty operator. */ public static Publisher empty() { return emptyPublisher(); @@ -3951,7 +3951,7 @@ public static Publisher empty() { * @return A new {@link Publisher} that never emits any item to its {@link Subscriber} and never call any terminal * methods on it. * - * @see ReactiveX never operator. + * @see ReactiveX never operator. */ public static Publisher never() { return neverPublisher(); @@ -3966,7 +3966,7 @@ public static Publisher never() { * @return A new {@link Publisher} that terminates its {@link Subscriber} with an error without emitting any item to * it. * - * @see ReactiveX error operator. + * @see ReactiveX error operator. */ public static Publisher failed(Throwable cause) { return new ErrorPublisher<>(cause); @@ -3982,7 +3982,7 @@ public static Publisher failed(Throwable cause) { * it is subscribed and forwards all items and terminal events from the newly created {@link Publisher} to its * {@link Subscriber}. * - * @see ReactiveX defer operator. + * @see ReactiveX defer operator. */ public static Publisher defer(Supplier> publisherSupplier) { return new PublisherDefer<>(publisherSupplier); diff --git a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/Single.java b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/Single.java index c4b947ed5a..946402991e 100644 --- a/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/Single.java +++ b/servicetalk-concurrent-api/src/main/java/io/servicetalk/concurrent/api/Single.java @@ -136,7 +136,7 @@ public final Single cast(Class clazz) { * @param itemSupplier returns the element to emit to {@link Subscriber#onSuccess(Object)}. * @return A {@link Single} which transform errors emitted on this {@link Single} into * {@link Subscriber#onSuccess(Object)} signal (e.g. swallows the error). - * @see ReactiveX catch operator. + * @see ReactiveX catch operator. */ public final Single onErrorReturn(Function itemSupplier) { return onErrorReturn(t -> true, itemSupplier); @@ -164,7 +164,7 @@ public final Single onErrorReturn(Function it * @param The type of {@link Throwable} to transform. * @return A {@link Single} which transform errors emitted on this {@link Single} into * {@link Subscriber#onSuccess(Object)} signal (e.g. swallows the error). - * @see ReactiveX catch operator. + * @see ReactiveX catch operator. */ public final Single onErrorReturn( Class type, Function itemSupplier) { @@ -195,7 +195,7 @@ public final Single onErrorReturn( * @param itemSupplier returns the element to emit to {@link Subscriber#onSuccess(Object)}. * @return A {@link Single} which transform errors emitted on this {@link Single} into * {@link Subscriber#onSuccess(Object)} signal (e.g. swallows the error). - * @see ReactiveX catch operator. + * @see ReactiveX catch operator. */ public final Single onErrorReturn(Predicate predicate, Function itemSupplier) { @@ -218,7 +218,7 @@ public final Single onErrorReturn(Predicate predicate, * } * @param mapper returns the error used to terminate the returned {@link Single}. * @return A {@link Single} which transform errors emitted on this {@link Single} into a different error. - * @see ReactiveX catch operator. + * @see ReactiveX catch operator. */ public final Single onErrorMap(Function mapper) { return onErrorMap(t -> true, mapper); @@ -245,7 +245,7 @@ public final Single onErrorMap(Function The type of {@link Throwable} to transform. * @return A {@link Single} which transform errors emitted on this {@link Single} into a different error. - * @see ReactiveX catch operator. + * @see ReactiveX catch operator. */ public final Single onErrorMap( Class type, Function mapper) { @@ -275,7 +275,7 @@ public final Single onErrorMap( * {@code false} to propagate the original error. * @param mapper returns the error used to terminate the returned {@link Single}. * @return A {@link Single} which transform errors emitted on this {@link Single} into a different error. - * @see ReactiveX catch operator. + * @see ReactiveX catch operator. */ public final Single onErrorMap(Predicate predicate, Function mapper) { @@ -330,7 +330,7 @@ public final Single onErrorResume(Function The type of {@link Throwable} to transform. * @return A {@link Single} that recovers from an error from this {@link Single} by using another * {@link Single} provided by the passed {@code nextFactory}. - * @see ReactiveX catch operator. + * @see ReactiveX catch operator. */ public final Single onErrorResume( Class type, Function> nextFactory) { @@ -365,7 +365,7 @@ public final Single onErrorResume( * @param nextFactory Returns the next {@link Single}, when this {@link Single} emits an error. * @return A {@link Single} that recovers from an error from this {@link Single} by using another * {@link Single} provided by the passed {@code nextFactory}. - * @see ReactiveX catch operator. + * @see ReactiveX catch operator. */ public final Single onErrorResume(Predicate predicate, Function> nextFactory) { @@ -636,7 +636,7 @@ public final Single whenCancel(Runnable onCancel) { * @param unit The units for {@code duration}. * @return a new {@link Single} that will mimic the signals of this {@link Single} but will terminate with a * {@link TimeoutException} if time {@code duration} elapses before {@link Subscriber#onSuccess(Object)}. - * @see ReactiveX timeout operator. + * @see ReactiveX timeout operator. */ public final Single timeout(long duration, TimeUnit unit) { return timeout(duration, unit, global()); @@ -656,7 +656,7 @@ public final Single timeout(long duration, TimeUnit unit) { * notifications. * @return a new {@link Single} that will mimic the signals of this {@link Single} but will terminate with a * {@link TimeoutException} if time {@code duration} elapses before {@link Subscriber#onSuccess(Object)}. - * @see ReactiveX timeout operator. + * @see ReactiveX timeout operator. */ public final Single timeout(long duration, TimeUnit unit, io.servicetalk.concurrent.Executor timeoutExecutor) { @@ -675,7 +675,7 @@ public final Single timeout(long duration, TimeUnit unit, * @param duration The time duration which is allowed to elapse before {@link Subscriber#onSuccess(Object)}. * @return a new {@link Single} that will mimic the signals of this {@link Single} but will terminate with a * {@link TimeoutException} if time {@code duration} elapses before {@link Subscriber#onSuccess(Object)}. - * @see ReactiveX timeout operator. + * @see ReactiveX timeout operator. */ public final Single timeout(Duration duration) { return timeout(duration, global()); @@ -694,7 +694,7 @@ public final Single timeout(Duration duration) { * notifications. * @return a new {@link Single} that will mimic the signals of this {@link Single} but will terminate with a * {@link TimeoutException} if time {@code duration} elapses before {@link Subscriber#onSuccess(Object)}. - * @see ReactiveX timeout operator. + * @see ReactiveX timeout operator. */ public final Single timeout(Duration duration, io.servicetalk.concurrent.Executor timeoutExecutor) { return new TimeoutSingle<>(this, duration, timeoutExecutor); @@ -813,7 +813,7 @@ public final Publisher concat(Publisher next, boolean deferSubsc * @param The result type of the zipper. * @return a new {@link Single} that emits the results of a specified zipper {@link BiFunction} to items emitted by * {@code this} and {@code other}. - * @see ReactiveX zip operator. + * @see ReactiveX zip operator. */ public final Single zipWith(Single other, BiFunction zipper) { @@ -839,7 +839,7 @@ public final Single zipWith(Single other, * @param The result type of the zipper. * @return a new {@link Single} that emits the results of a specified zipper {@link BiFunction} to items emitted by * {@code this} and {@code other}. - * @see ReactiveX zip operator. + * @see ReactiveX zip operator. */ public final Single zipWithDelayError(Single other, BiFunction zipper) { @@ -879,7 +879,7 @@ public final Single zipWithDelayError(Single other, * @return A {@link Single} that emits the result from this {@link Single} or re-subscribes if an error is emitted * and if the passed {@link BiIntPredicate} returned {@code true}. * - * @see ReactiveX retry operator. + * @see ReactiveX retry operator. */ public final Single retry(BiIntPredicate shouldRetry) { return new RetrySingle<>(this, shouldRetry); @@ -922,7 +922,7 @@ public final Single retry(BiIntPredicate shouldRetry) { * @return A {@link Single} that emits the result from this {@link Single} or re-subscribes if an error is emitted * and {@link Completable} returned by {@link BiIntFunction} completes successfully. * - * @see ReactiveX retry operator. + * @see ReactiveX retry operator. */ public final Single retryWhen(BiIntFunction retryWhen) { return new RetryWhenSingle<>(this, retryWhen); @@ -949,7 +949,7 @@ public final Single retryWhen(BiIntFunction * @return A {@link Publisher} that emits all items from this {@link Single} and from all re-subscriptions whenever * the operation is repeated. * - * @see ReactiveX repeat operator. + * @see ReactiveX repeat operator. */ public final Publisher repeat(IntPredicate shouldRepeat) { return repeatWhen((i, __) -> shouldRepeat.test(i) ? Completable.completed() : END_REPEAT_COMPLETABLE); @@ -978,7 +978,7 @@ public final Publisher repeat(IntPredicate shouldRepeat) { * @return A {@link Publisher} that emits all items from this {@link Single} and from all re-subscriptions whenever * the operation is repeated. * - * @see ReactiveX repeat operator. + * @see ReactiveX repeat operator. */ public final Publisher repeat(BiIntPredicate shouldRepeat) { return repeatWhen((i, t) -> shouldRepeat.test(i, t) ? Completable.completed() : END_REPEAT_COMPLETABLE); @@ -1015,7 +1015,7 @@ public final Publisher repeat(BiIntPredicate shouldRepeat) { * @return A {@link Publisher} that emits all items from this {@link Single} and from all re-subscriptions whenever * the operation is repeated. * - * @see ReactiveX retry operator. + * @see ReactiveX retry operator. */ public final Publisher repeatWhen(IntFunction repeatWhen) { return repeatWhen((i, __) -> repeatWhen.apply(i)); @@ -1051,7 +1051,7 @@ public final Publisher repeatWhen(IntFunction repeatWh * @return A {@link Publisher} that emits all items from this {@link Single} and from all re-subscriptions whenever * the operation is repeated. * - * @see ReactiveX retry operator. + * @see ReactiveX retry operator. */ public final Publisher repeatWhen(BiIntFunction repeatWhen) { return new RepeatWhenSingle<>(this, repeatWhen); @@ -1251,7 +1251,7 @@ public final Single beforeCancel(Runnable onCancel) { * * for Subscriptions/{@link Subscriber}s of the returned {@link Single}. MUST NOT throw. * @return The new {@link Single}. - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Single beforeFinally(Runnable doFinally) { return beforeFinally(new RunnableSingleTerminalSignalConsumer<>(doFinally)); @@ -1286,7 +1286,7 @@ public final Single beforeFinally(Runnable doFinally) { * @param doFinally For each subscribe of the returned {@link Single}, at most one method of this * {@link TerminalSignalConsumer} will be invoked. * @return The new {@link Single}. - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Single beforeFinally(TerminalSignalConsumer doFinally) { return new BeforeFinallySingle<>(this, new TerminalSingleTerminalSignalConsumer<>(doFinally)); @@ -1321,7 +1321,7 @@ public final Single beforeFinally(TerminalSignalConsumer doFinally) { * @param doFinally For each subscribe of the returned {@link Single}, at most one method of this * {@link SingleTerminalSignalConsumer} will be invoked. * @return The new {@link Single}. - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Single beforeFinally(SingleTerminalSignalConsumer doFinally) { return new BeforeFinallySingle<>(this, doFinally); @@ -1452,7 +1452,7 @@ public final Single afterCancel(Runnable onCancel) { * * for Subscriptions/{@link Subscriber}s of the returned {@link Single}. MUST NOT throw. * @return The new {@link Single}. - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Single afterFinally(Runnable doFinally) { return afterFinally(new RunnableSingleTerminalSignalConsumer<>(doFinally)); @@ -1487,7 +1487,7 @@ public final Single afterFinally(Runnable doFinally) { * @param doFinally For each subscribe of the returned {@link Single}, at most one method of this * {@link TerminalSignalConsumer} will be invoked. * @return The new {@link Single}. - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Single afterFinally(TerminalSignalConsumer doFinally) { return new AfterFinallySingle<>(this, new TerminalSingleTerminalSignalConsumer<>(doFinally)); @@ -1522,7 +1522,7 @@ public final Single afterFinally(TerminalSignalConsumer doFinally) { * @param doFinally For each subscribe of the returned {@link Single}, at most one method of this * {@link SingleTerminalSignalConsumer} will be invoked. * @return The new {@link Single}. - * @see ReactiveX do operator. + * @see ReactiveX do operator. */ public final Single afterFinally(SingleTerminalSignalConsumer doFinally) { return new AfterFinallySingle<>(this, doFinally); @@ -1741,7 +1741,7 @@ public final Single liftAsync(SingleOperator oper * @return A new {@link Single} that terminates with the result (either success or error) of either this * {@link Single} or the passed {@code other} {@link Single}, whichever terminates first. Therefore the result is * said to be ambiguous relative to which source it originated from. - * @see ReactiveX amb operator. + * @see ReactiveX amb operator. */ public final Single ambWith(final Single other) { return new SingleAmbWith<>(this, other); @@ -2270,7 +2270,7 @@ public static Single fromStage(CompletionStage stage) { * @return A new {@link Single} that terminates with the result (either success or error) of whichever amongst the * passed {@code singles} that terminates first. Therefore the result is said to be ambiguous * relative to which source it originated from. - * @see ReactiveX amb operator. + * @see ReactiveX amb operator. */ @SafeVarargs public static Single amb(final Single... singles) { @@ -2296,7 +2296,7 @@ public static Single amb(final Single... singles) { * @return A new {@link Single} that terminates with the result (either success or error) of whichever amongst the * passed {@code singles} that terminates first. Therefore the result is said to be ambiguous * relative to which source it originated from. - * @see ReactiveX amb operator. + * @see ReactiveX amb operator. */ public static Single amb(final Iterable> singles) { return new AmbSingles<>(singles); @@ -2318,7 +2318,7 @@ public static Single amb(final Iterable> singles) { * @param Type of the result of the individual {@link Single}s * @return A new {@link Single} that terminates with the result (either success or error) of whichever amongst the * passed {@code singles} that terminates first. - * @see ReactiveX amb operator. + * @see ReactiveX amb operator. */ @SafeVarargs public static Single anyOf(final Single... singles) { @@ -2341,7 +2341,7 @@ public static Single anyOf(final Single... singles) { * @param Type of the result of the individual {@link Single}s * @return A new {@link Single} that terminates with the result (either success or error) of whichever amongst the * passed {@code singles} that terminates first. - * @see ReactiveX amb operator. + * @see ReactiveX amb operator. */ public static Single anyOf(final Iterable> singles) { return amb(singles); @@ -2366,7 +2366,7 @@ public static Single anyOf(final Iterable> singles) { * @param The result type of the zipper. * @return a new {@link Single} that emits the results of a specified zipper {@link BiFunction} to items emitted by * {@code s1} and {@code s2}. - * @see ReactiveX zip operator. + * @see ReactiveX zip operator. */ public static Single zip(Single s1, Single s2, BiFunction zipper) { @@ -2394,7 +2394,7 @@ public static Single zip(Single s1, Single The result type of the zipper. * @return a new {@link Single} that emits the results of a specified zipper {@link BiFunction} to items emitted by * {@code s1} and {@code s2}. - * @see ReactiveX zip operator. + * @see ReactiveX zip operator. */ public static Single zipDelayError(Single s1, Single s2, BiFunction zipper) { @@ -2423,7 +2423,7 @@ public static Single zipDelayError(Single s1, Singl * @param The result type of the zipper. * @return a new {@link Single} that emits the results of a specified zipper {@link Function3} to items emitted by * {@code s1}, {@code s2}, and {@code s3}. - * @see ReactiveX zip operator. + * @see ReactiveX zip operator. */ public static Single zip( Single s1, Single s2, Single s3, @@ -2455,7 +2455,7 @@ public static Single zip( * @param The result type of the zipper. * @return a new {@link Single} that emits the results of a specified zipper {@link Function3} to items emitted by * {@code s1}, {@code s2}, and {@code s3}. - * @see ReactiveX zip operator. + * @see ReactiveX zip operator. */ public static Single zipDelayError( Single s1, Single s2, Single s3, @@ -2488,7 +2488,7 @@ public static Single zipDelayError( * @param The result type of the zipper. * @return a new {@link Single} that emits the results of a specified zipper {@link Function4} to items emitted by * {@code s1}, {@code s2}, {@code s3}, and {@code s4}. - * @see ReactiveX zip operator. + * @see ReactiveX zip operator. */ public static Single zip( Single s1, Single s2, Single s3, Single s4, @@ -2523,7 +2523,7 @@ public static Single zip( * @param The result type of the zipper. * @return a new {@link Single} that emits the results of a specified zipper {@link Function4} to items emitted by * {@code s1}, {@code s2}, {@code s3}, and {@code s4}. - * @see ReactiveX zip operator. + * @see ReactiveX zip operator. */ public static Single zipDelayError( Single s1, Single s2, Single s3, Single s4, @@ -2548,7 +2548,7 @@ public static Single zipDelayError( * @param The result type of the zipper. * @return a new {@link Single} that emits the results of a specified zipper {@link Function} to items emitted by * {@code singles}. - * @see ReactiveX zip operator. + * @see ReactiveX zip operator. */ public static Single zip(Function zipper, Single... singles) { return SingleZipper.zip(zipper, singles); @@ -2573,7 +2573,7 @@ public static Single zip(Function zipper, * @param The result type of the zipper. * @return a new {@link Single} that emits the results of a specified zipper {@link Function} to items emitted by * {@code singles}. - * @see ReactiveX zip operator. + * @see ReactiveX zip operator. */ public static Single zipDelayError(Function zipper, Single... singles) { return SingleZipper.zipDelayError(zipper, singles); diff --git a/servicetalk-examples/grpc/routeguide/src/main/java/io/servicetalk/examples/grpc/routeguide/RouteSummaryBuilder.java b/servicetalk-examples/grpc/routeguide/src/main/java/io/servicetalk/examples/grpc/routeguide/RouteSummaryBuilder.java index 19f16a423a..8c944a08a7 100644 --- a/servicetalk-examples/grpc/routeguide/src/main/java/io/servicetalk/examples/grpc/routeguide/RouteSummaryBuilder.java +++ b/servicetalk-examples/grpc/routeguide/src/main/java/io/servicetalk/examples/grpc/routeguide/RouteSummaryBuilder.java @@ -76,7 +76,7 @@ public RouteSummary buildSummary() { /** * Calculate the distance between two points using the "haversine" formula. - * The formula is based on http://mathforum.org/library/drmath/view/51879.html. + * The formula is based on https://en.wikipedia.org/wiki/Haversine_formula. * * @param start The starting point * @param end The end point diff --git a/servicetalk-examples/http/uds/src/main/java/io/servicetalk/examples/http/uds/blocking/BlockingUdsClient.java b/servicetalk-examples/http/uds/src/main/java/io/servicetalk/examples/http/uds/blocking/BlockingUdsClient.java index 9d3243e0b1..6d44b818e3 100644 --- a/servicetalk-examples/http/uds/src/main/java/io/servicetalk/examples/http/uds/blocking/BlockingUdsClient.java +++ b/servicetalk-examples/http/uds/src/main/java/io/servicetalk/examples/http/uds/blocking/BlockingUdsClient.java @@ -23,7 +23,7 @@ import static io.servicetalk.http.api.HttpSerializers.textSerializerUtf8; /** - * AF_UNIX socket client example. + * AF_UNIX socket client example. */ public final class BlockingUdsClient { public static void main(String[] args) throws Exception { diff --git a/servicetalk-examples/http/uds/src/main/java/io/servicetalk/examples/http/uds/blocking/BlockingUdsServer.java b/servicetalk-examples/http/uds/src/main/java/io/servicetalk/examples/http/uds/blocking/BlockingUdsServer.java index 7066251a71..24c8145f72 100644 --- a/servicetalk-examples/http/uds/src/main/java/io/servicetalk/examples/http/uds/blocking/BlockingUdsServer.java +++ b/servicetalk-examples/http/uds/src/main/java/io/servicetalk/examples/http/uds/blocking/BlockingUdsServer.java @@ -24,7 +24,7 @@ import static io.servicetalk.http.api.HttpSerializers.textSerializerUtf8; /** - * AF_UNIX socket server example. + * AF_UNIX socket server example. */ public final class BlockingUdsServer { public static void main(String[] args) throws Exception { diff --git a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/RedirectConfigBuilder.java b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/RedirectConfigBuilder.java index 265137424b..0586451fa6 100644 --- a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/RedirectConfigBuilder.java +++ b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/RedirectConfigBuilder.java @@ -188,8 +188,8 @@ public RedirectConfigBuilder headersToRedirect(final CharSequence... headerNames *

* Note: This option expects that the redirected {@link StreamingHttpRequest requests} have a * {@link StreamingHttpRequest#payloadBody() payload body} that is - * replayable, i.e. multiple subscribes to the - * payload {@link Publisher} observe the same data. {@link Publisher}s that do not emit any data or which are + * replayable, i.e. multiple subscribes to + * the payload {@link Publisher} observe the same data. {@link Publisher}s that do not emit any data or which are * created from in-memory data are typically replayable. * * @param redirectPayloadBody If {@code true}, payload body of the original request will be repeated for each diff --git a/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/HttpRequestEncoder.java b/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/HttpRequestEncoder.java index eb692108dc..02e04611cb 100644 --- a/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/HttpRequestEncoder.java +++ b/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/HttpRequestEncoder.java @@ -110,7 +110,7 @@ protected void encodeInitialLine(ChannelHandlerContext ctx, Buffer stBuffer, Htt if (uri.isEmpty()) { // Add " / " as absolute path if uri is not present. - // See http://tools.ietf.org/html/rfc2616#section-5.1.2 + // See https://tools.ietf.org/html/rfc2616#section-5.1.2 stBuffer.writeMedium(SPACE_SLASH_AND_SPACE_MEDIUM); } else { CharSequence uriCharSequence = uri; diff --git a/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/RetryingHttpRequesterFilter.java b/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/RetryingHttpRequesterFilter.java index 4669d03beb..44a1705105 100644 --- a/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/RetryingHttpRequesterFilter.java +++ b/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/RetryingHttpRequesterFilter.java @@ -695,9 +695,9 @@ public Builder retryRetryableExceptions( *

* Note: This predicate expects that the retried {@link StreamingHttpRequest requests} have a * {@link StreamingHttpRequest#payloadBody() payload body} that is - * replayable, i.e. multiple subscribes to - * the payload {@link Publisher} observe the same data. {@link Publisher}s that do not emit any data or which - * are created from in-memory data are typically replayable. + * replayable, i.e. multiple subscribes + * to the payload {@link Publisher} observe the same data. {@link Publisher}s that do not emit any data or + * which are created from in-memory data are typically replayable. * To disable retries you can return {@link BackOffPolicy#NO_RETRIES} from the {@code mapper}. * It's important that this {@link Function} doesn't block to avoid performance impacts. * diff --git a/servicetalk-opentracing-internal/src/main/java/io/servicetalk/opentracing/internal/ZipkinHeaderNames.java b/servicetalk-opentracing-internal/src/main/java/io/servicetalk/opentracing/internal/ZipkinHeaderNames.java index 718a7db853..43ed2c390b 100644 --- a/servicetalk-opentracing-internal/src/main/java/io/servicetalk/opentracing/internal/ZipkinHeaderNames.java +++ b/servicetalk-opentracing-internal/src/main/java/io/servicetalk/opentracing/internal/ZipkinHeaderNames.java @@ -16,7 +16,7 @@ package io.servicetalk.opentracing.internal; /** - * See zipkin documentation. + * See zipkin documentation. */ public final class ZipkinHeaderNames { // Use lowercase so the same header names can be used for HTTP/2 which requires lower case header names. diff --git a/servicetalk-transport-api/src/main/java/io/servicetalk/transport/api/DomainSocketAddress.java b/servicetalk-transport-api/src/main/java/io/servicetalk/transport/api/DomainSocketAddress.java index 7ef47c694e..43f0595715 100644 --- a/servicetalk-transport-api/src/main/java/io/servicetalk/transport/api/DomainSocketAddress.java +++ b/servicetalk-transport-api/src/main/java/io/servicetalk/transport/api/DomainSocketAddress.java @@ -22,7 +22,7 @@ /** * An address which represents a socket belonging to the - * AF_UNIX socket family. + * AF_UNIX socket family. */ public final class DomainSocketAddress extends SocketAddress { private static final long serialVersionUID = 7522601114230727837L; @@ -47,7 +47,7 @@ public DomainSocketAddress(File file) { /** * The file system path used to bind/connect for a UNIX domain socket. - * See AF_UNIX socket family docs. + * See AF_UNIX socket family docs. * @return The file system path used to bind/connect for a UNIX domain socket. */ public String getPath() { From 201748f2ca222a89e876edd7ccd92b52cb3557a9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Jun 2022 11:28:33 -0700 Subject: [PATCH 35/40] Bump dawidd6/action-download-artifact from 2.19.0 to 2.20.0 (#2233) Bumps [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact) from 2.19.0 to 2.20.0. - [Release notes](https://github.com/dawidd6/action-download-artifact/releases) - [Commits](https://github.com/dawidd6/action-download-artifact/compare/b2abf1705491048a2d7074f7d90513044fd25d39...80fcec8114889f74eb442780f3c71bff4d42a98a) --- updated-dependencies: - dependency-name: dawidd6/action-download-artifact dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-prb-reports.yml | 2 +- .github/workflows/ci-prq-reports.yml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-prb-reports.yml b/.github/workflows/ci-prb-reports.yml index 478e32bdce..de94fb434c 100644 --- a/.github/workflows/ci-prb-reports.yml +++ b/.github/workflows/ci-prb-reports.yml @@ -14,7 +14,7 @@ jobs: os: [ ubuntu-latest ] steps: - name: Download Artifacts - uses: dawidd6/action-download-artifact@b2abf1705491048a2d7074f7d90513044fd25d39 + uses: dawidd6/action-download-artifact@80fcec8114889f74eb442780f3c71bff4d42a98a with: github_token: ${{ secrets.GITHUB_TOKEN }} workflow: ${{ github.event.workflow_run.workflow_id }} diff --git a/.github/workflows/ci-prq-reports.yml b/.github/workflows/ci-prq-reports.yml index 68d364b52e..5068eb5824 100644 --- a/.github/workflows/ci-prq-reports.yml +++ b/.github/workflows/ci-prq-reports.yml @@ -12,7 +12,7 @@ jobs: java: [ 8, 11, 17 ] steps: - name: Download Artifacts - uses: dawidd6/action-download-artifact@b2abf1705491048a2d7074f7d90513044fd25d39 + uses: dawidd6/action-download-artifact@80fcec8114889f74eb442780f3c71bff4d42a98a with: github_token: ${{ secrets.GITHUB_TOKEN }} workflow: ${{ github.event.workflow_run.workflow_id }} @@ -35,7 +35,7 @@ jobs: java: [ 8, 11 ] steps: - name: Download Artifacts - uses: dawidd6/action-download-artifact@b2abf1705491048a2d7074f7d90513044fd25d39 + uses: dawidd6/action-download-artifact@80fcec8114889f74eb442780f3c71bff4d42a98a with: github_token: ${{ secrets.GITHUB_TOKEN }} workflow: ${{ github.event.workflow_run.workflow_id }} @@ -58,7 +58,7 @@ jobs: java: [ 8, 11 ] steps: - name: Download Artifacts - uses: dawidd6/action-download-artifact@b2abf1705491048a2d7074f7d90513044fd25d39 + uses: dawidd6/action-download-artifact@80fcec8114889f74eb442780f3c71bff4d42a98a with: github_token: ${{ secrets.GITHUB_TOKEN }} workflow: ${{ github.event.workflow_run.workflow_id }} From ff6436b174631c7910b1342d1abfb3250dc9dad8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Jun 2022 09:52:47 -0700 Subject: [PATCH 36/40] Bump dawidd6/action-download-artifact from 2.20.0 to 2.21.0 (#2236) Bumps [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact) from 2.20.0 to 2.21.0. - [Release notes](https://github.com/dawidd6/action-download-artifact/releases) - [Commits](https://github.com/dawidd6/action-download-artifact/compare/80fcec8114889f74eb442780f3c71bff4d42a98a...b7337e51c4775d1f22357423ade50ee0a5f5779e) --- updated-dependencies: - dependency-name: dawidd6/action-download-artifact dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-prb-reports.yml | 2 +- .github/workflows/ci-prq-reports.yml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-prb-reports.yml b/.github/workflows/ci-prb-reports.yml index de94fb434c..0134f57788 100644 --- a/.github/workflows/ci-prb-reports.yml +++ b/.github/workflows/ci-prb-reports.yml @@ -14,7 +14,7 @@ jobs: os: [ ubuntu-latest ] steps: - name: Download Artifacts - uses: dawidd6/action-download-artifact@80fcec8114889f74eb442780f3c71bff4d42a98a + uses: dawidd6/action-download-artifact@b7337e51c4775d1f22357423ade50ee0a5f5779e with: github_token: ${{ secrets.GITHUB_TOKEN }} workflow: ${{ github.event.workflow_run.workflow_id }} diff --git a/.github/workflows/ci-prq-reports.yml b/.github/workflows/ci-prq-reports.yml index 5068eb5824..14c4fe2106 100644 --- a/.github/workflows/ci-prq-reports.yml +++ b/.github/workflows/ci-prq-reports.yml @@ -12,7 +12,7 @@ jobs: java: [ 8, 11, 17 ] steps: - name: Download Artifacts - uses: dawidd6/action-download-artifact@80fcec8114889f74eb442780f3c71bff4d42a98a + uses: dawidd6/action-download-artifact@b7337e51c4775d1f22357423ade50ee0a5f5779e with: github_token: ${{ secrets.GITHUB_TOKEN }} workflow: ${{ github.event.workflow_run.workflow_id }} @@ -35,7 +35,7 @@ jobs: java: [ 8, 11 ] steps: - name: Download Artifacts - uses: dawidd6/action-download-artifact@80fcec8114889f74eb442780f3c71bff4d42a98a + uses: dawidd6/action-download-artifact@b7337e51c4775d1f22357423ade50ee0a5f5779e with: github_token: ${{ secrets.GITHUB_TOKEN }} workflow: ${{ github.event.workflow_run.workflow_id }} @@ -58,7 +58,7 @@ jobs: java: [ 8, 11 ] steps: - name: Download Artifacts - uses: dawidd6/action-download-artifact@80fcec8114889f74eb442780f3c71bff4d42a98a + uses: dawidd6/action-download-artifact@b7337e51c4775d1f22357423ade50ee0a5f5779e with: github_token: ${{ secrets.GITHUB_TOKEN }} workflow: ${{ github.event.workflow_run.workflow_id }} From 45019c5cc73c332aec7b6d55cfb5f30ac6b40391 Mon Sep 17 00:00:00 2001 From: Mike Duigou Date: Fri, 3 Jun 2022 12:19:02 -0700 Subject: [PATCH 37/40] Cleanup `HttpPredicateRouterBuilder` (#2234) Motivation: Some of the types used by `HttpPredicateRouterBuilder` have changed resulting in dead code. Modifications: Reduce complexity by removing code paths that are now impossible. Result: Cleaner, more obvious implementation. --- .../predicate/HttpPredicateRouterBuilder.java | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/servicetalk-http-router-predicate/src/main/java/io/servicetalk/http/router/predicate/HttpPredicateRouterBuilder.java b/servicetalk-http-router-predicate/src/main/java/io/servicetalk/http/router/predicate/HttpPredicateRouterBuilder.java index 6169265cc3..db83de979f 100644 --- a/servicetalk-http-router-predicate/src/main/java/io/servicetalk/http/router/predicate/HttpPredicateRouterBuilder.java +++ b/servicetalk-http-router-predicate/src/main/java/io/servicetalk/http/router/predicate/HttpPredicateRouterBuilder.java @@ -20,6 +20,7 @@ import io.servicetalk.http.api.HttpApiConversions.ServiceAdapterHolder; import io.servicetalk.http.api.HttpCookiePair; import io.servicetalk.http.api.HttpExecutionStrategy; +import io.servicetalk.http.api.HttpExecutionStrategyInfluencer; import io.servicetalk.http.api.HttpRequestMethod; import io.servicetalk.http.api.HttpService; import io.servicetalk.http.api.StreamingHttpRequest; @@ -29,7 +30,6 @@ import io.servicetalk.http.router.predicate.dsl.RouteStarter; import io.servicetalk.http.router.predicate.dsl.StringMultiValueMatcher; import io.servicetalk.transport.api.ConnectionContext; -import io.servicetalk.transport.api.ExecutionStrategyInfluencer; import java.util.ArrayList; import java.util.Iterator; @@ -42,7 +42,6 @@ import javax.annotation.Nullable; import static io.servicetalk.http.api.HttpApiConversions.toStreamingHttpService; -import static io.servicetalk.http.api.HttpExecutionStrategies.defaultStrategy; import static io.servicetalk.http.router.predicate.Predicates.method; import static io.servicetalk.http.router.predicate.Predicates.methodIsOneOf; import static io.servicetalk.http.router.predicate.Predicates.pathEquals; @@ -276,15 +275,11 @@ public RouteStarter thenRouteTo(final BlockingStreamingHttpService service) { return thenRouteTo0(adapterHolder.adaptor(), adapterHolder.serviceInvocationStrategy()); } - private HttpExecutionStrategy serviceOffloads(final Object service) { - return null != strategy ? strategy : - service instanceof ExecutionStrategyInfluencer ? - HttpExecutionStrategy.from(((ExecutionStrategyInfluencer) service).requiredOffloads()) : - defaultStrategy(); + private HttpExecutionStrategy serviceOffloads(final HttpExecutionStrategyInfluencer service) { + return null != strategy ? strategy : service.requiredOffloads(); } - private RouteStarter thenRouteTo0(final StreamingHttpService route, - @Nullable final HttpExecutionStrategy routeStrategy) { + private RouteStarter thenRouteTo0(final StreamingHttpService route, final HttpExecutionStrategy routeStrategy) { assert predicate != null; routes.add(new Route(predicate, route, null == strategy ? null : routeStrategy)); // Reset shared state since we have finished current route construction From f9091b0260f1f131ae7a9c58de707696568ef781 Mon Sep 17 00:00:00 2001 From: Idel Pivnitskiy Date: Fri, 3 Jun 2022 14:20:00 -0500 Subject: [PATCH 38/40] `HttpLifecycleObserver`: notify when payload body is requested (#2230) Motivation: Track how subscriber requests payload body items. Modifications: - Add `HttpRequestObserver#onRequestDataRequested(long)`; - Add `HttpResponseObserver#onResponseDataRequested(long)`; - Enhance `HttpLifecycleObserverTest` and `GrpcLifecycleObserverTest`; Result: Users can track how many items subscriber requests from payload body, and time difference between requested-delivered items. --- .../GrpcToHttpLifecycleObserverBridge.java | 10 +++++++++ .../grpc/netty/GrpcLifecycleObserverTest.java | 5 +++++ .../grpc/utils/BiGrpcLifecycleObserver.java | 18 ++++++++++++++++ .../utils/LoggingGrpcLifecycleObserver.java | 8 +++++++ .../http/api/HttpLifecycleObserver.java | 21 +++++++++++++++++++ .../AbstractLifecycleObserverHttpFilter.java | 13 ++++++++++-- .../http/netty/NoopHttpLifecycleObserver.java | 8 +++++++ .../http/netty/HttpLifecycleObserverTest.java | 13 ++++++++++++ .../http/utils/BiHttpLifecycleObserver.java | 18 ++++++++++++++++ .../utils/LoggingHttpLifecycleObserver.java | 8 +++++++ 10 files changed, 120 insertions(+), 2 deletions(-) diff --git a/servicetalk-grpc-netty/src/main/java/io/servicetalk/grpc/netty/GrpcToHttpLifecycleObserverBridge.java b/servicetalk-grpc-netty/src/main/java/io/servicetalk/grpc/netty/GrpcToHttpLifecycleObserverBridge.java index 78908a31f5..edeaafda8d 100644 --- a/servicetalk-grpc-netty/src/main/java/io/servicetalk/grpc/netty/GrpcToHttpLifecycleObserverBridge.java +++ b/servicetalk-grpc-netty/src/main/java/io/servicetalk/grpc/netty/GrpcToHttpLifecycleObserverBridge.java @@ -94,6 +94,11 @@ private static final class GrpcToHttpRequestObserver implements HttpRequestObser this.observer = observer; } + @Override + public void onRequestDataRequested(final long n) { + observer.onRequestDataRequested(n); + } + @Override public void onRequestData(final Buffer data) { observer.onRequestData(data); @@ -132,6 +137,11 @@ private static final class GrpcToHttpResponseObserver implements HttpResponseObs } } + @Override + public void onResponseDataRequested(final long n) { + observer.onResponseDataRequested(n); + } + @Override public void onResponseData(final Buffer data) { observer.onResponseData(data); diff --git a/servicetalk-grpc-netty/src/test/java/io/servicetalk/grpc/netty/GrpcLifecycleObserverTest.java b/servicetalk-grpc-netty/src/test/java/io/servicetalk/grpc/netty/GrpcLifecycleObserverTest.java index 2ffe5149a2..fab5d1e8ff 100644 --- a/servicetalk-grpc-netty/src/test/java/io/servicetalk/grpc/netty/GrpcLifecycleObserverTest.java +++ b/servicetalk-grpc-netty/src/test/java/io/servicetalk/grpc/netty/GrpcLifecycleObserverTest.java @@ -70,9 +70,12 @@ import static org.hamcrest.Matchers.is; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; @@ -236,6 +239,7 @@ private static void verifyObservers(boolean client, boolean error, boolean aggre inOrder.verify(exchange).onRequest(any(StreamingHttpRequest.class)); } inOrder.verify(exchange).onResponse(any(StreamingHttpResponse.class)); + verify(response, atLeastOnce()).onResponseDataRequested(anyLong()); if (!error) { inOrder.verify(response).onResponseData(any(Buffer.class)); inOrder.verify(response).onResponseTrailers(any(HttpHeaders.class)); @@ -258,6 +262,7 @@ private static void verifyObservers(boolean client, boolean error, boolean aggre } } + verify(request, atLeastOnce()).onRequestDataRequested(anyLong()); requestInOrder.verify(request).onRequestData(any(Buffer.class)); requestInOrder.verify(request, never()).onRequestTrailers(any(HttpHeaders.class)); requestInOrder.verify(request).onRequestComplete(); diff --git a/servicetalk-grpc-utils/src/main/java/io/servicetalk/grpc/utils/BiGrpcLifecycleObserver.java b/servicetalk-grpc-utils/src/main/java/io/servicetalk/grpc/utils/BiGrpcLifecycleObserver.java index d8be5a6fe4..4c08be9d59 100644 --- a/servicetalk-grpc-utils/src/main/java/io/servicetalk/grpc/utils/BiGrpcLifecycleObserver.java +++ b/servicetalk-grpc-utils/src/main/java/io/servicetalk/grpc/utils/BiGrpcLifecycleObserver.java @@ -128,6 +128,15 @@ private static final class BiGrpcRequestObserver implements GrpcRequestObserver this.second = requireNonNull(second); } + @Override + public void onRequestDataRequested(final long n) { + try { + first.onRequestDataRequested(n); + } finally { + second.onRequestDataRequested(n); + } + } + @Override public void onRequestData(final Buffer data) { try { @@ -184,6 +193,15 @@ private BiGrpcResponseObserver(final GrpcResponseObserver first, final GrpcRespo this.second = requireNonNull(second); } + @Override + public void onResponseDataRequested(final long n) { + try { + first.onResponseDataRequested(n); + } finally { + second.onResponseDataRequested(n); + } + } + @Override public void onResponseData(final Buffer data) { try { diff --git a/servicetalk-grpc-utils/src/main/java/io/servicetalk/grpc/utils/LoggingGrpcLifecycleObserver.java b/servicetalk-grpc-utils/src/main/java/io/servicetalk/grpc/utils/LoggingGrpcLifecycleObserver.java index 2e21490b50..4cb496db4e 100644 --- a/servicetalk-grpc-utils/src/main/java/io/servicetalk/grpc/utils/LoggingGrpcLifecycleObserver.java +++ b/servicetalk-grpc-utils/src/main/java/io/servicetalk/grpc/utils/LoggingGrpcLifecycleObserver.java @@ -95,6 +95,10 @@ public GrpcRequestObserver onRequest(final HttpRequestMetaData requestMetaData) return this; } + @Override + public void onRequestDataRequested(final long n) { + } + @Override public void onRequestData(final Buffer data) { requestSize += data.readableBytes(); @@ -131,6 +135,10 @@ public GrpcResponseObserver onResponse(final HttpResponseMetaData responseMetaDa return this; } + @Override + public void onResponseDataRequested(final long n) { + } + @Override public void onResponseData(final Buffer data) { responseSize += data.readableBytes(); diff --git a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/HttpLifecycleObserver.java b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/HttpLifecycleObserver.java index 053ddd8ef2..52e41ca7d7 100644 --- a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/HttpLifecycleObserver.java +++ b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/HttpLifecycleObserver.java @@ -109,6 +109,17 @@ interface HttpExchangeObserver { */ interface HttpRequestObserver { + /** + * Callback when subscriber requests {@code n} items of the request payload body. + *

+ * May be invoked multiple times. Helps to track when items are requested and when they are + * {@link #onRequestData(Buffer) delivered}. + * + * @param n number of requested items + */ + default void onRequestDataRequested(long n) { // FIXME: 0.43 - consider removing default impl + } + /** * Callback when the request payload body data chunk was observed. *

@@ -158,6 +169,16 @@ interface HttpRequestObserver { */ interface HttpResponseObserver { + /** + * Callback when subscriber requests {@code n} items of the response payload body. + *

+ * May be invoked multiple times. Helps to track when items are requested and when they are + * {@link #onResponseData delivered}. + * + * @param n number of requested items + */ + void onResponseDataRequested(long n); // FIXME: 0.43 - consider removing default impl + /** * Callback when the response payload body data chunk was observed. *

diff --git a/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/AbstractLifecycleObserverHttpFilter.java b/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/AbstractLifecycleObserverHttpFilter.java index 2deb50510d..96e4bddbf4 100644 --- a/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/AbstractLifecycleObserverHttpFilter.java +++ b/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/AbstractLifecycleObserverHttpFilter.java @@ -104,7 +104,9 @@ final Single trackLifecycle(@Nullable final ConnectionInf return NoopSubscriber.INSTANCE; }); } - return p.beforeOnNext(item -> { + return p.beforeRequest(n -> safeReport(onRequest::onRequestDataRequested, n, onRequest, + "onRequestDataRequested")) + .beforeOnNext(item -> { if (item instanceof Buffer) { safeReport(onRequest::onRequestData, (Buffer) item, onRequest, "onRequestData"); } else if (item instanceof HttpHeaders) { @@ -151,7 +153,9 @@ public void cancel() { // needs to be applied last. .map(resp -> { exchangeContext.onResponse(resp); - return resp.transformMessageBody(p -> p.beforeOnNext(exchangeContext::onResponseBody)); + return resp.transformMessageBody(p -> p + .beforeRequest(exchangeContext::onResponseDataRequested) + .beforeOnNext(exchangeContext::onResponseBody)); }).shareContextOnSubscribe(); }); } @@ -192,6 +196,11 @@ void onResponse(HttpResponseMetaData responseMetaData) { NoopHttpLifecycleObserver.NoopHttpResponseObserver.INSTANCE); } + void onResponseDataRequested(final long n) { + assert onResponse != null; + safeReport(onResponse::onResponseDataRequested, n, onResponse, "onResponseDataRequested"); + } + void onResponseBody(final Object item) { assert onResponse != null; if (item instanceof Buffer) { diff --git a/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/NoopHttpLifecycleObserver.java b/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/NoopHttpLifecycleObserver.java index dfd397d70f..406e9f383b 100644 --- a/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/NoopHttpLifecycleObserver.java +++ b/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/NoopHttpLifecycleObserver.java @@ -78,6 +78,10 @@ private NoopHttpRequestObserver() { // Singleton } + @Override + public void onRequestDataRequested(final long n) { + } + @Override public void onRequestData(final Buffer data) { } @@ -107,6 +111,10 @@ private NoopHttpResponseObserver() { // Singleton } + @Override + public void onResponseDataRequested(final long n) { + } + @Override public void onResponseData(final Buffer data) { } diff --git a/servicetalk-http-netty/src/test/java/io/servicetalk/http/netty/HttpLifecycleObserverTest.java b/servicetalk-http-netty/src/test/java/io/servicetalk/http/netty/HttpLifecycleObserverTest.java index 0a411cc633..f2f2593b83 100644 --- a/servicetalk-http-netty/src/test/java/io/servicetalk/http/netty/HttpLifecycleObserverTest.java +++ b/servicetalk-http-netty/src/test/java/io/servicetalk/http/netty/HttpLifecycleObserverTest.java @@ -73,6 +73,8 @@ import static org.hamcrest.Matchers.sameInstance; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.atMostOnce; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.inOrder; @@ -267,6 +269,7 @@ public Single handle(HttpServiceContext ctx, clientInOrder.verify(clientExchangeObserver).onRequest(any(StreamingHttpRequest.class)); clientInOrder.verify(clientExchangeObserver).onConnectionSelected(any(ConnectionInfo.class)); clientInOrder.verify(clientExchangeObserver).onResponseCancel(); + clientRequestInOrder.verify(clientRequestObserver).onRequestDataRequested(anyLong()); clientRequestInOrder.verify(clientRequestObserver).onRequestData(any(Buffer.class)); clientRequestInOrder.verify(clientRequestObserver).onRequestCancel(); clientInOrder.verify(clientExchangeObserver).onExchangeFinally(); @@ -276,11 +279,13 @@ public Single handle(HttpServiceContext ctx, serverInOrder.verify(serverLifecycleObserver).onNewExchange(); serverInOrder.verify(serverExchangeObserver).onConnectionSelected(any(ConnectionInfo.class)); serverInOrder.verify(serverExchangeObserver).onRequest(any(StreamingHttpRequest.class)); + serverRequestInOrder.verify(serverRequestObserver, atLeastOnce()).onRequestDataRequested(anyLong()); serverRequestInOrder.verify(serverRequestObserver).onRequestData(any(Buffer.class)); serverRequestInOrder.verify(serverRequestObserver).onRequestError(any(IOException.class)); // because of offloading, cancel from the IO-thread may race with an error propagated through request publisher: verify(serverExchangeObserver, atMostOnce()).onResponseCancel(); verify(serverExchangeObserver, atMostOnce()).onResponse(any(StreamingHttpResponse.class)); + verify(serverResponseObserver, atMostOnce()).onResponseDataRequested(anyLong()); verify(serverResponseObserver, atMostOnce()).onResponseComplete(); serverInOrder.verify(serverExchangeObserver).onExchangeFinally(); verifyNoMoreInteractions(serverLifecycleObserver, serverExchangeObserver, @@ -323,7 +328,9 @@ public Single handle(HttpServiceContext ctx, clientInOrder.verify(clientExchangeObserver).onConnectionSelected(any(ConnectionInfo.class)); clientInOrder.verify(clientExchangeObserver).onRequest(any(StreamingHttpRequest.class)); clientInOrder.verify(clientExchangeObserver).onResponse(any(StreamingHttpResponse.class)); + clientInOrder.verify(clientResponseObserver, atLeastOnce()).onResponseDataRequested(anyLong()); clientInOrder.verify(clientResponseObserver).onResponseCancel(); + verify(clientRequestObserver, atLeastOnce()).onRequestDataRequested(anyLong()); clientRequestInOrder.verify(clientRequestObserver).onRequestData(any(Buffer.class)); clientRequestInOrder.verify(clientRequestObserver).onRequestTrailers(any(HttpHeaders.class)); clientRequestInOrder.verify(clientRequestObserver).onRequestComplete(); @@ -335,8 +342,10 @@ public Single handle(HttpServiceContext ctx, serverInOrder.verify(serverExchangeObserver).onConnectionSelected(any(ConnectionInfo.class)); serverInOrder.verify(serverExchangeObserver).onRequest(any(StreamingHttpRequest.class)); serverInOrder.verify(serverExchangeObserver).onResponse(any(StreamingHttpResponse.class)); + verify(serverResponseObserver, atLeastOnce()).onResponseDataRequested(anyLong()); verify(serverResponseObserver, atMostOnce()).onResponseData(any(Buffer.class)); serverInOrder.verify(serverResponseObserver).onResponseCancel(); + serverRequestInOrder.verify(serverRequestObserver, atLeastOnce()).onRequestDataRequested(anyLong()); serverRequestInOrder.verify(serverRequestObserver).onRequestData(any(Buffer.class)); serverRequestInOrder.verify(serverRequestObserver).onRequestComplete(); serverInOrder.verify(serverExchangeObserver).onExchangeFinally(); @@ -367,11 +376,13 @@ private static void verifyObservers(boolean client, HttpLifecycleObserver lifecy inOrder.verify(exchange).onRequest(any(StreamingHttpRequest.class)); } inOrder.verify(exchange).onResponse(any(StreamingHttpResponse.class)); + verify(response, atLeastOnce()).onResponseDataRequested(anyLong()); inOrder.verify(response, hasMessageBody ? times(1) : never()).onResponseData(any(Buffer.class)); inOrder.verify(response, hasTrailers && !client ? times(1) : never()) .onResponseTrailers(any(HttpHeaders.class)); inOrder.verify(response).onResponseComplete(); + verify(request, atLeastOnce()).onRequestDataRequested(anyLong()); requestInOrder.verify(request, hasMessageBody ? times(1) : never()).onRequestData(any(Buffer.class)); requestInOrder.verify(request, hasTrailers && client ? times(1) : never()) .onRequestTrailers(any(HttpHeaders.class)); @@ -393,8 +404,10 @@ private static void verifyError(boolean client, HttpLifecycleObserver lifecycle, inOrder.verify(exchange).onRequest(any(StreamingHttpRequest.class)); } inOrder.verify(exchange).onResponse(any(StreamingHttpResponse.class)); + verify(response, atLeastOnce()).onResponseDataRequested(anyLong()); inOrder.verify(response).onResponseError(!client ? DELIBERATE_EXCEPTION : any()); + verify(request, atLeastOnce()).onRequestDataRequested(anyLong()); requestInOrder.verify(request, never()).onRequestTrailers(any(HttpHeaders.class)); requestInOrder.verify(request).onRequestComplete(); diff --git a/servicetalk-http-utils/src/main/java/io/servicetalk/http/utils/BiHttpLifecycleObserver.java b/servicetalk-http-utils/src/main/java/io/servicetalk/http/utils/BiHttpLifecycleObserver.java index aeae791679..b110aa9416 100644 --- a/servicetalk-http-utils/src/main/java/io/servicetalk/http/utils/BiHttpLifecycleObserver.java +++ b/servicetalk-http-utils/src/main/java/io/servicetalk/http/utils/BiHttpLifecycleObserver.java @@ -127,6 +127,15 @@ private static final class BiHttpRequestObserver implements HttpRequestObserver this.second = requireNonNull(second); } + @Override + public void onRequestDataRequested(final long n) { + try { + first.onRequestDataRequested(n); + } finally { + second.onRequestDataRequested(n); + } + } + @Override public void onRequestData(final Buffer data) { try { @@ -183,6 +192,15 @@ private BiHttpResponseObserver(final HttpResponseObserver first, final HttpRespo this.second = requireNonNull(second); } + @Override + public void onResponseDataRequested(final long n) { + try { + first.onResponseDataRequested(n); + } finally { + second.onResponseDataRequested(n); + } + } + @Override public void onResponseData(final Buffer data) { try { diff --git a/servicetalk-http-utils/src/main/java/io/servicetalk/http/utils/LoggingHttpLifecycleObserver.java b/servicetalk-http-utils/src/main/java/io/servicetalk/http/utils/LoggingHttpLifecycleObserver.java index 8be3531c46..7025447e41 100644 --- a/servicetalk-http-utils/src/main/java/io/servicetalk/http/utils/LoggingHttpLifecycleObserver.java +++ b/servicetalk-http-utils/src/main/java/io/servicetalk/http/utils/LoggingHttpLifecycleObserver.java @@ -91,6 +91,10 @@ public HttpRequestObserver onRequest(final HttpRequestMetaData requestMetaData) return this; } + @Override + public void onRequestDataRequested(final long n) { + } + @Override public void onRequestData(final Buffer data) { requestSize += data.readableBytes(); @@ -127,6 +131,10 @@ public HttpResponseObserver onResponse(final HttpResponseMetaData responseMetaDa return this; } + @Override + public void onResponseDataRequested(final long n) { + } + @Override public void onResponseData(final Buffer data) { responseSize += data.readableBytes(); From d85bc3fd8c16de7243fc713b36cf726849ab1358 Mon Sep 17 00:00:00 2001 From: Idel Pivnitskiy Date: Fri, 3 Jun 2022 14:25:12 -0500 Subject: [PATCH 39/40] Add `ConnectionObserver#connectionWritabilityChanged(boolean)` (#2229) Motivation: Callback helps users to see when channel's writability state changes. Modifications: - Add `ConnectionObserver#connectionWritabilityChanged(boolean)`; Result: Users can detect inefficient network configuration (too small outbound socket buffer) or when the remote peer reads slower than expected. --- .../netty/HttpTransportObserverAsyncContextTest.java | 5 +++++ .../servicetalk/transport/api/BiTransportObserver.java | 6 ++++++ .../transport/api/CatchAllTransportObserver.java | 6 ++++++ .../servicetalk/transport/api/ConnectionObserver.java | 10 ++++++++++ .../transport/api/NoopTransportObserver.java | 4 ++++ .../netty/internal/ConnectionObserverInitializer.java | 6 ++++++ .../netty/internal/NoopTransportObserver.java | 4 ++++ 7 files changed, 41 insertions(+) diff --git a/servicetalk-http-netty/src/test/java/io/servicetalk/http/netty/HttpTransportObserverAsyncContextTest.java b/servicetalk-http-netty/src/test/java/io/servicetalk/http/netty/HttpTransportObserverAsyncContextTest.java index c7c795006a..41e6a0c1a8 100644 --- a/servicetalk-http-netty/src/test/java/io/servicetalk/http/netty/HttpTransportObserverAsyncContextTest.java +++ b/servicetalk-http-netty/src/test/java/io/servicetalk/http/netty/HttpTransportObserverAsyncContextTest.java @@ -216,6 +216,11 @@ public MultiplexedObserver multiplexedConnectionEstablished(final ConnectionInfo return new AsyncContextCaptureMultiplexedObserver(); } + @Override + public void connectionWritabilityChanged(final boolean isWritable) { + // AsyncContext is unknown at this point because this event is triggered by network + } + @Override public void connectionClosed(final Throwable error) { // AsyncContext is unknown at this point because this event is triggered by network diff --git a/servicetalk-transport-api/src/main/java/io/servicetalk/transport/api/BiTransportObserver.java b/servicetalk-transport-api/src/main/java/io/servicetalk/transport/api/BiTransportObserver.java index c46036f122..939d24ed98 100644 --- a/servicetalk-transport-api/src/main/java/io/servicetalk/transport/api/BiTransportObserver.java +++ b/servicetalk-transport-api/src/main/java/io/servicetalk/transport/api/BiTransportObserver.java @@ -93,6 +93,12 @@ public MultiplexedObserver multiplexedConnectionEstablished(final ConnectionInfo second.multiplexedConnectionEstablished(info)); } + @Override + public void connectionWritabilityChanged(final boolean isWritable) { + first.connectionWritabilityChanged(isWritable); + second.connectionWritabilityChanged(isWritable); + } + @Override public void connectionClosed(final Throwable error) { first.connectionClosed(error); diff --git a/servicetalk-transport-api/src/main/java/io/servicetalk/transport/api/CatchAllTransportObserver.java b/servicetalk-transport-api/src/main/java/io/servicetalk/transport/api/CatchAllTransportObserver.java index 9236e86239..267a4eb9f2 100644 --- a/servicetalk-transport-api/src/main/java/io/servicetalk/transport/api/CatchAllTransportObserver.java +++ b/servicetalk-transport-api/src/main/java/io/servicetalk/transport/api/CatchAllTransportObserver.java @@ -106,6 +106,12 @@ public MultiplexedObserver multiplexedConnectionEstablished(final ConnectionInfo CatchAllMultiplexedObserver::new, NoopMultiplexedObserver.INSTANCE); } + @Override + public void connectionWritabilityChanged(final boolean isWritable) { + safeReport(() -> observer.connectionWritabilityChanged(isWritable), observer, + "connection writability changed"); + } + @Override public void connectionClosed(final Throwable error) { safeReport(() -> observer.connectionClosed(error), observer, "connection closed", error); diff --git a/servicetalk-transport-api/src/main/java/io/servicetalk/transport/api/ConnectionObserver.java b/servicetalk-transport-api/src/main/java/io/servicetalk/transport/api/ConnectionObserver.java index 740a7cd0c9..6348139344 100644 --- a/servicetalk-transport-api/src/main/java/io/servicetalk/transport/api/ConnectionObserver.java +++ b/servicetalk-transport-api/src/main/java/io/servicetalk/transport/api/ConnectionObserver.java @@ -89,6 +89,16 @@ public interface ConnectionObserver { */ MultiplexedObserver multiplexedConnectionEstablished(ConnectionInfo info); + /** + * Callback when a writable state of the connection changes. + * + * @param isWritable describes the current state of the connection: {@code true} when the I/O thread will perform + * the requested write operation immediately. If {@code false}, write requests will be queued until the I/O thread + * is ready to process the queued items and the transport will start applying backpressure. + */ + default void connectionWritabilityChanged(boolean isWritable) { // FIXME: 0.43 - consider removing default impl + } + /** * Callback when the connection is closed due to an {@link Throwable error}. * diff --git a/servicetalk-transport-api/src/main/java/io/servicetalk/transport/api/NoopTransportObserver.java b/servicetalk-transport-api/src/main/java/io/servicetalk/transport/api/NoopTransportObserver.java index f2c469ccb5..3a244c2369 100644 --- a/servicetalk-transport-api/src/main/java/io/servicetalk/transport/api/NoopTransportObserver.java +++ b/servicetalk-transport-api/src/main/java/io/servicetalk/transport/api/NoopTransportObserver.java @@ -77,6 +77,10 @@ public MultiplexedObserver multiplexedConnectionEstablished(final ConnectionInfo return NoopMultiplexedObserver.INSTANCE; } + @Override + public void connectionWritabilityChanged(final boolean isWritable) { + } + @Override public void connectionClosed(final Throwable error) { } diff --git a/servicetalk-transport-netty-internal/src/main/java/io/servicetalk/transport/netty/internal/ConnectionObserverInitializer.java b/servicetalk-transport-netty-internal/src/main/java/io/servicetalk/transport/netty/internal/ConnectionObserverInitializer.java index 35e942dffc..148803e09d 100644 --- a/servicetalk-transport-netty-internal/src/main/java/io/servicetalk/transport/netty/internal/ConnectionObserverInitializer.java +++ b/servicetalk-transport-netty-internal/src/main/java/io/servicetalk/transport/netty/internal/ConnectionObserverInitializer.java @@ -153,5 +153,11 @@ public void flush(final ChannelHandlerContext ctx) { observer.onFlush(); ctx.flush(); } + + @Override + public void channelWritabilityChanged(final ChannelHandlerContext ctx) { + observer.connectionWritabilityChanged(ctx.channel().isWritable()); + ctx.fireChannelWritabilityChanged(); + } } } diff --git a/servicetalk-transport-netty-internal/src/main/java/io/servicetalk/transport/netty/internal/NoopTransportObserver.java b/servicetalk-transport-netty-internal/src/main/java/io/servicetalk/transport/netty/internal/NoopTransportObserver.java index db193e3946..6ec5e8ed60 100644 --- a/servicetalk-transport-netty-internal/src/main/java/io/servicetalk/transport/netty/internal/NoopTransportObserver.java +++ b/servicetalk-transport-netty-internal/src/main/java/io/servicetalk/transport/netty/internal/NoopTransportObserver.java @@ -86,6 +86,10 @@ public MultiplexedObserver multiplexedConnectionEstablished(final ConnectionInfo return NoopMultiplexedObserver.INSTANCE; } + @Override + public void connectionWritabilityChanged(final boolean isWritable) { + } + @Override public void connectionClosed(final Throwable error) { } From 1d454a74a12f168ecc0c963d4709f74dcb8fd1e9 Mon Sep 17 00:00:00 2001 From: Idel Pivnitskiy Date: Fri, 3 Jun 2022 18:30:42 -0500 Subject: [PATCH 40/40] Clarify expectations for `TransportObserver` implementations (#2238) Motivation: `TransportObserver` does not clarify if users can block or not inside their implementations. Modifications: - Copy offloading requirements from `HttpLifecycleObserver` to `TransportObserver`; Result: `TransportObserver` javadoc clarifies expectations for non-blocking implementations and suggests to do manual offloading if necessary. --- .../io/servicetalk/http/api/HttpLifecycleObserver.java | 10 +++++----- .../servicetalk/transport/api/TransportObserver.java | 8 ++++++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/HttpLifecycleObserver.java b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/HttpLifecycleObserver.java index 52e41ca7d7..6ea9bb0021 100644 --- a/servicetalk-http-api/src/main/java/io/servicetalk/http/api/HttpLifecycleObserver.java +++ b/servicetalk-http-api/src/main/java/io/servicetalk/http/api/HttpLifecycleObserver.java @@ -24,11 +24,11 @@ * An observer interface that provides visibility into HTTP lifecycle events. *

* In order to deliver events at accurate time, callbacks on this interface can be invoked from the {@link IoExecutor}. - * Implementation of this observer must be non-blocking. If the - * consumer of events may block (uses a blocking library or - * logger configuration is not async), it has to - * offload publications to another {@link Executor} after capturing timing of events. If blocking code is - * executed inside callbacks without offloading, it will negatively impact {@link IoExecutor}. + * Implementation of this observer must be non-blocking. If the consumer of events may block (uses a blocking + * library or logger configuration is not async), + * it has to offload publications to another {@link Executor} after capturing timing of events. If blocking code + * is executed inside callbacks without offloading, it will negatively impact {@link IoExecutor} and overall performance + * of the application. *

* To install this observer for the server use {@link HttpServerBuilder#lifecycleObserver(HttpLifecycleObserver)}, for * the client use {@link SingleAddressHttpClientBuilder#appendClientFilter(StreamingHttpClientFilterFactory)} with diff --git a/servicetalk-transport-api/src/main/java/io/servicetalk/transport/api/TransportObserver.java b/servicetalk-transport-api/src/main/java/io/servicetalk/transport/api/TransportObserver.java index 001ec92b5a..c0337bf525 100644 --- a/servicetalk-transport-api/src/main/java/io/servicetalk/transport/api/TransportObserver.java +++ b/servicetalk-transport-api/src/main/java/io/servicetalk/transport/api/TransportObserver.java @@ -15,12 +15,20 @@ */ package io.servicetalk.transport.api; +import io.servicetalk.concurrent.api.Executor; import io.servicetalk.transport.api.NoopTransportObserver.NoopConnectionObserver; import javax.annotation.Nullable; /** * An observer interface that provides visibility into transport events. + *

+ * In order to deliver events at accurate time, callbacks on this interface can be invoked from the {@link IoExecutor}. + * Implementation of this observer must be non-blocking. If the consumer of events may block (uses a blocking + * library or logger configuration is not async), + * it has to offload publications to another {@link Executor} after capturing timing of events. If blocking code + * is executed inside callbacks without offloading, it will negatively impact {@link IoExecutor} and overall performance + * of the application. */ public interface TransportObserver {