diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS deleted file mode 100644 index a1d58a77c..000000000 --- a/.github/CODEOWNERS +++ /dev/null @@ -1,7 +0,0 @@ -# Code owners file. -# This file controls who is tagged for review for any given pull request. -# -# For syntax help see: -# https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners#codeowners-syntax - -* @googleapis/actools-java @googleapis/yoshi-java @googleapis/cloud-java-team-teamsync diff --git a/.github/snippet-bot.yml b/.github/snippet-bot.yml deleted file mode 100644 index 1488c14ec..000000000 --- a/.github/snippet-bot.yml +++ /dev/null @@ -1,2 +0,0 @@ -aggregateChecks: false -alwaysCreateStatusCheck: false diff --git a/.github/sync-repo-settings.yaml b/.github/sync-repo-settings.yaml deleted file mode 100644 index 4ff4f40b1..000000000 --- a/.github/sync-repo-settings.yaml +++ /dev/null @@ -1,45 +0,0 @@ -rebaseMergeAllowed: false -squashMergeAllowed: true -mergeCommitAllowed: false -branchProtectionRules: - - pattern: main - isAdminEnforced: true - requiredApprovingReviewCount: 1 - requiresCodeOwnerReviews: true - requiresStrictStatusChecks: false - requiredStatusCheckContexts: - - bazel - - units (8) - - units (11) - - cla/google - - pattern: 2.16.x - isAdminEnforced: true - requiredApprovingReviewCount: 1 - requiresCodeOwnerReviews: true - requiresStrictStatusChecks: true - requiredStatusCheckContexts: - - bazel - - units (8) - - units (11) - - cla/google - - pattern: 2.19.x - isAdminEnforced: true - requiredApprovingReviewCount: 1 - requiresCodeOwnerReviews: true - requiresStrictStatusChecks: false - requiredStatusCheckContexts: - - bazel - - units (8) - - units (11) - - cla/google -permissionRules: - - team: yoshi-admins - permission: admin - - team: yoshi-java-admins - permission: admin - - team: yoshi-java - permission: push - - team: actools - permission: admin - - team: actools-java - permission: push diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml deleted file mode 100644 index b05c1da3d..000000000 --- a/.github/workflows/ci.yaml +++ /dev/null @@ -1,113 +0,0 @@ -on: - push: - branches: - - main - pull_request: -name: ci -jobs: - clirr: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 - with: - distribution: temurin - java-version: 8 - - run: echo "JAVA8_HOME=${JAVA_HOME}" >> $GITHUB_ENV - - uses: actions/setup-java@v3 - with: - distribution: temurin - java-version: 11 - - run: echo "JAVA11_HOME=${JAVA_HOME}" >> $GITHUB_ENV - - run: .kokoro/build.sh - env: - JOB_TYPE: clirr - units-java11: - name: "units (11)" - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 - with: - java-version: 11 - distribution: zulu - - run: java -version - - run: .kokoro/build.sh - env: - JOB_TYPE: test - units-java8: - name: "units (8)" - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - # Java 8 tests uses JDK 11 to compile and JDK 8 to run tests. See .kokoro/ - # build.sh for the setup. - - uses: actions/setup-java@v3 - with: - java-version: 8 - distribution: zulu - - run: echo "JAVA8_HOME=${JAVA_HOME}" >> $GITHUB_ENV - - uses: actions/setup-java@v3 - with: - java-version: 11 - distribution: zulu - - run: echo "JAVA11_HOME=${JAVA_HOME}" >> $GITHUB_ENV - - run: printenv - - run: .kokoro/build.sh - env: - JOB_TYPE: test - bazel: - runs-on: ubuntu-latest - # Not using a container. The ubuntu-latest has Bazel 4.2 installed as of - # November 2021. gRPC 1.42 requires Bazel 4. - # https://github.com/grpc/grpc-java/pull/7598 - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-java@v1 - with: - java-version: 8 - - run: java -version - - - name: Bazel File Cache Setup - id: cache-bazel - uses: actions/cache@v3 - with: - path: ~/.cache/bazel - key: ${{ runner.os }}-bazel-20210105-${{ secrets.CACHE_VERSION }} - - - name: Bazel Cache Not Found - if: steps.cache-bazel.outputs.cache-hit != 'true' - run: | - echo "No cache found." - - name: Bazel Cache Found - if: steps.cache-bazel.outputs.cache-hit == 'true' - run: | - echo -n "Cache found. Cache size: " - du -sh ~/.cache/bazel - echo "If the cache seems broken, update the CACHE_VERSION secret in" - echo "https://github.com/googleapis/googleapis-discovery/settings/secrets/actions" - echo "(use any random string, any GUID will work)" - echo "and it will start over with a clean cache." - echo "The old one will disappear after 7 days." - - - name: Run bazel tests - run: | - which bazel - bazel --version - bazel --batch test //... --noshow_progress --test_output=errors - - - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: test-artifacts - path: ~/.cache/bazel/*/*/*/gax-java/bazel-out/*/testlogs/* - retention-days: 5 - requirements: - name: "requirements" - runs-on: ubuntu-latest - container: gcr.io/cloud-devrel-public-resources/java8 - steps: - - uses: actions/checkout@v2 - - run: | - python3 --version - python3 -m pip install --require-hashes -r .kokoro/requirements.txt diff --git a/.github/workflows/downstream-native-image.yaml b/.github/workflows/downstream-native-image.yaml deleted file mode 100644 index 5e0b4431c..000000000 --- a/.github/workflows/downstream-native-image.yaml +++ /dev/null @@ -1,41 +0,0 @@ -on: - push: - branches: - - main - pull_request: - -# Keeping this file separate as the dependencies check would use more -# repositories than needed this downstream check for GraalVM native image -# compilation. -name: downstream -jobs: - # GraalVM job ensures the compatibility of GraaVM version - graalvm: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - graalvm: [22.3.0] - java: [11, 17] - repo: - # GAPIC library that doesn't use a real GCP project in integration tests - - orgpolicy - steps: - - uses: actions/checkout@v2 - - uses: stCarolas/setup-maven@v4 - with: - maven-version: 3.8.1 - - uses: ayltai/setup-graalvm@v1 - with: - java-version: ${{matrix.java}} - # When a new version of native-maven-plugin fails to run in a downstream - # library, it's likely to be an incompatibility with the GraalVM version. - # In that case, you need to upgrade the Docker container used in the - # tests in the downstream repositories (not just this value below). - # Example: https://github.com/googleapis/testing-infra-docker/pull/195 - graalvm-version: ${{matrix.graalvm}} - native-image: true - - run: java -version - - run: sudo apt-get update -y - - run: sudo apt-get install libxml2-utils - - run: .kokoro/downstream-client-library-check.sh ${{matrix.repo}} graalvm diff --git a/.github/workflows/downstream.yaml b/.github/workflows/downstream.yaml deleted file mode 100644 index 45e45fa25..000000000 --- a/.github/workflows/downstream.yaml +++ /dev/null @@ -1,144 +0,0 @@ -on: - pull_request: - types: [ labeled ] - branches: - - main -name: downstream -jobs: - dependencies: - if: ${{ github.event.label.name == 'downstream-check:run' }} - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - java: [11] - repo: - # This list needs to be updated manually until an automated solution is in place. - - accessapproval - - accesscontextmanager - - aiplatform - - analytics-admin - - analytics-data - - api-gateway - - apigee-connect - - appengine-admin - - area120-tables - - artifact-registry - - asset - - assured-workloads - - automl - - bigquery - - bigqueryconnection - - bigquerydatatransfer - - bigquerymigration - - bigqueryreservation - - bigtable - - billing - - billingbudgets - - binary-authorization - - channel - - cloudbuild - - compute - - contact-center-insights - - container - - containeranalysis - - data-fusion - - datacatalog - - dataflow - - datalabeling - - dataproc - - dataproc-metastore - - datastore - - datastream - - debugger-client - - deploy - - dialogflow - - dialogflow-cx - - dlp - - dms - - dns - - document-ai - - domains - - errorreporting - - essential-contacts - - eventarc - - filestore - - firestore - - functions - - game-servers - - gke-connect-gateway - - gkehub - - gsuite-addons - - iam-admin - - iamcredentials - - iot - - kms - - language - - life-sciences - - logging - - logging-logback - - managed-identities - - mediatranslation - - memcache - - monitoring - - monitoring-dashboards - - network-management - - network-security - - networkconnectivity - - notebooks - - orchestration-airflow - - orgpolicy - - os-config - - os-login - - phishingprotection - - policy-troubleshooter - - private-catalog - - profiler - - pubsublite - - recaptchaenterprise - - recommendations-ai - - recommender - - redis - - resource-settings - - resourcemanager - - retail - - scheduler - - secretmanager - - security-private-ca - - securitycenter - - securitycenter-settings - - service-control - - service-management - - service-usage - - servicedirectory - - shell - - spanner - - spanner-jdbc - - speech - - storage - - storage-nio - - storage-transfer - - talent - - tasks - - texttospeech - - tpu - - trace - - translate - - video-intelligence - - video-transcoder - - vision - - vpcaccess - - webrisk - - websecurityscanner - - workflow-executions - - workflows - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-java@v3 - with: - distribution: zulu - java-version: ${{matrix.java}} - - run: java -version - - run: sudo apt-get update -y - - run: sudo apt-get install libxml2-utils - - run: .kokoro/downstream-client-library-check.sh ${{matrix.repo}} test diff --git a/.github/workflows/sonar.yaml b/.github/workflows/sonar.yaml deleted file mode 100644 index 1eb2608b8..000000000 --- a/.github/workflows/sonar.yaml +++ /dev/null @@ -1,38 +0,0 @@ -name: Sonar -on: - push: - branches: - - main - pull_request: - types: [opened, synchronize, reopened] -jobs: - sonar-maven: - name: Java 11 Maven Build - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - - name: Set up JDK 11 - uses: actions/setup-java@v3 - with: - distribution: temurin - java-version: 11 - - name: Cache SonarCloud packages - uses: actions/cache@v3 - with: - path: ~/.sonar/cache - key: ${{ runner.os }}-sonar - restore-keys: ${{ runner.os }}-sonar - - name: Cache Maven packages - uses: actions/cache@v3 - with: - path: ~/.m2/repository - key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} - restore-keys: ${{ runner.os }}-m2 - - name: Build and analyze - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - run: mvn -B verify sonar:sonar -Dsonar.projectKey=googleapis_gax-java -Dsonar.organization=googleapis -Dsonar.host.url=https://sonarcloud.io - diff --git a/.gitignore b/.gitignore deleted file mode 100644 index e6010998c..000000000 --- a/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Build results -bin -build -.gradle -tmp_docs -bazel-* -target - -# Eclipse -.apt_generated* -.classpath -.factorypath -.project -.settings - -# IntelliJ -.idea -*.iml -out - -# Vim. -*.sw* -*.vim - diff --git a/.kokoro/build.sh b/.kokoro/build.sh deleted file mode 100755 index a9e909f0d..000000000 --- a/.kokoro/build.sh +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/bash -# Copyright 2018 Google LLC -# -# 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 -eo pipefail - -scriptDir=$(realpath $(dirname "${BASH_SOURCE[0]}")) -# cd to the parent directory, i.e. the root of the git repo -cd ${scriptDir}/.. - -echo $JOB_TYPE - -function setJava() { - export JAVA_HOME=$1 - export PATH=${JAVA_HOME}/bin:$PATH -} - -# This project requires compiling the classes in JDK 11 or higher for GraalVM -# classes. Compiling this project with Java 8 or earlier would fail with "class -# file has wrong version 55.0, should be 53.0" and "unrecognized --release 8 -# option" (set in build.gradle). -if [ ! -z "${JAVA11_HOME}" ]; then - setJava "${JAVA11_HOME}" -fi - -mvn -V -B -ntp clean install -DskipTests - -# We ensure the generated class files are compatible with Java 8 -if [ ! -z "${JAVA8_HOME}" ]; then - setJava "${JAVA8_HOME}" -fi - -RETURN_CODE=0 - -case "${JOB_TYPE}" in -test) - # run tests in Java 8 with the source compiled in Java 11 - mvn -V -B -ntp surefire:test - RETURN_CODE=$? - ;; -clirr) - mvn -B -ntp clirr:check - RETURN_CODE=$? - ;; -*) ;; -esac - -echo "exiting with ${RETURN_CODE}" -exit ${RETURN_CODE} \ No newline at end of file diff --git a/.kokoro/common.cfg b/.kokoro/common.cfg deleted file mode 100644 index e97bed17f..000000000 --- a/.kokoro/common.cfg +++ /dev/null @@ -1,13 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -# Download trampoline resources. These will be in ${KOKORO_GFILE_DIR} -gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" - -# All builds use the trampoline script to run in docker. -build_file: "gax-java/.kokoro/trampoline.sh" - -# Tell the trampoline which build file to use. -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/gax-java/.kokoro/build.sh" -} diff --git a/.kokoro/downstream-client-library-check.sh b/.kokoro/downstream-client-library-check.sh deleted file mode 100755 index 612fd793b..000000000 --- a/.kokoro/downstream-client-library-check.sh +++ /dev/null @@ -1,99 +0,0 @@ -#!/bin/bash -# Copyright 2022 Google LLC -# -# 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 -eo pipefail -# Display commands being run. -set -x - -CLIENT_LIBRARY=$1 - -# Example JOB_TYPE: "test" or "graalvm" -export JOB_TYPE=$2 -## Get the directory of the build script -scriptDir="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" -## cd to the parent directory, i.e. the root of the git repo -cd "${scriptDir}"/.. - -# Round 1 -# Publish gax to local maven to make it available for downstream libraries -./gradlew publishToMavenLocal - -# Read current gax version -GAX_VERSION=$( ./gradlew -q :gax:properties | grep '^version: ' | cut -d' ' -f2 ) - -# Round 2 -# Run this gax-java against HEAD of java-shared dependencies - -git clone "https://github.com/googleapis/java-shared-dependencies.git" --depth=1 -pushd java-shared-dependencies/first-party-dependencies - -# replace version -xmllint --shell pom.xml << EOF -setns x=http://maven.apache.org/POM/4.0.0 -cd .//x:artifactId[text()="gax-bom"] -cd ../x:version -set ${GAX_VERSION} -cd ../.. -cd .//x:artifactId[text()="gax-grpc"] -cd ../x:version -set ${GAX_VERSION} -save pom.xml -EOF - -cd .. -mvn verify install -B -V -ntp -fae \ --DskipTests=true \ --Dmaven.javadoc.skip=true \ --Dgcloud.download.skip=true \ --Denforcer.skip=true - -# Namespace (xmlns) prevents xmllint from specifying tag names in XPath -SHARED_DEPS_VERSION=$( sed -e 's/xmlns=".*"//' pom.xml | xmllint --xpath '/project/version/text()' - ) - -if [ -z "${SHARED_DEPS_VERSION}" ]; then - echo "Version is not found in pom.xml" - exit 1 -fi - -# Round 3 -# Run this shared-dependencies BOM against java client libraries -git clone "https://github.com/googleapis/java-${CLIENT_LIBRARY}.git" --depth=1 -pushd java-"${CLIENT_LIBRARY}" - -if [[ $CLIENT_LIBRARY == "bigtable" ]]; then - pushd google-cloud-bigtable-deps-bom -fi - -# replace version -xmllint --shell pom.xml << EOF -setns x=http://maven.apache.org/POM/4.0.0 -cd .//x:artifactId[text()="google-cloud-shared-dependencies"] -cd ../x:version -set ${SHARED_DEPS_VERSION} -save pom.xml -EOF - -if [[ $CLIENT_LIBRARY == "bigtable" ]]; then - popd -fi - -echo "Modification on the shared dependencies BOM:" -git diff -echo - -export INTEGRATION_TEST_ARGS="-Denforcer.skip=true" - -# This reads the JOB_TYPE environmental variable ("test" or "graalvm") -.kokoro/build.sh diff --git a/.kokoro/populate-secrets.sh b/.kokoro/populate-secrets.sh deleted file mode 100755 index f52514257..000000000 --- a/.kokoro/populate-secrets.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash -# Copyright 2020 Google LLC. -# -# 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 -eo pipefail - -function now { date +"%Y-%m-%d %H:%M:%S" | tr -d '\n' ;} -function msg { println "$*" >&2 ;} -function println { printf '%s\n' "$(now) $*" ;} - - -# Populates requested secrets set in SECRET_MANAGER_KEYS from service account: -# kokoro-trampoline@cloud-devrel-kokoro-resources.iam.gserviceaccount.com -SECRET_LOCATION="${KOKORO_GFILE_DIR}/secret_manager" -msg "Creating folder on disk for secrets: ${SECRET_LOCATION}" -mkdir -p ${SECRET_LOCATION} -for key in $(echo ${SECRET_MANAGER_KEYS} | sed "s/,/ /g") -do - msg "Retrieving secret ${key}" - docker run --entrypoint=gcloud \ - --volume=${KOKORO_GFILE_DIR}:${KOKORO_GFILE_DIR} \ - gcr.io/google.com/cloudsdktool/cloud-sdk \ - secrets versions access latest \ - --project cloud-devrel-kokoro-resources \ - --secret ${key} > \ - "${SECRET_LOCATION}/${key}" - if [[ $? == 0 ]]; then - msg "Secret written to ${SECRET_LOCATION}/${key}" - else - msg "Error retrieving secret ${key}" - fi -done diff --git a/BUILD.bazel b/BUILD.bazel deleted file mode 100644 index 2f08384e0..000000000 --- a/BUILD.bazel +++ /dev/null @@ -1,28 +0,0 @@ -load("//:gax_java.bzl", "google_java_format", "google_java_format_verification") - -exports_files(["dependencies.properties"]) - -JAVA_COPTS = [ - "-source", - "1.7", - "-target", - "1.7", -] - -java_plugin( - name = "auto_value_plugin", - processor_class = "com.google.auto.value.processor.AutoValueProcessor", - deps = ["@com_google_auto_value_auto_value//jar"], - visibility = ["//visibility:public"], -) - -# google-java-format -java_binary( - name = "google_java_format_binary", - # Not letting the formatter consume too much memory (essential for CI builds) - jvm_flags = ["-Xmx512m"], - main_class = "com.google.googlejavaformat.java.Main", - visibility = ["//visibility:public"], - runtime_deps = ["@google_java_format_all_deps//jar"], -) - diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index dc948dcd8..000000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,812 +0,0 @@ -# Changelog - -## [2.20.1](https://github.com/googleapis/gax-java/compare/v2.20.0...v2.20.1) (2022-12-02) - - -### Bug Fixes - -* **deps:** Update dependency com.google.api.grpc:grpc-google-common-protos to v2.11.0 ([#1906](https://github.com/googleapis/gax-java/issues/1906)) ([d27d848](https://github.com/googleapis/gax-java/commit/d27d8485d3da4de00253c1f5df435516d1af8d8e)) -* **deps:** Update dependency com.google.api.grpc:proto-google-common-protos to v2.11.0 ([#1907](https://github.com/googleapis/gax-java/issues/1907)) ([7504e37](https://github.com/googleapis/gax-java/commit/7504e37163d39d10bd8388101e9ce614e2839aca)) -* **deps:** Update dependency com.google.cloud:google-cloud-shared-config to v1.5.5 ([#1911](https://github.com/googleapis/gax-java/issues/1911)) ([772c221](https://github.com/googleapis/gax-java/commit/772c2213dfa10120b6efccf411550e77df3f9de7)) -* **deps:** Update dependency com.google.protobuf:protobuf-bom to v3.21.10 ([#1912](https://github.com/googleapis/gax-java/issues/1912)) ([f508f24](https://github.com/googleapis/gax-java/commit/f508f245a59b2086c4b56d55f0cb25e9e7c29136)) -* Watchdog controls lifecycle of the future, not executor ([#1890](https://github.com/googleapis/gax-java/issues/1890)) ([bd1714e](https://github.com/googleapis/gax-java/commit/bd1714e484eef8aa8f09632eee976c9da26da5f1)) - -## [2.20.0](https://github.com/googleapis/gax-java/compare/v2.19.5...v2.20.0) (2022-11-30) - - -### Features - -* De-experiment google-c2p resolver ([#1896](https://github.com/googleapis/gax-java/issues/1896)) ([66b348b](https://github.com/googleapis/gax-java/commit/66b348b9fd817e0986c67eb02e0609646fb822b3)) -* Next release from main branch is 2.20.0 ([#1867](https://github.com/googleapis/gax-java/issues/1867)) ([c7aeed3](https://github.com/googleapis/gax-java/commit/c7aeed3362352b77f86749e86ccebd1d1390de48)) - - -### Bug Fixes - -* **deps:** Update dependency com.google.auth:google-auth-library-credentials to v1.13.0 ([#1881](https://github.com/googleapis/gax-java/issues/1881)) ([d059db7](https://github.com/googleapis/gax-java/commit/d059db7131c6866c9782c0c3ac39b980b13911df)) -* **deps:** Update dependency com.google.auth:google-auth-library-oauth2-http to v1.13.0 ([#1882](https://github.com/googleapis/gax-java/issues/1882)) ([67af68a](https://github.com/googleapis/gax-java/commit/67af68a02198360dad2941eefa9897628342ee60)) -* **deps:** Update dependency io.grpc:grpc-bom to v1.51.0 ([#1889](https://github.com/googleapis/gax-java/issues/1889)) ([85af72c](https://github.com/googleapis/gax-java/commit/85af72c4159a416e7026cf47a0d8e4fc5ef23be0)) -* **deps:** Update dependency org.mockito:mockito-core to v4.9.0 ([#1879](https://github.com/googleapis/gax-java/issues/1879)) ([9505cb1](https://github.com/googleapis/gax-java/commit/9505cb1d89de8f6fc47f5f4a7a083129b4ffc58d)) - -## [2.19.5](https://github.com/googleapis/gax-java/compare/v2.19.4...v2.19.5) (2022-11-07) - - -### Bug Fixes - -* **deps:** Update dependency com.google.cloud:google-cloud-shared-config to v1.5.4 ([#1840](https://github.com/googleapis/gax-java/issues/1840)) ([8f7a38c](https://github.com/googleapis/gax-java/commit/8f7a38ca0a9d187af49649adf7d96ef97c9e9915)) -* **deps:** Update dependency com.google.code.gson:gson to v2.10 ([#1845](https://github.com/googleapis/gax-java/issues/1845)) ([816e666](https://github.com/googleapis/gax-java/commit/816e6665e06bc65cbaf2703617342c8db9780115)) -* **deps:** Update dependency com.google.protobuf:protobuf-bom to v3.21.9 ([#1850](https://github.com/googleapis/gax-java/issues/1850)) ([f270ac4](https://github.com/googleapis/gax-java/commit/f270ac45b6a21d531eb8bd75157f2784fcad90fc)) -* **deps:** Update dependency io.grpc:grpc-bom to v1.50.2 ([#1842](https://github.com/googleapis/gax-java/issues/1842)) ([11c4a7c](https://github.com/googleapis/gax-java/commit/11c4a7caf31de256f29678de829f11f9558adcfd)) -* **deps:** Update dependency org.mockito:mockito-core to v4.8.1 ([#1843](https://github.com/googleapis/gax-java/issues/1843)) ([bf67fc2](https://github.com/googleapis/gax-java/commit/bf67fc26236286d72b9ddcb2e66113fdac74b51a)) -* **deps:** Update dependency org.threeten:threetenbp to v1.6.4 ([#1857](https://github.com/googleapis/gax-java/issues/1857)) ([a9e2374](https://github.com/googleapis/gax-java/commit/a9e23744a40f6e5484f1834824515f8ae952873c)) - - -### Dependencies - -* update dependency com.google.api:api-common to 2.2.2 ([ad7ad1c](https://github.com/googleapis/gax-java/commit/ad7ad1c5b450cd0569ff34d3b553dd1493fa462c)) -* update dependency com.google.api.grpc:grpc-google-common-protos to 2.10.0 ([ad7ad1c](https://github.com/googleapis/gax-java/commit/ad7ad1c5b450cd0569ff34d3b553dd1493fa462c)) -* Update dependency com.google.api.grpc:proto-google-common-protos to 2.10.0 ([ad7ad1c](https://github.com/googleapis/gax-java/commit/ad7ad1c5b450cd0569ff34d3b553dd1493fa462c)) -* update dependency com.google.auth:google-auth-library-credentials to 1.12.1 ([ad7ad1c](https://github.com/googleapis/gax-java/commit/ad7ad1c5b450cd0569ff34d3b553dd1493fa462c)) -* update dependency com.google.auth:google-auth-library-oauth2-http to 1.12.1 ([ad7ad1c](https://github.com/googleapis/gax-java/commit/ad7ad1c5b450cd0569ff34d3b553dd1493fa462c)) -* update dependency com.google.http-client:google-http-client to 1.42.3 ([ad7ad1c](https://github.com/googleapis/gax-java/commit/ad7ad1c5b450cd0569ff34d3b553dd1493fa462c)) -* update dependency com.google.http-client:google-http-client-gson to 1.42.3 ([ad7ad1c](https://github.com/googleapis/gax-java/commit/ad7ad1c5b450cd0569ff34d3b553dd1493fa462c)) - -## [2.19.4](https://github.com/googleapis/gax-java/compare/v2.19.3...v2.19.4) (2022-10-19) - - -### Bug Fixes - -* Scope the throttling metric to exclude element size calculation ([#1835](https://github.com/googleapis/gax-java/issues/1835)) ([0287f83](https://github.com/googleapis/gax-java/commit/0287f83f9cabbb9dff6cb7e8ea3068ccc1ab12d9)) - -## [2.19.3](https://github.com/googleapis/gax-java/compare/v2.19.2...v2.19.3) (2022-10-19) - - -### Bug Fixes - -* **deps:** Update dependency com.google.auth:google-auth-library-credentials to v1.12.0 ([#1822](https://github.com/googleapis/gax-java/issues/1822)) ([ad139e4](https://github.com/googleapis/gax-java/commit/ad139e45d29bd0fbf6b6f080b12ef9a987fa2e0d)) -* **deps:** Update dependency com.google.auth:google-auth-library-credentials to v1.12.1 ([#1830](https://github.com/googleapis/gax-java/issues/1830)) ([d726921](https://github.com/googleapis/gax-java/commit/d7269210767a92e94568712920b34064278dddbc)) -* **deps:** Update dependency com.google.auth:google-auth-library-oauth2-http to v1.12.0 ([#1823](https://github.com/googleapis/gax-java/issues/1823)) ([c6180ca](https://github.com/googleapis/gax-java/commit/c6180cacdaf4d191098e499eff0f6b014e730654)) -* **deps:** Update dependency com.google.auth:google-auth-library-oauth2-http to v1.12.1 ([#1831](https://github.com/googleapis/gax-java/issues/1831)) ([227c8af](https://github.com/googleapis/gax-java/commit/227c8af66c95e86e8d90e5de9dd3f429895b44cc)) -* **deps:** Update dependency com.google.protobuf:protobuf-bom to v3.21.8 ([#1828](https://github.com/googleapis/gax-java/issues/1828)) ([462a100](https://github.com/googleapis/gax-java/commit/462a1009a84a046da28298ad10f23cadfb7a61ea)) -* **deps:** Update dependency io.grpc:grpc-bom to v1.50.1 ([#1819](https://github.com/googleapis/gax-java/issues/1819)) ([75600ea](https://github.com/googleapis/gax-java/commit/75600eab90ec2e33378c00824535763f5df87b24)) -* **deps:** Update dependency org.graalvm.sdk:graal-sdk to v22.2.0.1 ([#1817](https://github.com/googleapis/gax-java/issues/1817)) ([a8f8ae2](https://github.com/googleapis/gax-java/commit/a8f8ae2b5e035dc08ce161134ec2e441e6c2d4fc)) -* **deps:** Update dependency org.threeten:threetenbp to v1.6.3 ([#1821](https://github.com/googleapis/gax-java/issues/1821)) ([3bca572](https://github.com/googleapis/gax-java/commit/3bca572486e7780ff8fb8b581aa691738885401c)) -* **java:** Address ClassNotFoundException in GraalVM 22.2.0 ([#1816](https://github.com/googleapis/gax-java/issues/1816)) ([ae6e8be](https://github.com/googleapis/gax-java/commit/ae6e8beb6ed5525504df1a3bb7ce71bdf114a233)) -* **java:** Address reachability issues in native image compilation with version 22.2.0 ([#1815](https://github.com/googleapis/gax-java/issues/1815)) ([0f3215f](https://github.com/googleapis/gax-java/commit/0f3215f98bfc5def4e608c780d91953900e17946)) - -## [2.19.2](https://github.com/googleapis/gax-java/compare/v2.19.1...v2.19.2) (2022-10-02) - - -### Bug Fixes - -* **deps:** Update dependency com.google.api.grpc:grpc-google-common-protos to v2.9.3 ([#1797](https://github.com/googleapis/gax-java/issues/1797)) ([50c6a75](https://github.com/googleapis/gax-java/commit/50c6a75db05537b873d0d143fdccab82f46bc644)) -* **deps:** Update dependency com.google.api.grpc:grpc-google-common-protos to v2.9.4 ([#1800](https://github.com/googleapis/gax-java/issues/1800)) ([6d4e62d](https://github.com/googleapis/gax-java/commit/6d4e62de5c2303d7c31faa046966b8842cbcfe53)) -* **deps:** Update dependency com.google.api.grpc:grpc-google-common-protos to v2.9.5 ([#1805](https://github.com/googleapis/gax-java/issues/1805)) ([1f9fe38](https://github.com/googleapis/gax-java/commit/1f9fe38e3b152dad50a026adea8ea9b488acf786)) -* **deps:** Update dependency com.google.api.grpc:grpc-google-common-protos to v2.9.6 ([#1810](https://github.com/googleapis/gax-java/issues/1810)) ([a206f46](https://github.com/googleapis/gax-java/commit/a206f46a095812c77cce1085a546692ba871deef)) -* **deps:** Update dependency com.google.api.grpc:proto-google-common-protos to v2.9.3 ([#1798](https://github.com/googleapis/gax-java/issues/1798)) ([8a1c732](https://github.com/googleapis/gax-java/commit/8a1c732bf938818a40c907b5656025cac52b9645)) -* **deps:** Update dependency com.google.api.grpc:proto-google-common-protos to v2.9.4 ([#1801](https://github.com/googleapis/gax-java/issues/1801)) ([0e2a405](https://github.com/googleapis/gax-java/commit/0e2a4053d945f4d4da55f8b5486df6dbcab66c2f)) -* **deps:** Update dependency com.google.api.grpc:proto-google-common-protos to v2.9.5 ([#1806](https://github.com/googleapis/gax-java/issues/1806)) ([da9dff8](https://github.com/googleapis/gax-java/commit/da9dff8a9cd2db63b396df42830c679b3555187d)) -* **deps:** Update dependency com.google.api.grpc:proto-google-common-protos to v2.9.6 ([#1811](https://github.com/googleapis/gax-java/issues/1811)) ([bb5dffa](https://github.com/googleapis/gax-java/commit/bb5dffa51de48a6f97304a50c4a596e21673bb6e)) -* **deps:** Update dependency com.google.protobuf:protobuf-bom to v3.21.6 ([#1792](https://github.com/googleapis/gax-java/issues/1792)) ([d94482e](https://github.com/googleapis/gax-java/commit/d94482ef19f45b6dfbe775d7facf3467b09cb194)) -* **deps:** Update dependency com.google.protobuf:protobuf-bom to v3.21.7 ([#1803](https://github.com/googleapis/gax-java/issues/1803)) ([534250b](https://github.com/googleapis/gax-java/commit/534250bdb165576bea7793a61b39c11312e4ec31)) -* **deps:** Update dependency io.grpc:grpc-bom to v1.49.1 ([#1796](https://github.com/googleapis/gax-java/issues/1796)) ([9cb8d36](https://github.com/googleapis/gax-java/commit/9cb8d3640ff40f30f8dae2efd7341578fd449a7d)) -* **deps:** Update dependency io.grpc:grpc-bom to v1.49.2 ([#1808](https://github.com/googleapis/gax-java/issues/1808)) ([b27f15d](https://github.com/googleapis/gax-java/commit/b27f15d277f74bc11e10e6e25b588b1767f8e5ee)) -* **deps:** Update dependency org.threeten:threetenbp to v1.6.2 ([#1799](https://github.com/googleapis/gax-java/issues/1799)) ([6a45067](https://github.com/googleapis/gax-java/commit/6a450679302c611960710f5a98e32d278bda2b60)) -* remove --allow-incomplete-classpath which has been deprecated as of Graalvm 22.1.0 ([e5c739c](https://github.com/googleapis/gax-java/commit/e5c739c093067f6f2340f873ed96dfea8ef9b7d6)) -* Remove --allow-incomplete-classpath which was deprecated as of Graalvm 22.1.0 ([#1794](https://github.com/googleapis/gax-java/issues/1794)) ([e5c739c](https://github.com/googleapis/gax-java/commit/e5c739c093067f6f2340f873ed96dfea8ef9b7d6)) - -## [2.19.1](https://github.com/googleapis/gax-java/compare/v2.19.0...v2.19.1) (2022-09-13) - - -### Bug Fixes - -* **deps:** Update dependency com.google.auth:google-auth-library-credentials to v1.11.0 ([#1786](https://github.com/googleapis/gax-java/issues/1786)) ([4889ff7](https://github.com/googleapis/gax-java/commit/4889ff7ccd3ae13052c4b7009ce81bcd88d650a9)) -* **deps:** Update dependency com.google.auth:google-auth-library-oauth2-http to v1.11.0 ([#1787](https://github.com/googleapis/gax-java/issues/1787)) ([4f5cd42](https://github.com/googleapis/gax-java/commit/4f5cd428f416e7d43f3268de32e5314ac3317460)) -* **deps:** Update dependency io.grpc:grpc-bom to v1.49.0 ([#1779](https://github.com/googleapis/gax-java/issues/1779)) ([037e131](https://github.com/googleapis/gax-java/commit/037e131ad46690f6d1badb45dc2f31ca981c1348)) -* **deps:** Update dependency org.mockito:mockito-core to v4.8.0 ([#1785](https://github.com/googleapis/gax-java/issues/1785)) ([f2989bd](https://github.com/googleapis/gax-java/commit/f2989bd706e7b3c524d2f0b8ceaa1d576dd7f751)) -* **httpjson:** Handle message derived query params ([#1784](https://github.com/googleapis/gax-java/issues/1784)) ([4524fad](https://github.com/googleapis/gax-java/commit/4524fadbe688d96a7c5e715ab88b542b4bb3891a)) - -## [2.19.0](https://github.com/googleapis/gax-java/compare/v2.18.7...v2.19.0) (2022-08-22) - - -### Features - -* Add numeric enum support. ([#1743](https://github.com/googleapis/gax-java/issues/1743)) ([3f7628e](https://github.com/googleapis/gax-java/commit/3f7628e27495806675ec8c8521e9c33725908936)) - - -### Bug Fixes - -* **deps:** update dependency com.google.auth:google-auth-library-credentials to v1.10.0 ([#1768](https://github.com/googleapis/gax-java/issues/1768)) ([3f2188d](https://github.com/googleapis/gax-java/commit/3f2188d83751272de1a4c3db85e95d79b690e3fc)) -* **deps:** update dependency com.google.auth:google-auth-library-credentials to v1.9.0 ([#1765](https://github.com/googleapis/gax-java/issues/1765)) ([103db3c](https://github.com/googleapis/gax-java/commit/103db3cc06cfaafeda1a043b6e19e668083ed782)) -* **deps:** update dependency com.google.auth:google-auth-library-oauth2-http to v1.10.0 ([#1769](https://github.com/googleapis/gax-java/issues/1769)) ([0b1eb92](https://github.com/googleapis/gax-java/commit/0b1eb924aefc79b6fc4757d253d4c8a93a094c84)) -* **deps:** update dependency com.google.auth:google-auth-library-oauth2-http to v1.9.0 ([#1766](https://github.com/googleapis/gax-java/issues/1766)) ([2677f07](https://github.com/googleapis/gax-java/commit/2677f07a8e20c82403f60c6aa1f9d46c1274b37f)) -* **deps:** update dependency com.google.code.gson:gson to v2.9.1 ([#1757](https://github.com/googleapis/gax-java/issues/1757)) ([ea2a075](https://github.com/googleapis/gax-java/commit/ea2a07504899703e4fcd428f31d615fb208a50aa)) -* **deps:** update dependency com.google.protobuf:protobuf-bom to v3.21.5 ([#1772](https://github.com/googleapis/gax-java/issues/1772)) ([d7a48d1](https://github.com/googleapis/gax-java/commit/d7a48d1886a3f39acb26580d1d35a288102af436)) -* **deps:** update dependency io.grpc:grpc-bom to v1.48.1 ([#1763](https://github.com/googleapis/gax-java/issues/1763)) ([e5e4232](https://github.com/googleapis/gax-java/commit/e5e423200260c210071ce626612d7e54af0695e4)) -* **deps:** update dependency org.graalvm.sdk:graal-sdk to v22.2.0 ([#1740](https://github.com/googleapis/gax-java/issues/1740)) ([ded44a6](https://github.com/googleapis/gax-java/commit/ded44a66d3de8a2678fa4c5efe8b3ded4484de2b)) -* **deps:** update dependency org.mockito:mockito-core to v4.7.0 ([#1774](https://github.com/googleapis/gax-java/issues/1774)) ([29678c8](https://github.com/googleapis/gax-java/commit/29678c805855c97b4c26f0156923a41820411a10)) -* **deps:** update dependency org.threeten:threetenbp to v1.6.1 ([#1773](https://github.com/googleapis/gax-java/issues/1773)) ([d2c84e6](https://github.com/googleapis/gax-java/commit/d2c84e6fb22a2752b68fecc9b6c9e480f398b87c)) -* **test:** testThrottlingBlocking flakyness fix ([#1775](https://github.com/googleapis/gax-java/issues/1775)) ([e69393c](https://github.com/googleapis/gax-java/commit/e69393c32ffe32306acc8f495b1f41198d86f507)) - - -### Documentation - -* explaining UNIX environment is required ([#1760](https://github.com/googleapis/gax-java/issues/1760)) ([1d31e90](https://github.com/googleapis/gax-java/commit/1d31e90e70867cb4b896d7a393f9271788b6371f)) - -## [2.18.7](https://github.com/googleapis/gax-java/compare/v2.18.6...v2.18.7) (2022-08-01) - - -### Bug Fixes - -* **java:** initialize netty class at run time ([#1758](https://github.com/googleapis/gax-java/issues/1758)) ([e1d6eb9](https://github.com/googleapis/gax-java/commit/e1d6eb979da21e9795b3c3d2fffb9200ee43ed15)) - -## [2.18.6](https://github.com/googleapis/gax-java/compare/v2.18.5...v2.18.6) (2022-07-29) - - -### Bug Fixes - -* **deps:** update dependency com.google.cloud:google-cloud-shared-config to v1.5.2 ([#1746](https://github.com/googleapis/gax-java/issues/1746)) ([8163f8a](https://github.com/googleapis/gax-java/commit/8163f8aa822881d8cd6f1f72aca66b50fbd2e66a)) -* **deps:** update dependency com.google.cloud:google-cloud-shared-config to v1.5.3 ([#1748](https://github.com/googleapis/gax-java/issues/1748)) ([f2b7cb2](https://github.com/googleapis/gax-java/commit/f2b7cb2b6b783095547b798da054b6879d3764f1)) -* **deps:** update dependency com.google.protobuf:protobuf-bom to v3.21.4 ([#1747](https://github.com/googleapis/gax-java/issues/1747)) ([0b2b1ef](https://github.com/googleapis/gax-java/commit/0b2b1efcf38ff9f253e426af8c21722d646c8627)) -* Exclude error_prone_annotations from guava. ([#1750](https://github.com/googleapis/gax-java/issues/1750)) ([e1c91a4](https://github.com/googleapis/gax-java/commit/e1c91a40bcf413af5210da1d43e409d44dcf13bd)) - -## [2.18.5](https://github.com/googleapis/gax-java/compare/v2.18.4...v2.18.5) (2022-07-25) - - -### Bug Fixes - -* **deps:** update dependency com.google.api.grpc:grpc-google-common-protos to v2.9.2 ([#1735](https://github.com/googleapis/gax-java/issues/1735)) ([d7f00be](https://github.com/googleapis/gax-java/commit/d7f00beae84c093a732982aaeedd7d6a8752e52c)) -* **deps:** update dependency com.google.api.grpc:proto-google-common-protos to v2.9.2 ([#1736](https://github.com/googleapis/gax-java/issues/1736)) ([ee3d4ad](https://github.com/googleapis/gax-java/commit/ee3d4ad29a84da9113790dd03b8f0bbd89625a7c)) -* **deps:** update dependency com.google.auth:google-auth-library-credentials to v1.8.1 ([#1737](https://github.com/googleapis/gax-java/issues/1737)) ([24bc629](https://github.com/googleapis/gax-java/commit/24bc629aa1ffc0513ba766858935ead7ab18bf9e)) -* **deps:** update dependency com.google.auth:google-auth-library-oauth2-http to v1.8.1 ([#1738](https://github.com/googleapis/gax-java/issues/1738)) ([1030eb6](https://github.com/googleapis/gax-java/commit/1030eb6b1df5008f304d0989fd991f88f148cc2a)) -* **deps:** update dependency com.google.cloud:google-cloud-shared-config to v1.5.1 ([#1726](https://github.com/googleapis/gax-java/issues/1726)) ([bdffb86](https://github.com/googleapis/gax-java/commit/bdffb86c05235c4ad783ab7afd28724386465569)) -* **deps:** update dependency com.google.http-client:google-http-client-bom to v1.42.2 ([#1727](https://github.com/googleapis/gax-java/issues/1727)) ([030e9b3](https://github.com/googleapis/gax-java/commit/030e9b33ec6bd98122fba59a1bc39513444c3511)) -* **deps:** update dependency com.google.protobuf:protobuf-bom to v3.21.3 ([#1742](https://github.com/googleapis/gax-java/issues/1742)) ([9215e1f](https://github.com/googleapis/gax-java/commit/9215e1f58ebcc6eccef42c53981ab90865fe366a)) -* **deps:** update dependency io.grpc:grpc-bom to v1.48.0 ([#1741](https://github.com/googleapis/gax-java/issues/1741)) ([4735a4b](https://github.com/googleapis/gax-java/commit/4735a4b29b686ba510a25ad8458142870e50b1c5)) -* remove initialization of logger classes which is conflicting with slf4j ([#1733](https://github.com/googleapis/gax-java/issues/1733)) ([ccaf265](https://github.com/googleapis/gax-java/commit/ccaf26537a189dacb9b3bb58760a4c6f6cd48a87)) - -## [2.18.4](https://github.com/googleapis/gax-java/compare/v2.18.3...v2.18.4) (2022-07-11) - - -### Bug Fixes - -* Build routing header params map with the last entry if multiple entries have the same key. ([#1729](https://github.com/googleapis/gax-java/issues/1729)) ([878bcf2](https://github.com/googleapis/gax-java/commit/878bcf2da215e14d9e3bcb4717b85d867f149cee)) -* **deps:** update dependency com.google.api.grpc:grpc-google-common-protos to v2.9.1 ([#1721](https://github.com/googleapis/gax-java/issues/1721)) ([bef0af7](https://github.com/googleapis/gax-java/commit/bef0af71b4d1923980fe7a64cf1ac4435463e2db)) -* **deps:** update dependency com.google.api.grpc:proto-google-common-protos to v2.9.1 ([#1722](https://github.com/googleapis/gax-java/issues/1722)) ([7034ead](https://github.com/googleapis/gax-java/commit/7034ead57d990b8e2382ff015ba47fc97cdf271b)) -* **deps:** update dependency com.google.auth:google-auth-library-credentials to v1.8.0 ([#1723](https://github.com/googleapis/gax-java/issues/1723)) ([b062d6d](https://github.com/googleapis/gax-java/commit/b062d6d861fa7162f0f9e8287c988802e4a194c5)) -* **deps:** update dependency com.google.auth:google-auth-library-oauth2-http to v1.8.0 ([#1724](https://github.com/googleapis/gax-java/issues/1724)) ([bd8ee04](https://github.com/googleapis/gax-java/commit/bd8ee04f202b7faa7f13ccb868e574055ffb3c88)) - -## [2.18.3](https://github.com/googleapis/gax-java/compare/v2.18.2...v2.18.3) (2022-06-27) - - -### Bug Fixes - -* **deps:** update dependency com.google.api.grpc:grpc-google-common-protos to v2.9.0 ([#1706](https://github.com/googleapis/gax-java/issues/1706)) ([eb195c0](https://github.com/googleapis/gax-java/commit/eb195c000b19472fc15a2586320f4421b6ee92a3)) -* **deps:** update dependency com.google.api.grpc:proto-google-common-protos to v2.9.0 ([#1708](https://github.com/googleapis/gax-java/issues/1708)) ([0a606f5](https://github.com/googleapis/gax-java/commit/0a606f5d6f40a44b153f186d824e3a731586bb49)) -* **deps:** update dependency com.google.cloud:google-cloud-shared-config to v1.5.0 ([#1711](https://github.com/googleapis/gax-java/issues/1711)) ([eb11bb0](https://github.com/googleapis/gax-java/commit/eb11bb027cde3e4abc8049a04056907de79386ab)) -* **deps:** update dependency com.google.protobuf:protobuf-bom to v3.21.2 ([#1720](https://github.com/googleapis/gax-java/issues/1720)) ([19a38cf](https://github.com/googleapis/gax-java/commit/19a38cffd13fbaa547a9992f61689d70239b6ee4)) -* **deps:** update dependency org.mockito:mockito-core to v4.6.1 ([#1705](https://github.com/googleapis/gax-java/issues/1705)) ([7befaa4](https://github.com/googleapis/gax-java/commit/7befaa4a2525f9b09091225b2f74a3e2fbfa3175)) -* **deps:** update dependency org.threeten:threetenbp to v1.6.0 ([#1709](https://github.com/googleapis/gax-java/issues/1709)) ([42cdcaa](https://github.com/googleapis/gax-java/commit/42cdcaa5a5d2362e86f94a13870f3c9c48f8b7f7)) - -## [2.18.2](https://github.com/googleapis/gax-java/compare/v2.18.1...v2.18.2) (2022-06-16) - - -### Bug Fixes - -* **deps:** update dependency com.google.api:api-common to v2.2.1 ([#1699](https://github.com/googleapis/gax-java/issues/1699)) ([be79d10](https://github.com/googleapis/gax-java/commit/be79d108601290d533126e996600a5864a7e810f)) -* **deps:** update dependency com.google.auth:google-auth-library-credentials to v1.7.0 ([#1700](https://github.com/googleapis/gax-java/issues/1700)) ([640525e](https://github.com/googleapis/gax-java/commit/640525ea4d2df46c187f867f7c13325aebd819c6)) -* **deps:** update dependency com.google.auth:google-auth-library-oauth2-http to v1.7.0 ([#1701](https://github.com/googleapis/gax-java/issues/1701)) ([0f27ef7](https://github.com/googleapis/gax-java/commit/0f27ef7b63aa37fd7797e43803802a519d710658)) -* **deps:** update dependency com.google.http-client:google-http-client-bom to v1.42.0 ([#1702](https://github.com/googleapis/gax-java/issues/1702)) ([96c4fa8](https://github.com/googleapis/gax-java/commit/96c4fa8b76e485fb6e19b183c11d660bd949c6c2)) -* **deps:** update dependency com.google.protobuf:protobuf-bom to v3.21.1 ([#1703](https://github.com/googleapis/gax-java/issues/1703)) ([3e07036](https://github.com/googleapis/gax-java/commit/3e07036bba7c6945c76a76cd623726c71d74ade2)) -* **deps:** update dependency io.grpc:grpc-bom to v1.47.0 ([#1704](https://github.com/googleapis/gax-java/issues/1704)) ([0317926](https://github.com/googleapis/gax-java/commit/0317926ea97940df73738d1617e0b154e70b7e32)) -* **deps:** update dependency io.opencensus:opencensus-api to v0.31.1 ([#1697](https://github.com/googleapis/gax-java/issues/1697)) ([f9f9e1e](https://github.com/googleapis/gax-java/commit/f9f9e1e2a16532c3051595138bc2e99c71268f3a)) -* **deps:** update dependency org.graalvm.sdk:graal-sdk to v22.1.0.1 ([#1698](https://github.com/googleapis/gax-java/issues/1698)) ([59fbff9](https://github.com/googleapis/gax-java/commit/59fbff938981be18134c1410c02d86dbf801f4a7)) - - -### Dependencies - -* update dependency com.google.api.grpc:proto-google-common-protos to v2.9.0 ([#1713](https://github.com/googleapis/gax-java/issues/1713)) ([c5eb06e](https://github.com/googleapis/gax-java/commit/c5eb06eec5d2cde85d37b096418e873c1bd83470)) -* update dependency io.grpc:grpc-bom to v1.47.0 ([c5eb06e](https://github.com/googleapis/gax-java/commit/c5eb06eec5d2cde85d37b096418e873c1bd83470)) -* update dependency io.opencensus:opencensus-api to v0.31.1 ([c5eb06e](https://github.com/googleapis/gax-java/commit/c5eb06eec5d2cde85d37b096418e873c1bd83470)) -* update dependency org.mockito:mockito-core to v4.6.1 ([c5eb06e](https://github.com/googleapis/gax-java/commit/c5eb06eec5d2cde85d37b096418e873c1bd83470)) -* update dependency org.threeten:threetenbp to v1.6.0 ([c5eb06e](https://github.com/googleapis/gax-java/commit/c5eb06eec5d2cde85d37b096418e873c1bd83470)) -* update io.netty dependencies to v4.1.72.Final ([c5eb06e](https://github.com/googleapis/gax-java/commit/c5eb06eec5d2cde85d37b096418e873c1bd83470)) -* update plugin org.sonarqube to v3.4.0.2513 ([c5eb06e](https://github.com/googleapis/gax-java/commit/c5eb06eec5d2cde85d37b096418e873c1bd83470)) - -### [2.18.1](https://github.com/googleapis/gax-java/compare/v2.18.0...v2.18.1) (2022-05-19) - - -### Dependencies - -* upgrade grpc to 1.46.0 ([#1688](https://github.com/googleapis/gax-java/issues/1688)) ([18147a4](https://github.com/googleapis/gax-java/commit/18147a4f558635b27d30eb05468321b52321db13)) - -## [2.18.0](https://github.com/googleapis/gax-java/compare/v2.17.0...v2.18.0) (2022-05-18) - - -### Features - -* [REGAPIC] Add support for additional bindings ([#1680](https://github.com/googleapis/gax-java/issues/1680)) ([59b3699](https://github.com/googleapis/gax-java/commit/59b3699b6acbc98c55dc043bf8665b457a0615a9)) -* upgrade graal-sdk to 22.1.0 ([#1683](https://github.com/googleapis/gax-java/issues/1683)) ([46f899d](https://github.com/googleapis/gax-java/commit/46f899de06e60a792f5a6c1dc617673f0f180c00)) - - -### Bug Fixes - -* **java:** remove conflicting reflection configuration to address UnsupportedFeatureException with GraalVM 22.1.0 ([#1682](https://github.com/googleapis/gax-java/issues/1682)) ([97c6c8b](https://github.com/googleapis/gax-java/commit/97c6c8bfa0d5397e30d3699e92f823e09ee283e6)) -* remove svm dependency ([#1679](https://github.com/googleapis/gax-java/issues/1679)) ([c1b88e3](https://github.com/googleapis/gax-java/commit/c1b88e3788ab866bcc1ba3db94c2998198a0b35e)) - - -### Dependencies - -* update dependency com.google.api:api-common to 2.2.0 ([#1685](https://github.com/googleapis/gax-java/issues/1685)) ([a5a316b](https://github.com/googleapis/gax-java/commit/a5a316bde322733eb5a80093206eb12b36945580)) - -## [2.17.0](https://github.com/googleapis/gax-java/compare/v2.16.0...v2.17.0) (2022-05-10) - - -### Features - -* next release from main branch is 2.17.0 ([#1659](https://github.com/googleapis/gax-java/issues/1659)) ([5a31361](https://github.com/googleapis/gax-java/commit/5a3136121bc8365a798aa2f5c363e86de6224391)) - - -### Bug Fixes - -* Fix handling of null responses in rest transport ([#1668](https://github.com/googleapis/gax-java/issues/1668)) ([8def947](https://github.com/googleapis/gax-java/commit/8def947620610b7aab526413a1ac14fd4f890dbf)) -* use graal-sdk 21.3.2 ([#1670](https://github.com/googleapis/gax-java/issues/1670)) ([92c2697](https://github.com/googleapis/gax-java/commit/92c2697b211b2aa9e5456dbb1078870a30f0703a)) - -## [2.16.0](https://github.com/googleapis/gax-java/compare/v2.15.0...v2.16.0) (2022-04-14) - - -### Features - -* relocate ApiClientSubstitutions from java-core to gax ([#1651](https://github.com/googleapis/gax-java/issues/1651)) ([321103f](https://github.com/googleapis/gax-java/commit/321103f129cb1ece3f3a4d62e3c050c975d33179)) -* relocate GoogleJsonClientFeature from java-core to gax ([#1655](https://github.com/googleapis/gax-java/issues/1655)) ([6e75ec7](https://github.com/googleapis/gax-java/commit/6e75ec76f2bf448eb56f644e61019efb3940a388)) -* relocate netty and gax substitutions from java-core ([#1650](https://github.com/googleapis/gax-java/issues/1650)) ([afd1917](https://github.com/googleapis/gax-java/commit/afd19177c44c9cd0a982e545e4b0e60c0313d6f4)) -* relocate Opencensus configurations from java-core to gax ([#1646](https://github.com/googleapis/gax-java/issues/1646)) ([b34ffb1](https://github.com/googleapis/gax-java/commit/b34ffb1fb2af6b18a4272dcc951b2f4294c75317)) -* relocate resource-config from java-core to gax ([#1656](https://github.com/googleapis/gax-java/issues/1656)) ([a9e5483](https://github.com/googleapis/gax-java/commit/a9e5483d5b67e080d1a8b012f0a3fb4ca8aadf18)) - - -### Dependencies - -* google-common-protos 2.8.3 ([#1657](https://github.com/googleapis/gax-java/issues/1657)) ([24b9138](https://github.com/googleapis/gax-java/commit/24b9138cc8088c2124f6d9e2ebc8ddc88a08fd9e)) - -## [2.15.0](https://github.com/googleapis/gax-java/compare/v2.14.0...v2.15.0) (2022-04-06) - - -### Features - -* Error Details Improvements - GRPC ([#1634](https://github.com/googleapis/gax-java/issues/1634)) ([00c3b9d](https://github.com/googleapis/gax-java/commit/00c3b9ddae11736e1231e4aa45965deff7689f2a)) -* relocate native image properties from java-core to gax ([#1648](https://github.com/googleapis/gax-java/issues/1648)) ([609c2aa](https://github.com/googleapis/gax-java/commit/609c2aab94ff215c879932e60ae041309f20c2c7)) - - -### Dependencies - -* upgrade grpc to 1.45.1 and auth to 1.6.0 ([#1652](https://github.com/googleapis/gax-java/issues/1652)) ([8f8f625](https://github.com/googleapis/gax-java/commit/8f8f62572795c83b4459f6d3a0f33f31a1ecfb71)) - -## [2.14.0](https://github.com/googleapis/gax-java/compare/v2.13.0...v2.14.0) (2022-04-01) - - -### Features - -* relocate Netty Native Image configurations from java-core to gax ([#1638](https://github.com/googleapis/gax-java/issues/1638)) ([aafded4](https://github.com/googleapis/gax-java/commit/aafded4a0b779c68d0d5702b722672a0f86ccdd1)) -* relocate protobuf configurations from java-core to gax-java ([#1641](https://github.com/googleapis/gax-java/issues/1641)) ([01d395f](https://github.com/googleapis/gax-java/commit/01d395f486ccd7c364c03ccdfcfbf83b900192c3)) - - -### Bug Fixes - -* update the runtime dependency grpc-java xds to googleapis ([#1643](https://github.com/googleapis/gax-java/issues/1643)) ([b8d9e30](https://github.com/googleapis/gax-java/commit/b8d9e30c3e2209bcd4cc0f808dfdf0a0608aa466)) - -## [2.13.0](https://github.com/googleapis/gax-java/compare/v2.12.2...v2.13.0) (2022-03-25) - - -### Features - -* dynamic channel pool scaled by number of outstanding request ([#1569](https://github.com/googleapis/gax-java/issues/1569)) ([fff2bab](https://github.com/googleapis/gax-java/commit/fff2babaf2620686c2e0be1b6d338ac088248cf6)) - - -### Dependencies - -* update dependency com_google_protobuf to 3.19.4 ([5c01174](https://github.com/googleapis/gax-java/commit/5c0117408ecfaec4e445b4fd813da6478415ea8e)) -* update dependency com.google.api:api-common to 2.1.5 ([5c01174](https://github.com/googleapis/gax-java/commit/5c0117408ecfaec4e445b4fd813da6478415ea8e)) -* update dependency com.google.api.grpc:grpc-google-common-protos to 2.8.0 ([5c01174](https://github.com/googleapis/gax-java/commit/5c0117408ecfaec4e445b4fd813da6478415ea8e)) -* update dependency com.google.api.grpc:proto-google-common-protos to 2.8.0 ([5c01174](https://github.com/googleapis/gax-java/commit/5c0117408ecfaec4e445b4fd813da6478415ea8e)) -* update dependency com.google.guava:guava to 31.1-jre ([5c01174](https://github.com/googleapis/gax-java/commit/5c0117408ecfaec4e445b4fd813da6478415ea8e)) -* update dependency com.google.http-client:google-http-client to 1.41.5 ([5c01174](https://github.com/googleapis/gax-java/commit/5c0117408ecfaec4e445b4fd813da6478415ea8e)) -* update dependency com.google.http-client:google-http-client-gson to 1.41.5 ([5c01174](https://github.com/googleapis/gax-java/commit/5c0117408ecfaec4e445b4fd813da6478415ea8e)) -* update dependency io_grpc to 1.45.0. ([#1639](https://github.com/googleapis/gax-java/issues/1639)) ([5c01174](https://github.com/googleapis/gax-java/commit/5c0117408ecfaec4e445b4fd813da6478415ea8e)) - -### [2.12.2](https://github.com/googleapis/gax-java/compare/v2.12.1...v2.12.2) (2022-02-09) - - -### Bug Fixes - -* REST: Make make LRO stub accept APIs of different versions ([#1622](https://github.com/googleapis/gax-java/issues/1622)) ([3ae8d85](https://github.com/googleapis/gax-java/commit/3ae8d850c5599ce487778d98d562d5b9b9e85d25)) - -### [2.12.1](https://github.com/googleapis/gax-java/compare/v2.12.0...v2.12.1) (2022-02-09) - - -### Bug Fixes - -* revert "feat: add api key support ([#1436](https://github.com/googleapis/gax-java/issues/1436))" ([#1617](https://github.com/googleapis/gax-java/issues/1617)) ([47f98b8](https://github.com/googleapis/gax-java/commit/47f98b872c6896ad2af37e30db440321c2adb492)) - -## [2.12.0](https://github.com/googleapis/gax-java/compare/v2.11.0...v2.12.0) (2022-01-28) - - -### Features - -* add REST interceptors infrastructure ([#1607](https://github.com/googleapis/gax-java/issues/1607)) ([0572eed](https://github.com/googleapis/gax-java/commit/0572eed8aa29879c74794b22e8ae79e414dd5821)) - -## [2.11.0](https://github.com/googleapis/gax-java/compare/v2.10.0...v2.11.0) (2022-01-27) - - -### Features - -* Add a builder to handle the common logic of extracting routing header values from request ([#1598](https://github.com/googleapis/gax-java/issues/1598)) ([2836baa](https://github.com/googleapis/gax-java/commit/2836baafa1114761cffbfdd4aee2322a4a931f8f)) - - -### Dependencies - -* update dependency com_google_protobuf to 3.19.3 ([734906e](https://github.com/googleapis/gax-java/commit/734906efd15064ea0d36b308f217508c9bf5ed42)) -* update dependency com.google.api:api-common to 2.1.3 ([734906e](https://github.com/googleapis/gax-java/commit/734906efd15064ea0d36b308f217508c9bf5ed42)) -* update dependency com.google.api.grpc:grpc-google-common-protos to 2.7.2 ([734906e](https://github.com/googleapis/gax-java/commit/734906efd15064ea0d36b308f217508c9bf5ed42)) -* update dependency com.google.api.grpc:proto-google-common-protos to 2.7.2 ([734906e](https://github.com/googleapis/gax-java/commit/734906efd15064ea0d36b308f217508c9bf5ed42)) -* update dependency com.google.errorprone:error_prone_annotations to v2.11.0 ([734906e](https://github.com/googleapis/gax-java/commit/734906efd15064ea0d36b308f217508c9bf5ed42)) -* update dependency com.google.http-client:google-http-client to 1.41.2 ([734906e](https://github.com/googleapis/gax-java/commit/734906efd15064ea0d36b308f217508c9bf5ed42)) -* update dependency com.google.http-client:google-http-client-gson to 1.41.2 ([734906e](https://github.com/googleapis/gax-java/commit/734906efd15064ea0d36b308f217508c9bf5ed42)) -* update dependency io_grpc to 1.44.0 ([#1610](https://github.com/googleapis/gax-java/issues/1610)) ([734906e](https://github.com/googleapis/gax-java/commit/734906efd15064ea0d36b308f217508c9bf5ed42)) - -## [2.10.0](https://github.com/googleapis/gax-java/compare/v2.9.0...v2.10.0) (2022-01-21) - - -### Features - -* add api key support ([#1436](https://github.com/googleapis/gax-java/issues/1436)) ([5081ec6](https://github.com/googleapis/gax-java/commit/5081ec6541da8ca3f5a4c0d20aa75bd20010a642)) -* introduce HttpJsonClientCall, Listeners infrastructure and ServerStreaming support in REST transport ([#1599](https://github.com/googleapis/gax-java/issues/1599)) ([3c97529](https://github.com/googleapis/gax-java/commit/3c97529b8bd0e8141c5d722f887cb7ae1ed30b69)) - -## [2.9.0](https://github.com/googleapis/gax-java/compare/v2.8.1...v2.9.0) (2022-01-14) - - -### Features - -* pass a CallCredentials to grpc-java for DirectPath ([#1488](https://github.com/googleapis/gax-java/issues/1488)) ([4a7713a](https://github.com/googleapis/gax-java/commit/4a7713ad683e70380087437d6b52cbe3e115d1fb)) - -### [2.8.1](https://www.github.com/googleapis/gax-java/compare/v2.8.0...v2.8.1) (2022-01-06) - - -### Dependencies - -* update dependency com.google.api:api-common to 2.1.2 ([#1590](https://www.github.com/googleapis/gax-java/issues/1590)) ([1b34870](https://www.github.com/googleapis/gax-java/commit/1b34870358a26bd4542594b6c746dca190f65d24)) -* update dependency com.google.auto.value:auto-value to v1.9 ([1b34870](https://www.github.com/googleapis/gax-java/commit/1b34870358a26bd4542594b6c746dca190f65d24)) - -## [2.8.0](https://www.github.com/googleapis/gax-java/compare/v2.7.1...v2.8.0) (2022-01-06) - - -### Features - -* update DirectPath xds scheme ([#1585](https://www.github.com/googleapis/gax-java/issues/1585)) ([7915f85](https://www.github.com/googleapis/gax-java/commit/7915f850313ddfdf35332d976d2567f31c2aa8a7)) - - -### Dependencies - -* update dependency com.google.api.grpc:proto-google-common-protos to v2.7.1 ([#1587](https://www.github.com/googleapis/gax-java/issues/1587)) ([eb0e9d1](https://www.github.com/googleapis/gax-java/commit/eb0e9d106a64af5f583d75d7291cdc17652fd5e7)) -* update dependency com.google.http-client:google-http-client-bom to v1.41.0 ([eb0e9d1](https://www.github.com/googleapis/gax-java/commit/eb0e9d106a64af5f583d75d7291cdc17652fd5e7)) -* update dependency com.google.protobuf:protobuf-bom to v3.19.2 ([eb0e9d1](https://www.github.com/googleapis/gax-java/commit/eb0e9d106a64af5f583d75d7291cdc17652fd5e7)) -* upgrade common-protos to 2.7.0 ([#1579](https://www.github.com/googleapis/gax-java/issues/1579)) ([0a10f5f](https://www.github.com/googleapis/gax-java/commit/0a10f5fe77ab26b3ac7d4c590360945ead72eca1)) - -### [2.7.1](https://www.github.com/googleapis/gax-java/compare/v2.7.0...v2.7.1) (2021-12-02) - - -### Bug Fixes - -* fix gRPC code conversion ([#1555](https://www.github.com/googleapis/gax-java/issues/1555)) ([09b99d5](https://www.github.com/googleapis/gax-java/commit/09b99d591497b44c3c25b1a54abb0f1cb69d7376)) -* pass error message when creating ApiException ([#1556](https://www.github.com/googleapis/gax-java/issues/1556)) ([918ae41](https://www.github.com/googleapis/gax-java/commit/918ae419f84ad5721638ca10eca992333e9f7c3d)) -* revert generics syntax change in MockHttpService test utility ([#1574](https://www.github.com/googleapis/gax-java/issues/1574)) ([b629488](https://www.github.com/googleapis/gax-java/commit/b629488ffc7d68158158d9197695158f97229c7b)) -* update exception mapping on HTTP error responses ([#1570](https://www.github.com/googleapis/gax-java/issues/1570)) ([8a170d1](https://www.github.com/googleapis/gax-java/commit/8a170d19b42e9b13d4c69dcfbe531d4d4ca69c90)) - - -### Dependencies - -* update grpc to 1.42.1 ([#1559](https://www.github.com/googleapis/gax-java/issues/1559)) ([92b7632](https://www.github.com/googleapis/gax-java/commit/92b76325d54604c98c798c489b3a963fdf21a75c)) -* upgrade protobuf to 3.19.1 ([#1571](https://www.github.com/googleapis/gax-java/issues/1571)) ([7b354e7](https://www.github.com/googleapis/gax-java/commit/7b354e73b8ce49008bed51076afb255ca5dc68e4)) - -## [2.7.0](https://www.github.com/googleapis/gax-java/compare/v2.6.0...v2.7.0) (2021-11-03) - - -### Features - -* add batch throttled time to tracer ([#1463](https://www.github.com/googleapis/gax-java/issues/1463)) ([14c25cd](https://www.github.com/googleapis/gax-java/commit/14c25cdfae2c0602d99fcd07c9067138fc172a7f)) -* add google-c2p dependence to DirectPath ([#1521](https://www.github.com/googleapis/gax-java/issues/1521)) ([d4222e7](https://www.github.com/googleapis/gax-java/commit/d4222e757d35e874a57d030f2f964e8d61c71d6d)) -* next release from main branch is 2.7.0 ([#1530](https://www.github.com/googleapis/gax-java/issues/1530)) ([a96953e](https://www.github.com/googleapis/gax-java/commit/a96953e2c889ad9195b420ce5ae49b20258fb6ea)) -* pass request in ApiTracer ([#1491](https://www.github.com/googleapis/gax-java/issues/1491)) ([27bf265](https://www.github.com/googleapis/gax-java/commit/27bf2655120972d929e6118b73d8d556b0440fcf)) - - -### Bug Fixes - -* call ResponseMetadataHanlder#onTrailers before calling onClose ([#1549](https://www.github.com/googleapis/gax-java/issues/1549)) ([19a77a4](https://www.github.com/googleapis/gax-java/commit/19a77a4f6c62e84bba4879690992bbc494730d23)) -* declare depenencies of API surfaces as api ([#1535](https://www.github.com/googleapis/gax-java/issues/1535)) ([725414f](https://www.github.com/googleapis/gax-java/commit/725414f4ccb1e5ac4625790ea990c6c8dfa4fdff)) - -## [2.6.0](https://www.github.com/googleapis/gax-java/compare/v2.5.3...v2.6.0) (2021-10-15) - - -### Features - -* remove deprecated Generated annotation ([2d76bff](https://www.github.com/googleapis/gax-java/commit/2d76bff6d64da818a3aff7ea0bdf5a36b82c3464)) - - -### Bug Fixes - -* Fix com.google.rpc.Code to StatusCode.Code conversion logic ([2d76bff](https://www.github.com/googleapis/gax-java/commit/2d76bff6d64da818a3aff7ea0bdf5a36b82c3464)) - - -### Dependencies - -* update api-common to 2.0.5 ([2d76bff](https://www.github.com/googleapis/gax-java/commit/2d76bff6d64da818a3aff7ea0bdf5a36b82c3464)) -* update auto-value to 1.8.2 ([2d76bff](https://www.github.com/googleapis/gax-java/commit/2d76bff6d64da818a3aff7ea0bdf5a36b82c3464)) -* update com_google_protobuf to 3.18.1 ([#1519](https://www.github.com/googleapis/gax-java/issues/1519)) ([2d76bff](https://www.github.com/googleapis/gax-java/commit/2d76bff6d64da818a3aff7ea0bdf5a36b82c3464)) -* update google-http-client to 1.40.1 ([2d76bff](https://www.github.com/googleapis/gax-java/commit/2d76bff6d64da818a3aff7ea0bdf5a36b82c3464)) -* update grpc to 1.41.0 ([2d76bff](https://www.github.com/googleapis/gax-java/commit/2d76bff6d64da818a3aff7ea0bdf5a36b82c3464)) -* update guava to v31 ([2d76bff](https://www.github.com/googleapis/gax-java/commit/2d76bff6d64da818a3aff7ea0bdf5a36b82c3464)) - -### [2.5.3](https://www.github.com/googleapis/gax-java/compare/v2.5.2...v2.5.3) (2021-10-13) - - -### Bug Fixes - -* Fix `com.google.rpc.Code` to `StatusCode.Code` conversion logic ([#1508](https://www.github.com/googleapis/gax-java/issues/1508)) ([61b1617](https://www.github.com/googleapis/gax-java/commit/61b161799faf292be1394111381f8a35e757b85a)) - -### [2.5.2](https://www.github.com/googleapis/gax-java/compare/v2.5.1...v2.5.2) (2021-10-13) - - -### Dependencies - -* release multiple artifacts at once ([#1506](https://www.github.com/googleapis/gax-java/issues/1506)) ([8c022f6](https://www.github.com/googleapis/gax-java/commit/8c022f69f7878280e00f200f65a931ff0f8cfe45)) - -### [2.5.1](https://www.github.com/googleapis/gax-java/compare/v2.5.0...v2.5.1) (2021-10-08) - - -### Dependencies - -* fix release pipeline ([#1500](https://www.github.com/googleapis/gax-java/issues/1500)) ([f8ae03b](https://www.github.com/googleapis/gax-java/commit/f8ae03bbf0389d5fd943d214c1058ee012be757b)) - -## [2.5.0](https://www.github.com/googleapis/gax-java/compare/v2.4.1...v2.5.0) (2021-09-21) - - -### Features - -* Add REST AIP-151 LRO support ([#1484](https://www.github.com/googleapis/gax-java/issues/1484)) ([95ca348](https://www.github.com/googleapis/gax-java/commit/95ca3482d272b5c5c5ac2c85ba007f0ba9f7b5cf)) - -### [2.4.1](https://www.github.com/googleapis/gax-java/compare/v2.4.0...v2.4.1) (2021-09-08) - - -### Bug Fixes - -* REGAPIC fix socket timeout for wait calls ([#1476](https://www.github.com/googleapis/gax-java/issues/1476)) ([86c68b3](https://www.github.com/googleapis/gax-java/commit/86c68b3ffd241f6932516d0e7b5d9ae5714b89e0)) - -## [2.4.0](https://www.github.com/googleapis/gax-java/compare/v2.3.0...v2.4.0) (2021-08-27) - - -### Bug Fixes - -* Fix PATCH being unsupported ([#1465](https://www.github.com/googleapis/gax-java/issues/1465)) ([2c6ac24](https://www.github.com/googleapis/gax-java/commit/2c6ac24b1fce1de356e69370bbe6a4348825e3f9)) - - -### Dependencies - -* update google-common-prots and google-http-client ([#1471](https://www.github.com/googleapis/gax-java/issues/1471)) ([80e17a3](https://www.github.com/googleapis/gax-java/commit/80e17a35feb00aff0af3a65876625c705eb6ca46)) - -## [2.3.0](https://www.github.com/googleapis/gax-java/compare/v2.2.0...v2.3.0) (2021-08-16) - - -### Features - -* add custom options to ApiCallContext ([#1435](https://www.github.com/googleapis/gax-java/issues/1435)) ([0fe20f3](https://www.github.com/googleapis/gax-java/commit/0fe20f379feba1570e562e60e3f0bf7cc4e485bd)) -* add UseJwtAccessWithScope to GoogleCredentialsProvider ([#1420](https://www.github.com/googleapis/gax-java/issues/1420)) ([ed39c34](https://www.github.com/googleapis/gax-java/commit/ed39c34693783460fc03effb47e7027914cfb5bc)) - -## [2.2.0](https://www.github.com/googleapis/gax-java/compare/v2.1.0...v2.2.0) (2021-08-13) - - -### Features - -* Add AIP-151 LRO OperationsClient to gax-httpjson ([#1458](https://www.github.com/googleapis/gax-java/issues/1458)) ([314acb6](https://www.github.com/googleapis/gax-java/commit/314acb6a5c335732e8406bec86f6c37296ebf3f3)) - -## [2.1.0](https://www.github.com/googleapis/gax-java/compare/v2.0.0...v2.1.0) (2021-08-11) - - -### Features - -* add allowNonDefaultServiceAccount option for DirectPath ([#1433](https://www.github.com/googleapis/gax-java/issues/1433)) ([209b494](https://www.github.com/googleapis/gax-java/commit/209b4944feba1c62be2c9de4545e3b01a806b738)) - - -### Bug Fixes - -* fix httpjson executor ([#1448](https://www.github.com/googleapis/gax-java/issues/1448)) ([8f48b70](https://www.github.com/googleapis/gax-java/commit/8f48b7027b95e8e75872d1f9dac537ea697d0acc)) -* make closeAsync don't interrupt running thread ([#1446](https://www.github.com/googleapis/gax-java/issues/1446)) ([7c6c298](https://www.github.com/googleapis/gax-java/commit/7c6c29824487346d444730388ea6967408692696)) - - -### Dependencies - -* update dependency com.google.api:api-common to v2.0.1 ([#1452](https://www.github.com/googleapis/gax-java/issues/1452)) ([a52f16f](https://www.github.com/googleapis/gax-java/commit/a52f16f6cef8340357acb374ff31c8a6f248403c)) - -## [2.0.0](https://www.github.com/googleapis/gax-java/compare/v1.67.0...v2.0.0) (2021-07-30) - - -### Features - -* promote to 2.0.0 ([#1444](https://www.github.com/googleapis/gax-java/issues/1444)) ([776b1aa](https://www.github.com/googleapis/gax-java/commit/776b1aa73022bedec55e69732245b73cd04608f8)) - - -### Bug Fixes - -* stop overriding default grpc executor ([#1355](https://www.github.com/googleapis/gax-java/issues/1355)) ([b1f8c43](https://www.github.com/googleapis/gax-java/commit/b1f8c43cc90eb8e5ef78d142878841689356738c)) - - -### Dependencies - -* update api-common, guava, google-auth-library-credentials ([#1442](https://www.github.com/googleapis/gax-java/issues/1442)) ([2925ed7](https://www.github.com/googleapis/gax-java/commit/2925ed78cfb74db07a87da28839aeebc9027ac72)) - -## [1.67.0](https://www.github.com/googleapis/gax-java/compare/v1.66.0...v1.67.0) (2021-07-19) - - -### Features - -* introduce closeAsync to Batcher ([#1423](https://www.github.com/googleapis/gax-java/issues/1423)) ([aab5288](https://www.github.com/googleapis/gax-java/commit/aab528803405c2b5f9fc89641f47abff948a876d)) -* optimize unary callables to not wait for trailers ([#1356](https://www.github.com/googleapis/gax-java/issues/1356)) ([dd5f955](https://www.github.com/googleapis/gax-java/commit/dd5f955a3ab740c677fbc6f1247094798eb814a3)) -* update DirectPath environment variables ([#1412](https://www.github.com/googleapis/gax-java/issues/1412)) ([4f63b61](https://www.github.com/googleapis/gax-java/commit/4f63b61f1259936aa4a1eaf9162218c787b92f2a)) - - -### Bug Fixes - -* remove `extends ApiMessage` from `HttpJsonStubCallableFactory` definition ([#1426](https://www.github.com/googleapis/gax-java/issues/1426)) ([87636a5](https://www.github.com/googleapis/gax-java/commit/87636a5812874a77e9004aab07607121efa43736)) - -## [1.66.0](https://www.github.com/googleapis/gax-java/compare/v1.65.1...v1.66.0) (2021-06-24) - - -### Features - -* make ApiTracer internal API ([#1414](https://www.github.com/googleapis/gax-java/issues/1414)) ([e3e8462](https://www.github.com/googleapis/gax-java/commit/e3e8462a2f9e866480ec2106dc59555d41ea4bb5)) - -### [1.65.1](https://www.github.com/googleapis/gax-java/compare/v1.65.0...v1.65.1) (2021-06-08) - - -### Bug Fixes - -* fix grammar in StubSetting comment ([#1397](https://www.github.com/googleapis/gax-java/issues/1397)) ([b015910](https://www.github.com/googleapis/gax-java/commit/b0159102b52fd4b778a9bde15b1acd2e9fa6958e)) - -## [1.65.0](https://www.github.com/googleapis/gax-java/compare/v1.64.0...v1.65.0) (2021-06-02) - - -### Features - -* add mtls feature to http and grpc transport provider ([#1249](https://www.github.com/googleapis/gax-java/issues/1249)) ([b863041](https://www.github.com/googleapis/gax-java/commit/b863041bc4c03c8766e0feca8cb10f531373dc44)) - -## [1.64.0](https://www.github.com/googleapis/gax-java/compare/v1.63.4...v1.64.0) (2021-05-10) - - -### Features - -* release 1.64.0 ([#1375](https://www.github.com/googleapis/gax-java/issues/1375)) ([499682e](https://www.github.com/googleapis/gax-java/commit/499682ec3b96ddeaac75f6e71cc3bc85a854da97)) - -### [1.63.4](https://www.github.com/googleapis/gax-java/compare/v1.63.3...v1.63.4) (2021-05-07) - - -### Bug Fixes - -* Make x-goog-api-client header report rest-based transport clients with `rest/` token instead of `httpson/`. ([#1370](https://www.github.com/googleapis/gax-java/issues/1370)) ([b1b0b49](https://www.github.com/googleapis/gax-java/commit/b1b0b498ba188a51b17d179988074bcf34fb7590)) - -### [1.63.3](https://www.github.com/googleapis/gax-java/compare/v1.63.2...v1.63.3) (2021-05-04) - - -### Bug Fixes - -* fix flaky tests and non blocking semaphore ([#1365](https://www.github.com/googleapis/gax-java/issues/1365)) ([fc8e520](https://www.github.com/googleapis/gax-java/commit/fc8e520acfaf843ac61e806bdb4b5fe393d0b447)) -* Remove a flacky test in FlowControllerTest ([#1360](https://www.github.com/googleapis/gax-java/issues/1360)) ([2cca0bf](https://www.github.com/googleapis/gax-java/commit/2cca0bf9e96271dd52e8bffa00b8f2d45d358d35)) - -### [1.63.2](https://www.github.com/googleapis/gax-java/compare/v1.63.1...v1.63.2) (2021-04-30) - - -### Bug Fixes - -* Remove default value handling ([#1353](https://www.github.com/googleapis/gax-java/issues/1353)) ([ed0fc79](https://www.github.com/googleapis/gax-java/commit/ed0fc791b22db45bd20de890b0abecd1839d2d86)) - - -### Dependencies - -* remove codecov.io ([#1354](https://www.github.com/googleapis/gax-java/issues/1354)) ([06a53ac](https://www.github.com/googleapis/gax-java/commit/06a53aca36ed0825122be160479b1ea0ba8635a0)) - -### [1.63.1](https://www.github.com/googleapis/gax-java/compare/v1.63.0...v1.63.1) (2021-04-26) - - -### Bug Fixes - -* fix dynamic flow control setting checks ([#1347](https://www.github.com/googleapis/gax-java/issues/1347)) ([69458b4](https://www.github.com/googleapis/gax-java/commit/69458b4deefe5b9c2c33a3b51389face968ff52f)) -* fix watchdog NPE red herring ([#1344](https://www.github.com/googleapis/gax-java/issues/1344)) ([06dbf12](https://www.github.com/googleapis/gax-java/commit/06dbf129ce63d28430e1022137679c9cfdf433ee)) - -## [1.63.0](https://www.github.com/googleapis/gax-java/compare/v1.62.0...v1.63.0) (2021-04-05) - - -### Features - -* add setLogicalTimeout helper to RetrySettings ([#1334](https://www.github.com/googleapis/gax-java/issues/1334)) ([97d3214](https://www.github.com/googleapis/gax-java/commit/97d32144e9de38a9e351dc34270aa41aef351151)) -* dynamic flow control for batcher part 2 ([#1310](https://www.github.com/googleapis/gax-java/issues/1310)) ([20f6ecf](https://www.github.com/googleapis/gax-java/commit/20f6ecf4807bb4dffd0fa80717302c1f46b1d789)) -* dynamic flow control p3: add FlowControllerEventStats ([#1332](https://www.github.com/googleapis/gax-java/issues/1332)) ([5329ea4](https://www.github.com/googleapis/gax-java/commit/5329ea43c024ca14cea1012c5ab46e694e199492)) -* support retry settings and retryable codes in call context ([#1238](https://www.github.com/googleapis/gax-java/issues/1238)) ([7f7aa25](https://www.github.com/googleapis/gax-java/commit/7f7aa252ce96413cb09e01cc2e76672b167b1baf)) -* wrap non-retryable RPCs in retry machinery ([#1328](https://www.github.com/googleapis/gax-java/issues/1328)) ([51c40ab](https://www.github.com/googleapis/gax-java/commit/51c40abd408ab0637f3b65cf5697a4ee85a544a4)) - - -### Bug Fixes - -* add BetaApi tag to setLogicalTimeout ([#1335](https://www.github.com/googleapis/gax-java/issues/1335)) ([fc7169d](https://www.github.com/googleapis/gax-java/commit/fc7169d431baf2db90992241a0ef3d40c72567a5)) -* retain user RPC timeout if set via withTimeout ([#1324](https://www.github.com/googleapis/gax-java/issues/1324)) ([3fe1db9](https://www.github.com/googleapis/gax-java/commit/3fe1db913b134e4fddee4c769ee4497847d8e01f)) - - -### Documentation - -* cloud rad java doc generation ([#1336](https://www.github.com/googleapis/gax-java/issues/1336)) ([751ccf3](https://www.github.com/googleapis/gax-java/commit/751ccf3cb351cd5a037104242cdb763a104d6bc3)) - -## [1.62.0](https://www.github.com/googleapis/gax-java/compare/v1.61.0...v1.62.0) (2021-02-25) - - -### ⚠ BREAKING CHANGES - -* deprecate RetrySettings.isJittered [gax-java] (#1308) - -### Features - -* deprecate RetrySettings.isJittered [gax-java] ([#1308](https://www.github.com/googleapis/gax-java/issues/1308)) ([68644a4](https://www.github.com/googleapis/gax-java/commit/68644a4e24f29223f8f533a3d353dff7457d9737)) -* dynamic flow control part 1 - add FlowController to Batcher ([#1289](https://www.github.com/googleapis/gax-java/issues/1289)) ([bae5eb6](https://www.github.com/googleapis/gax-java/commit/bae5eb6070e690c26b95e7b908d15300aa54ef1c)) - - -### Bug Fixes - -* prevent unchecked warnings in gax-httpjson ([#1306](https://www.github.com/googleapis/gax-java/issues/1306)) ([ee370f6](https://www.github.com/googleapis/gax-java/commit/ee370f62c5d411738a9b25cf4cfc095aa06d9e07)) -* remove unused @InternalExtensionOnly from CallContext classes ([#1304](https://www.github.com/googleapis/gax-java/issues/1304)) ([a8d3a2d](https://www.github.com/googleapis/gax-java/commit/a8d3a2dca96efdb1ce154a976c3e0844e3f501d6)) - - -### Dependencies - -* update google-auth-library to 0.24.0 ([#1315](https://www.github.com/googleapis/gax-java/issues/1315)) ([772331e](https://www.github.com/googleapis/gax-java/commit/772331eda5c47e9de376e505e7d8ee502b01ec72)) -* update google-common-protos to 2.0.1 ([772331e](https://www.github.com/googleapis/gax-java/commit/772331eda5c47e9de376e505e7d8ee502b01ec72)) -* update google-http-client to 1.39.0 ([772331e](https://www.github.com/googleapis/gax-java/commit/772331eda5c47e9de376e505e7d8ee502b01ec72)) -* update google-iam ([#1313](https://www.github.com/googleapis/gax-java/issues/1313)) ([327b53c](https://www.github.com/googleapis/gax-java/commit/327b53ca7739d9be6e24305b23af2c7a35cb6f4d)) -* update gRPC to 1.36.0 ([772331e](https://www.github.com/googleapis/gax-java/commit/772331eda5c47e9de376e505e7d8ee502b01ec72)) -* update opencensus to 0.28.0 ([772331e](https://www.github.com/googleapis/gax-java/commit/772331eda5c47e9de376e505e7d8ee502b01ec72)) -* update protobuf to 3.15.2 ([772331e](https://www.github.com/googleapis/gax-java/commit/772331eda5c47e9de376e505e7d8ee502b01ec72)) - -## [1.61.0](https://www.github.com/googleapis/gax-java/compare/v1.60.1...v1.61.0) (2021-02-17) - - -### Features - -* **operations:** Add WaitOperation API surface [gax-java] ([#1284](https://www.github.com/googleapis/gax-java/issues/1284)) ([68761a7](https://www.github.com/googleapis/gax-java/commit/68761a7de17489c02362e079ca766ee06da5e247)) - - -### Bug Fixes - -* InstantiatingGrpcChannelProvider.toBuilder() should carry over all config data ([#1298](https://www.github.com/googleapis/gax-java/issues/1298)) ([0bc5dc5](https://www.github.com/googleapis/gax-java/commit/0bc5dc54c8eea00f2dc0e1d6a4a42e3417c64fc7)) -* **lro:** Add Operation name to headers in {Get,List}Operation requests [gax-java] ([#1281](https://www.github.com/googleapis/gax-java/issues/1281)) ([721617b](https://www.github.com/googleapis/gax-java/commit/721617b0cb80ebcd40c3aa2f6c5b86f679dad811)) -* **operations:** Make Operations a manual client [gax-java] ([#1282](https://www.github.com/googleapis/gax-java/issues/1282)) ([5be66cd](https://www.github.com/googleapis/gax-java/commit/5be66cd3ebf2ccf34f21db40463a2d9115a77798)) - - -### Dependencies - -* update com.google.http-client:google-http-client to 1.38.1 ([#1265](https://www.github.com/googleapis/gax-java/issues/1265)) ([5815a7c](https://www.github.com/googleapis/gax-java/commit/5815a7ce815cc2fc47b39b928010de0c2cea8716)) -* update common protos ([#1258](https://www.github.com/googleapis/gax-java/issues/1258)) ([7287e84](https://www.github.com/googleapis/gax-java/commit/7287e84979ba9076e4888ec3678995c08f1ea690)) -* update gRPC ([#1263](https://www.github.com/googleapis/gax-java/issues/1263)) ([95a7dab](https://www.github.com/googleapis/gax-java/commit/95a7dab77800dffaf551018c85e1d78596411e8f)) -* update Guava ([#1262](https://www.github.com/googleapis/gax-java/issues/1262)) ([cdc0366](https://www.github.com/googleapis/gax-java/commit/cdc0366d23317d6fddd3dc86592664449aaa8a6f)) -* update iam protos to v1.0.7 ([#1266](https://www.github.com/googleapis/gax-java/issues/1266)) ([69b6dc4](https://www.github.com/googleapis/gax-java/commit/69b6dc44f5e81d5919553b9de6248346d172adcd)) -* update protobuf ([#1256](https://www.github.com/googleapis/gax-java/issues/1256)) ([ef9b3aa](https://www.github.com/googleapis/gax-java/commit/ef9b3aaac30406b0b17a985ab959530c1254b145)) - -### [1.60.1](https://www.github.com/googleapis/gax-java/compare/v1.60.0...v1.60.1) (2020-11-19) - - -### Bug Fixes - -* check Compute Engine environment for DirectPath ([#1250](https://www.github.com/googleapis/gax-java/issues/1250)) ([656b613](https://www.github.com/googleapis/gax-java/commit/656b613d2fe73e5bd19d43d4a2d8d0c6bb9ad5f2)) - - -### Dependencies - -* update api-common to 1.10.1 ([#1240](https://www.github.com/googleapis/gax-java/issues/1240)) ([d8b2bf7](https://www.github.com/googleapis/gax-java/commit/d8b2bf7b59d83a11e2e0eba703ed758fd1adb0ce)) -* update auth libaries ([#1251](https://www.github.com/googleapis/gax-java/issues/1251)) ([d455da2](https://www.github.com/googleapis/gax-java/commit/d455da2cd73f1e015d7570e8d634864a38bdb042)) -* update autovalue annotations ([#1246](https://www.github.com/googleapis/gax-java/issues/1246)) ([60bb103](https://www.github.com/googleapis/gax-java/commit/60bb10326cd3a0092d69e8388eb5f7fed55a715c)) -* update dependency com.google.auto.value:auto-value to v1.7.4 ([#1031](https://www.github.com/googleapis/gax-java/issues/1031)) ([1e7e13c](https://www.github.com/googleapis/gax-java/commit/1e7e13c07bf4c79d0b3cbfd0f15a4908278c1ffa)) -* update google-http-client to 1.38.0 ([#1244](https://www.github.com/googleapis/gax-java/issues/1244)) ([6b53f0f](https://www.github.com/googleapis/gax-java/commit/6b53f0fe3a95346596c670f62d34267483a12c68)) -* update Guava to 30.0-android ([#1237](https://www.github.com/googleapis/gax-java/issues/1237)) ([64806c4](https://www.github.com/googleapis/gax-java/commit/64806c474f1aab87ed62f59e9746aa22c5982e96)) -* update threetenbp to 1.5.0 ([#1243](https://www.github.com/googleapis/gax-java/issues/1243)) ([6232599](https://www.github.com/googleapis/gax-java/commit/6232599506fda164e5675162e71809a78258efbd)) - -## [1.60.0](https://www.github.com/googleapis/gax-java/compare/v1.59.1...v1.60.0) (2020-10-19) - - -### Features - -* REST Gapic (REGAPIC) Support ([#1177](https://www.github.com/googleapis/gax-java/issues/1177)) ([12b18ee](https://www.github.com/googleapis/gax-java/commit/12b18ee255d3fabe13bb3969df40753b29f830d5)) - - -### Bug Fixes - -* prevent npe caused by missing parentheses ([#1198](https://www.github.com/googleapis/gax-java/issues/1198)) ([b856351](https://www.github.com/googleapis/gax-java/commit/b85635123f987f9808086f14a58dd8c7418a3bd8)) - - -### Dependencies - -* upgrade grpc to 1.32.2 ([#1212](https://www.github.com/googleapis/gax-java/issues/1212)) ([03c4c0f](https://www.github.com/googleapis/gax-java/commit/03c4c0f621f439c30752122568d2a9a7703e5e16)) - -### [1.59.1](https://www.github.com/googleapis/gax-java/compare/v1.59.0...v1.59.1) (2020-10-05) - - -### Bug Fixes - -* Fix race condition in BatcherImpl flush ([#1200](https://www.github.com/googleapis/gax-java/issues/1200)) ([c6308c9](https://www.github.com/googleapis/gax-java/commit/c6308c906171ce05765ccacb716aa7162d95d9a2)) -* update owners file with actools-java ([#1194](https://www.github.com/googleapis/gax-java/issues/1194)) ([9977dd2](https://www.github.com/googleapis/gax-java/commit/9977dd2564ff6919fc6a6b658eb69b5ea8a66520)) - -## [1.59.0](https://www.github.com/googleapis/gax-java/compare/v1.58.3...v1.59.0) (2020-09-28) - - -### Features - -* Allow user-agents to be specified by both internal headers and user headers ([#1190](https://www.github.com/googleapis/gax-java/issues/1190)) ([266329e](https://www.github.com/googleapis/gax-java/commit/266329e89642bfc6be579e600d3f995f4416ae4e)), closes [/github.com/googleapis/java-bigtable/pull/404#pullrequestreview-480972135](https://www.github.com/googleapis//github.com/googleapis/java-bigtable/pull/404/issues/pullrequestreview-480972135) - - -### Bug Fixes - -* truncate RPC timeouts to time remaining in totalTimeout ([#1191](https://www.github.com/googleapis/gax-java/issues/1191)) ([1d0c940](https://www.github.com/googleapis/gax-java/commit/1d0c94061bab124be81a649ac3fa1ce5d9a2df23)) - - -### Dependencies - -* update guava to 29.0-android ([#1174](https://www.github.com/googleapis/gax-java/issues/1174)) ([287cada](https://www.github.com/googleapis/gax-java/commit/287cadae528549545da9e7e9d63fd70c1268e3c1)), closes [#1151](https://www.github.com/googleapis/gax-java/issues/1151) - -### [1.58.3](https://www.github.com/googleapis/gax-java/compare/v1.58.2...v1.58.3) (2020-09-15) - - -### Bug Fixes - -* [gax-java] Add speedy Bazel builds to Travis ([#1181](https://www.github.com/googleapis/gax-java/issues/1181)) ([2fb85fe](https://www.github.com/googleapis/gax-java/commit/2fb85fed095c6043ee39b63a0f7dff3fd93cbd7b)) -* [gax-java] add Vim files to .gitignore ([#1179](https://www.github.com/googleapis/gax-java/issues/1179)) ([2de22b6](https://www.github.com/googleapis/gax-java/commit/2de22b6645fbfd7ada7d0067e5cdd3c2039ec190)) -* [gax-java] Fix broken Bazel build ([#1180](https://www.github.com/googleapis/gax-java/issues/1180)) ([834c05e](https://www.github.com/googleapis/gax-java/commit/834c05e1d35a17f90bf8cd1b2cdce40bea451c95)) - -### [1.58.2](https://www.github.com/googleapis/gax-java/compare/v1.58.1...v1.58.2) (2020-08-07) - - -### Bug Fixes - -* Settings objects should not try to read quotaProjectId from credentials ([#1162](https://www.github.com/googleapis/gax-java/issues/1162)) ([1b09bcf](https://www.github.com/googleapis/gax-java/commit/1b09bcff1ddfaed8cfa58b92c787f8fc9b08abef)) - -### [1.58.1](https://www.github.com/googleapis/gax-java/compare/v1.58.0...v1.58.1) (2020-08-06) - - -### Bug Fixes - -* fix dependencies.properties resource file creation during deployment ([#1163](https://www.github.com/googleapis/gax-java/issues/1163)) ([3e7e1f1](https://www.github.com/googleapis/gax-java/commit/3e7e1f1e64bdeb23a51b5155faea975beec0bc84)) -* Watchdog.shutdownNow() does not shutdown executor ([#1158](https://www.github.com/googleapis/gax-java/issues/1158)) ([6241a21](https://www.github.com/googleapis/gax-java/commit/6241a2118690d07dd28ffb9447423363f3f914e4)) - -## [1.58.0](https://www.github.com/googleapis/gax-java/compare/v1.57.2...v1.58.0) (2020-07-31) - - -### Features - -* add retry logging ([#1160](https://www.github.com/googleapis/gax-java/issues/1160)) ([1575715](https://www.github.com/googleapis/gax-java/commit/15757151d4965276bd01e6772c10288959bb17ec)) -* enable setting quota_project_id ([#1128](https://www.github.com/googleapis/gax-java/issues/1128)) ([20bb200](https://www.github.com/googleapis/gax-java/commit/20bb200c8019ad1df8acbfe210cea7d5e9a9a57c)) -* non-retryable RPCs use totalTimeout ([#1149](https://www.github.com/googleapis/gax-java/issues/1149)) ([b7646a3](https://www.github.com/googleapis/gax-java/commit/b7646a3a959b7e5ef40158851f26ce6701da8ca4)) - - -### Bug Fixes - -* retain context timeouts in ServerStreamingAttemptCallable ([#1155](https://www.github.com/googleapis/gax-java/issues/1155)) ([461ff84](https://www.github.com/googleapis/gax-java/commit/461ff846ca551c2242bf6c60e61234997d0ba58e)) - -### [1.57.2](https://www.github.com/googleapis/gax-java/compare/v1.57.1...v1.57.2) (2020-07-21) - - -### Bug Fixes - -* Fix javadoc generation on Java11 ([#1145](https://www.github.com/googleapis/gax-java/issues/1145)) ([c7a039e](https://www.github.com/googleapis/gax-java/commit/c7a039e07be02298d9dd906b08e1e1bb995e85e2)) -* Preconditions only supports %s format ([#1153](https://www.github.com/googleapis/gax-java/issues/1153)) ([8145311](https://www.github.com/googleapis/gax-java/commit/8145311b38fdd3bf82a4958f8aef5313857b70c0)) - -### [1.57.1](https://www.github.com/googleapis/gax-java/compare/v1.57.0...v1.57.1) (2020-07-07) - - -### Bug Fixes - -* add back javax.annotation dependency ([#1129](https://www.github.com/googleapis/gax-java/issues/1129)) ([77a4cc3](https://www.github.com/googleapis/gax-java/commit/77a4cc373914396dd343891e38cf743166668c96)) - - -### Dependencies - -* update google-auth-library to 0.21.0 ([#1134](https://www.github.com/googleapis/gax-java/issues/1134)) ([6528e5c](https://www.github.com/googleapis/gax-java/commit/6528e5cb9cec50ef01c0d2601c6db518df825747)) diff --git a/RELEASING.md b/RELEASING.md deleted file mode 100644 index 37e4b2044..000000000 --- a/RELEASING.md +++ /dev/null @@ -1,72 +0,0 @@ -One-time setup -============== - -Set up Sonatype Account ------------------------ -* Sign up for a Sonatype JIRA account [here](https://issues.sonatype.org) -* Click *Sign Up* in the login box, follow instructions - -Get access to repository ------------------------- -* Go to [community support](https://issues.sonatype.org/browse/OSSRH) -* Ask for publish rights by creating an issue similar to [this one](https://issues.sonatype.org/browse/OSSRH-32031) - * You must be logged in to create a new issue - * Use the *Create* button at the top tab - -* Generate the key `gpg --gen-key` - * Keep the defaults, but specify a passphrase - -* Determine your `gpg` version: `gpg --version` - -* Find the ID of your public key - * If you're using GPG version 1.y.z, `gpg --list-secret-keys` - * Look for the line with format `sec 2048R/ABCDEFGH 2015-11-17` - * The `ABCDEFGH` is the ID for your public key - * If you're using GPG version 2.y.z `gpg --list-secret-keys --keyid-format LONG` - * Look for line with format `sec rsa2048/ABCDEFGHIJKLMNOP` - * The `ABCDEFGHIJKLMNOP` is the ID. It is 16-byte long, but Gradle - only support 8-byte keys. Use the *last* 8 bytes of the key when - following the rest of this document. - * `gpg --export-secret-keys > $HOME/.gnupg/secring.gpg` - -* Upload your public key to a public server: `gpg --send-keys --keyserver hkp://pgp.mit.edu ` - -Add deploy credential settings ------------------------- -* Create a settings file at `$HOME/.gradle/gradle.properties` with your key information and your sonatype username/password - -``` -signing.keyId= -signing.password= -signing.secretKeyRingFile=/usr/local/google/home//.gnupg/secring.gpg - -ossrhUsername= -ossrhPassword= -``` - -Install releasetool -------------------- -See [releasetool](https://github.com/googleapis/releasetool) for installation instructions. You will -need python 3.6+ to run this tool. - -To prepare a release -==================== - -Update version and deploy to Sonatype -------------------------------------- -1. Run `releasetool start`. Select "minor" or "patch" for the release type. This will bump the - artifact versions, ask you to edit release notes, and create the release pull request. When - prompted, choose to autorelease. - * Note: be sure to make these notes nice as they will be used for the release notes as well. -2. Request a review on the PR. -3. Submit the PR. -4. Automation will run in the background to handle the release. -5. It will take some time (~10 min to ~8 hours) for the package to transition -6. Automation will publish a new release on Github using releasetool and publish javadocs to - https://googleapis.dev/java/gax/latest. - -Bump development version ------------------------- -1. Run `releasetool start` again, but specify "snapshot" when prompted for the type of release. - This will bump the artifact versions and create a new snapshot pull request. -2. Review and submit the PR. diff --git a/WORKSPACE b/WORKSPACE deleted file mode 100644 index 9c65d85e8..000000000 --- a/WORKSPACE +++ /dev/null @@ -1,45 +0,0 @@ -workspace(name = "com_google_api_gax_java") - -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") -load("//:repository_rules.bzl", "com_google_api_gax_java_properties") - -com_google_api_gax_java_properties( - name = "com_google_api_gax_java_properties", - file = "//:dependencies.properties", -) - -load("//:repositories.bzl", "com_google_api_gax_java_repositories") - -com_google_api_gax_java_repositories() - -load("@com_google_protobuf//:protobuf_deps.bzl", - "PROTOBUF_MAVEN_ARTIFACTS", "protobuf_deps") - -# From protobuf 3.19, protobuf project started to provide -# PROTOBUF_MAVEN_ARTIFACTS variable so that the Bazel users can resolve their -# dependencies through maven_install. -# https://github.com/protocolbuffers/protobuf/issues/9132 -RULES_JVM_EXTERNAL_TAG = "4.2" -RULES_JVM_EXTERNAL_SHA = "cd1a77b7b02e8e008439ca76fd34f5b07aecb8c752961f9640dea15e9e5ba1ca" -http_archive( - name = "rules_jvm_external", - strip_prefix = "rules_jvm_external-%s" % RULES_JVM_EXTERNAL_TAG, - sha256 = RULES_JVM_EXTERNAL_SHA, - url = "https://github.com/bazelbuild/rules_jvm_external/archive/%s.zip" % RULES_JVM_EXTERNAL_TAG, -) - -load("@rules_jvm_external//:defs.bzl", "maven_install") - -maven_install( - artifacts = PROTOBUF_MAVEN_ARTIFACTS, - generate_compat_repositories = True, - repositories = [ - "https://repo.maven.apache.org/maven2/", - ], -) - -protobuf_deps() - -load("@io_grpc_grpc_java//:repositories.bzl", "grpc_java_repositories") - -grpc_java_repositories() diff --git a/build.gradle b/build.gradle deleted file mode 100644 index d6a194c00..000000000 --- a/build.gradle +++ /dev/null @@ -1,329 +0,0 @@ -import groovy.io.FileType - -plugins { - id 'java' - id 'io.github.gradle-nexus.publish-plugin' version '1.1.0' - - id 'com.diffplug.eclipse.apt' version '3.40.0' apply false - id 'com.dorongold.task-tree' version '2.1.1' apply false - id 'com.github.johnrengelman.shadow' version '7.1.2' apply false - id 'com.github.sherter.google-java-format' version '0.9' apply false - - id 'org.sonarqube' version '3.5.0.2730' -} - -// TODO: Populate this from dependencies.properties version property (for proper Gradle-Bazel sync) -project.version = "2.20.1" // {x-version-update:gax:current} - -allprojects { - group = 'com.google.api' -} - -// Project names not using the default publication configuration -def nonJavaProjects = ['gax-bom'] - -ext { - libraryVendor = 'Google' - - // Load Dependencies shared between Bazel and Gradle build scripts - libraries = new Properties() - file('dependencies.properties').withReader { libraries.load(it) } - // Gradle-specific build script dependencies - libraries.putAll( - 'maven.io_grpc_grpc_bom': "io.grpc:grpc-bom:${libraries['version.io_grpc']}", - 'maven.io_grpc_grpc_core': "io.grpc:grpc-core:${libraries['version.io_grpc']}", - 'maven.io_grpc_grpc_context': "io.grpc:grpc-context:${libraries['version.io_grpc']}", - 'maven.io_grpc_grpc_stub': "io.grpc:grpc-stub:${libraries['version.io_grpc']}", - 'maven.io_grpc_grpc_api': "io.grpc:grpc-api:${libraries['version.io_grpc']}", - 'maven.io_grpc_grpc_auth': "io.grpc:grpc-auth:${libraries['version.io_grpc']}", - 'maven.io_grpc_grpc_protobuf': "io.grpc:grpc-protobuf:${libraries['version.io_grpc']}", - 'maven.io_grpc_grpc_netty_shaded': "io.grpc:grpc-netty-shaded:${libraries['version.io_grpc']}", - 'maven.io_grpc_grpc_alts': "io.grpc:grpc-alts:${libraries['version.io_grpc']}", - 'maven.io_grpc_grpc_googleapis': "io.grpc:grpc-googleapis:${libraries['version.io_grpc']}", - 'maven.com_google_protobuf': "com.google.protobuf:protobuf-java:${libraries['version.com_google_protobuf']}", - 'maven.com_google_protobuf_java_util': "com.google.protobuf:protobuf-java-util:${libraries['version.com_google_protobuf']}") -} - -nexusPublishing { - packageGroup = 'com.google.api' - repositories { - sonatype { - nexusUrl = uri('https://google.oss.sonatype.org/service/local/') - snapshotRepositoryUrl = uri('https://google.oss.sonatype.org/content/repositories/snapshots/') - username = findProperty('ossrhUsername') - password = findProperty('ossrhPassword') - } - } -} - -def javaProjects = subprojects.findAll { !nonJavaProjects.contains(it.name) } -configure(javaProjects) { - apply plugin: 'java-library' - apply plugin: 'eclipse' - apply plugin: 'idea' - apply plugin: 'jacoco' - - apply plugin: 'com.diffplug.eclipse.apt' - apply plugin: 'com.dorongold.task-tree' - apply plugin: 'com.github.johnrengelman.shadow' - apply plugin: 'com.github.sherter.google-java-format' - - sourceCompatibility = 1.8 - targetCompatibility = 1.8 - - // Formatting tasks - // ================ - googleJavaFormat { - toolVersion '1.7' - exclude '.apt_generated*/**' - exclude 'bin/**' - exclude 'build/**' - exclude 'bazel*/**' - } - test.dependsOn verifyGoogleJavaFormat - - task verifyLicense { - doLast { - def licenseText = new File('license-header-javadoc.txt').text - def srcFiles = [] - sourceSets - .collectMany{it.allJava.getSrcDirs()} - .grep{it.exists()} - .each{it.eachFileRecurse(FileType.FILES, {srcFiles << new Tuple(it, it.text)})} - srcFiles = srcFiles - .findAll{it.get(0).path.endsWith('.java')} - .collect{new Tuple(it.get(0), it.get(1).replaceAll('Copyright 20[0-9]{2}', 'Copyright 20xx'))} - .findAll{!it.get(1).startsWith(licenseText)} - if (srcFiles.asList().size() > 0) { - srcFiles.each({println 'missing license: ' + it.get(0)}) - throw new IllegalStateException('Above files do not have licenses') - } - } - } - test.dependsOn verifyLicense - - tasks.withType(JavaCompile) { - options.compilerArgs << '-Xlint:unchecked' << '-Xlint:deprecation' - // This flag is only available in JDK 9+. This flag ensures the generated - // bytecode is compatible with Java 8. (targetCompatibility = 1.8 is not - // sufficient) - options.compilerArgs.addAll(['--release', '8']) - } - - // Dependencies - // ------------ - - repositories { - mavenLocal() - mavenCentral() - } - - configurations { - shadowNoGuava - implementation.exclude group: 'com.google.guava', module: 'guava-jdk5' - } - - jacoco.toolVersion = '0.8.5' - jacocoTestReport { - reports { - xml.required = true - html.required = true - } - afterEvaluate { - getClassDirectories().setFrom files(classDirectories.files.collect { - fileTree(dir: it, exclude: ['**/AutoValue_*']) - }) - } - } - check.dependsOn jacocoTestReport - - - // Source jar - // ---------- - - task sourcesJar(type: Jar, dependsOn: classes) { - archiveClassifier = 'sources' - - from sourceSets.main.allSource, sourceSets.test.allSource - exclude('**/*Test.java') - } - - javadoc.options { - encoding = 'UTF-8' - links 'https://docs.oracle.com/javase/8/docs/api/' - - if (JavaVersion.current().isJava8Compatible()) { - addStringOption('Xdoclint:all,-missing', '-quiet') - } - if (JavaVersion.current().isJava11Compatible()) { - addStringOption('-release', '8') - } - } - - // JavaDocV1 html - // ------- - task javadocJar(type: Jar) { - archiveClassifier = 'javadoc' - from javadoc - } - - // JavaDocV3 - docFX - // ------- - task javadocJarV3(type: Jar) { - archiveClassifier = 'javadoc' - from javadoc - } - - // Test jar - // -------- - - task testlibJar(type: Jar, dependsOn: test) { - archiveClassifier = 'testlib' - from sourceSets.test.output - - include('com/google/api/gax/rpc/testing/**') - include('com/google/api/gax/grpc/testing/**') - include('com/google/api/gax/httpjson/testing/**') - } - - // ShadowJar - // --------- - - shadowJar { - archiveClassifier = 'guavashaded' - relocate 'com.google.common', 'com.google.api.gax.repackaged.com.google.common' - relocate 'io.grpc.stub', 'com.google.api.gax.repackaged.io.grpc.stub' - relocate 'io.grpc.protobuf', 'com.google.api.gax.repackaged.io.grpc.protobuf' - configurations = [project.configurations.shadowNoGuava] - exclude('io/grpc/*') - exclude('io/grpc/internal/**') - exclude('io/grpc/inprocess/**') - exclude('io/grpc/util/**') - } - - // Test Logging - // ------------ - - test { - testLogging { - events 'passed', 'skipped', 'failed', 'standardOut', 'standardError' - exceptionFormat = 'full' - } - } - - // Eclipse annotation processing auto-setup - eclipse.synchronizationTasks eclipseJdtApt, eclipseJdt, eclipseFactorypath -} - -def normalReleasableProjects = subprojects.findAll { - !nonJavaProjects.contains(it.name) -} -configure(normalReleasableProjects) { - apply plugin: 'maven-publish' - apply plugin: 'signing' - - afterEvaluate { - publishing { - publications { - mavenJava(MavenPublication) { - version = project.version - - from components.java - - artifact javadocJar - artifact sourcesJar - artifact testlibJar - - pom { - name = 'GAX (Google Api eXtensions) for Java' - packaging = 'jar' - artifactId = project.name - description = 'Google Api eXtensions for Java' - url = 'https://github.com/googleapis/gax-java' - - scm { - url = 'https://github.com/googleapis/gax-java' - connection = 'scm:git:https://github.com/googleapis/gax-java.git' - } - - licenses { - license { - name = 'BSD' - url = 'https://github.com/googleapis/gax-java/blob/master/LICENSE' - } - } - - developers { - developer { - id = 'GoogleAPIs' - name = 'GoogleAPIs' - email = 'googleapis@googlegroups.com' - url = 'https://github.com/googleapis/gax-java' - organization = 'Google LLC' - organizationUrl = 'https://www.google.com' - } - } - } - } - } - repositories { - maven { - url 'https://google.oss.sonatype.org/service/local/staging/deploy/maven2/' - credentials { - username = findProperty('ossrhUsername') - password = findProperty('ossrhPassword') - } - } - } - } - } - - signing { - required { gradle.taskGraph.hasTask ":${name}:publishToSonatype" } - if (project.hasProperty('signing.gnupg.executable')) { - useGpgCmd() - } - sign publishing.publications - } -} - -javadoc.options { - encoding = 'UTF-8' - links 'https://docs.oracle.com/javase/7/docs/api/' -} - -// JavaDocV1 html -// ------- -task javadocCombined(type: Javadoc) { - source subprojects.collect {project -> project.sourceSets.main.allJava } - classpath = files(subprojects.collect {project -> project.sourceSets.main.compileClasspath}) - destinationDir = file('tmp_docs') -} - -// JavaDocV3 docFX -// ------- -task javadocCombinedV3(type: Javadoc) { - source subprojects.collect {project -> project.sourceSets.main.allJava } - classpath = files(subprojects.collect {project -> project.sourceSets.main.compileClasspath}) - destinationDir = file('tmp_docs/docfx-yml') - - options.addStringOption('encoding', 'UTF-8') - options.addStringOption('doclet', 'com.microsoft.doclet.DocFxDoclet') - options.addStringOption('projectname', 'gax') - options.docletpath = [file(System.getenv('KOKORO_GFILE_DIR') + '/java-docfx-doclet-1.5.0.jar')] - // Newer Gradle 6 passes -notimestamp by default, which the doclet above doesn't understand: - // https://github.com/gradle/gradle/issues/11898 - options.noTimestamp false -} - -clean { - delete 'tmp_docs/' -} - -sonarqube { - properties { - property 'sonar.projectKey', 'googleapis_gax-java' - property 'sonar.organization', 'googleapis' - property 'sonar.host.url', 'https://sonarcloud.io' - } -} diff --git a/dependabot.yml b/dependabot.yml deleted file mode 100644 index bd36675ae..000000000 --- a/dependabot.yml +++ /dev/null @@ -1,14 +0,0 @@ -version: 2 -updates: - - package-ecosystem: "maven" - directory: "/" - schedule: - interval: "daily" - # Disable version updates for Maven dependencies - open-pull-requests-limit: 0 - - package-ecosystem: "pip" - directory: "/" - schedule: - interval: "daily" - # Disable version updates for pip dependencies - open-pull-requests-limit: 0 diff --git a/dependencies.properties b/dependencies.properties deleted file mode 100644 index 46ff94871..000000000 --- a/dependencies.properties +++ /dev/null @@ -1,83 +0,0 @@ -# This file is shared between gradle and bazel build scripts and exists to keep the dependencies -# configuration between the two build systems in sync. - -# The properties format is the following: -# .= - -# Target workspace name: com_google_api_gax_java - -# Versions of oneself -# {x-version-update-start:gax:current} -version.gax=2.20.1 -# {x-version-update-end} -# {x-version-update-start:gax:current} -version.gax_grpc=2.20.1 -# {x-version-update-end} -# {x-version-update-start:gax:current} -version.gax_bom=2.20.1 -# {x-version-update-end} -# {x-version-update-start:gax-httpjson:current} -version.gax_httpjson=0.105.1 -# {x-version-update-end} - -# Versions for dependencies which actual artifacts differ between Bazel and Gradle. -# Gradle build depends on prebuilt maven artifacts, while Bazel build depends on Bazel workspaces -# with the sources. -version.com_google_protobuf=3.21.12 -version.google_java_format=1.15.0 -version.io_grpc=1.51.1 - -# Maven artifacts. -# Note, the actual name of each property matters (bazel build scripts depend on it). -# It should be constructed the following way: -# 1) Take full artifact id (including the group and classifier (if any) portions) and remove version portion. -# 2) Replace all characters which are neither alphabetic nor digits with the underscore ('_') character -maven.com_google_api_grpc_proto_google_common_protos=com.google.api.grpc:proto-google-common-protos:2.11.0 -maven.com_google_api_grpc_grpc_google_common_protos=com.google.api.grpc:grpc-google-common-protos:2.11.0 -maven.com_google_auth_google_auth_library_oauth2_http=com.google.auth:google-auth-library-oauth2-http:1.13.0 -maven.com_google_auth_google_auth_library_credentials=com.google.auth:google-auth-library-credentials:1.13.0 -maven.io_opencensus_opencensus_api=io.opencensus:opencensus-api:0.31.1 -maven.io_opencensus_opencensus_contrib_grpc_metrics=io.opencensus:opencensus-contrib-grpc-metrics:0.31.1 -maven.io_opencensus_opencensus_contrib_http_util=io.opencensus:opencensus-contrib-http-util:0.31.1 -maven.io_netty_netty_tcnative_boringssl_static=io.netty:netty-tcnative-boringssl-static:2.0.46.Final -maven.io_netty_netty_handler=io.netty:netty-handler:4.1.72.Final -maven.io_netty_netty_common=io.netty:netty-common:4.1.72.Final -maven.io_netty_netty_codec_socks=io.netty:netty-codec-socks:4.1.72.Final -maven.io_netty_netty_codec_http2=io.netty:netty-codec-http2:4.1.72.Final -maven.io_netty_netty_codec_http=io.netty:netty-codec-http:4.1.72.Final -maven.io_netty_netty_codec=io.netty:netty-codec:4.1.72.Final -maven.io_netty_netty_buffer=io.netty:netty-buffer:4.1.72.Final -maven.io_netty_netty_resolver=io.netty:netty-resolver:4.1.72.Final -maven.io_netty_netty_transport=io.netty:netty-transport:4.1.72.Final -maven.io_netty_netty_handler_proxy=io.netty:netty-handler-proxy:4.1.72.Final -maven.io_netty_netty_transport_native_unix_common=io.netty:netty-transport-native-unix-common:4.1.72.Final -maven.io_perfmark_perfmark_api=io.perfmark:perfmark-api:0.25.0 -maven.org_apache_tomcat_annotations_api=org.apache.tomcat:annotations-api:6.0.53 -maven.com_google_code_gson_gson=com.google.code.gson:gson:2.10 -maven.com_google_guava_guava=com.google.guava:guava:31.1-jre -maven.com_google_guava_failureaccess=com.google.guava:failureaccess:1.0.1 -maven.org_apache_commons_commons_lang3=org.apache.commons:commons-lang3:3.8.1 -maven.com_google_android_annotations=com.google.android:annotations:4.1.1.4 -maven.com_google_code_findbugs_jsr305=com.google.code.findbugs:jsr305:3.0.2 -maven.com_google_errorprone_error_prone_annotations=com.google.errorprone:error_prone_annotations:2.11.0 -maven.com_google_j2objc_j2objc_annotations=com.google.j2objc:j2objc-annotations:1.3 -maven.com_google_auto_value_auto_value=com.google.auto.value:auto-value:1.10.1 -maven.com_google_auto_value_auto_value_annotations=com.google.auto.value:auto-value-annotations:1.10.1 -maven.com_google_api_api_common=com.google.api:api-common:2.3.1 -maven.org_threeten_threetenbp=org.threeten:threetenbp:1.6.4 -maven.com_google_api_grpc_grpc_google_iam_v1=com.google.api.grpc:grpc-google-iam-v1:1.4.0 -maven.com_google_api_grpc_proto_google_iam_v1=com.google.api.grpc:proto-google-iam-v1:1.4.0 -maven.com_google_http_client_google_http_client=com.google.http-client:google-http-client:1.42.3 -maven.com_google_http_client_google_http_client_gson=com.google.http-client:google-http-client-gson:1.42.3 -maven.org_codehaus_mojo_animal_sniffer_annotations=org.codehaus.mojo:animal-sniffer-annotations:1.18 -maven.javax_annotation_javax_annotation_api=javax.annotation:javax.annotation-api:1.3.2 -maven.org_graalvm_sdk=org.graalvm.sdk:graal-sdk:22.3.0 - -# Testing maven artifacts -maven.junit_junit=junit:junit:4.13.2 -maven.org_mockito_mockito_core=org.mockito:mockito-core:2.28.2 -maven.org_hamcrest_hamcrest_core=org.hamcrest:hamcrest-core:1.3 -maven.com_google_truth_truth=com.google.truth:truth:1.1.2 -maven.com_googlecode_java_diff_utils_diffutils=com.googlecode.java-diff-utils:diffutils:1.3.0 -maven.net_bytebuddy_byte_buddy=net.bytebuddy:byte-buddy:1.9.7 -maven.org_objenesis_objenesis=org.objenesis:objenesis:2.6 diff --git a/gax-bom/BUILD.bazel b/gax-bom/BUILD.bazel deleted file mode 100644 index e69de29bb..000000000 diff --git a/gax-bom/build.gradle b/gax-bom/build.gradle deleted file mode 100644 index 6dfd30ff5..000000000 --- a/gax-bom/build.gradle +++ /dev/null @@ -1,81 +0,0 @@ -plugins { - id 'maven-publish' - id 'signing' -} - -archivesBaseName = 'gax-bom' - -project.version = "2.20.1" // {x-version-update:gax-bom:current} - -def mavenJavaDir = "$buildDir/publications/mavenJava" -def mavenJavaBomOutputFile = file(mavenJavaDir + '/pom-default.xml') -def mavenJavaBomAscOutputFile = file(mavenJavaDir + '/pom-default.xml.asc') - -// Copy our pom.xml to the location where a generated POM would go -task copyPom() { - doLast { - new File(mavenJavaDir).mkdirs() - copy { - from 'pom.xml' - into mavenJavaDir - rename 'pom.xml', 'pom-default.xml' - } - } -} - -// We want to use our own pom.xml instead of the generated one, so we disable -// the pom.xml generation and have the publish tasks depend on `copyPom` instead. -tasks.whenTaskAdded { task -> - if (task.name == 'generatePomFileForMavenJavaPublication') { - task.enabled = false - } else if (task.name == 'publishMavenJavaPublicationToMavenLocal') { - task.dependsOn copyPom - } else if (task.name == 'publishMavenJavaPublicationToMavenRepository') { - task.dependsOn copyPom - } else if (task.name == 'publishMavenJavaPublicationToSonatypeRepository') { - task.dependsOn copyPom - } -} - -// We can't use the `publishing` section from the main build.gradle because -// we don't want all the Java artifacts, and we want to use our own pom.xml -// instead of the generated one. -publishing { - publications { - mavenJava(MavenPublication) { - version = project.version - artifact mavenJavaBomOutputFile - } - } - repositories { - maven { - url 'https://google.oss.sonatype.org/service/local/staging/deploy/maven2/' - credentials { - username = findProperty('ossrhUsername') - password = findProperty('ossrhPassword') - } - } - } -} - -signing { - required { gradle.taskGraph.hasTask ":${name}:publishToSonatype" } - if (project.hasProperty('signing.gnupg.executable')) { - useGpgCmd() - } - sign publishing.publications -} - -// Unlike other regular subprojects, pom.asc (signature file) generated by -// signing is not automatically picked up. It may be because gax-bom uses a -// pre-written pom.xml instead of using an auto-generated one. -// https://discuss.gradle.org/t/how-to-publish-artifacts-signatures-asc-files-using-maven-publish-plugin/7422 -task addPomAscFileToPublication { - onlyIf { mavenJavaBomAscOutputFile.exists() } - doLast { - publishing.publications.mavenJava(MavenPublication) { - artifact(mavenJavaBomAscOutputFile) { extension 'pom.asc' } - } - } -} -signMavenJavaPublication.finalizedBy addPomAscFileToPublication diff --git a/gax-bom/pom.xml b/gax-bom/pom.xml deleted file mode 100644 index 1681cf4f9..000000000 --- a/gax-bom/pom.xml +++ /dev/null @@ -1,103 +0,0 @@ - - - 4.0.0 - com.google.api - gax-bom - 2.20.1 - pom - GAX (Google Api eXtensions) for Java (BOM) - Google Api eXtensions for Java (BOM) - - - com.google.cloud - google-cloud-shared-config - 1.5.5 - - - - - GoogleAPIs - GoogleAPIs - googleapis@googlegroups.com - https://github.com/googleapis/gax-java - Google, LLC - https://www.google.com - - - - - scm:git:https://github.com/googleapis/gax-java.git - https://github.com/googleapis/gax-java - - - - - BSD - https://github.com/googleapis/gax-java/blob/master/LICENSE - - - - - - - com.google.api - gax - 2.20.1 - - - com.google.api - gax - 2.20.1 - testlib - - - com.google.api - gax-grpc - 2.20.1 - - - com.google.api - gax-grpc - 2.20.1 - testlib - - - com.google.api - gax-httpjson - 0.105.1 - - - com.google.api - gax-httpjson - 0.105.1 - testlib - - - - - - - - org.apache.maven.plugins - maven-checkstyle-plugin - - true - - - - org.apache.maven.plugins - maven-jar-plugin - - - - test-jar - - - true - - - - - - - diff --git a/gax-grpc/BUILD.bazel b/gax-grpc/BUILD.bazel deleted file mode 100644 index f1dfe02fc..000000000 --- a/gax-grpc/BUILD.bazel +++ /dev/null @@ -1,89 +0,0 @@ -load("//:gax_java.bzl", "google_java_format", "google_java_format_verification", "java_tests") - -_JAVA_COPTS = [ - "-source", - "1.8", - "-target", - "1.8", -] - -_COMPILE_DEPS = [ - "@io_grpc_grpc_java//core:core", - "@io_grpc_grpc_java//stub:stub", - "@io_grpc_grpc_java//auth:auth", - "@io_grpc_grpc_java//protobuf:protobuf", - "@com_google_protobuf//:protobuf_java", - "@com_google_guava_guava//jar", - "@com_google_code_findbugs_jsr305//jar", - "@com_google_code_gson_gson//jar", - "@org_threeten_threetenbp//jar", - "@com_google_auth_google_auth_library_oauth2_http//jar", - "@com_google_auth_google_auth_library_credentials//jar", - "@com_google_api_grpc_proto_google_common_protos//jar", - "@com_google_api_api_common//jar", - "@com_google_auto_value_auto_value//jar", - "@com_google_auto_value_auto_value_annotations//jar", - "@com_google_http_client_google_http_client//jar", - "@io_grpc_grpc_java//context:context", - "@io_grpc_grpc_netty_shaded//jar", - "@io_grpc_grpc_grpclb//jar", - "@io_grpc_grpc_java//alts:alts", - "@io_netty_netty_tcnative_boringssl_static//jar", - "@javax_annotation_javax_annotation_api//jar", - "//gax:gax", - "@org_graalvm_sdk//jar" -] - -_TEST_COMPILE_DEPS = [ - "@junit_junit//jar", - "@org_mockito_mockito_core//jar", - "@com_google_truth_truth//jar", - "@io_grpc_grpc_java//core:inprocess", - "@com_google_api_grpc_grpc_google_common_protos//jar", - "//gax:gax_testlib", - "@com_googlecode_java_diff_utils_diffutils//jar", -] - -java_library( - name = "gax_grpc", - srcs = glob(["src/main/java/**/*.java"]), - javacopts = _JAVA_COPTS, - plugins = ["//:auto_value_plugin"], - resources = ["//:dependencies.properties"], - visibility = ["//visibility:public"], - deps = _COMPILE_DEPS, -) - -java_library( - name = "gax_grpc_testlib", - srcs = glob(["src/test/java/**/*.java"]), - javacopts = _JAVA_COPTS, - plugins = ["//:auto_value_plugin"], - visibility = ["//visibility:public"], - deps = [":gax_grpc"] + _COMPILE_DEPS + _TEST_COMPILE_DEPS, -) - -java_tests( - name = "gax_grpc_tests", - size = "small", - srcs = glob( - include = ["src/test/java/**/*Test.java"], - exclude = [ - "src/test/java/**/Abstract*Test.java", - ], - ), - runtime_deps = [":gax_grpc_testlib"], -) - -google_java_format( - name = "google_java_format", - srcs = glob(["src/**/*.java"]), - formatter = "//:google_java_format_binary", -) - -#Uncomment once java formatter is upgraded to 1.6+ -#google_java_format_verification( -# name = "google_java_format_verification", -# srcs = glob(["src/**/*.java"]), -# formatter = "//:google_java_format_binary", -#) diff --git a/gax-grpc/build.gradle b/gax-grpc/build.gradle deleted file mode 100644 index 5c5c86807..000000000 --- a/gax-grpc/build.gradle +++ /dev/null @@ -1,50 +0,0 @@ -archivesBaseName = 'gax-grpc' - -// TODO: Populate this from dependencies.properties version property (for proper Gradle-Bazel sync) -project.version = "2.20.1" // {x-version-update:gax-grpc:current} - -dependencies { - api(project(':gax'), - libraries['maven.com_google_api_api_common'], - libraries['maven.com_google_api_grpc_proto_google_common_protos'], - libraries['maven.com_google_auth_google_auth_library_credentials'], - libraries['maven.com_google_guava_guava'], - libraries['maven.io_grpc_grpc_api'], - libraries['maven.org_threeten_threetenbp']) - - implementation(libraries['maven.com_google_auth_google_auth_library_oauth2_http'], - libraries['maven.com_google_code_findbugs_jsr305'], - libraries['maven.io_grpc_grpc_alts'], - libraries['maven.io_grpc_grpc_auth'], - libraries['maven.io_grpc_grpc_netty_shaded'], - libraries['maven.io_grpc_grpc_protobuf'], - libraries['maven.io_grpc_grpc_stub']) - - runtimeOnly libraries['maven.io_grpc_grpc_googleapis'] - - compileOnly(libraries['maven.com_google_auto_value_auto_value'], - libraries['maven.org_graalvm_sdk']) - - testImplementation( project(':gax').sourceSets.test.output, - libraries['maven.junit_junit'], - libraries['maven.org_mockito_mockito_core'], - libraries['maven.com_google_truth_truth'], - libraries['maven.com_google_api_grpc_grpc_google_common_protos']) - - annotationProcessor libraries['maven.com_google_auto_value_auto_value'] - - shadowNoGuava libraries['maven.com_google_guava_guava'], - libraries['maven.io_grpc_grpc_stub'], - libraries['maven.io_grpc_grpc_protobuf'] -} - -jar { - manifest { - attributes 'Specification-Title': project.name, - 'Specification-Version': project.version, - 'Specification-Vendor': libraryVendor, - 'Implementation-Title': project.name, - 'Implementation-Version': project.version, - 'Implementation-Vendor': libraryVendor - } -} diff --git a/gax-grpc/pom.xml b/gax-grpc/pom.xml deleted file mode 100644 index ad7addccd..000000000 --- a/gax-grpc/pom.xml +++ /dev/null @@ -1,129 +0,0 @@ - - - 4.0.0 - - gax-grpc - 2.20.1 - jar - GAX (Google Api eXtensions) for Java (gRPC) - Google Api eXtensions for Java (gRPC) - - - com.google.api - gax-parent - 2.20.1 - - - - - com.google.api - gax - - - com.google.api - api-common - - - com.google.api.grpc - proto-google-common-protos - - - com.google.auth - google-auth-library-credentials - - - com.google.guava - guava - - - io.grpc - grpc-api - - - org.threeten - threetenbp - - - com.google.auth - google-auth-library-oauth2-http - - - io.grpc - grpc-alts - - - io.grpc - grpc-auth - - - io.grpc - grpc-protobuf - - - io.grpc - grpc-stub - - - io.grpc - grpc-netty-shaded - runtime - - - io.grpc - grpc-googleapis - runtime - - - com.google.code.findbugs - jsr305 - provided - - - org.graalvm.sdk - graal-sdk - provided - - - com.google.auto.value - auto-value-annotations - provided - - - - - com.google.api.grpc - grpc-google-common-protos - test - - - com.google.api - gax - test-jar - test - testlib - - - - - - - org.apache.maven.plugins - maven-jar-plugin - - - - test-jar - - - false - testlib - - com/google/api/gax/grpc/testing/** - - - - - - - - \ No newline at end of file diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/ApiStreamObserverDelegate.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/ApiStreamObserverDelegate.java deleted file mode 100644 index c19818751..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/ApiStreamObserverDelegate.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.gax.rpc.ApiStreamObserver; -import io.grpc.stub.StreamObserver; - -/** - * A delegate class that transfers calls to the ApiStreamObserver object. - * - *

Package-private for internal use. - */ -class ApiStreamObserverDelegate implements StreamObserver { - - private final ApiStreamObserver delegate; - - public ApiStreamObserverDelegate(ApiStreamObserver delegate) { - this.delegate = delegate; - } - - @Override - public void onNext(V v) { - delegate.onNext(v); - } - - @Override - public void onError(Throwable throwable) { - delegate.onError(throwable); - } - - @Override - public void onCompleted() { - delegate.onCompleted(); - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/CallOptionsUtil.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/CallOptionsUtil.java deleted file mode 100644 index f36da0d4d..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/CallOptionsUtil.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableMap; -import io.grpc.CallOptions; -import io.grpc.Metadata; -import io.grpc.Metadata.Key; -import java.util.Collections; -import java.util.Map; - -/** A utility class that provides helper functions to work with custom call options. */ -class CallOptionsUtil { - // this is a call option name, not a header name, it is not transferred over the wire - private static final CallOptions.Key, String>> DYNAMIC_HEADERS_CALL_OPTION_KEY = - CallOptions.Key.createWithDefault( - "gax_dynamic_headers", Collections., String>emptyMap()); - // this is the header name, it is transferred over the wire - static Metadata.Key REQUEST_PARAMS_HEADER_KEY = - Metadata.Key.of("x-goog-request-params", Metadata.ASCII_STRING_MARSHALLER); - private static final CallOptions.Key METADATA_HANDLER_CALL_OPTION_KEY = - CallOptions.Key.createWithDefault("gax_metadata_handler", null); - - private CallOptionsUtil() {} - - static CallOptions putRequestParamsDynamicHeaderOption( - CallOptions callOptions, String requestParams) { - if (callOptions == null || requestParams.isEmpty()) { - return callOptions; - } - - Map, String> dynamicHeadersOption = - callOptions.getOption(DYNAMIC_HEADERS_CALL_OPTION_KEY); - - // This will fail, if REQUEST_PARAMS_HEADER_KEY is already there - dynamicHeadersOption = - ImmutableMap., String>builder() - .putAll(dynamicHeadersOption) - .put(REQUEST_PARAMS_HEADER_KEY, requestParams) - .build(); - - return callOptions.withOption(DYNAMIC_HEADERS_CALL_OPTION_KEY, dynamicHeadersOption); - } - - static Map, String> getDynamicHeadersOption(CallOptions callOptions) { - return callOptions.getOption(DYNAMIC_HEADERS_CALL_OPTION_KEY); - } - - static CallOptions putMetadataHandlerOption( - CallOptions callOptions, ResponseMetadataHandler handler) { - Preconditions.checkNotNull(callOptions); - Preconditions.checkNotNull(handler); - return callOptions.withOption(METADATA_HANDLER_CALL_OPTION_KEY, handler); - } - - public static ResponseMetadataHandler getMetadataHandlerOption(CallOptions callOptions) { - return callOptions.getOption(METADATA_HANDLER_CALL_OPTION_KEY); - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/ChannelFactory.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/ChannelFactory.java deleted file mode 100644 index 416ce4469..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/ChannelFactory.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.core.InternalApi; -import io.grpc.ManagedChannel; -import java.io.IOException; - -/** - * This interface represents a factory for creating one ManagedChannel - * - *

This is public only for technical reasons, for advanced usage. - */ -@InternalApi("For internal use by google-cloud-java clients only") -public interface ChannelFactory { - ManagedChannel createSingleChannel() throws IOException; -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/ChannelPool.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/ChannelPool.java deleted file mode 100644 index 5215b4d9b..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/ChannelPool.java +++ /dev/null @@ -1,548 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.core.InternalApi; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableList; -import io.grpc.CallOptions; -import io.grpc.Channel; -import io.grpc.ClientCall; -import io.grpc.ForwardingClientCall.SimpleForwardingClientCall; -import io.grpc.ForwardingClientCallListener.SimpleForwardingClientCallListener; -import io.grpc.ManagedChannel; -import io.grpc.Metadata; -import io.grpc.MethodDescriptor; -import io.grpc.Status; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; -import java.util.logging.Level; -import java.util.logging.Logger; -import org.threeten.bp.Duration; - -/** - * A {@link ManagedChannel} that will send requests round-robin via a set of channels. - * - *

In addition to spreading requests over a set of child connections, the pool will also actively - * manage the lifecycle of the channels. Currently lifecycle management is limited to pre-emptively - * replacing channels every hour. In the future it will dynamically size the pool based on number of - * outstanding requests. - * - *

Package-private for internal use. - */ -class ChannelPool extends ManagedChannel { - private static final Logger LOG = Logger.getLogger(ChannelPool.class.getName()); - private static final Duration REFRESH_PERIOD = Duration.ofMinutes(50); - - private final ChannelPoolSettings settings; - private final ChannelFactory channelFactory; - private final ScheduledExecutorService executor; - - private final Object entryWriteLock = new Object(); - @VisibleForTesting final AtomicReference> entries = new AtomicReference<>(); - private final AtomicInteger indexTicker = new AtomicInteger(); - private final String authority; - - static ChannelPool create(ChannelPoolSettings settings, ChannelFactory channelFactory) - throws IOException { - return new ChannelPool(settings, channelFactory, Executors.newSingleThreadScheduledExecutor()); - } - - /** - * Initializes the channel pool. Assumes that all channels have the same authority. - * - * @param settings options for controling the ChannelPool sizing behavior - * @param channelFactory method to create the channels - * @param executor periodically refreshes the channels - */ - @VisibleForTesting - ChannelPool( - ChannelPoolSettings settings, - ChannelFactory channelFactory, - ScheduledExecutorService executor) - throws IOException { - this.settings = settings; - this.channelFactory = channelFactory; - - ImmutableList.Builder initialListBuilder = ImmutableList.builder(); - - for (int i = 0; i < settings.getInitialChannelCount(); i++) { - initialListBuilder.add(new Entry(channelFactory.createSingleChannel())); - } - - entries.set(initialListBuilder.build()); - authority = entries.get().get(0).channel.authority(); - this.executor = executor; - - if (!settings.isStaticSize()) { - executor.scheduleAtFixedRate( - this::resizeSafely, - ChannelPoolSettings.RESIZE_INTERVAL.getSeconds(), - ChannelPoolSettings.RESIZE_INTERVAL.getSeconds(), - TimeUnit.SECONDS); - } - if (settings.isPreemptiveRefreshEnabled()) { - executor.scheduleAtFixedRate( - this::refreshSafely, - REFRESH_PERIOD.getSeconds(), - REFRESH_PERIOD.getSeconds(), - TimeUnit.SECONDS); - } - } - - /** {@inheritDoc} */ - @Override - public String authority() { - return authority; - } - - /** - * Create a {@link ClientCall} on a Channel from the pool chosen in a round-robin fashion to the - * remote operation specified by the given {@link MethodDescriptor}. The returned {@link - * ClientCall} does not trigger any remote behavior until {@link - * ClientCall#start(ClientCall.Listener, io.grpc.Metadata)} is invoked. - */ - @Override - public ClientCall newCall( - MethodDescriptor methodDescriptor, CallOptions callOptions) { - return getChannel(indexTicker.getAndIncrement()).newCall(methodDescriptor, callOptions); - } - - Channel getChannel(int affinity) { - return new AffinityChannel(affinity); - } - - /** {@inheritDoc} */ - @Override - public ManagedChannel shutdown() { - List localEntries = entries.get(); - for (Entry entry : localEntries) { - entry.channel.shutdown(); - } - if (executor != null) { - // shutdownNow will cancel scheduled tasks - executor.shutdownNow(); - } - return this; - } - - /** {@inheritDoc} */ - @Override - public boolean isShutdown() { - List localEntries = entries.get(); - for (Entry entry : localEntries) { - if (!entry.channel.isShutdown()) { - return false; - } - } - return executor == null || executor.isShutdown(); - } - - /** {@inheritDoc} */ - @Override - public boolean isTerminated() { - List localEntries = entries.get(); - for (Entry entry : localEntries) { - if (!entry.channel.isTerminated()) { - return false; - } - } - - return executor == null || executor.isTerminated(); - } - - /** {@inheritDoc} */ - @Override - public ManagedChannel shutdownNow() { - List localEntries = entries.get(); - for (Entry entry : localEntries) { - entry.channel.shutdownNow(); - } - if (executor != null) { - executor.shutdownNow(); - } - return this; - } - - /** {@inheritDoc} */ - @Override - public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { - long endTimeNanos = System.nanoTime() + unit.toNanos(timeout); - List localEntries = entries.get(); - for (Entry entry : localEntries) { - long awaitTimeNanos = endTimeNanos - System.nanoTime(); - if (awaitTimeNanos <= 0) { - break; - } - entry.channel.awaitTermination(awaitTimeNanos, TimeUnit.NANOSECONDS); - } - if (executor != null) { - long awaitTimeNanos = endTimeNanos - System.nanoTime(); - executor.awaitTermination(awaitTimeNanos, TimeUnit.NANOSECONDS); - } - return isTerminated(); - } - - private void resizeSafely() { - try { - synchronized (entryWriteLock) { - resize(); - } - } catch (Exception e) { - LOG.log(Level.WARNING, "Failed to resize channel pool", e); - } - } - - /** - * Resize the number of channels based on the number of outstanding RPCs. - * - *

This method is expected to be called on a fixed interval. On every invocation it will: - * - *

    - *
  • Get the maximum number of outstanding RPCs since last invocation - *
  • Determine a valid range of number of channels to handle that many outstanding RPCs - *
  • If the current number of channel falls outside of that range, add or remove at most - * {@link ChannelPoolSettings#MAX_RESIZE_DELTA} to get closer to middle of that range. - *
- * - *

Not threadsafe, must be called under the entryWriteLock monitor - */ - @VisibleForTesting - void resize() { - List localEntries = entries.get(); - // Estimate the peak of RPCs in the last interval by summing the peak of RPCs per channel - int actualOutstandingRpcs = - localEntries.stream().mapToInt(Entry::getAndResetMaxOutstanding).sum(); - - // Number of channels if each channel operated at max capacity - int minChannels = - (int) Math.ceil(actualOutstandingRpcs / (double) settings.getMaxRpcsPerChannel()); - // Limit the threshold to absolute range - if (minChannels < settings.getMinChannelCount()) { - minChannels = settings.getMinChannelCount(); - } - - // Number of channels if each channel operated at minimum capacity - // Note: getMinRpcsPerChannel() can return 0, but division by 0 shouldn't cause a problem. - int maxChannels = - (int) Math.ceil(actualOutstandingRpcs / (double) settings.getMinRpcsPerChannel()); - // Limit the threshold to absolute range - if (maxChannels > settings.getMaxChannelCount()) { - maxChannels = settings.getMaxChannelCount(); - } - if (maxChannels < minChannels) { - maxChannels = minChannels; - } - - // If the pool were to be resized, try to aim for the middle of the bound, but limit rate of - // change. - int tentativeTarget = (maxChannels + minChannels) / 2; - int currentSize = localEntries.size(); - int delta = tentativeTarget - currentSize; - int dampenedTarget = tentativeTarget; - if (Math.abs(delta) > ChannelPoolSettings.MAX_RESIZE_DELTA) { - dampenedTarget = - currentSize + (int) Math.copySign(ChannelPoolSettings.MAX_RESIZE_DELTA, delta); - } - - // Only resize the pool when thresholds are crossed - if (localEntries.size() < minChannels) { - LOG.fine( - String.format( - "Detected throughput peak of %d, expanding channel pool size: %d -> %d.", - actualOutstandingRpcs, currentSize, dampenedTarget)); - - expand(dampenedTarget); - } else if (localEntries.size() > maxChannels) { - LOG.fine( - String.format( - "Detected throughput drop to %d, shrinking channel pool size: %d -> %d.", - actualOutstandingRpcs, currentSize, dampenedTarget)); - - shrink(dampenedTarget); - } - } - - /** Not threadsafe, must be called under the entryWriteLock monitor */ - private void shrink(int desiredSize) { - ImmutableList localEntries = entries.get(); - Preconditions.checkState( - localEntries.size() >= desiredSize, "current size is already smaller than the desired"); - - // Set the new list - entries.set(localEntries.subList(0, desiredSize)); - // clean up removed entries - List removed = localEntries.subList(desiredSize, localEntries.size()); - removed.forEach(Entry::requestShutdown); - } - - /** Not threadsafe, must be called under the entryWriteLock monitor */ - private void expand(int desiredSize) { - List localEntries = entries.get(); - Preconditions.checkState( - localEntries.size() <= desiredSize, "current size is already bigger than the desired"); - - ImmutableList.Builder newEntries = ImmutableList.builder().addAll(localEntries); - - for (int i = 0; i < desiredSize - localEntries.size(); i++) { - try { - newEntries.add(new Entry(channelFactory.createSingleChannel())); - } catch (IOException e) { - LOG.log(Level.WARNING, "Failed to add channel", e); - } - } - - entries.set(newEntries.build()); - } - - private void refreshSafely() { - try { - refresh(); - } catch (Exception e) { - LOG.log(Level.WARNING, "Failed to pre-emptively refresh channnels", e); - } - } - - /** - * Replace all of the channels in the channel pool with fresh ones. This is meant to mitigate the - * hourly GFE disconnects by giving clients the ability to prime the channel on reconnect. - * - *

This is done on a best effort basis. If the replacement channel fails to construct, the old - * channel will continue to be used. - */ - @InternalApi("Visible for testing") - void refresh() { - // Note: synchronization is necessary in case refresh is called concurrently: - // - thread1 fails to replace a single entry - // - thread2 succeeds replacing an entry - // - thread1 loses the race to replace the list - // - then thread2 will shut down channel that thread1 will put back into circulation (after it - // replaces the list) - synchronized (entryWriteLock) { - ArrayList newEntries = new ArrayList<>(entries.get()); - - for (int i = 0; i < newEntries.size(); i++) { - try { - newEntries.set(i, new Entry(channelFactory.createSingleChannel())); - } catch (IOException e) { - LOG.log(Level.WARNING, "Failed to refresh channel, leaving old channel", e); - } - } - - ImmutableList replacedEntries = entries.getAndSet(ImmutableList.copyOf(newEntries)); - - // Shutdown the channels that were cycled out. - for (Entry e : replacedEntries) { - if (!newEntries.contains(e)) { - e.requestShutdown(); - } - } - } - } - - /** - * Get and retain a Channel Entry. The returned Entry will have its rpc count incremented, - * preventing it from getting recycled. - */ - Entry getRetainedEntry(int affinity) { - // The maximum number of concurrent calls to this method for any given time span is at most 2, - // so the loop can actually be 2 times. But going for 5 times for a safety margin for potential - // code evolving - for (int i = 0; i < 5; i++) { - Entry entry = getEntry(affinity); - if (entry.retain()) { - return entry; - } - } - // It is unlikely to reach here unless the pool code evolves to increase the maximum possible - // concurrent calls to this method. If it does, this is a bug in the channel pool implementation - // the number of retries above should be greater than the number of contending maintenance - // tasks. - throw new IllegalStateException("Bug: failed to retain a channel"); - } - - /** - * Returns one of the channels managed by this pool. The pool continues to "own" the channel, and - * the caller should not shut it down. - * - * @param affinity Two calls to this method with the same affinity returns the same channel most - * of the time, if the channel pool was refreshed since the last call, a new channel will be - * returned. The reverse is not true: Two calls with different affinities might return the - * same channel. However, the implementation should attempt to spread load evenly. - */ - private Entry getEntry(int affinity) { - List localEntries = entries.get(); - - int index = Math.abs(affinity % localEntries.size()); - - return localEntries.get(index); - } - - /** Bundles a gRPC {@link ManagedChannel} with some usage accounting. */ - private static class Entry { - private final ManagedChannel channel; - private final AtomicInteger outstandingRpcs = new AtomicInteger(0); - private final AtomicInteger maxOutstanding = new AtomicInteger(); - - // Flag that the channel should be closed once all of the outstanding RPC complete. - private final AtomicBoolean shutdownRequested = new AtomicBoolean(); - // Flag that the channel has been closed. - private final AtomicBoolean shutdownInitiated = new AtomicBoolean(); - - private Entry(ManagedChannel channel) { - this.channel = channel; - } - - int getAndResetMaxOutstanding() { - return maxOutstanding.getAndSet(outstandingRpcs.get()); - } - - /** - * Try to increment the outstanding RPC count. The method will return false if the channel is - * closing and the caller should pick a different channel. If the method returned true, the - * channel has been successfully retained and it is the responsibility of the caller to release - * it. - */ - private boolean retain() { - // register desire to start RPC - int currentOutstanding = outstandingRpcs.incrementAndGet(); - - // Rough book keeping - int prevMax = maxOutstanding.get(); - if (currentOutstanding > prevMax) { - maxOutstanding.incrementAndGet(); - } - - // abort if the channel is closing - if (shutdownRequested.get()) { - release(); - return false; - } - return true; - } - - /** - * Notify the channel that the number of outstanding RPCs has decreased. If shutdown has been - * previously requested, this method will shutdown the channel if its the last outstanding RPC. - */ - private void release() { - int newCount = outstandingRpcs.decrementAndGet(); - if (newCount < 0) { - throw new IllegalStateException("Bug: reference count is negative!: " + newCount); - } - - // Must check outstandingRpcs after shutdownRequested (in reverse order of retain()) to ensure - // mutual exclusion. - if (shutdownRequested.get() && outstandingRpcs.get() == 0) { - shutdown(); - } - } - - /** - * Request a shutdown. The actual shutdown will be delayed until there are no more outstanding - * RPCs. - */ - private void requestShutdown() { - shutdownRequested.set(true); - if (outstandingRpcs.get() == 0) { - shutdown(); - } - } - - /** Ensure that shutdown is only called once. */ - private void shutdown() { - if (shutdownInitiated.compareAndSet(false, true)) { - channel.shutdown(); - } - } - } - - /** Thin wrapper to ensure that new calls are properly reference counted. */ - private class AffinityChannel extends Channel { - private final int affinity; - - public AffinityChannel(int affinity) { - this.affinity = affinity; - } - - @Override - public String authority() { - return authority; - } - - @Override - public ClientCall newCall( - MethodDescriptor methodDescriptor, CallOptions callOptions) { - - Entry entry = getRetainedEntry(affinity); - - return new ReleasingClientCall<>(entry.channel.newCall(methodDescriptor, callOptions), entry); - } - } - - /** ClientCall wrapper that makes sure to decrement the outstanding RPC count on completion. */ - static class ReleasingClientCall extends SimpleForwardingClientCall { - final Entry entry; - - public ReleasingClientCall(ClientCall delegate, Entry entry) { - super(delegate); - this.entry = entry; - } - - @Override - public void start(Listener responseListener, Metadata headers) { - try { - super.start( - new SimpleForwardingClientCallListener(responseListener) { - @Override - public void onClose(Status status, Metadata trailers) { - try { - super.onClose(status, trailers); - } finally { - entry.release(); - } - } - }, - headers); - } catch (Exception e) { - // In case start failed, make sure to release - entry.release(); - } - } - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/ChannelPoolSettings.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/ChannelPoolSettings.java deleted file mode 100644 index 19e62782a..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/ChannelPoolSettings.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.gax.grpc; - -import com.google.api.core.BetaApi; -import com.google.auto.value.AutoValue; -import com.google.common.base.Preconditions; -import java.time.Duration; - -/** - * Settings to control {@link ChannelPool} behavior. - * - *

To facilitate low latency/high throughout applications, gax provides a {@link ChannelPool}. - * The pool is meant to facilitate high throughput/low latency clients. By splitting load across - * multiple gRPC channels the client can spread load across multiple frontends and overcome gRPC's - * limit of 100 concurrent RPCs per channel. However oversizing the {@link ChannelPool} can lead to - * underutilized channels which will lead to high tail latency due to GFEs disconnecting idle - * channels. - * - *

The {@link ChannelPool} is designed to adapt to varying traffic patterns by tracking - * outstanding RPCs and resizing the pool size. This class configures the behavior. In general - * clients should aim to have less than 50 concurrent RPCs per channel and at least 1 outstanding - * per channel per minute. - * - *

The settings in this class will be applied every minute. - */ -@BetaApi("surface for channel pool sizing is not yet stable") -@AutoValue -public abstract class ChannelPoolSettings { - /** How often to check and possibly resize the {@link ChannelPool}. */ - static final Duration RESIZE_INTERVAL = Duration.ofMinutes(1); - /** The maximum number of channels that can be added or removed at a time. */ - static final int MAX_RESIZE_DELTA = 2; - - /** - * Threshold to start scaling down the channel pool. - * - *

When the average of the maximum number of outstanding RPCs in a single minute drop below - * this threshold, channels will be removed from the pool. - */ - public abstract int getMinRpcsPerChannel(); - - /** - * Threshold to start scaling up the channel pool. - * - *

When the average of the maximum number of outstanding RPCs in a single minute surpass this - * threshold, channels will be added to the pool. For google services, gRPC channels will start - * locally queuing RPC when there are 100 concurrent RPCs. - */ - public abstract int getMaxRpcsPerChannel(); - - /** - * The absolute minimum size of the channel pool. - * - *

Regardless of the current throughput, the number of channels will not drop below this limit - */ - public abstract int getMinChannelCount(); - - /** - * The absolute maximum size of the channel pool. - * - *

Regardless of the current throughput, the number of channels will not exceed this limit - */ - public abstract int getMaxChannelCount(); - - /** - * The initial size of the channel pool. - * - *

During client construction the client open this many connections. This will be scaled up or - * down in the next period. - */ - public abstract int getInitialChannelCount(); - - /** - * If all of the channels should be replaced on an hourly basis. - * - *

The GFE will forcibly disconnect active channels after an hour. To minimize the cost of - * reconnects, this will create a new channel asynchronuously, prime it and then swap it with an - * old channel. - */ - public abstract boolean isPreemptiveRefreshEnabled(); - - /** Helper to check if the {@link ChannelPool} implementation can skip dynamic size logic */ - boolean isStaticSize() { - // When range is restricted to a single size - if (getMinChannelCount() == getMaxChannelCount()) { - return true; - } - // When the scaling threshold are not set - if (getMinRpcsPerChannel() == 0 && getMaxRpcsPerChannel() == Integer.MAX_VALUE) { - return true; - } - - return false; - } - - public abstract Builder toBuilder(); - - public static ChannelPoolSettings staticallySized(int size) { - return builder() - .setInitialChannelCount(size) - .setMinRpcsPerChannel(0) - .setMaxRpcsPerChannel(Integer.MAX_VALUE) - .setMinChannelCount(size) - .setMaxChannelCount(size) - .build(); - } - - public static Builder builder() { - return new AutoValue_ChannelPoolSettings.Builder() - .setInitialChannelCount(1) - .setMinChannelCount(1) - .setMaxChannelCount(200) - .setMinRpcsPerChannel(0) - .setMaxRpcsPerChannel(Integer.MAX_VALUE) - .setPreemptiveRefreshEnabled(false); - } - - @AutoValue.Builder - public abstract static class Builder { - public abstract Builder setMinRpcsPerChannel(int count); - - public abstract Builder setMaxRpcsPerChannel(int count); - - public abstract Builder setMinChannelCount(int count); - - public abstract Builder setMaxChannelCount(int count); - - public abstract Builder setInitialChannelCount(int count); - - public abstract Builder setPreemptiveRefreshEnabled(boolean enabled); - - abstract ChannelPoolSettings autoBuild(); - - public ChannelPoolSettings build() { - ChannelPoolSettings s = autoBuild(); - - Preconditions.checkState( - s.getMinRpcsPerChannel() <= s.getMaxRpcsPerChannel(), "rpcsPerChannel range is invalid"); - Preconditions.checkState( - s.getMinChannelCount() > 0, "Minimum channel count must be at least 1"); - Preconditions.checkState( - s.getMinChannelCount() <= s.getMaxRpcsPerChannel(), "absolute channel range is invalid"); - Preconditions.checkState( - s.getMinChannelCount() <= s.getInitialChannelCount(), - "initial channel count be at least minChannelCount"); - Preconditions.checkState( - s.getInitialChannelCount() <= s.getMaxChannelCount(), - "initial channel count must be less than maxChannelCount"); - Preconditions.checkState( - s.getInitialChannelCount() > 0, "Initial channel count must be greater than 0"); - return s; - } - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/ChannelPrimer.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/ChannelPrimer.java deleted file mode 100644 index 5964de957..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/ChannelPrimer.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.core.InternalApi; -import io.grpc.ManagedChannel; - -/** - * An interface to prepare a ManagedChannel for normal requests by priming the channel - * - *

This is public only for technical reasons, for advanced usage. - */ -@InternalApi("For internal use by google-cloud-java clients only") -public interface ChannelPrimer { - void primeChannel(ManagedChannel managedChannel); -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/ExceptionResponseObserver.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/ExceptionResponseObserver.java deleted file mode 100644 index f9357f9d5..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/ExceptionResponseObserver.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.gax.rpc.ResponseObserver; -import com.google.api.gax.rpc.StateCheckingResponseObserver; -import com.google.api.gax.rpc.StreamController; -import java.util.concurrent.CancellationException; - -/** Package-private for internal use. */ -class ExceptionResponseObserver - extends StateCheckingResponseObserver { - private ResponseObserver innerObserver; - private volatile CancellationException cancellationException; - private final GrpcApiExceptionFactory exceptionFactory; - - public ExceptionResponseObserver( - ResponseObserver innerObserver, GrpcApiExceptionFactory exceptionFactory) { - this.innerObserver = innerObserver; - this.exceptionFactory = exceptionFactory; - } - - @Override - protected void onStartImpl(final StreamController controller) { - innerObserver.onStart( - new StreamController() { - @Override - public void cancel() { - cancellationException = new CancellationException("User cancelled stream"); - controller.cancel(); - } - - @Override - public void disableAutoInboundFlowControl() { - controller.disableAutoInboundFlowControl(); - } - - @Override - public void request(int count) { - controller.request(count); - } - }); - } - - @Override - protected void onResponseImpl(ResponseT response) { - innerObserver.onResponse(response); - } - - @Override - protected void onErrorImpl(Throwable t) { - if (cancellationException != null) { - t = cancellationException; - } else { - t = exceptionFactory.create(t); - } - innerObserver.onError(t); - } - - @Override - protected void onCompleteImpl() { - innerObserver.onComplete(); - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/GaxGrpcProperties.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/GaxGrpcProperties.java deleted file mode 100644 index e36665501..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/GaxGrpcProperties.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.core.InternalApi; -import com.google.api.gax.core.GaxProperties; -import io.grpc.Channel; -import java.util.regex.Pattern; - -/** Provides properties of the GAX-GRPC library. */ -@InternalApi -public class GaxGrpcProperties { - private static final String GAX_GRPC_VERSION = - GaxProperties.getLibraryVersion(GaxGrpcProperties.class, "version.gax_grpc"); - private static final String GRPC_VERSION = - GaxProperties.getLibraryVersion(Channel.class, "version.io_grpc"); - private static final Pattern DEFAULT_API_CLIENT_HEADER_PATTERN = - Pattern.compile("gl-java/.+ gapic/.* gax/.+ grpc/.+"); - - private GaxGrpcProperties() {} - - /** Returns the current version of gRPC */ - public static String getGrpcVersion() { - return GRPC_VERSION; - } - - public static String getGrpcTokenName() { - return "grpc"; - } - - public static String getGaxGrpcVersion() { - return GAX_GRPC_VERSION; - } - - /** Returns default api client header pattern (to facilitate testing) */ - public static Pattern getDefaultApiClientHeaderPattern() { - return DEFAULT_API_CLIENT_HEADER_PATTERN; - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcApiExceptionFactory.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcApiExceptionFactory.java deleted file mode 100644 index 9c3dd0a84..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcApiExceptionFactory.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.gax.rpc.ApiException; -import com.google.api.gax.rpc.ApiExceptionFactory; -import com.google.api.gax.rpc.ErrorDetails; -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.ImmutableSet; -import com.google.protobuf.InvalidProtocolBufferException; -import io.grpc.Metadata; -import io.grpc.Status; -import io.grpc.StatusException; -import io.grpc.StatusRuntimeException; -import java.util.Set; - -/** - * Core logic for transforming GRPC exceptions into {@link ApiException}s. This logic is shared - * amongst all the call types. - * - *

Package-private for internal use. - */ -class GrpcApiExceptionFactory { - - @VisibleForTesting static final String ERROR_DETAIL_KEY = "grpc-status-details-bin"; - private final ImmutableSet retryableCodes; - - GrpcApiExceptionFactory(Set retryCodes) { - this.retryableCodes = ImmutableSet.copyOf(retryCodes); - } - - ApiException create(Throwable throwable) { - if (throwable instanceof StatusException) { - StatusException e = (StatusException) throwable; - return create(throwable, e.getStatus().getCode(), e.getTrailers()); - } else if (throwable instanceof StatusRuntimeException) { - StatusRuntimeException e = (StatusRuntimeException) throwable; - return create(throwable, e.getStatus().getCode(), e.getTrailers()); - } else if (throwable instanceof ApiException) { - return (ApiException) throwable; - } else { - // Do not retry on unknown throwable, even when UNKNOWN is in retryableCodes - return ApiExceptionFactory.createException( - throwable, GrpcStatusCode.of(Status.Code.UNKNOWN), false); - } - } - - private ApiException create(Throwable throwable, Status.Code statusCode, Metadata metadata) { - boolean canRetry = retryableCodes.contains(GrpcStatusCode.grpcCodeToStatusCode(statusCode)); - GrpcStatusCode grpcStatusCode = GrpcStatusCode.of(statusCode); - - if (metadata == null) { - return ApiExceptionFactory.createException(throwable, grpcStatusCode, canRetry); - } - - byte[] bytes = metadata.get(Metadata.Key.of(ERROR_DETAIL_KEY, Metadata.BINARY_BYTE_MARSHALLER)); - if (bytes == null) { - return ApiExceptionFactory.createException(throwable, grpcStatusCode, canRetry); - } - - com.google.rpc.Status status; - try { - status = com.google.rpc.Status.parseFrom(bytes); - } catch (InvalidProtocolBufferException e) { - return ApiExceptionFactory.createException(throwable, grpcStatusCode, canRetry); - } - - ErrorDetails.Builder errorDetailsBuilder = ErrorDetails.builder(); - errorDetailsBuilder.setRawErrorMessages(status.getDetailsList()); - return ApiExceptionFactory.createException( - throwable, grpcStatusCode, canRetry, errorDetailsBuilder.build()); - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcCallContext.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcCallContext.java deleted file mode 100644 index 5f33c3644..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcCallContext.java +++ /dev/null @@ -1,580 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.core.BetaApi; -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.StatusCode; -import com.google.api.gax.rpc.TransportChannel; -import com.google.api.gax.rpc.internal.ApiCallContextOptions; -import com.google.api.gax.rpc.internal.Headers; -import com.google.api.gax.tracing.ApiTracer; -import com.google.api.gax.tracing.BaseApiTracer; -import com.google.auth.Credentials; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import io.grpc.CallCredentials; -import io.grpc.CallOptions; -import io.grpc.Channel; -import io.grpc.Deadline; -import io.grpc.Metadata; -import io.grpc.auth.MoreCallCredentials; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import org.threeten.bp.Duration; - -/** - * GrpcCallContext encapsulates context data used to make a grpc call. - * - *

GrpcCallContext is immutable in the sense that none of its methods modifies the - * GrpcCallContext itself or the underlying data. Methods of the form {@code withX}, such as {@link - * #withTransportChannel}, return copies of the object, but with one field changed. The immutability - * and thread safety of the arguments solely depends on the arguments themselves. - */ -@BetaApi("Reference ApiCallContext instead - this class is likely to experience breaking changes") -public final class GrpcCallContext implements ApiCallContext { - static final CallOptions.Key TRACER_KEY = CallOptions.Key.create("gax.tracer"); - - private final Channel channel; - private final CallOptions callOptions; - @Nullable private final Duration timeout; - @Nullable private final Duration streamWaitTimeout; - @Nullable private final Duration streamIdleTimeout; - @Nullable private final Integer channelAffinity; - @Nullable private final RetrySettings retrySettings; - @Nullable private final ImmutableSet retryableCodes; - private final ImmutableMap> extraHeaders; - private final ApiCallContextOptions options; - - /** Returns an empty instance with a null channel and default {@link CallOptions}. */ - public static GrpcCallContext createDefault() { - return new GrpcCallContext( - null, - CallOptions.DEFAULT, - null, - null, - null, - null, - ImmutableMap.>of(), - ApiCallContextOptions.getDefaultOptions(), - null, - null); - } - - /** Returns an instance with the given channel and {@link CallOptions}. */ - public static GrpcCallContext of(Channel channel, CallOptions callOptions) { - return new GrpcCallContext( - channel, - callOptions, - null, - null, - null, - null, - ImmutableMap.>of(), - ApiCallContextOptions.getDefaultOptions(), - null, - null); - } - - private GrpcCallContext( - Channel channel, - CallOptions callOptions, - @Nullable Duration timeout, - @Nullable Duration streamWaitTimeout, - @Nullable Duration streamIdleTimeout, - @Nullable Integer channelAffinity, - ImmutableMap> extraHeaders, - ApiCallContextOptions options, - @Nullable RetrySettings retrySettings, - @Nullable Set retryableCodes) { - this.channel = channel; - this.callOptions = Preconditions.checkNotNull(callOptions); - this.timeout = timeout; - this.streamWaitTimeout = streamWaitTimeout; - this.streamIdleTimeout = streamIdleTimeout; - this.channelAffinity = channelAffinity; - this.extraHeaders = Preconditions.checkNotNull(extraHeaders); - this.options = Preconditions.checkNotNull(options); - this.retrySettings = retrySettings; - this.retryableCodes = retryableCodes == null ? null : ImmutableSet.copyOf(retryableCodes); - } - - /** - * Returns inputContext cast to {@link GrpcCallContext}, or an empty {@link GrpcCallContext} if - * inputContext is null. - * - * @param inputContext the {@link ApiCallContext} to cast if it is not null - */ - @Override - public GrpcCallContext nullToSelf(ApiCallContext inputContext) { - GrpcCallContext grpcCallContext; - if (inputContext == null) { - grpcCallContext = this; - } else { - if (!(inputContext instanceof GrpcCallContext)) { - throw new IllegalArgumentException( - "context must be an instance of GrpcCallContext, but found " - + inputContext.getClass().getName()); - } - grpcCallContext = (GrpcCallContext) inputContext; - } - return grpcCallContext; - } - - @Override - public GrpcCallContext withCredentials(Credentials newCredentials) { - Preconditions.checkNotNull(newCredentials); - CallCredentials callCredentials = MoreCallCredentials.from(newCredentials); - return withCallOptions(callOptions.withCallCredentials(callCredentials)); - } - - @Override - public GrpcCallContext withTransportChannel(TransportChannel inputChannel) { - Preconditions.checkNotNull(inputChannel); - if (!(inputChannel instanceof GrpcTransportChannel)) { - throw new IllegalArgumentException( - "Expected GrpcTransportChannel, got " + inputChannel.getClass().getName()); - } - GrpcTransportChannel transportChannel = (GrpcTransportChannel) inputChannel; - return withChannel(transportChannel.getChannel()); - } - - @Override - public GrpcCallContext withTimeout(@Nullable Duration timeout) { - // Default RetrySettings use 0 for RPC timeout. Treat that as disabled timeouts. - if (timeout != null && (timeout.isZero() || timeout.isNegative())) { - timeout = null; - } - - // Prevent expanding timeouts - if (timeout != null && this.timeout != null && this.timeout.compareTo(timeout) <= 0) { - return this; - } - - return new GrpcCallContext( - channel, - callOptions, - timeout, - streamWaitTimeout, - streamIdleTimeout, - channelAffinity, - extraHeaders, - options, - retrySettings, - retryableCodes); - } - - @Nullable - @Override - public Duration getTimeout() { - return timeout; - } - - @Override - public GrpcCallContext withStreamWaitTimeout(@Nullable Duration streamWaitTimeout) { - if (streamWaitTimeout != null) { - Preconditions.checkArgument( - streamWaitTimeout.compareTo(Duration.ZERO) >= 0, "Invalid timeout: < 0 s"); - } - - return new GrpcCallContext( - channel, - callOptions, - timeout, - streamWaitTimeout, - streamIdleTimeout, - channelAffinity, - extraHeaders, - options, - retrySettings, - retryableCodes); - } - - @Override - public GrpcCallContext withStreamIdleTimeout(@Nullable Duration streamIdleTimeout) { - if (streamIdleTimeout != null) { - Preconditions.checkArgument( - streamIdleTimeout.compareTo(Duration.ZERO) >= 0, "Invalid timeout: < 0 s"); - } - - return new GrpcCallContext( - channel, - callOptions, - timeout, - streamWaitTimeout, - streamIdleTimeout, - channelAffinity, - extraHeaders, - options, - retrySettings, - retryableCodes); - } - - @BetaApi("The surface for channel affinity is not stable yet and may change in the future.") - public GrpcCallContext withChannelAffinity(@Nullable Integer affinity) { - return new GrpcCallContext( - channel, - callOptions, - timeout, - streamWaitTimeout, - streamIdleTimeout, - affinity, - extraHeaders, - options, - retrySettings, - retryableCodes); - } - - @BetaApi("The surface for extra headers is not stable yet and may change in the future.") - @Override - public GrpcCallContext withExtraHeaders(Map> extraHeaders) { - Preconditions.checkNotNull(extraHeaders); - ImmutableMap> newExtraHeaders = - Headers.mergeHeaders(this.extraHeaders, extraHeaders); - return new GrpcCallContext( - channel, - callOptions, - timeout, - streamWaitTimeout, - streamIdleTimeout, - channelAffinity, - newExtraHeaders, - options, - retrySettings, - retryableCodes); - } - - @Override - public RetrySettings getRetrySettings() { - return retrySettings; - } - - @Override - public GrpcCallContext withRetrySettings(RetrySettings retrySettings) { - return new GrpcCallContext( - channel, - callOptions, - timeout, - streamWaitTimeout, - streamIdleTimeout, - channelAffinity, - extraHeaders, - options, - retrySettings, - retryableCodes); - } - - @Override - public Set getRetryableCodes() { - return retryableCodes; - } - - @Override - public GrpcCallContext withRetryableCodes(Set retryableCodes) { - return new GrpcCallContext( - channel, - callOptions, - timeout, - streamWaitTimeout, - streamIdleTimeout, - channelAffinity, - extraHeaders, - options, - retrySettings, - retryableCodes); - } - - @Override - public ApiCallContext merge(ApiCallContext inputCallContext) { - if (inputCallContext == null) { - return this; - } - if (!(inputCallContext instanceof GrpcCallContext)) { - throw new IllegalArgumentException( - "context must be an instance of GrpcCallContext, but found " - + inputCallContext.getClass().getName()); - } - GrpcCallContext grpcCallContext = (GrpcCallContext) inputCallContext; - - Channel newChannel = grpcCallContext.channel; - if (newChannel == null) { - newChannel = channel; - } - - Deadline newDeadline = grpcCallContext.callOptions.getDeadline(); - if (newDeadline == null) { - newDeadline = callOptions.getDeadline(); - } - - CallCredentials newCallCredentials = grpcCallContext.callOptions.getCredentials(); - if (newCallCredentials == null) { - newCallCredentials = callOptions.getCredentials(); - } - - ApiTracer newTracer = grpcCallContext.callOptions.getOption(TRACER_KEY); - if (newTracer == null) { - newTracer = callOptions.getOption(TRACER_KEY); - } - - Duration newTimeout = grpcCallContext.timeout; - if (newTimeout == null) { - newTimeout = timeout; - } - - Duration newStreamWaitTimeout = grpcCallContext.streamWaitTimeout; - if (newStreamWaitTimeout == null) { - newStreamWaitTimeout = streamWaitTimeout; - } - - Duration newStreamIdleTimeout = grpcCallContext.streamIdleTimeout; - if (newStreamIdleTimeout == null) { - newStreamIdleTimeout = streamIdleTimeout; - } - - Integer newChannelAffinity = grpcCallContext.channelAffinity; - if (newChannelAffinity == null) { - newChannelAffinity = channelAffinity; - } - - RetrySettings newRetrySettings = grpcCallContext.retrySettings; - if (newRetrySettings == null) { - newRetrySettings = retrySettings; - } - - Set newRetryableCodes = grpcCallContext.retryableCodes; - if (newRetryableCodes == null) { - newRetryableCodes = retryableCodes; - } - - ImmutableMap> newExtraHeaders = - Headers.mergeHeaders(extraHeaders, grpcCallContext.extraHeaders); - - ApiCallContextOptions newOptions = options.merge(grpcCallContext.options); - - CallOptions newCallOptions = - grpcCallContext - .callOptions - .withCallCredentials(newCallCredentials) - .withDeadline(newDeadline); - - if (newTracer != null) { - newCallOptions = newCallOptions.withOption(TRACER_KEY, newTracer); - } - - return new GrpcCallContext( - newChannel, - newCallOptions, - newTimeout, - newStreamWaitTimeout, - newStreamIdleTimeout, - newChannelAffinity, - newExtraHeaders, - newOptions, - newRetrySettings, - newRetryableCodes); - } - - /** The {@link Channel} set on this context. */ - public Channel getChannel() { - return channel; - } - - /** The {@link CallOptions} set on this context. */ - public CallOptions getCallOptions() { - return callOptions; - } - - /** - * The stream wait timeout set for this context. - * - * @see ApiCallContext#withStreamWaitTimeout(Duration) - */ - @Override - @Nullable - public Duration getStreamWaitTimeout() { - return streamWaitTimeout; - } - - /** - * The stream idle timeout set for this context. - * - * @see ApiCallContext#withStreamIdleTimeout(Duration) - */ - @Override - @Nullable - public Duration getStreamIdleTimeout() { - return streamIdleTimeout; - } - - /** The channel affinity for this context. */ - @Nullable - public Integer getChannelAffinity() { - return channelAffinity; - } - - /** The extra header for this context. */ - @BetaApi("The surface for extra headers is not stable yet and may change in the future.") - @Override - public Map> getExtraHeaders() { - return extraHeaders; - } - - /** Returns a new instance with the channel set to the given channel. */ - public GrpcCallContext withChannel(Channel newChannel) { - return new GrpcCallContext( - newChannel, - callOptions, - timeout, - streamWaitTimeout, - streamIdleTimeout, - channelAffinity, - extraHeaders, - options, - retrySettings, - retryableCodes); - } - - /** Returns a new instance with the call options set to the given call options. */ - public GrpcCallContext withCallOptions(CallOptions newCallOptions) { - return new GrpcCallContext( - channel, - newCallOptions, - timeout, - streamWaitTimeout, - streamIdleTimeout, - channelAffinity, - extraHeaders, - options, - retrySettings, - retryableCodes); - } - - public GrpcCallContext withRequestParamsDynamicHeaderOption(String requestParams) { - CallOptions newCallOptions = - CallOptionsUtil.putRequestParamsDynamicHeaderOption(callOptions, requestParams); - - return withCallOptions(newCallOptions); - } - - /** {@inheritDoc} */ - @Override - @Nonnull - public ApiTracer getTracer() { - ApiTracer tracer = callOptions.getOption(TRACER_KEY); - if (tracer == null) { - tracer = BaseApiTracer.getInstance(); - } - return tracer; - } - - /** {@inheritDoc} */ - @Override - public GrpcCallContext withTracer(@Nonnull ApiTracer tracer) { - Preconditions.checkNotNull(tracer); - return withCallOptions(callOptions.withOption(TRACER_KEY, tracer)); - } - - /** {@inheritDoc} */ - @Override - public GrpcCallContext withOption(Key key, T value) { - ApiCallContextOptions newOptions = options.withOption(key, value); - return new GrpcCallContext( - channel, - callOptions, - timeout, - streamWaitTimeout, - streamIdleTimeout, - channelAffinity, - extraHeaders, - newOptions, - retrySettings, - retryableCodes); - } - - /** {@inheritDoc} */ - @Override - public T getOption(Key key) { - return options.getOption(key); - } - - @Override - public int hashCode() { - return Objects.hash( - channel, - callOptions, - timeout, - streamWaitTimeout, - streamIdleTimeout, - channelAffinity, - extraHeaders, - options, - retrySettings, - retryableCodes); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - GrpcCallContext that = (GrpcCallContext) o; - return Objects.equals(channel, that.channel) - && Objects.equals(callOptions, that.callOptions) - && Objects.equals(timeout, that.timeout) - && Objects.equals(streamWaitTimeout, that.streamWaitTimeout) - && Objects.equals(streamIdleTimeout, that.streamIdleTimeout) - && Objects.equals(channelAffinity, that.channelAffinity) - && Objects.equals(extraHeaders, that.extraHeaders) - && Objects.equals(options, that.options) - && Objects.equals(retrySettings, that.retrySettings) - && Objects.equals(retryableCodes, that.retryableCodes); - } - - Metadata getMetadata() { - Metadata metadata = new Metadata(); - for (Map.Entry> header : extraHeaders.entrySet()) { - String headerKey = header.getKey(); - for (String headerValue : header.getValue()) { - metadata.put(Metadata.Key.of(headerKey, Metadata.ASCII_STRING_MARSHALLER), headerValue); - } - } - return metadata; - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcCallSettings.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcCallSettings.java deleted file mode 100644 index a5aef3d69..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcCallSettings.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.core.BetaApi; -import com.google.api.gax.rpc.RequestParamsExtractor; -import io.grpc.MethodDescriptor; - -/** Grpc-specific settings for creating callables. */ -public class GrpcCallSettings { - private final MethodDescriptor methodDescriptor; - private final RequestParamsExtractor paramsExtractor; - private final boolean alwaysAwaitTrailers; - - private GrpcCallSettings(Builder builder) { - this.methodDescriptor = builder.methodDescriptor; - this.paramsExtractor = builder.paramsExtractor; - this.alwaysAwaitTrailers = builder.shouldAwaitTrailers; - } - - public MethodDescriptor getMethodDescriptor() { - return methodDescriptor; - } - - public RequestParamsExtractor getParamsExtractor() { - return paramsExtractor; - } - - @BetaApi - public boolean shouldAwaitTrailers() { - return alwaysAwaitTrailers; - } - - public static Builder newBuilder() { - return new Builder().setShouldAwaitTrailers(true); - } - - public static GrpcCallSettings create( - MethodDescriptor methodDescriptor) { - return GrpcCallSettings.newBuilder() - .setMethodDescriptor(methodDescriptor) - .build(); - } - - public Builder toBuilder() { - return new Builder<>(this); - } - - public static class Builder { - private MethodDescriptor methodDescriptor; - private RequestParamsExtractor paramsExtractor; - private boolean shouldAwaitTrailers; - - private Builder() {} - - private Builder(GrpcCallSettings settings) { - this.methodDescriptor = settings.methodDescriptor; - this.paramsExtractor = settings.paramsExtractor; - this.shouldAwaitTrailers = settings.alwaysAwaitTrailers; - } - - public Builder setMethodDescriptor( - MethodDescriptor methodDescriptor) { - this.methodDescriptor = methodDescriptor; - return this; - } - - public Builder setParamsExtractor( - RequestParamsExtractor paramsExtractor) { - this.paramsExtractor = paramsExtractor; - return this; - } - - @BetaApi - public Builder setShouldAwaitTrailers(boolean b) { - this.shouldAwaitTrailers = b; - return this; - } - - public GrpcCallSettings build() { - return new GrpcCallSettings<>(this); - } - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcCallableFactory.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcCallableFactory.java deleted file mode 100644 index 8a0c4e0b3..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcCallableFactory.java +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.core.InternalApi; -import com.google.api.gax.longrunning.OperationSnapshot; -import com.google.api.gax.rpc.BatchingCallSettings; -import com.google.api.gax.rpc.BidiStreamingCallable; -import com.google.api.gax.rpc.Callables; -import com.google.api.gax.rpc.ClientContext; -import com.google.api.gax.rpc.ClientStreamingCallable; -import com.google.api.gax.rpc.LongRunningClient; -import com.google.api.gax.rpc.OperationCallSettings; -import com.google.api.gax.rpc.OperationCallable; -import com.google.api.gax.rpc.PagedCallSettings; -import com.google.api.gax.rpc.ServerStreamingCallSettings; -import com.google.api.gax.rpc.ServerStreamingCallable; -import com.google.api.gax.rpc.StatusCode; -import com.google.api.gax.rpc.StreamingCallSettings; -import com.google.api.gax.rpc.UnaryCallSettings; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.api.gax.tracing.SpanName; -import com.google.api.gax.tracing.TracedBatchingCallable; -import com.google.api.gax.tracing.TracedBidiCallable; -import com.google.api.gax.tracing.TracedClientStreamingCallable; -import com.google.api.gax.tracing.TracedOperationCallable; -import com.google.api.gax.tracing.TracedOperationInitialCallable; -import com.google.api.gax.tracing.TracedServerStreamingCallable; -import com.google.api.gax.tracing.TracedUnaryCallable; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableSet; -import com.google.longrunning.Operation; -import com.google.longrunning.stub.OperationsStub; -import io.grpc.MethodDescriptor; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import javax.annotation.Nonnull; - -/** Class with utility methods to create grpc-based direct callables. */ -public class GrpcCallableFactory { - // Used to extract service and method name from a grpc MethodDescriptor. - private static final Pattern FULL_METHOD_NAME_REGEX = Pattern.compile("^.*?([^./]+)/([^./]+)$"); - - private GrpcCallableFactory() {} - - /** - * Create a Unary callable object with minimal grpc-specific functionality. - * - * @param grpcCallSettings the gRPC call settings - * @param callSettings the Unary call settings - * @param clientContext {@link ClientContext} to use to connect to the service. - */ - public static UnaryCallable createBaseUnaryCallable( - GrpcCallSettings grpcCallSettings, - UnaryCallSettings callSettings, - ClientContext clientContext) { - UnaryCallable callable = - GrpcRawCallableFactory.createUnaryCallable( - grpcCallSettings, callSettings.getRetryableCodes()); - - callable = Callables.retrying(callable, callSettings, clientContext); - - return callable; - } - - /** - * Create a callable object with grpc-specific functionality. Designed for use by generated code. - * - * @param grpcCallSettings the gRPC call settings - */ - public static UnaryCallable createUnaryCallable( - GrpcCallSettings grpcCallSettings, - UnaryCallSettings callSettings, - ClientContext clientContext) { - UnaryCallable callable = - createBaseUnaryCallable(grpcCallSettings, callSettings, clientContext); - - callable = - new TracedUnaryCallable<>( - callable, - clientContext.getTracerFactory(), - getSpanName(grpcCallSettings.getMethodDescriptor())); - - return callable.withDefaultCallContext(clientContext.getDefaultCallContext()); - } - - /** - * Create a paged callable object that represents a paged API method. Designed for use by - * generated code. - * - * @param grpcCallSettings the gRPC call settings - * @param pagedCallSettings {@link PagedCallSettings} to configure the paged settings with. - * @param clientContext {@link ClientContext} to use to connect to the service. - * @return {@link UnaryCallable} callable object. - */ - public static - UnaryCallable createPagedCallable( - GrpcCallSettings grpcCallSettings, - PagedCallSettings pagedCallSettings, - ClientContext clientContext) { - UnaryCallable innerCallable = - createBaseUnaryCallable(grpcCallSettings, pagedCallSettings, clientContext); - UnaryCallable pagedCallable = - Callables.paged(innerCallable, pagedCallSettings); - return pagedCallable.withDefaultCallContext(clientContext.getDefaultCallContext()); - } - - /** - * Create a callable object that represents a batching API method. Designed for use by generated - * code. - * - * @param grpcCallSettings the gRPC call settings - * @param batchingCallSettings {@link BatchingCallSettings} to configure the batching related - * settings with. - * @param clientContext {@link ClientContext} to use to connect to the service. - * @return {@link UnaryCallable} callable object. - */ - public static UnaryCallable createBatchingCallable( - GrpcCallSettings grpcCallSettings, - BatchingCallSettings batchingCallSettings, - ClientContext clientContext) { - UnaryCallable baseCallable = - createBaseUnaryCallable(grpcCallSettings, batchingCallSettings, clientContext); - - // NOTE: Since batching happens asynchronously and the outermost callable simply buffers the - // request. Tracing will only start on the inner callable that accepts the batch. - UnaryCallable tracedCallable = - new TracedBatchingCallable<>( - baseCallable, - clientContext.getTracerFactory(), - getSpanName(grpcCallSettings.getMethodDescriptor()), - batchingCallSettings.getBatchingDescriptor()); - - UnaryCallable batchingCallable = - Callables.batching(tracedCallable, batchingCallSettings, clientContext); - return batchingCallable.withDefaultCallContext(clientContext.getDefaultCallContext()); - } - - /** - * Creates a callable object that represents a long-running operation. Designed for use by - * generated code. - * - * @param grpcCallSettings the gRPC call settings - * @param operationCallSettings {@link OperationCallSettings} to configure the method-level - * settings with. - * @param clientContext {@link ClientContext} to use to connect to the service. - * @param operationsStub {@link OperationsStub} to use to poll for updates on the Operation. - * @return {@link com.google.api.gax.rpc.OperationCallable} callable object. - */ - public static - OperationCallable createOperationCallable( - GrpcCallSettings grpcCallSettings, - OperationCallSettings operationCallSettings, - ClientContext clientContext, - OperationsStub operationsStub) { - - SpanName initialSpanName = getSpanName(grpcCallSettings.getMethodDescriptor()); - SpanName operationSpanName = - SpanName.of(initialSpanName.getClientName(), initialSpanName.getMethodName() + "Operation"); - - UnaryCallable initialGrpcCallable = - createBaseUnaryCallable( - grpcCallSettings, operationCallSettings.getInitialCallSettings(), clientContext); - UnaryCallable initialCallable = - new GrpcOperationSnapshotCallable<>(initialGrpcCallable); - - // Create a sub-trace for the initial RPC that starts the operation. - UnaryCallable tracedInitialCallable = - new TracedOperationInitialCallable<>( - initialCallable, clientContext.getTracerFactory(), initialSpanName); - - LongRunningClient longRunningClient = new GrpcLongRunningClient(operationsStub); - OperationCallable operationCallable = - Callables.longRunningOperation( - tracedInitialCallable, operationCallSettings, clientContext, longRunningClient); - - OperationCallable tracedOperationCallable = - new TracedOperationCallable<>( - operationCallable, clientContext.getTracerFactory(), operationSpanName); - - return tracedOperationCallable.withDefaultCallContext(clientContext.getDefaultCallContext()); - } - - /** - * Create a bidirectional streaming callable object with grpc-specific functionality. Designed for - * use by generated code. - * - * @param grpcCallSettings the gRPC call settings - * @param streamingCallSettings {@link StreamingCallSettings} to configure the method-level - * settings with. - * @param clientContext {@link ClientContext} to use to connect to the service. - * @return {@link BidiStreamingCallable} callable object. - */ - public static - BidiStreamingCallable createBidiStreamingCallable( - GrpcCallSettings grpcCallSettings, - StreamingCallSettings streamingCallSettings, - ClientContext clientContext) { - BidiStreamingCallable callable = - GrpcRawCallableFactory.createBidiStreamingCallable( - grpcCallSettings, ImmutableSet.of()); - - callable = - new TracedBidiCallable<>( - callable, - clientContext.getTracerFactory(), - getSpanName(grpcCallSettings.getMethodDescriptor())); - - return callable.withDefaultCallContext(clientContext.getDefaultCallContext()); - } - - /** - * Create a server-streaming callable with grpc-specific functionality. Designed for use by - * generated code. - * - * @param grpcCallSettings the gRPC call settings - * @param streamingCallSettings {@link StreamingCallSettings} to configure the method-level - * settings with. - * @param clientContext {@link ClientContext} to use to connect to the service. - * @deprecated Please use ServerStreamingCallSettings - */ - @Deprecated - public static - ServerStreamingCallable createServerStreamingCallable( - GrpcCallSettings grpcCallSettings, - StreamingCallSettings streamingCallSettings, - ClientContext clientContext) { - - // up convert to new settings - ServerStreamingCallSettings serverStreamingCallSettings = - ServerStreamingCallSettings.newBuilder().build(); - - return createServerStreamingCallable( - grpcCallSettings, serverStreamingCallSettings, clientContext); - } - - /** - * Create a server-streaming callable with grpc-specific functionality. Designed for use by - * generated code. - * - * @param grpcCallSettings the gRPC call settings - * @param streamingCallSettings {@link StreamingCallSettings} to configure the method-level - * settings with. - * @param clientContext {@link ClientContext} to use to connect to the service. - */ - public static - ServerStreamingCallable createServerStreamingCallable( - GrpcCallSettings grpcCallSettings, - ServerStreamingCallSettings streamingCallSettings, - ClientContext clientContext) { - ServerStreamingCallable callable = - GrpcRawCallableFactory.createServerStreamingCallable( - grpcCallSettings, streamingCallSettings.getRetryableCodes()); - - if (clientContext.getStreamWatchdog() != null) { - callable = Callables.watched(callable, streamingCallSettings, clientContext); - } - - callable = Callables.retrying(callable, streamingCallSettings, clientContext); - - callable = - new TracedServerStreamingCallable<>( - callable, - clientContext.getTracerFactory(), - getSpanName(grpcCallSettings.getMethodDescriptor())); - - return callable.withDefaultCallContext(clientContext.getDefaultCallContext()); - } - - /** - * Create a client-streaming callable object with grpc-specific functionality. Designed for use by - * generated code. - * - * @param grpcCallSettings the gRPC call settings - * @param streamingCallSettings {@link StreamingCallSettings} to configure the method-level - * settings with. - * @param clientContext {@link ClientContext} to use to connect to the service. - * @return {@link ClientStreamingCallable} callable object. - */ - public static - ClientStreamingCallable createClientStreamingCallable( - GrpcCallSettings grpcCallSettings, - StreamingCallSettings streamingCallSettings, - ClientContext clientContext) { - ClientStreamingCallable callable = - GrpcRawCallableFactory.createClientStreamingCallable( - grpcCallSettings, ImmutableSet.of()); - - callable = - new TracedClientStreamingCallable<>( - callable, - clientContext.getTracerFactory(), - getSpanName(grpcCallSettings.getMethodDescriptor())); - - return callable.withDefaultCallContext(clientContext.getDefaultCallContext()); - } - - @InternalApi("Visible for testing") - static SpanName getSpanName(@Nonnull MethodDescriptor methodDescriptor) { - Matcher matcher = FULL_METHOD_NAME_REGEX.matcher(methodDescriptor.getFullMethodName()); - - Preconditions.checkArgument(matcher.matches(), "Invalid fullMethodName"); - return SpanName.of(matcher.group(1), matcher.group(2)); - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcChannelUUIDInterceptor.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcChannelUUIDInterceptor.java deleted file mode 100644 index ac450689e..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcChannelUUIDInterceptor.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.gax.tracing.ApiTracer; -import io.grpc.CallOptions; -import io.grpc.Channel; -import io.grpc.ClientCall; -import io.grpc.ClientInterceptor; -import io.grpc.MethodDescriptor; -import java.util.UUID; - -class GrpcChannelUUIDInterceptor implements ClientInterceptor { - private final String uuid = UUID.randomUUID().toString(); - - @Override - public ClientCall interceptCall( - MethodDescriptor methodDescriptor, CallOptions callOptions, Channel channel) { - - ApiTracer apiTracer = callOptions.getOption(GrpcCallContext.TRACER_KEY); - if (apiTracer != null) { - apiTracer.connectionSelected(uuid); - } - - return channel.newCall(methodDescriptor, callOptions); - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcClientCalls.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcClientCalls.java deleted file mode 100644 index bc72f6f1f..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcClientCalls.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.client.util.Preconditions; -import com.google.api.core.AbstractApiFuture; -import com.google.api.core.ApiFuture; -import com.google.api.core.BetaApi; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.tracing.ApiTracer.Scope; -import io.grpc.CallOptions; -import io.grpc.Channel; -import io.grpc.ClientCall; -import io.grpc.ClientInterceptor; -import io.grpc.ClientInterceptors; -import io.grpc.Deadline; -import io.grpc.Metadata; -import io.grpc.MethodDescriptor; -import io.grpc.Status; -import io.grpc.stub.MetadataUtils; -import java.util.concurrent.TimeUnit; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * {@code GrpcClientCalls} creates a new {@code ClientCall} from the given call context. - * - *

Package-private for internal use. - */ -class GrpcClientCalls { - private static final Logger LOGGER = Logger.getLogger(GrpcDirectCallable.class.getName()); - - private GrpcClientCalls() {}; - - public static ClientCall newCall( - MethodDescriptor descriptor, ApiCallContext context) { - if (!(context instanceof GrpcCallContext)) { - throw new IllegalArgumentException( - "context must be an instance of GrpcCallContext, but found " - + context.getClass().getName()); - } - - GrpcCallContext grpcContext = (GrpcCallContext) context; - Preconditions.checkNotNull(grpcContext.getChannel()); - - CallOptions callOptions = grpcContext.getCallOptions(); - Preconditions.checkNotNull(callOptions); - - // Try to convert the timeout into a deadline and use it if it occurs before the actual deadline - if (grpcContext.getTimeout() != null) { - Deadline newDeadline = - Deadline.after(grpcContext.getTimeout().toMillis(), TimeUnit.MILLISECONDS); - Deadline oldDeadline = callOptions.getDeadline(); - - if (oldDeadline == null || newDeadline.isBefore(oldDeadline)) { - callOptions = callOptions.withDeadline(newDeadline); - } - } - - Channel channel = grpcContext.getChannel(); - if (grpcContext.getChannelAffinity() != null && channel instanceof ChannelPool) { - channel = ((ChannelPool) channel).getChannel(grpcContext.getChannelAffinity()); - } - - if (!grpcContext.getExtraHeaders().isEmpty()) { - ClientInterceptor interceptor = - MetadataUtils.newAttachHeadersInterceptor(grpcContext.getMetadata()); - channel = ClientInterceptors.intercept(channel, interceptor); - } - - try (Scope ignored = grpcContext.getTracer().inScope()) { - return channel.newCall(descriptor, callOptions); - } - } - - /** - * A work-alike of {@link io.grpc.stub.ClientCalls#futureUnaryCall(ClientCall, Object)}. - * - *

The only difference is that unlike grpc-stub's implementation. This implementation doesn't - * wait for trailers to resolve a unary RPC. This can save milliseconds when the server is - * overloaded. - */ - @BetaApi - static ApiFuture eagerFutureUnaryCall( - ClientCall clientCall, RequestT request) { - // Start the call - GrpcFuture future = new GrpcFuture<>(clientCall); - clientCall.start(new EagerFutureListener<>(future), new Metadata()); - - // Send the request - try { - clientCall.sendMessage(request); - clientCall.halfClose(); - // Request an extra message to detect misconfigured servers - clientCall.request(2); - } catch (Throwable sendError) { - // Cancel if anything goes wrong - try { - clientCall.cancel(null, sendError); - } catch (Throwable cancelError) { - LOGGER.log(Level.SEVERE, "Error encountered while closing it", sendError); - } - - throw sendError; - } - - return future; - } - - /** Thin wrapper around an ApiFuture that will cancel the underlying ClientCall. */ - private static class GrpcFuture extends AbstractApiFuture { - private final ClientCall call; - - private GrpcFuture(ClientCall call) { - this.call = call; - } - - @Override - protected void interruptTask() { - call.cancel("GrpcFuture was cancelled", null); - } - - @Override - public boolean set(T value) { - return super.set(value); - } - - @Override - public boolean setException(Throwable throwable) { - return super.setException(throwable); - } - } - - /** - * A bridge between gRPC's ClientCall.Listener to an ApiFuture. - * - *

The Listener will eagerly resolve the future when the first message is received and will not - * wait for the trailers. This should cut down on the latency at the expense of safety. If the - * server is misconfigured and sends a second response for a unary call, the error will be logged, - * but the future will still be successful. - */ - private static class EagerFutureListener extends ClientCall.Listener { - private final GrpcFuture future; - - private EagerFutureListener(GrpcFuture future) { - this.future = future; - } - - @Override - public void onMessage(T message) { - if (!future.set(message)) { - throw Status.INTERNAL - .withDescription("More than one value received for unary call") - .asRuntimeException(); - } - } - - @Override - public void onClose(Status status, Metadata trailers) { - if (!future.isDone()) { - future.setException( - Status.INTERNAL - .withDescription("No value received for unary call") - .asException(trailers)); - } - if (!status.isOk()) { - LOGGER.log( - Level.WARNING, "Received error for unary call after receiving a successful response"); - } - } - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcDirectBidiStreamingCallable.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcDirectBidiStreamingCallable.java deleted file mode 100644 index 178044dc9..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcDirectBidiStreamingCallable.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.BidiStreamingCallable; -import com.google.api.gax.rpc.ClientStream; -import com.google.api.gax.rpc.ClientStreamReadyObserver; -import com.google.api.gax.rpc.ResponseObserver; -import com.google.common.base.Preconditions; -import io.grpc.ClientCall; -import io.grpc.MethodDescriptor; - -/** - * {@code GrpcDirectBidiStreamingCallable} creates bidirectional streaming gRPC calls. - * - *

It is used to bridge the abstractions provided by gRPC and GAX. - * - *

Package-private for internal use. - */ -class GrpcDirectBidiStreamingCallable - extends BidiStreamingCallable { - private final MethodDescriptor descriptor; - - GrpcDirectBidiStreamingCallable(MethodDescriptor descriptor) { - this.descriptor = Preconditions.checkNotNull(descriptor); - } - - @Override - public ClientStream internalCall( - ResponseObserver responseObserver, - final ClientStreamReadyObserver onReady, - ApiCallContext context) { - Preconditions.checkNotNull(responseObserver); - final ClientCall call = GrpcClientCalls.newCall(descriptor, context); - final ClientStream clientStream = - new ClientStream() { - @Override - public void send(RequestT request) { - call.sendMessage(request); - } - - @Override - public void closeSendWithError(Throwable t) { - call.cancel(null, t); - } - - @Override - public void closeSend() { - call.halfClose(); - } - - @Override - public boolean isSendReady() { - return call.isReady(); - } - }; - - GrpcDirectStreamController controller = - new GrpcDirectStreamController<>( - call, - responseObserver, - new Runnable() { - @Override - public void run() { - onReady.onReady(clientStream); - } - }); - controller.startBidi(); - - return clientStream; - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcDirectCallable.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcDirectCallable.java deleted file mode 100644 index 5b6a5f1ba..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcDirectCallable.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.core.ApiFuture; -import com.google.api.core.ListenableFutureToApiFuture; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.common.base.Preconditions; -import io.grpc.ClientCall; -import io.grpc.MethodDescriptor; -import io.grpc.stub.ClientCalls; - -/** - * {@code GrpcDirectCallable} creates gRPC calls. - * - *

Package-private for internal use. - */ -class GrpcDirectCallable extends UnaryCallable { - private final MethodDescriptor descriptor; - private final boolean awaitTrailers; - - GrpcDirectCallable(MethodDescriptor descriptor, boolean awaitTrailers) { - this.descriptor = Preconditions.checkNotNull(descriptor); - this.awaitTrailers = awaitTrailers; - } - - @Override - public ApiFuture futureCall(RequestT request, ApiCallContext inputContext) { - Preconditions.checkNotNull(request); - Preconditions.checkNotNull(inputContext); - - ClientCall clientCall = GrpcClientCalls.newCall(descriptor, inputContext); - - if (awaitTrailers) { - return new ListenableFutureToApiFuture<>(ClientCalls.futureUnaryCall(clientCall, request)); - } else { - return GrpcClientCalls.eagerFutureUnaryCall(clientCall, request); - } - } - - @Override - public String toString() { - return String.format("direct(%s)", descriptor); - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcDirectClientStreamingCallable.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcDirectClientStreamingCallable.java deleted file mode 100644 index 93c1a9562..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcDirectClientStreamingCallable.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.ApiStreamObserver; -import com.google.api.gax.rpc.ClientStreamingCallable; -import com.google.common.base.Preconditions; -import io.grpc.ClientCall; -import io.grpc.MethodDescriptor; -import io.grpc.stub.ClientCalls; - -/** - * {@code GrpcDirectClientStreamingCallable} creates client-streaming gRPC calls. - * - *

It is used to bridge the abstractions provided by gRPC and GAX. - * - *

Package-private for internal use. - */ -class GrpcDirectClientStreamingCallable - extends ClientStreamingCallable { - private final MethodDescriptor descriptor; - - GrpcDirectClientStreamingCallable(MethodDescriptor descriptor) { - this.descriptor = Preconditions.checkNotNull(descriptor); - } - - @Override - public ApiStreamObserver clientStreamingCall( - ApiStreamObserver responseObserver, ApiCallContext context) { - Preconditions.checkNotNull(responseObserver); - ClientCall call = GrpcClientCalls.newCall(descriptor, context); - return new StreamObserverDelegate<>( - ClientCalls.asyncClientStreamingCall( - call, new ApiStreamObserverDelegate<>(responseObserver))); - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcDirectServerStreamingCallable.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcDirectServerStreamingCallable.java deleted file mode 100644 index 2b562f07a..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcDirectServerStreamingCallable.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.ResponseObserver; -import com.google.api.gax.rpc.ServerStreamingCallable; -import com.google.api.gax.rpc.StreamController; -import com.google.common.base.Preconditions; -import io.grpc.ClientCall; -import io.grpc.MethodDescriptor; - -/** - * {@code GrpcDirectServerStreamingCallable} creates server-streaming gRPC calls. - * - *

In a chain of {@link ServerStreamingCallable}s this is the innermost callable. It wraps a - * {@link ClientCall} in a {@link StreamController} and the downstream {@link ResponseObserver} in a - * {@link ClientCall.Listener}. This forms a bidirectional bridge between gax & grpc. This is - * implemented on top of {@link ClientCall.Listener} because {@link - * io.grpc.stub.ClientResponseObserver} is currently marked as {@link io.grpc.ExperimentalApi}. - * - *

Package-private for internal use. - */ -class GrpcDirectServerStreamingCallable - extends ServerStreamingCallable { - private final MethodDescriptor descriptor; - - GrpcDirectServerStreamingCallable(MethodDescriptor descriptor) { - this.descriptor = Preconditions.checkNotNull(descriptor); - } - - @Override - public void call( - RequestT request, ResponseObserver responseObserver, ApiCallContext context) { - Preconditions.checkNotNull(request); - Preconditions.checkNotNull(responseObserver); - - ClientCall call = GrpcClientCalls.newCall(descriptor, context); - GrpcDirectStreamController controller = - new GrpcDirectStreamController<>(call, responseObserver); - controller.start(request); - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcDirectStreamController.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcDirectStreamController.java deleted file mode 100644 index e7b52b808..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcDirectStreamController.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.gax.rpc.ResponseObserver; -import com.google.api.gax.rpc.StreamController; -import com.google.common.base.Preconditions; -import io.grpc.ClientCall; -import io.grpc.Metadata; -import io.grpc.Status; -import java.util.concurrent.CancellationException; - -/** - * Wraps a GRPC ClientCall in a {@link StreamController}. It feeds events to a {@link - * ResponseObserver} and allows for back pressure. - * - *

Package-private for internal use. - */ -class GrpcDirectStreamController implements StreamController { - private static final Runnable NOOP_RUNNABLE = - new Runnable() { - @Override - public void run() {} - }; - - private final ClientCall clientCall; - private final ResponseObserver responseObserver; - private final Runnable onReady; - private boolean hasStarted; - private boolean autoflowControl = true; - private int numRequested; - private volatile CancellationException cancellationException; - - GrpcDirectStreamController( - ClientCall clientCall, ResponseObserver responseObserver) { - this(clientCall, responseObserver, NOOP_RUNNABLE); - } - - GrpcDirectStreamController( - ClientCall clientCall, - ResponseObserver responseObserver, - Runnable onReady) { - this.clientCall = clientCall; - this.responseObserver = responseObserver; - this.onReady = onReady; - } - - @Override - public void cancel() { - cancellationException = new CancellationException("User cancelled stream"); - clientCall.cancel(null, cancellationException); - } - - @Override - public void disableAutoInboundFlowControl() { - Preconditions.checkState( - !hasStarted, "Can't disable automatic flow control after the stream has started."); - autoflowControl = false; - } - - @Override - public void request(int count) { - Preconditions.checkState(!autoflowControl, "Autoflow control is enabled."); - - // Buffer the requested count in case the consumer requested responses in the onStart() - if (!hasStarted) { - numRequested += count; - } else { - clientCall.request(count); - } - } - - void start(RequestT request) { - startCommon(); - clientCall.sendMessage(request); - clientCall.halfClose(); - } - - void startBidi() { - startCommon(); - } - - private void startCommon() { - responseObserver.onStart(this); - - this.hasStarted = true; - - clientCall.start(new ResponseObserverAdapter(), new Metadata()); - - if (autoflowControl) { - clientCall.request(1); - } else if (numRequested > 0) { - clientCall.request(numRequested); - } - } - - private class ResponseObserverAdapter extends ClientCall.Listener { - /** - * Notifies the outerObserver of the new message and if automatic flow control is enabled, - * requests the next message. Any errors raised by the outerObserver will be bubbled up to GRPC, - * which cancel the ClientCall and close this listener. - * - * @param message The new message. - */ - @Override - public void onMessage(ResponseT message) { - responseObserver.onResponse(message); - - if (autoflowControl) { - clientCall.request(1); - } - } - - @Override - public void onClose(Status status, Metadata trailers) { - if (status.isOk()) { - responseObserver.onComplete(); - } else if (cancellationException != null) { - // Intercept cancellations and replace with the top level cause - responseObserver.onError(cancellationException); - } else { - responseObserver.onError(status.asRuntimeException(trailers)); - } - } - - @Override - public void onReady() { - onReady.run(); - } - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcExceptionBidiStreamingCallable.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcExceptionBidiStreamingCallable.java deleted file mode 100644 index b6a9ee024..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcExceptionBidiStreamingCallable.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.ApiException; -import com.google.api.gax.rpc.BidiStreamingCallable; -import com.google.api.gax.rpc.ClientStream; -import com.google.api.gax.rpc.ClientStreamReadyObserver; -import com.google.api.gax.rpc.ResponseObserver; -import com.google.api.gax.rpc.StatusCode; -import java.util.Set; - -/** - * Transforms all {@code Throwable}s thrown during a call into an instance of {@link ApiException}. - * - *

Package-private for internal use. - */ -final class GrpcExceptionBidiStreamingCallable - extends BidiStreamingCallable { - private final BidiStreamingCallable innerCallable; - private final GrpcApiExceptionFactory exceptionFactory; - - GrpcExceptionBidiStreamingCallable( - BidiStreamingCallable innerCallable, - Set retryableCodes) { - this.innerCallable = innerCallable; - this.exceptionFactory = new GrpcApiExceptionFactory(retryableCodes); - } - - @Override - public ClientStream internalCall( - final ResponseObserver responseObserver, - ClientStreamReadyObserver onReady, - ApiCallContext context) { - return innerCallable.internalCall( - new ExceptionResponseObserver<>(responseObserver, exceptionFactory), onReady, context); - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcExceptionCallable.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcExceptionCallable.java deleted file mode 100644 index b069294d0..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcExceptionCallable.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import static com.google.common.util.concurrent.MoreExecutors.directExecutor; - -import com.google.api.core.AbstractApiFuture; -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutureCallback; -import com.google.api.core.ApiFutures; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.ApiException; -import com.google.api.gax.rpc.StatusCode; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.common.base.Preconditions; -import java.util.Set; -import java.util.concurrent.CancellationException; - -/** - * Transforms all {@code Throwable}s thrown during a call into an instance of {@link ApiException}. - * - *

Package-private for internal use. - */ -class GrpcExceptionCallable extends UnaryCallable { - private final UnaryCallable callable; - private final GrpcApiExceptionFactory exceptionFactory; - - GrpcExceptionCallable( - UnaryCallable callable, Set retryableCodes) { - this.callable = Preconditions.checkNotNull(callable); - this.exceptionFactory = new GrpcApiExceptionFactory(retryableCodes); - } - - @Override - public ApiFuture futureCall(RequestT request, ApiCallContext inputContext) { - GrpcCallContext context = GrpcCallContext.createDefault().nullToSelf(inputContext); - ApiFuture innerCallFuture = callable.futureCall(request, context); - ExceptionTransformingFuture transformingFuture = - new ExceptionTransformingFuture(innerCallFuture); - ApiFutures.addCallback(innerCallFuture, transformingFuture, directExecutor()); - return transformingFuture; - } - - private class ExceptionTransformingFuture extends AbstractApiFuture - implements ApiFutureCallback { - private ApiFuture innerCallFuture; - private volatile boolean cancelled = false; - - public ExceptionTransformingFuture(ApiFuture innerCallFuture) { - this.innerCallFuture = innerCallFuture; - } - - @Override - protected void interruptTask() { - cancelled = true; - innerCallFuture.cancel(true); - } - - @Override - public void onSuccess(ResponseT r) { - super.set(r); - } - - @Override - public void onFailure(Throwable throwable) { - if (throwable instanceof CancellationException && cancelled) { - // this just circled around, so ignore. - return; - } else { - setException(exceptionFactory.create(throwable)); - } - } - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcExceptionClientStreamingCallable.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcExceptionClientStreamingCallable.java deleted file mode 100644 index d3a785638..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcExceptionClientStreamingCallable.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.ApiException; -import com.google.api.gax.rpc.ApiStreamObserver; -import com.google.api.gax.rpc.ClientStreamingCallable; -import com.google.api.gax.rpc.StatusCode; -import java.util.Set; - -/** - * Transforms all {@code Throwable}s thrown during a call into an instance of {@link ApiException}. - * - *

Package-private for internal use. - */ -final class GrpcExceptionClientStreamingCallable - extends ClientStreamingCallable { - private final ClientStreamingCallable innerCallable; - private final GrpcApiExceptionFactory exceptionFactory; - - GrpcExceptionClientStreamingCallable( - ClientStreamingCallable innerCallable, - Set retryableCodes) { - this.innerCallable = innerCallable; - this.exceptionFactory = new GrpcApiExceptionFactory(retryableCodes); - } - - @Override - public ApiStreamObserver clientStreamingCall( - ApiStreamObserver responseObserver, ApiCallContext context) { - - GrpcExceptionTranslatingStreamObserver innerObserver = - new GrpcExceptionTranslatingStreamObserver<>(responseObserver, exceptionFactory); - - return innerCallable.clientStreamingCall(innerObserver, context); - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcExceptionServerStreamingCallable.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcExceptionServerStreamingCallable.java deleted file mode 100644 index 088817487..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcExceptionServerStreamingCallable.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.ApiException; -import com.google.api.gax.rpc.ResponseObserver; -import com.google.api.gax.rpc.ServerStreamingCallable; -import com.google.api.gax.rpc.StatusCode.Code; -import java.util.Set; - -/** - * Transforms all {@code Throwable}s thrown during a call into an instance of {@link ApiException}. - * - *

Package-private for internal use. - */ -class GrpcExceptionServerStreamingCallable - extends ServerStreamingCallable { - private final ServerStreamingCallable inner; - private final GrpcApiExceptionFactory exceptionFactory; - - public GrpcExceptionServerStreamingCallable( - ServerStreamingCallable inner, Set retryableCodes) { - this.inner = inner; - this.exceptionFactory = new GrpcApiExceptionFactory(retryableCodes); - } - - @Override - public void call( - RequestT request, ResponseObserver responseObserver, ApiCallContext context) { - - inner.call( - request, new ExceptionResponseObserver<>(responseObserver, exceptionFactory), context); - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcExceptionTranslatingStreamObserver.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcExceptionTranslatingStreamObserver.java deleted file mode 100644 index 7725344ed..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcExceptionTranslatingStreamObserver.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.gax.rpc.ApiStreamObserver; - -/** - * An {@link ApiStreamObserver} that wraps grpc's errors into {@link - * com.google.api.gax.rpc.ApiException}s. - * - *

Package-private for internal use. - * - * @param - */ -final class GrpcExceptionTranslatingStreamObserver - implements ApiStreamObserver { - private final ApiStreamObserver innerObserver; - private final GrpcApiExceptionFactory exceptionFactory; - - GrpcExceptionTranslatingStreamObserver( - ApiStreamObserver innerObserver, GrpcApiExceptionFactory exceptionFactory) { - this.innerObserver = innerObserver; - this.exceptionFactory = exceptionFactory; - } - - @Override - public void onNext(ResponseT value) { - innerObserver.onNext(value); - } - - @Override - public void onError(Throwable t) { - innerObserver.onError(exceptionFactory.create(t)); - } - - @Override - public void onCompleted() { - innerObserver.onCompleted(); - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcHeaderInterceptor.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcHeaderInterceptor.java deleted file mode 100644 index 9e74538da..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcHeaderInterceptor.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.core.InternalApi; -import com.google.common.collect.ImmutableMap; -import io.grpc.CallOptions; -import io.grpc.Channel; -import io.grpc.ClientCall; -import io.grpc.ClientInterceptor; -import io.grpc.ForwardingClientCall.SimpleForwardingClientCall; -import io.grpc.Metadata; -import io.grpc.Metadata.Key; -import io.grpc.MethodDescriptor; -import java.util.Map; -import java.util.Map.Entry; - -/** - * An interceptor to handle custom headers. - * - *

Package-private for internal usage. - */ -@InternalApi -public class GrpcHeaderInterceptor implements ClientInterceptor { - private final Map, String> staticHeaders; - private final String userAgentHeader; - - public GrpcHeaderInterceptor(Map staticHeaders) { - ImmutableMap.Builder, String> grpcHeaders = ImmutableMap.builder(); - String userAgentStaticHeader = null; - for (Map.Entry header : staticHeaders.entrySet()) { - Metadata.Key headerKey = - Metadata.Key.of(header.getKey(), Metadata.ASCII_STRING_MARSHALLER); - - // User-Agent is overridden on gRPC level. The custom User-Agent is supposed to be provided - // differently and only merging with gRPC default value for User-Agent is permitted. - // Specifically the User-Agent will be provided via ManagedChannelBuilder#userAgent(String) - // during channel construction (calling #getUserAgentHeader() to get the value, initialized - // here). - if ("user-agent".equals(headerKey.name())) { - userAgentStaticHeader = header.getValue(); - } else { - grpcHeaders.put(headerKey, header.getValue()); - } - } - this.staticHeaders = grpcHeaders.build(); - this.userAgentHeader = userAgentStaticHeader; - } - - @Override - public ClientCall interceptCall( - MethodDescriptor method, final CallOptions callOptions, Channel next) { - ClientCall call = next.newCall(method, callOptions); - return new SimpleForwardingClientCall(call) { - @Override - public void start(ClientCall.Listener responseListener, Metadata headers) { - for (Entry, String> staticHeader : staticHeaders.entrySet()) { - headers.put(staticHeader.getKey(), staticHeader.getValue()); - } - - Map, String> dynamicHeaders = - CallOptionsUtil.getDynamicHeadersOption(callOptions); - for (Entry, String> dynamicHeader : dynamicHeaders.entrySet()) { - headers.put(dynamicHeader.getKey(), dynamicHeader.getValue()); - } - - super.start(responseListener, headers); - } - }; - } - - public String getUserAgentHeader() { - return userAgentHeader; - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcInterceptorProvider.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcInterceptorProvider.java deleted file mode 100644 index f3d4de8ba..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcInterceptorProvider.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import io.grpc.ClientInterceptor; -import java.util.List; - -/** Provider of custom gRPC ClientInterceptors. */ -public interface GrpcInterceptorProvider { - - /** - * Get the list of client interceptors. - * - * @return interceptors - */ - List getInterceptors(); -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcLongRunningClient.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcLongRunningClient.java deleted file mode 100644 index fca5e73b9..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcLongRunningClient.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.core.ApiFunction; -import com.google.api.gax.longrunning.OperationSnapshot; -import com.google.api.gax.rpc.LongRunningClient; -import com.google.api.gax.rpc.TranslatingUnaryCallable; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.longrunning.CancelOperationRequest; -import com.google.longrunning.DeleteOperationRequest; -import com.google.longrunning.GetOperationRequest; -import com.google.longrunning.Operation; -import com.google.longrunning.stub.OperationsStub; -import com.google.protobuf.Empty; - -/** - * Implementation of LongRunningClient based on gRPC. - * - *

Package-private for internal usage. - */ -class GrpcLongRunningClient implements LongRunningClient { - private final OperationsStub operationsStub; - - public GrpcLongRunningClient(OperationsStub operationsStub) { - this.operationsStub = operationsStub; - } - - @Override - public UnaryCallable getOperationCallable() { - return TranslatingUnaryCallable.create( - operationsStub.getOperationCallable(), - new ApiFunction() { - @Override - public GetOperationRequest apply(String request) { - return GetOperationRequest.newBuilder().setName(request).build(); - } - }, - new ApiFunction() { - @Override - public OperationSnapshot apply(Operation operation) { - return GrpcOperationSnapshot.create(operation); - } - }); - } - - @Override - public UnaryCallable cancelOperationCallable() { - return TranslatingUnaryCallable.create( - operationsStub.cancelOperationCallable(), - new ApiFunction() { - @Override - public CancelOperationRequest apply(String request) { - return CancelOperationRequest.newBuilder().setName(request).build(); - } - }, - new ApiFunction() { - @Override - public Void apply(Empty empty) { - return null; - } - }); - } - - @Override - public UnaryCallable deleteOperationCallable() { - return TranslatingUnaryCallable.create( - operationsStub.deleteOperationCallable(), - new ApiFunction() { - @Override - public DeleteOperationRequest apply(String request) { - return DeleteOperationRequest.newBuilder().setName(request).build(); - } - }, - new ApiFunction() { - @Override - public Void apply(Empty empty) { - return null; - } - }); - } - - public static GrpcLongRunningClient create(OperationsStub operationsStub) { - return new GrpcLongRunningClient(operationsStub); - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcMetadataHandlerInterceptor.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcMetadataHandlerInterceptor.java deleted file mode 100644 index c3940f4db..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcMetadataHandlerInterceptor.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.core.InternalApi; -import io.grpc.CallOptions; -import io.grpc.Channel; -import io.grpc.ClientCall; -import io.grpc.ClientInterceptor; -import io.grpc.ForwardingClientCall.SimpleForwardingClientCall; -import io.grpc.ForwardingClientCallListener.SimpleForwardingClientCallListener; -import io.grpc.Metadata; -import io.grpc.MethodDescriptor; -import io.grpc.Status; - -/** - * An interceptor to handle receiving the response headers. - * - *

Package-private for internal usage. - */ -@InternalApi -class GrpcMetadataHandlerInterceptor implements ClientInterceptor { - - @Override - public ClientCall interceptCall( - MethodDescriptor method, final CallOptions callOptions, Channel next) { - ClientCall call = next.newCall(method, callOptions); - - final ResponseMetadataHandler metadataHandler = - CallOptionsUtil.getMetadataHandlerOption(callOptions); - - if (metadataHandler == null) { - return call; - } - return new SimpleForwardingClientCall(call) { - @Override - public void start(Listener responseListener, Metadata headers) { - Listener forwardingResponseListener = - new SimpleForwardingClientCallListener(responseListener) { - @Override - public void onHeaders(Metadata headers) { - super.onHeaders(headers); - metadataHandler.onHeaders(headers); - } - - @Override - public void onClose(Status status, Metadata trailers) { - metadataHandler.onTrailers(trailers); - super.onClose(status, trailers); - } - }; - super.start(forwardingResponseListener, headers); - } - }; - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcOperationSnapshot.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcOperationSnapshot.java deleted file mode 100644 index 4483ef1cf..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcOperationSnapshot.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.gax.longrunning.OperationSnapshot; -import com.google.api.gax.rpc.StatusCode; -import com.google.longrunning.Operation; -import io.grpc.Status; - -/** - * Implementation of OperationSnapshot based on gRPC. - * - *

Package-private for internal usage. - */ -class GrpcOperationSnapshot implements OperationSnapshot { - - private final Operation operation; - - public GrpcOperationSnapshot(Operation operation) { - this.operation = operation; - } - - @Override - public String getName() { - return operation.getName(); - } - - @Override - public Object getMetadata() { - return operation.getMetadata(); - } - - @Override - public boolean isDone() { - return operation.getDone(); - } - - @Override - public Object getResponse() { - return operation.getResponse(); - } - - @Override - public StatusCode getErrorCode() { - return GrpcStatusCode.of(Status.fromCodeValue(operation.getError().getCode()).getCode()); - } - - @Override - public String getErrorMessage() { - return operation.getError().getMessage(); - } - - public static GrpcOperationSnapshot create(Operation operation) { - return new GrpcOperationSnapshot(operation); - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcOperationSnapshotCallable.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcOperationSnapshotCallable.java deleted file mode 100644 index a7f467a99..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcOperationSnapshotCallable.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import static com.google.common.util.concurrent.MoreExecutors.directExecutor; - -import com.google.api.core.ApiFunction; -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.api.gax.longrunning.OperationSnapshot; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.longrunning.Operation; - -/** - * A {@code UnaryCallable} that wraps a UnaryCallable returning an Operation and returns an - * OperationSnapshot instead. - * - *

Package-private for internal usage. - */ -class GrpcOperationSnapshotCallable extends UnaryCallable { - private final UnaryCallable innerCallable; - - public GrpcOperationSnapshotCallable(UnaryCallable innerCallable) { - this.innerCallable = innerCallable; - } - - @Override - public ApiFuture futureCall(RequestT request, ApiCallContext context) { - return ApiFutures.transform( - innerCallable.futureCall(request, context), - new ApiFunction() { - @Override - public OperationSnapshot apply(Operation operation) { - return new GrpcOperationSnapshot(operation); - } - }, - directExecutor()); - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcRawCallableFactory.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcRawCallableFactory.java deleted file mode 100644 index 1375fe9fb..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcRawCallableFactory.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.core.InternalApi; -import com.google.api.gax.rpc.BidiStreamingCallable; -import com.google.api.gax.rpc.ClientStreamingCallable; -import com.google.api.gax.rpc.ServerStreamingCallable; -import com.google.api.gax.rpc.StatusCode; -import com.google.api.gax.rpc.UnaryCallable; -import java.util.Set; - -/** Class with utility methods to create low level grpc-based direct callables. */ -@InternalApi("For internal use by google-cloud-java clients only") -public class GrpcRawCallableFactory { - private GrpcRawCallableFactory() {} - - /** - * Create a Unary callable object with minimal grpc-specific functionality. - * - * @param grpcCallSettings the gRPC call settings - * @param retryableCodes the {@link StatusCode.Code} that should be marked as retryable - */ - public static UnaryCallable createUnaryCallable( - GrpcCallSettings grpcCallSettings, Set retryableCodes) { - UnaryCallable callable = - new GrpcDirectCallable<>( - grpcCallSettings.getMethodDescriptor(), grpcCallSettings.shouldAwaitTrailers()); - - if (grpcCallSettings.getParamsExtractor() != null) { - callable = - new GrpcUnaryRequestParamCallable<>(callable, grpcCallSettings.getParamsExtractor()); - } - return new GrpcExceptionCallable<>(callable, retryableCodes); - } - - /** - * Create a bidirectional streaming callable object with grpc-specific functionality. Designed for - * use by generated code. - * - * @param grpcCallSettings the gRPC call settings - * @param retryableCodes the {@link StatusCode.Code} that should be marked as retryable - * @return {@link BidiStreamingCallable} callable object. - */ - public static - BidiStreamingCallable createBidiStreamingCallable( - GrpcCallSettings grpcCallSettings, - Set retryableCodes) { - BidiStreamingCallable callable = - new GrpcDirectBidiStreamingCallable<>(grpcCallSettings.getMethodDescriptor()); - - return new GrpcExceptionBidiStreamingCallable<>(callable, retryableCodes); - } - - /** - * Create a server-streaming callable with grpc-specific functionality. Designed for use by - * generated code. - * - * @param grpcCallSettings the gRPC call settings - * @param retryableCodes the {@link StatusCode.Code} that should be marked as retryable - */ - public static - ServerStreamingCallable createServerStreamingCallable( - GrpcCallSettings grpcCallSettings, - Set retryableCodes) { - ServerStreamingCallable callable = - new GrpcDirectServerStreamingCallable<>(grpcCallSettings.getMethodDescriptor()); - if (grpcCallSettings.getParamsExtractor() != null) { - callable = - new GrpcServerStreamingRequestParamCallable<>( - callable, grpcCallSettings.getParamsExtractor()); - } - return new GrpcExceptionServerStreamingCallable<>(callable, retryableCodes); - } - /** - * Create a client-streaming callable object with grpc-specific functionality. Designed for use by - * generated code. - * - * @param grpcCallSettings the gRPC call settings - * @param retryableCodes the {@link StatusCode.Code} that should be marked as retryable - */ - public static - ClientStreamingCallable createClientStreamingCallable( - GrpcCallSettings grpcCallSettings, - Set retryableCodes) { - ClientStreamingCallable callable = - new GrpcDirectClientStreamingCallable<>(grpcCallSettings.getMethodDescriptor()); - - return new GrpcExceptionClientStreamingCallable<>(callable, retryableCodes); - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcResponseMetadata.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcResponseMetadata.java deleted file mode 100644 index 9e018eefb..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcResponseMetadata.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.gax.rpc.ApiCallContext; -import com.google.common.base.Preconditions; -import io.grpc.Metadata; - -/** - * GrpcResponseMetadata provides a mechanism to access the headers and trailers returned by a gRPC - * client method. - * - *

NOTE: the GrpcResponseMetadata class is not thread-safe and should NOT be re-used for multiple - * calls. A new instance of GrpcResponseMetadata should be constructed for each call that requires - * metadata to be accessed. - * - *

Example usage: - * - *

- * 
- * GrpcResponseMetadata grpcResponseMetadata = new GrpcResponseMetadata();
- * Foo foo = client.getFooCallable().call(getFooRequest, grpcResponseMetadata.createContextWithHandlers());
- * Metadata headers = grpcResponseMetadata.getMetadata();
- * Metadata trailers = grpcResponseMetadata.getTrailingMetadata();
- * 
- * 
- */ -public class GrpcResponseMetadata implements ResponseMetadataHandler { - - private volatile Metadata responseMetadata; - private volatile Metadata trailingMetadata; - - /** - * Constructs a new call context from an existing ApiCallContext, and sets the CallOptions to add - * handlers to retrieve the headers and trailers, and make them available via the getMetadata and - * getTrailingMetadata methods. - */ - public GrpcCallContext addHandlers(ApiCallContext apiCallContext) { - if (Preconditions.checkNotNull(apiCallContext) instanceof GrpcCallContext) { - return addHandlers((GrpcCallContext) apiCallContext); - } - throw new IllegalArgumentException( - "context must be an instance of GrpcCallContext, but found " - + apiCallContext.getClass().getName()); - } - - /** - * Constructs a new call context and sets the CallOptions to add handlers to retrieve the headers - * and trailers, and make them available via the getMetadata and getTrailingMetadata methods. - */ - public GrpcCallContext createContextWithHandlers() { - return addHandlers(GrpcCallContext.createDefault()); - } - - private GrpcCallContext addHandlers(GrpcCallContext grpcCallContext) { - return Preconditions.checkNotNull(grpcCallContext) - .withCallOptions( - CallOptionsUtil.putMetadataHandlerOption(grpcCallContext.getCallOptions(), this)); - } - - /** - * Returns the headers from the gRPC method as Metadata. If the call has not completed, will - * return null. - */ - public Metadata getMetadata() { - return responseMetadata; - } - - /** - * Returns the trailers from the gRPC method as Metadata. If the call has not completed, will - * return null. - */ - public Metadata getTrailingMetadata() { - return trailingMetadata; - } - - @Override - public void onHeaders(Metadata metadata) { - responseMetadata = metadata; - } - - @Override - public void onTrailers(Metadata metadata) { - trailingMetadata = metadata; - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcServerStreamingRequestParamCallable.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcServerStreamingRequestParamCallable.java deleted file mode 100644 index 5e0a59851..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcServerStreamingRequestParamCallable.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.RequestParamsExtractor; -import com.google.api.gax.rpc.RequestUrlParamsEncoder; -import com.google.api.gax.rpc.ResponseObserver; -import com.google.api.gax.rpc.ServerStreamingCallable; -import com.google.common.base.Preconditions; - -/** - * A {@code ServerStreamingCallable} that extracts values from the fields of the request and inserts - * them into headers. - * - *

Package-private for internal usage. - */ -class GrpcServerStreamingRequestParamCallable - extends ServerStreamingCallable { - private final ServerStreamingCallable callable; - private final RequestUrlParamsEncoder paramsEncoder; - - GrpcServerStreamingRequestParamCallable( - ServerStreamingCallable callable, - RequestParamsExtractor paramsExtractor) { - this.callable = Preconditions.checkNotNull(callable); - this.paramsEncoder = - new RequestUrlParamsEncoder<>(Preconditions.checkNotNull(paramsExtractor), false); - } - - @Override - public void call( - RequestT request, ResponseObserver responseObserver, ApiCallContext context) { - callable.call(request, responseObserver, contextWithParamsEncoder(request, context)); - } - - private ApiCallContext contextWithParamsEncoder(RequestT request, ApiCallContext inputContext) { - return GrpcCallContext.createDefault() - .nullToSelf(inputContext) - .withRequestParamsDynamicHeaderOption(paramsEncoder.encode(request)); - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcStatusCode.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcStatusCode.java deleted file mode 100644 index b3db79eda..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcStatusCode.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.core.InternalExtensionOnly; -import com.google.api.gax.rpc.StatusCode; -import com.google.auto.value.AutoValue; -import io.grpc.Status; - -/** A failure code specific to a gRPC call. */ -@InternalExtensionOnly -@AutoValue -public abstract class GrpcStatusCode implements StatusCode { - /** Creates a new instance with the given {@link Status.Code}. */ - public static GrpcStatusCode of(Status.Code grpcCode) { - return new AutoValue_GrpcStatusCode(grpcCode); - } - - static StatusCode.Code grpcCodeToStatusCode(Status.Code code) { - switch (code) { - case OK: - return StatusCode.Code.OK; - case CANCELLED: - return StatusCode.Code.CANCELLED; - case UNKNOWN: - return StatusCode.Code.UNKNOWN; - case INVALID_ARGUMENT: - return StatusCode.Code.INVALID_ARGUMENT; - case DEADLINE_EXCEEDED: - return StatusCode.Code.DEADLINE_EXCEEDED; - case NOT_FOUND: - return StatusCode.Code.NOT_FOUND; - case ALREADY_EXISTS: - return StatusCode.Code.ALREADY_EXISTS; - case PERMISSION_DENIED: - return StatusCode.Code.PERMISSION_DENIED; - case RESOURCE_EXHAUSTED: - return StatusCode.Code.RESOURCE_EXHAUSTED; - case FAILED_PRECONDITION: - return StatusCode.Code.FAILED_PRECONDITION; - case ABORTED: - return StatusCode.Code.ABORTED; - case OUT_OF_RANGE: - return StatusCode.Code.OUT_OF_RANGE; - case UNIMPLEMENTED: - return StatusCode.Code.UNIMPLEMENTED; - case INTERNAL: - return StatusCode.Code.INTERNAL; - case UNAVAILABLE: - return StatusCode.Code.UNAVAILABLE; - case DATA_LOSS: - return StatusCode.Code.DATA_LOSS; - case UNAUTHENTICATED: - return StatusCode.Code.UNAUTHENTICATED; - default: - throw new IllegalStateException("Unrecognized status code: " + code); - } - } - - /** Returns the {@link Status.Code} from grpc. */ - @Override - public StatusCode.Code getCode() { - return grpcCodeToStatusCode(getTransportCode()); - } - - @Override - public abstract Status.Code getTransportCode(); -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcStubCallableFactory.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcStubCallableFactory.java deleted file mode 100644 index 131dafc1f..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcStubCallableFactory.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.gax.rpc.BatchingCallSettings; -import com.google.api.gax.rpc.BidiStreamingCallable; -import com.google.api.gax.rpc.ClientContext; -import com.google.api.gax.rpc.ClientStreamingCallable; -import com.google.api.gax.rpc.OperationCallSettings; -import com.google.api.gax.rpc.OperationCallable; -import com.google.api.gax.rpc.PagedCallSettings; -import com.google.api.gax.rpc.ServerStreamingCallSettings; -import com.google.api.gax.rpc.ServerStreamingCallable; -import com.google.api.gax.rpc.StreamingCallSettings; -import com.google.api.gax.rpc.UnaryCallSettings; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.longrunning.Operation; -import com.google.longrunning.stub.OperationsStub; - -public interface GrpcStubCallableFactory { - - /** - * Create a callable object with grpc-specific functionality. Designed for use by generated code. - * - * @param grpcCallSettings the gRPC call settings - */ - UnaryCallable createUnaryCallable( - GrpcCallSettings grpcCallSettings, - UnaryCallSettings callSettings, - ClientContext clientContext); - - /** - * Create a paged callable object that represents a paged API method. Designed for use by - * generated code. - * - * @param grpcCallSettings the gRPC call settings - * @param pagedCallSettings {@link PagedCallSettings} to configure the paged settings with. - * @param clientContext {@link ClientContext} to use to connect to the service. - * @return {@link UnaryCallable} callable object. - */ - - UnaryCallable createPagedCallable( - GrpcCallSettings grpcCallSettings, - PagedCallSettings pagedCallSettings, - ClientContext clientContext); - - /** - * Create a callable object that represents a batching API method. Designed for use by generated - * code. - * - * @param grpcCallSettings the gRPC call settings - * @param batchingCallSettings {@link BatchingCallSettings} to configure the batching related - * settings with. - * @param clientContext {@link ClientContext} to use to connect to the service. - * @return {@link UnaryCallable} callable object. - */ - UnaryCallable createBatchingCallable( - GrpcCallSettings grpcCallSettings, - BatchingCallSettings batchingCallSettings, - ClientContext clientContext); - - /** - * Creates a callable object that represents a long-running operation. Designed for use by - * generated code. - * - * @param grpcCallSettings the gRPC call settings - * @param operationCallSettings {@link OperationCallSettings} to configure the method-level - * settings with. - * @param clientContext {@link ClientContext} to use to connect to the service. - * @param operationsStub {@link OperationsStub} to use to poll for updates on the Operation. - * @return {@link OperationCallable} callable object. - */ - - OperationCallable createOperationCallable( - GrpcCallSettings grpcCallSettings, - OperationCallSettings operationCallSettings, - ClientContext clientContext, - OperationsStub operationsStub); - - /** - * Create a bidirectional streaming callable object with grpc-specific functionality. Designed for - * use by generated code. - * - * @param grpcCallSettings the gRPC call settings - * @param streamingCallSettings {@link StreamingCallSettings} to configure the method-level - * settings with. - * @param clientContext {@link ClientContext} to use to connect to the service. - * @return {@link BidiStreamingCallable} callable object. - */ - BidiStreamingCallable createBidiStreamingCallable( - GrpcCallSettings grpcCallSettings, - StreamingCallSettings streamingCallSettings, - ClientContext clientContext); - - /** - * Create a server-streaming callable with grpc-specific functionality. Designed for use by - * generated code. - * - * @param grpcCallSettings the gRPC call settings - * @param streamingCallSettings {@link StreamingCallSettings} to configure the method-level - * settings with. - * @param clientContext {@link ClientContext} to use to connect to the service. - */ - ServerStreamingCallable createServerStreamingCallable( - GrpcCallSettings grpcCallSettings, - ServerStreamingCallSettings streamingCallSettings, - ClientContext clientContext); - - /** - * Create a client-streaming callable object with grpc-specific functionality. Designed for use by - * generated code. - * - * @param grpcCallSettings the gRPC call settings - * @param streamingCallSettings {@link StreamingCallSettings} to configure the method-level - * settings with. - * @param clientContext {@link ClientContext} to use to connect to the service. - * @return {@link ClientStreamingCallable} callable object. - */ - ClientStreamingCallable createClientStreamingCallable( - GrpcCallSettings grpcCallSettings, - StreamingCallSettings streamingCallSettings, - ClientContext clientContext); -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcTransportChannel.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcTransportChannel.java deleted file mode 100644 index 9e63bb2a6..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcTransportChannel.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.core.InternalExtensionOnly; -import com.google.api.gax.core.ResourceCloseException; -import com.google.api.gax.rpc.TransportChannel; -import com.google.auto.value.AutoValue; -import io.grpc.Channel; -import io.grpc.ManagedChannel; -import java.util.concurrent.TimeUnit; - -/** Implementation of TransportChannel based on gRPC. */ -@AutoValue -@InternalExtensionOnly -public abstract class GrpcTransportChannel implements TransportChannel { - - /** The name of the Grpc transport. */ - public static String getGrpcTransportName() { - return "grpc"; - } - - @Override - public String getTransportName() { - return getGrpcTransportName(); - } - - @Override - public GrpcCallContext getEmptyCallContext() { - return GrpcCallContext.createDefault(); - } - - /** The channel in use. */ - abstract ManagedChannel getManagedChannel(); - - public Channel getChannel() { - return getManagedChannel(); - } - - @Override - public void shutdown() { - getManagedChannel().shutdown(); - } - - @Override - public boolean isShutdown() { - return getManagedChannel().isShutdown(); - } - - @Override - public boolean isTerminated() { - return getManagedChannel().isTerminated(); - } - - @Override - public void shutdownNow() { - getManagedChannel().shutdownNow(); - } - - @Override - public boolean awaitTermination(long duration, TimeUnit unit) throws InterruptedException { - return getManagedChannel().awaitTermination(duration, unit); - } - - @Override - public void close() { - getManagedChannel().shutdown(); - try { - awaitTermination(6, TimeUnit.MINUTES); - } catch (InterruptedException e) { - throw new ResourceCloseException(e); - } - } - - public static Builder newBuilder() { - return new AutoValue_GrpcTransportChannel.Builder(); - } - - public static GrpcTransportChannel create(ManagedChannel channel) { - return newBuilder().setManagedChannel(channel).build(); - } - - @AutoValue.Builder - public abstract static class Builder { - public abstract Builder setManagedChannel(ManagedChannel value); - - public abstract GrpcTransportChannel build(); - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcUnaryRequestParamCallable.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcUnaryRequestParamCallable.java deleted file mode 100644 index 9eb78aca0..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/GrpcUnaryRequestParamCallable.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.core.ApiFuture; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.RequestParamsExtractor; -import com.google.api.gax.rpc.RequestUrlParamsEncoder; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.common.base.Preconditions; - -/** - * A {@code UnaryCallable} that extracts values from the fields of the request and inserts them into - * headers. - * - *

Package-private for internal usage. - */ -class GrpcUnaryRequestParamCallable - extends UnaryCallable { - private final UnaryCallable callable; - private final RequestUrlParamsEncoder paramsEncoder; - - GrpcUnaryRequestParamCallable( - UnaryCallable callable, - RequestParamsExtractor paramsExtractor) { - this.callable = Preconditions.checkNotNull(callable); - this.paramsEncoder = - new RequestUrlParamsEncoder<>(Preconditions.checkNotNull(paramsExtractor), false); - } - - @Override - public ApiFuture futureCall(RequestT request, ApiCallContext inputContext) { - GrpcCallContext newCallContext = - GrpcCallContext.createDefault() - .nullToSelf(inputContext) - .withRequestParamsDynamicHeaderOption(paramsEncoder.encode(request)); - - return callable.futureCall(request, newCallContext); - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java deleted file mode 100644 index 40e2bd139..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java +++ /dev/null @@ -1,753 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.core.ApiFunction; -import com.google.api.core.BetaApi; -import com.google.api.core.InternalApi; -import com.google.api.core.InternalExtensionOnly; -import com.google.api.gax.core.ExecutorProvider; -import com.google.api.gax.rpc.FixedHeaderProvider; -import com.google.api.gax.rpc.HeaderProvider; -import com.google.api.gax.rpc.TransportChannel; -import com.google.api.gax.rpc.TransportChannelProvider; -import com.google.api.gax.rpc.internal.EnvironmentProvider; -import com.google.api.gax.rpc.mtls.MtlsProvider; -import com.google.auth.Credentials; -import com.google.auth.oauth2.ComputeEngineCredentials; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.io.Files; -import io.grpc.CallCredentials; -import io.grpc.ChannelCredentials; -import io.grpc.Grpc; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import io.grpc.TlsChannelCredentials; -import io.grpc.alts.GoogleDefaultChannelCredentials; -import io.grpc.auth.MoreCallCredentials; -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.security.GeneralSecurityException; -import java.security.KeyStore; -import java.util.Map; -import java.util.concurrent.Executor; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import javax.annotation.Nullable; -import javax.net.ssl.KeyManagerFactory; -import org.threeten.bp.Duration; - -/** - * InstantiatingGrpcChannelProvider is a TransportChannelProvider which constructs a gRPC - * ManagedChannel with a number of configured inputs every time getChannel(...) is called. These - * inputs include a port, a service address, and credentials. - * - *

The credentials can either be supplied directly (by providing a FixedCredentialsProvider to - * Builder.setCredentialsProvider()) or acquired implicitly from Application Default Credentials (by - * providing a GoogleCredentialsProvider to Builder.setCredentialsProvider()). - * - *

The client lib header and generator header values are used to form a value that goes into the - * http header of requests to the service. - */ -@InternalExtensionOnly -public final class InstantiatingGrpcChannelProvider implements TransportChannelProvider { - static final String DIRECT_PATH_ENV_VAR = "GOOGLE_CLOUD_ENABLE_DIRECT_PATH"; - private static final String DIRECT_PATH_ENV_DISABLE_DIRECT_PATH = - "GOOGLE_CLOUD_DISABLE_DIRECT_PATH"; - private static final String DIRECT_PATH_ENV_ENABLE_XDS = "GOOGLE_CLOUD_ENABLE_DIRECT_PATH_XDS"; - static final long DIRECT_PATH_KEEP_ALIVE_TIME_SECONDS = 3600; - static final long DIRECT_PATH_KEEP_ALIVE_TIMEOUT_SECONDS = 20; - static final String GCE_PRODUCTION_NAME_PRIOR_2016 = "Google"; - static final String GCE_PRODUCTION_NAME_AFTER_2016 = "Google Compute Engine"; - - private final int processorCount; - private final Executor executor; - private final HeaderProvider headerProvider; - private final String endpoint; - // TODO: remove. envProvider currently provides DirectPath environment variable, and is only used - // during initial rollout for DirectPath. This provider will be removed once the DirectPath - // environment is not used. - private final EnvironmentProvider envProvider; - @Nullable private final GrpcInterceptorProvider interceptorProvider; - @Nullable private final Integer maxInboundMessageSize; - @Nullable private final Integer maxInboundMetadataSize; - @Nullable private final Duration keepAliveTime; - @Nullable private final Duration keepAliveTimeout; - @Nullable private final Boolean keepAliveWithoutCalls; - private final ChannelPoolSettings channelPoolSettings; - @Nullable private final Credentials credentials; - @Nullable private final ChannelPrimer channelPrimer; - @Nullable private final Boolean attemptDirectPath; - @Nullable private final Boolean allowNonDefaultServiceAccount; - @VisibleForTesting final ImmutableMap directPathServiceConfig; - @Nullable private final MtlsProvider mtlsProvider; - - @Nullable - private final ApiFunction channelConfigurator; - - private InstantiatingGrpcChannelProvider(Builder builder) { - this.processorCount = builder.processorCount; - this.executor = builder.executor; - this.headerProvider = builder.headerProvider; - this.endpoint = builder.endpoint; - this.mtlsProvider = builder.mtlsProvider; - this.envProvider = builder.envProvider; - this.interceptorProvider = builder.interceptorProvider; - this.maxInboundMessageSize = builder.maxInboundMessageSize; - this.maxInboundMetadataSize = builder.maxInboundMetadataSize; - this.keepAliveTime = builder.keepAliveTime; - this.keepAliveTimeout = builder.keepAliveTimeout; - this.keepAliveWithoutCalls = builder.keepAliveWithoutCalls; - this.channelPoolSettings = builder.channelPoolSettings; - this.channelConfigurator = builder.channelConfigurator; - this.credentials = builder.credentials; - this.channelPrimer = builder.channelPrimer; - this.attemptDirectPath = builder.attemptDirectPath; - this.allowNonDefaultServiceAccount = builder.allowNonDefaultServiceAccount; - this.directPathServiceConfig = - builder.directPathServiceConfig == null - ? getDefaultDirectPathServiceConfig() - : builder.directPathServiceConfig; - } - - /** - * @deprecated If executor is not set, this channel provider will create channels with default - * grpc executor. - */ - @Deprecated - @Override - public boolean needsExecutor() { - return executor == null; - } - - @Deprecated - @Override - public TransportChannelProvider withExecutor(ScheduledExecutorService executor) { - return withExecutor((Executor) executor); - } - - @Override - public TransportChannelProvider withExecutor(Executor executor) { - return toBuilder().setExecutor(executor).build(); - } - - @Override - public boolean needsHeaders() { - return headerProvider == null; - } - - @Override - public TransportChannelProvider withHeaders(Map headers) { - return toBuilder().setHeaderProvider(FixedHeaderProvider.create(headers)).build(); - } - - @Override - public String getTransportName() { - return GrpcTransportChannel.getGrpcTransportName(); - } - - @Override - public boolean needsEndpoint() { - return endpoint == null; - } - - /** - * Specify the endpoint the channel should connect to. - * - *

The value of {@code endpoint} must be of the form {@code host:port}. - * - * @param endpoint The endpoint to connect to - * @return A new {@link InstantiatingGrpcChannelProvider} with the specified endpoint configured - */ - @Override - public TransportChannelProvider withEndpoint(String endpoint) { - validateEndpoint(endpoint); - return toBuilder().setEndpoint(endpoint).build(); - } - - /** @deprecated Please modify pool settings via {@link #toBuilder()} */ - @Deprecated - @Override - public boolean acceptsPoolSize() { - return true; - } - - /** @deprecated Please modify pool settings via {@link #toBuilder()} */ - @Deprecated - @Override - public TransportChannelProvider withPoolSize(int size) { - return toBuilder().setPoolSize(size).build(); - } - - @Override - public boolean needsCredentials() { - return credentials == null; - } - - @Override - public TransportChannelProvider withCredentials(Credentials credentials) { - return toBuilder().setCredentials(credentials).build(); - } - - @Override - public TransportChannel getTransportChannel() throws IOException { - if (needsHeaders()) { - throw new IllegalStateException("getTransportChannel() called when needsHeaders() is true"); - } else if (needsEndpoint()) { - throw new IllegalStateException("getTransportChannel() called when needsEndpoint() is true"); - } else { - return createChannel(); - } - } - - private TransportChannel createChannel() throws IOException { - return GrpcTransportChannel.create( - ChannelPool.create( - channelPoolSettings, InstantiatingGrpcChannelProvider.this::createSingleChannel)); - } - - // TODO(mohanli): Use attemptDirectPath as the only indicator once setAttemptDirectPath is adapted - // and the env var is removed from client environment. - private boolean isDirectPathEnabled(String serviceAddress) { - String disableDirectPathEnv = envProvider.getenv(DIRECT_PATH_ENV_DISABLE_DIRECT_PATH); - boolean isDirectPathDisabled = Boolean.parseBoolean(disableDirectPathEnv); - if (isDirectPathDisabled) { - return false; - } - // Only check attemptDirectPath when DIRECT_PATH_ENV_DISABLE_DIRECT_PATH is not set. - if (attemptDirectPath != null) { - return attemptDirectPath; - } - // Only check DIRECT_PATH_ENV_VAR when attemptDirectPath is not set. - String whiteList = envProvider.getenv(DIRECT_PATH_ENV_VAR); - if (whiteList == null) { - return false; - } - for (String service : whiteList.split(",")) { - if (!service.isEmpty() && serviceAddress.contains(service)) { - return true; - } - } - return false; - } - - private boolean isNonDefaultServiceAccountAllowed() { - if (allowNonDefaultServiceAccount != null && allowNonDefaultServiceAccount) { - return true; - } - return credentials instanceof ComputeEngineCredentials; - } - - // DirectPath should only be used on Compute Engine. - // Notice Windows is supported for now. - static boolean isOnComputeEngine() { - String osName = System.getProperty("os.name"); - if ("Linux".equals(osName)) { - try { - String result = - Files.asCharSource(new File("/sys/class/dmi/id/product_name"), StandardCharsets.UTF_8) - .readFirstLine(); - return result.contains(GCE_PRODUCTION_NAME_PRIOR_2016) - || result.contains(GCE_PRODUCTION_NAME_AFTER_2016); - } catch (IOException ignored) { - return false; - } - } - return false; - } - - @VisibleForTesting - ChannelCredentials createMtlsChannelCredentials() throws IOException, GeneralSecurityException { - if (mtlsProvider.useMtlsClientCertificate()) { - KeyStore mtlsKeyStore = mtlsProvider.getKeyStore(); - if (mtlsKeyStore != null) { - KeyManagerFactory factory = - KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - factory.init(mtlsKeyStore, new char[] {}); - return TlsChannelCredentials.newBuilder().keyManager(factory.getKeyManagers()).build(); - } - } - return null; - } - - private ManagedChannel createSingleChannel() throws IOException { - GrpcHeaderInterceptor headerInterceptor = - new GrpcHeaderInterceptor(headerProvider.getHeaders()); - GrpcMetadataHandlerInterceptor metadataHandlerInterceptor = - new GrpcMetadataHandlerInterceptor(); - - int colon = endpoint.lastIndexOf(':'); - if (colon < 0) { - throw new IllegalStateException("invalid endpoint - should have been validated: " + endpoint); - } - int port = Integer.parseInt(endpoint.substring(colon + 1)); - String serviceAddress = endpoint.substring(0, colon); - - ManagedChannelBuilder builder; - - // Check DirectPath traffic. - boolean isDirectPathXdsEnabled = false; - if (isDirectPathEnabled(serviceAddress) - && isNonDefaultServiceAccountAllowed() - && isOnComputeEngine()) { - CallCredentials callCreds = MoreCallCredentials.from(credentials); - ChannelCredentials channelCreds = - GoogleDefaultChannelCredentials.newBuilder().callCredentials(callCreds).build(); - isDirectPathXdsEnabled = Boolean.parseBoolean(envProvider.getenv(DIRECT_PATH_ENV_ENABLE_XDS)); - if (isDirectPathXdsEnabled) { - // google-c2p: CloudToProd(C2P) Directpath. This scheme is defined in - // io.grpc.googleapis.GoogleCloudToProdNameResolverProvider. - // This resolver target must not have a port number. - builder = Grpc.newChannelBuilder("google-c2p:///" + serviceAddress, channelCreds); - } else { - builder = Grpc.newChannelBuilderForAddress(serviceAddress, port, channelCreds); - builder.defaultServiceConfig(directPathServiceConfig); - } - // Set default keepAliveTime and keepAliveTimeout when directpath environment is enabled. - // Will be overridden by user defined values if any. - builder.keepAliveTime(DIRECT_PATH_KEEP_ALIVE_TIME_SECONDS, TimeUnit.SECONDS); - builder.keepAliveTimeout(DIRECT_PATH_KEEP_ALIVE_TIMEOUT_SECONDS, TimeUnit.SECONDS); - } else { - ChannelCredentials channelCredentials; - try { - channelCredentials = createMtlsChannelCredentials(); - } catch (GeneralSecurityException e) { - throw new IOException(e); - } - if (channelCredentials != null) { - builder = Grpc.newChannelBuilder(endpoint, channelCredentials); - } else { - builder = ManagedChannelBuilder.forAddress(serviceAddress, port); - } - } - // google-c2p resolver requires service config lookup - if (!isDirectPathXdsEnabled) { - // See https://github.com/googleapis/gapic-generator/issues/2816 - builder.disableServiceConfigLookUp(); - } - builder = - builder - .intercept(new GrpcChannelUUIDInterceptor()) - .intercept(headerInterceptor) - .intercept(metadataHandlerInterceptor) - .userAgent(headerInterceptor.getUserAgentHeader()) - .executor(executor); - - if (maxInboundMetadataSize != null) { - builder.maxInboundMetadataSize(maxInboundMetadataSize); - } - if (maxInboundMessageSize != null) { - builder.maxInboundMessageSize(maxInboundMessageSize); - } - if (keepAliveTime != null) { - builder.keepAliveTime(keepAliveTime.toMillis(), TimeUnit.MILLISECONDS); - } - if (keepAliveTimeout != null) { - builder.keepAliveTimeout(keepAliveTimeout.toMillis(), TimeUnit.MILLISECONDS); - } - if (keepAliveWithoutCalls != null) { - builder.keepAliveWithoutCalls(keepAliveWithoutCalls); - } - if (interceptorProvider != null) { - builder.intercept(interceptorProvider.getInterceptors()); - } - if (channelConfigurator != null) { - builder = channelConfigurator.apply(builder); - } - - ManagedChannel managedChannel = builder.build(); - if (channelPrimer != null) { - channelPrimer.primeChannel(managedChannel); - } - return managedChannel; - } - - /** The endpoint to be used for the channel. */ - public String getEndpoint() { - return endpoint; - } - - /** The time without read activity before sending a keepalive ping. */ - public Duration getKeepAliveTime() { - return keepAliveTime; - } - - /** The time without read activity after sending a keepalive ping. */ - public Duration getKeepAliveTimeout() { - return keepAliveTimeout; - } - - /** Whether keepalive will be performed when there are no outstanding RPCs. */ - public Boolean getKeepAliveWithoutCalls() { - return keepAliveWithoutCalls; - } - - /** The maximum metadata size allowed to be received on the channel. */ - @BetaApi("The surface for maximum metadata size is not stable yet and may change in the future.") - public Integer getMaxInboundMetadataSize() { - return maxInboundMetadataSize; - } - - @Override - public boolean shouldAutoClose() { - return true; - } - - public Builder toBuilder() { - return new Builder(this); - } - - public static Builder newBuilder() { - return new Builder(); - } - - public static final class Builder { - @Deprecated private int processorCount; - private Executor executor; - private HeaderProvider headerProvider; - private String endpoint; - private EnvironmentProvider envProvider; - private MtlsProvider mtlsProvider = new MtlsProvider(); - @Nullable private GrpcInterceptorProvider interceptorProvider; - @Nullable private Integer maxInboundMessageSize; - @Nullable private Integer maxInboundMetadataSize; - @Nullable private Duration keepAliveTime; - @Nullable private Duration keepAliveTimeout; - @Nullable private Boolean keepAliveWithoutCalls; - @Nullable private ApiFunction channelConfigurator; - @Nullable private Credentials credentials; - @Nullable private ChannelPrimer channelPrimer; - private ChannelPoolSettings channelPoolSettings; - @Nullable private Boolean attemptDirectPath; - @Nullable private Boolean allowNonDefaultServiceAccount; - @Nullable private ImmutableMap directPathServiceConfig; - - private Builder() { - processorCount = Runtime.getRuntime().availableProcessors(); - envProvider = System::getenv; - channelPoolSettings = ChannelPoolSettings.staticallySized(1); - } - - private Builder(InstantiatingGrpcChannelProvider provider) { - this.processorCount = provider.processorCount; - this.executor = provider.executor; - this.headerProvider = provider.headerProvider; - this.endpoint = provider.endpoint; - this.envProvider = provider.envProvider; - this.interceptorProvider = provider.interceptorProvider; - this.maxInboundMessageSize = provider.maxInboundMessageSize; - this.maxInboundMetadataSize = provider.maxInboundMetadataSize; - this.keepAliveTime = provider.keepAliveTime; - this.keepAliveTimeout = provider.keepAliveTimeout; - this.keepAliveWithoutCalls = provider.keepAliveWithoutCalls; - this.channelConfigurator = provider.channelConfigurator; - this.credentials = provider.credentials; - this.channelPrimer = provider.channelPrimer; - this.channelPoolSettings = provider.channelPoolSettings; - this.attemptDirectPath = provider.attemptDirectPath; - this.allowNonDefaultServiceAccount = provider.allowNonDefaultServiceAccount; - this.directPathServiceConfig = provider.directPathServiceConfig; - this.mtlsProvider = provider.mtlsProvider; - } - - /** - * Sets the number of available CPUs, used internally for testing. - * - * @deprecated CPU based channel scaling is deprecated, please use RPC based scaling instead via - * {@link Builder#setChannelPoolSettings(ChannelPoolSettings)} - */ - @Deprecated - Builder setProcessorCount(int processorCount) { - this.processorCount = processorCount; - return this; - } - - /** - * Sets the Executor for this TransportChannelProvider. - * - *

This is optional; if it is not provided, needsExecutor() will return true, meaning that an - * Executor must be provided when getChannel is called on the constructed - * TransportChannelProvider instance. Note: GrpcTransportProvider will automatically provide its - * own Executor in this circumstance when it calls getChannel. - */ - public Builder setExecutor(Executor executor) { - this.executor = executor; - return this; - } - - /** @deprecated Please use {@link #setExecutor(Executor)}. */ - @Deprecated - public Builder setExecutorProvider(ExecutorProvider executorProvider) { - return setExecutor((Executor) executorProvider.getExecutor()); - } - - /** - * Sets the HeaderProvider for this TransportChannelProvider. - * - *

This is optional; if it is not provided, needsHeaders() will return true, meaning that - * headers must be provided when getChannel is called on the constructed - * TransportChannelProvider instance. - */ - public Builder setHeaderProvider(HeaderProvider headerProvider) { - this.headerProvider = headerProvider; - return this; - } - - /** Sets the endpoint used to reach the service, eg "localhost:8080". */ - public Builder setEndpoint(String endpoint) { - validateEndpoint(endpoint); - this.endpoint = endpoint; - return this; - } - - @VisibleForTesting - Builder setMtlsProvider(MtlsProvider mtlsProvider) { - this.mtlsProvider = mtlsProvider; - return this; - } - - /** - * Sets the GrpcInterceptorProvider for this TransportChannelProvider. - * - *

The provider will be called once for each underlying gRPC ManagedChannel that is created. - * It is recommended to return a new list of new interceptors on each call so that interceptors - * are not shared among channels, but this is not required. - */ - public Builder setInterceptorProvider(GrpcInterceptorProvider interceptorProvider) { - this.interceptorProvider = interceptorProvider; - return this; - } - - public String getEndpoint() { - return endpoint; - } - - /** The maximum message size allowed to be received on the channel. */ - public Builder setMaxInboundMessageSize(Integer max) { - this.maxInboundMessageSize = max; - return this; - } - - /** The maximum message size allowed to be received on the channel. */ - public Integer getMaxInboundMessageSize() { - return maxInboundMessageSize; - } - - /** The maximum metadata size allowed to be received on the channel. */ - @BetaApi( - "The surface for maximum metadata size is not stable yet and may change in the future.") - public Builder setMaxInboundMetadataSize(Integer max) { - this.maxInboundMetadataSize = max; - return this; - } - - /** The maximum metadata size allowed to be received on the channel. */ - @BetaApi( - "The surface for maximum metadata size is not stable yet and may change in the future.") - public Integer getMaxInboundMetadataSize() { - return maxInboundMetadataSize; - } - - /** The time without read activity before sending a keepalive ping. */ - public Builder setKeepAliveTime(Duration duration) { - this.keepAliveTime = duration; - return this; - } - - /** The time without read activity before sending a keepalive ping. */ - public Duration getKeepAliveTime() { - return keepAliveTime; - } - - /** The time without read activity after sending a keepalive ping. */ - public Builder setKeepAliveTimeout(Duration duration) { - this.keepAliveTimeout = duration; - return this; - } - - /** The time without read activity after sending a keepalive ping. */ - public Duration getKeepAliveTimeout() { - return keepAliveTimeout; - } - - /** Whether keepalive will be performed when there are no outstanding RPCs. */ - public Builder setKeepAliveWithoutCalls(Boolean keepalive) { - this.keepAliveWithoutCalls = keepalive; - return this; - } - - /** Whether keepalive will be performed when there are no outstanding RPCs. */ - public Boolean getKeepAliveWithoutCalls() { - return keepAliveWithoutCalls; - } - - /** @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} */ - @Deprecated - public int getPoolSize() { - return channelPoolSettings.getInitialChannelCount(); - } - - /** @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} */ - @Deprecated - public Builder setPoolSize(int poolSize) { - channelPoolSettings = ChannelPoolSettings.staticallySized(poolSize); - return this; - } - - /** @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} */ - @Deprecated - public Builder setChannelsPerCpu(double multiplier) { - return setChannelsPerCpu(multiplier, 100); - } - - /** @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} */ - @Deprecated - public Builder setChannelsPerCpu(double multiplier, int maxChannels) { - Preconditions.checkArgument(multiplier > 0, "multiplier must be positive"); - Preconditions.checkArgument(maxChannels > 0, "maxChannels must be positive"); - - int channelCount = (int) Math.ceil(processorCount * multiplier); - if (channelCount > maxChannels) { - channelCount = maxChannels; - } - return setChannelPoolSettings(ChannelPoolSettings.staticallySized(channelCount)); - } - - @BetaApi("Channel pool sizing api is not yet stable") - public Builder setChannelPoolSettings(ChannelPoolSettings settings) { - this.channelPoolSettings = settings; - return this; - } - - public Builder setCredentials(Credentials credentials) { - this.credentials = credentials; - return this; - } - - /** - * By setting a channelPrimer, the ChannelPool created by the provider will be refreshing - * ChannelPool. channelPrimer will be invoked periodically when the channels are refreshed - * - *

This is public only for technical reasons, for advanced usage. - * - * @param channelPrimer invoked when the channels are refreshed - * @return builder for the provider - */ - @InternalApi("For internal use by google-cloud-java clients only") - public Builder setChannelPrimer(ChannelPrimer channelPrimer) { - this.channelPrimer = channelPrimer; - return this; - } - - /** Whether attempt DirectPath. */ - @InternalApi("For internal use by google-cloud-java clients only") - public Builder setAttemptDirectPath(boolean attemptDirectPath) { - this.attemptDirectPath = attemptDirectPath; - return this; - } - - /** Whether allow non-default service account for DirectPath. */ - @InternalApi("For internal use by google-cloud-java clients only") - public Builder setAllowNonDefaultServiceAccount(boolean allowNonDefaultServiceAccount) { - this.allowNonDefaultServiceAccount = allowNonDefaultServiceAccount; - return this; - } - - /** - * Sets a service config for direct path. If direct path is not enabled, the provided service - * config will be ignored. - * - *

See - * the service config proto definition for more details. - */ - @InternalApi("For internal use by google-cloud-java clients only") - public Builder setDirectPathServiceConfig(Map serviceConfig) { - Preconditions.checkNotNull(serviceConfig, "serviceConfig"); - this.directPathServiceConfig = ImmutableMap.copyOf(serviceConfig); - return this; - } - - public InstantiatingGrpcChannelProvider build() { - return new InstantiatingGrpcChannelProvider(this); - } - - /** - * Add a callback that can intercept channel creation. - * - *

This can be used for advanced configuration like setting the netty event loop. The - * callback will be invoked with a fully configured channel builder, which the callback can - * augment or replace. - */ - @BetaApi("Surface for advanced channel configuration is not yet stable") - public Builder setChannelConfigurator( - @Nullable ApiFunction channelConfigurator) { - this.channelConfigurator = channelConfigurator; - return this; - } - - @Nullable - public ApiFunction getChannelConfigurator() { - return channelConfigurator; - } - } - - private static ImmutableMap getDefaultDirectPathServiceConfig() { - // When channel pooling is enabled, force the pick_first grpclb strategy. - // This is necessary to avoid the multiplicative effect of creating channel pool with - // `poolSize` number of `ManagedChannel`s, each with a `subSetting` number of number of - // subchannels. - // See the service config proto definition for more details: - // https://github.com/grpc/grpc-proto/blob/master/grpc/service_config/service_config.proto - ImmutableMap pickFirstStrategy = - ImmutableMap.of("pick_first", ImmutableMap.of()); - - ImmutableMap childPolicy = - ImmutableMap.of("childPolicy", ImmutableList.of(pickFirstStrategy)); - - ImmutableMap grpcLbPolicy = - ImmutableMap.of("grpclb", childPolicy); - - return ImmutableMap.of("loadBalancingConfig", ImmutableList.of(grpcLbPolicy)); - } - - private static void validateEndpoint(String endpoint) { - int colon = endpoint.lastIndexOf(':'); - if (colon < 0) { - throw new IllegalArgumentException( - String.format("invalid endpoint, expecting \":\"")); - } - Integer.parseInt(endpoint.substring(colon + 1)); - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/ProtoOperationTransformers.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/ProtoOperationTransformers.java deleted file mode 100644 index e3d990d9e..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/ProtoOperationTransformers.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.core.ApiFunction; -import com.google.api.gax.longrunning.OperationSnapshot; -import com.google.api.gax.rpc.ApiExceptionFactory; -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.protobuf.Any; -import com.google.protobuf.InvalidProtocolBufferException; -import com.google.protobuf.Message; - -/** Public for technical reasons; intended for use by generated code. */ -public class ProtoOperationTransformers { - private ProtoOperationTransformers() {} - - public static class ResponseTransformer - implements ApiFunction { - private final AnyTransformer transformer; - - private ResponseTransformer(Class packedClass) { - this.transformer = new AnyTransformer<>(packedClass); - } - - @Override - public ResponseT apply(OperationSnapshot operationSnapshot) { - if (!operationSnapshot.getErrorCode().getCode().equals(Code.OK)) { - throw ApiExceptionFactory.createException( - "Operation with name \"" - + operationSnapshot.getName() - + "\" failed with status = " - + operationSnapshot.getErrorCode() - + " and message = " - + operationSnapshot.getErrorMessage(), - null, - operationSnapshot.getErrorCode(), - false); - } - - if (!(operationSnapshot.getResponse() instanceof Any)) { - return (ResponseT) operationSnapshot.getResponse(); - } - - try { - return transformer.apply((Any) operationSnapshot.getResponse()); - } catch (RuntimeException e) { - throw ApiExceptionFactory.createException( - "Operation with name \"" - + operationSnapshot.getName() - + "\" succeeded, but encountered a problem unpacking it.", - e, - operationSnapshot.getErrorCode(), - false); - } - } - - public static ResponseTransformer create( - Class packedClass) { - return new ResponseTransformer<>(packedClass); - } - } - - public static class MetadataTransformer - implements ApiFunction { - private final AnyTransformer transformer; - - private MetadataTransformer(Class packedClass) { - this.transformer = new AnyTransformer<>(packedClass); - } - - @Override - public MetadataT apply(OperationSnapshot operationSnapshot) { - if (!(operationSnapshot.getMetadata() instanceof Any)) { - return (MetadataT) operationSnapshot.getMetadata(); - } - try { - return transformer.apply((Any) operationSnapshot.getMetadata()); - } catch (RuntimeException e) { - throw ApiExceptionFactory.createException( - "Polling operation with name \"" - + operationSnapshot.getName() - + "\" succeeded, but encountered a problem unpacking it.", - e, - operationSnapshot.getErrorCode(), - false); - } - } - - public static MetadataTransformer create( - Class packedClass) { - return new MetadataTransformer<>(packedClass); - } - } - - static class AnyTransformer implements ApiFunction { - private final Class packedClass; - - public AnyTransformer(Class packedClass) { - this.packedClass = packedClass; - } - - @Override - public PackedT apply(Any input) { - try { - return input == null || packedClass == null ? null : input.unpack(packedClass); - } catch (InvalidProtocolBufferException | ClassCastException e) { - throw new IllegalStateException( - "Failed to unpack object from 'any' field. Expected " - + packedClass.getName() - + ", found " - + input.getTypeUrl()); - } - } - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/ResponseMetadataHandler.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/ResponseMetadataHandler.java deleted file mode 100644 index 4ce195602..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/ResponseMetadataHandler.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import io.grpc.Metadata; - -/** - * An interface to handle metadata returned from an RPC. A ResponseMetadataHandler is used by the - * GrpcMetadataHandlerInterceptor class to provide custom handling of the returned headers and - * trailers. - */ -public interface ResponseMetadataHandler { - - /** Handle the headers returned by an RPC. */ - void onHeaders(Metadata metadata); - - /** Handle the trailers returned by an RPC. */ - void onTrailers(Metadata metadata); -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/StreamObserverDelegate.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/StreamObserverDelegate.java deleted file mode 100644 index 3b66ba1ca..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/StreamObserverDelegate.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.gax.rpc.ApiStreamObserver; -import io.grpc.stub.StreamObserver; - -/** - * A delegate class that transfers calls to the StreamObserver object. - * - *

Package-private for internal use. - */ -class StreamObserverDelegate implements ApiStreamObserver { - - private final StreamObserver delegate; - - public StreamObserverDelegate(StreamObserver delegate) { - this.delegate = delegate; - } - - @Override - public void onNext(V v) { - delegate.onNext(v); - } - - @Override - public void onError(Throwable throwable) { - delegate.onError(throwable); - } - - @Override - public void onCompleted() { - delegate.onCompleted(); - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/nativeimage/GrpcNettyFeature.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/nativeimage/GrpcNettyFeature.java deleted file mode 100644 index c2cf0a28d..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/nativeimage/GrpcNettyFeature.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.gax.grpc.nativeimage; - -import static com.google.api.gax.nativeimage.NativeImageUtils.registerClassForReflection; -import static com.google.api.gax.nativeimage.NativeImageUtils.registerClassHierarchyForReflection; -import static com.google.api.gax.nativeimage.NativeImageUtils.registerForReflectiveInstantiation; -import static com.google.api.gax.nativeimage.NativeImageUtils.registerForUnsafeFieldAccess; - -import org.graalvm.nativeimage.hosted.Feature; - -/** Configures Native Image settings for the grpc-netty-shaded dependency. */ -final class GrpcNettyFeature implements Feature { - - private static final String GRPC_NETTY_SHADED_CLASS = - "io.grpc.netty.shaded.io.grpc.netty.NettyServer"; - - private static final String GOOGLE_AUTH_CLASS = - "com.google.auth.oauth2.ServiceAccountCredentials"; - - private static final String NETTY_SHADED_PACKAGE = - "io.grpc.netty.shaded.io.netty.util.internal.shaded."; - - @Override - public void beforeAnalysis(BeforeAnalysisAccess access) { - loadGoogleAuthClasses(access); - loadGrpcNettyClasses(access); - loadMiscClasses(access); - } - - private static void loadGoogleAuthClasses(BeforeAnalysisAccess access) { - // For com.google.auth:google-auth-library-oauth2-http - Class authClass = access.findClassByName(GOOGLE_AUTH_CLASS); - if (authClass != null) { - registerClassHierarchyForReflection(access, GOOGLE_AUTH_CLASS); - registerClassHierarchyForReflection( - access, "com.google.auth.oauth2.ServiceAccountJwtAccessCredentials"); - } - } - - private static void loadGrpcNettyClasses(BeforeAnalysisAccess access) { - // For io.grpc:grpc-netty-shaded - Class nettyShadedClass = access.findClassByName(GRPC_NETTY_SHADED_CLASS); - if (nettyShadedClass != null) { - // Misc. classes used by grpc-netty-shaded - registerForReflectiveInstantiation( - access, "io.grpc.netty.shaded.io.netty.channel.socket.nio.NioSocketChannel"); - registerClassForReflection( - access, "io.grpc.netty.shaded.io.netty.util.internal.NativeLibraryUtil"); - registerClassForReflection(access, "io.grpc.netty.shaded.io.netty.util.ReferenceCountUtil"); - registerClassForReflection( - access, "io.grpc.netty.shaded.io.netty.buffer.AbstractByteBufAllocator"); - - // Epoll Libraries - registerClassForReflection(access, "io.grpc.netty.shaded.io.netty.channel.epoll.Epoll"); - registerClassForReflection( - access, "io.grpc.netty.shaded.io.netty.channel.epoll.EpollChannelOption"); - registerClassForReflection( - access, "io.grpc.netty.shaded.io.netty.channel.epoll.EpollEventLoopGroup"); - registerForReflectiveInstantiation( - access, "io.grpc.netty.shaded.io.netty.channel.epoll.EpollServerSocketChannel"); - registerForReflectiveInstantiation( - access, "io.grpc.netty.shaded.io.netty.channel.epoll.EpollSocketChannel"); - - // Unsafe field accesses - registerForUnsafeFieldAccess( - access, - NETTY_SHADED_PACKAGE + "org.jctools.queues.MpscArrayQueueProducerIndexField", - "producerIndex"); - registerForUnsafeFieldAccess( - access, - NETTY_SHADED_PACKAGE + "org.jctools.queues.MpscArrayQueueProducerLimitField", - "producerLimit"); - registerForUnsafeFieldAccess( - access, - NETTY_SHADED_PACKAGE + "org.jctools.queues.MpscArrayQueueConsumerIndexField", - "consumerIndex"); - registerForUnsafeFieldAccess( - access, - NETTY_SHADED_PACKAGE + "org.jctools.queues.BaseMpscLinkedArrayQueueProducerFields", - "producerIndex"); - registerForUnsafeFieldAccess( - access, - NETTY_SHADED_PACKAGE + "org.jctools.queues.BaseMpscLinkedArrayQueueColdProducerFields", - "producerLimit"); - registerForUnsafeFieldAccess( - access, - NETTY_SHADED_PACKAGE + "org.jctools.queues.BaseMpscLinkedArrayQueueConsumerFields", - "consumerIndex"); - } - } - - /** Miscellaneous classes that need to be registered coming from various JARs. */ - private static void loadMiscClasses(BeforeAnalysisAccess access) { - registerClassHierarchyForReflection(access, "com.google.protobuf.DescriptorProtos"); - registerClassForReflection(access, "com.google.api.FieldBehavior"); - - registerForUnsafeFieldAccess(access, "javax.net.ssl.SSLContext", "contextSpi"); - } -} diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/nativeimage/ProtobufMessageFeature.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/nativeimage/ProtobufMessageFeature.java deleted file mode 100644 index edea6dee7..000000000 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/nativeimage/ProtobufMessageFeature.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.gax.grpc.nativeimage; - -import com.google.api.gax.nativeimage.NativeImageUtils; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.List; -import org.graalvm.nativeimage.hosted.Feature; -import org.graalvm.nativeimage.hosted.RuntimeReflection; - -/** - * A optional feature which registers reflective usages of the GRPC Protobuf libraries. - * - *

This feature is only needed if you need to access proto objects reflectively (such as - * printing/logging proto objects). - */ -final class ProtobufMessageFeature implements Feature { - - // Proto classes to check on the classpath. - private static final String PROTO_MESSAGE_CLASS = "com.google.protobuf.GeneratedMessageV3"; - private static final String PROTO_ENUM_CLASS = "com.google.protobuf.ProtocolMessageEnum"; - private static final String ENUM_VAL_DESCRIPTOR_CLASS = - "com.google.protobuf.Descriptors$EnumValueDescriptor"; - - // Prefixes of methods accessed reflectively by - // com.google.protobuf.GeneratedMessageV3$ReflectionInvoker - private static final List METHOD_ACCESSOR_PREFIXES = - Arrays.asList("get", "set", "has", "add", "clear", "newBuilder"); - - @Override - public void beforeAnalysis(BeforeAnalysisAccess access) { - Class protoMessageClass = access.findClassByName(PROTO_MESSAGE_CLASS); - if (protoMessageClass != null) { - Method internalAccessorMethod = - NativeImageUtils.getMethodOrFail(protoMessageClass, "internalGetFieldAccessorTable"); - - // Finds every class whose `internalGetFieldAccessorTable()` is reached and registers it. - // `internalGetFieldAccessorTable()` is used downstream to access the class reflectively. - access.registerMethodOverrideReachabilityHandler( - (duringAccess, method) -> { - registerFieldAccessors(method.getDeclaringClass()); - registerFieldAccessors(getBuilderClass(method.getDeclaringClass())); - }, - internalAccessorMethod); - } - - Class protoEnumClass = access.findClassByName(PROTO_ENUM_CLASS); - if (protoEnumClass != null) { - // Finds every reachable proto enum class and registers specific methods for reflection. - access.registerSubtypeReachabilityHandler( - (duringAccess, subtypeClass) -> { - if (!PROTO_ENUM_CLASS.equals(subtypeClass.getName())) { - Method method = - NativeImageUtils.getMethodOrFail( - subtypeClass, - "valueOf", - duringAccess.findClassByName(ENUM_VAL_DESCRIPTOR_CLASS)); - RuntimeReflection.register(method); - - method = NativeImageUtils.getMethodOrFail(subtypeClass, "getValueDescriptor"); - RuntimeReflection.register(method); - } - }, - protoEnumClass); - } - } - - /** Given a proto class, registers the public accessor methods for the provided proto class. */ - private static void registerFieldAccessors(Class protoClass) { - for (Method method : protoClass.getMethods()) { - boolean hasAccessorPrefix = - METHOD_ACCESSOR_PREFIXES.stream().anyMatch(prefix -> method.getName().startsWith(prefix)); - if (hasAccessorPrefix) { - RuntimeReflection.register(method); - } - } - } - - /** Given a proto class, returns the Builder nested class. */ - private static Class getBuilderClass(Class protoClass) { - for (Class clazz : protoClass.getClasses()) { - if (clazz.getName().endsWith("Builder")) { - return clazz; - } - } - return null; - } -} diff --git a/gax-grpc/src/main/java/com/google/longrunning/OperationsClient.java b/gax-grpc/src/main/java/com/google/longrunning/OperationsClient.java deleted file mode 100644 index 024950cda..000000000 --- a/gax-grpc/src/main/java/com/google/longrunning/OperationsClient.java +++ /dev/null @@ -1,666 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.longrunning; - -import static com.google.common.util.concurrent.MoreExecutors.directExecutor; - -import com.google.api.core.ApiFunction; -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.api.gax.core.BackgroundResource; -import com.google.api.gax.paging.AbstractFixedSizeCollection; -import com.google.api.gax.paging.AbstractPage; -import com.google.api.gax.paging.AbstractPagedListResponse; -import com.google.api.gax.rpc.PageContext; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.longrunning.stub.OperationsStub; -import com.google.longrunning.stub.OperationsStubSettings; -import com.google.protobuf.Empty; -import java.io.IOException; -import java.util.List; -import java.util.concurrent.TimeUnit; - -/** - * Service Description: Manages long-running operations with an API service. - * - *

When an API method normally takes long time to complete, it can be designed to return - * [Operation][google.longrunning.Operation] to the client, and the client can use this interface to - * receive the real response asynchronously by polling the operation resource, or pass the operation - * resource to another API (such as Google Cloud Pub/Sub API) to receive the response. Any API - * service that returns long-running operations should implement the `Operations` interface so - * developers can have a consistent client experience. - * - *

This class provides the ability to make remote calls to the backing service through method - * calls that map to API methods. Sample code to get started: - * - *

- * 
- * try (OperationsClient operationsClient = OperationsClient.create()) {
- *   String name = "";
- *   Operation response = operationsClient.getOperation(name);
- * }
- * 
- * 
- * - *

Note: close() needs to be called on the operationsClient object to clean up resources such as - * threads. In the example above, try-with-resources is used, which automatically calls close(). - * - *

The surface of this class includes several types of Java methods for each of the API's - * methods: - * - *

    - *
  1. A "flattened" method. With this type of method, the fields of the request type have been - * converted into function parameters. It may be the case that not all fields are available as - * parameters, and not every API method will have a flattened method entry point. - *
  2. A "request object" method. This type of method only takes one parameter, a request object, - * which must be constructed before the call. Not every API method will have a request object - * method. - *
  3. A "callable" method. This type of method takes no parameters and returns an immutable API - * callable object, which can be used to initiate calls to the service. - *
- * - *

See the individual methods for example code. - * - *

Many parameters require resource names to be formatted in a particular way. To assist with - * these names, this class includes a format method for each type of name, and additionally a parse - * method to extract the individual identifiers contained within names that are returned. - * - *

This class can be customized by passing in a custom instance of OperationsSettings to - * create(). For example: - * - *

To customize credentials: - * - *

- * 
- * OperationsSettings operationsSettings =
- *     OperationsSettings.newBuilder()
- *         .setCredentialsProvider(FixedCredentialsProvider.create(myCredentials))
- *         .build();
- * OperationsClient operationsClient =
- *     OperationsClient.create(operationsSettings);
- * 
- * 
- */ -public class OperationsClient implements BackgroundResource { - private final OperationsSettings settings; - private final OperationsStub stub; - - /** - * Constructs an instance of OperationsClient, using the given settings. The channels are created - * based on the settings passed in, or defaults for any settings that are not set. - */ - public static final OperationsClient create(OperationsSettings settings) throws IOException { - return new OperationsClient(settings); - } - - /** - * Constructs an instance of OperationsClient, using the given stub for making calls. This is for - * advanced usage - prefer to use OperationsSettings}. - */ - public static final OperationsClient create(OperationsStub stub) { - return new OperationsClient(stub); - } - - /** - * Constructs an instance of OperationsClient, using the given settings. This is protected so that - * it is easy to make a subclass, but otherwise, the static factory methods should be preferred. - */ - protected OperationsClient(OperationsSettings settings) throws IOException { - this.settings = settings; - this.stub = ((OperationsStubSettings) settings.getStubSettings()).createStub(); - } - - protected OperationsClient(OperationsStub stub) { - this.settings = null; - this.stub = stub; - } - - public final OperationsSettings getSettings() { - return settings; - } - - public OperationsStub getStub() { - return stub; - } - - /** - * Gets the latest state of a long-running operation. Clients can use this method to poll the - * operation result at intervals as recommended by the API service. - * - *

Sample code: - * - *


-   * try (OperationsClient operationsClient = OperationsClient.create()) {
-   *   String name = "";
-   *   Operation response = operationsClient.getOperation(name);
-   * }
-   * 
- * - * @param name The name of the operation resource. - * @throws com.google.api.gax.rpc.ApiException if the remote call fails - */ - public final Operation getOperation(String name) { - - GetOperationRequest request = GetOperationRequest.newBuilder().setName(name).build(); - return getOperation(request); - } - - /** - * Gets the latest state of a long-running operation. Clients can use this method to poll the - * operation result at intervals as recommended by the API service. - * - *

Sample code: - * - *


-   * try (OperationsClient operationsClient = OperationsClient.create()) {
-   *   String name = "";
-   *   GetOperationRequest request = GetOperationRequest.newBuilder()
-   *     .setName(name)
-   *     .build();
-   *   Operation response = operationsClient.getOperation(request);
-   * }
-   * 
- * - * @param request the request object containing all of the parameters for the API call - * @throws com.google.api.gax.rpc.ApiException if the remote call fails - */ - private final Operation getOperation(GetOperationRequest request) { - return getOperationCallable().call(request); - } - - /** - * Gets the latest state of a long-running operation. Clients can use this method to poll the - * operation result at intervals as recommended by the API service. - * - *

Sample code: - * - *


-   * try (OperationsClient operationsClient = OperationsClient.create()) {
-   *   String name = "";
-   *   GetOperationRequest request = GetOperationRequest.newBuilder()
-   *     .setName(name)
-   *     .build();
-   *   ApiFuture<Operation> future = operationsClient.getOperationCallable().futureCall(request);
-   *   // Do something
-   *   Operation response = future.get();
-   * }
-   * 
- */ - public final UnaryCallable getOperationCallable() { - return stub.getOperationCallable(); - } - - /** - * Lists operations that match the specified filter in the request. If the server doesn't support - * this method, it returns `UNIMPLEMENTED`. - * - *

NOTE: the `name` binding below allows API services to override the binding to use different - * resource name schemes, such as `users/*/operations`. - * - *

Sample code: - * - *


-   * try (OperationsClient operationsClient = OperationsClient.create()) {
-   *   String name = "";
-   *   String filter = "";
-   *   for (Operation element : operationsClient.listOperations(name, filter).iterateAll()) {
-   *     // doThingsWith(element);
-   *   }
-   * }
-   * 
- * - * @param name The name of the operation collection. - * @param filter The standard list filter. - * @throws com.google.api.gax.rpc.ApiException if the remote call fails - */ - public final ListOperationsPagedResponse listOperations(String name, String filter) { - ListOperationsRequest request = - ListOperationsRequest.newBuilder().setName(name).setFilter(filter).build(); - return listOperations(request); - } - - /** - * Lists operations that match the specified filter in the request. If the server doesn't support - * this method, it returns `UNIMPLEMENTED`. - * - *

NOTE: the `name` binding below allows API services to override the binding to use different - * resource name schemes, such as `users/*/operations`. - * - *

Sample code: - * - *


-   * try (OperationsClient operationsClient = OperationsClient.create()) {
-   *   String name = "";
-   *   String filter = "";
-   *   ListOperationsRequest request = ListOperationsRequest.newBuilder()
-   *     .setName(name)
-   *     .setFilter(filter)
-   *     .build();
-   *   for (Operation element : operationsClient.listOperations(request).iterateAll()) {
-   *     // doThingsWith(element);
-   *   }
-   * }
-   * 
- * - * @param request The request object containing all of the parameters for the API call. - * @throws com.google.api.gax.rpc.ApiException if the remote call fails - */ - public final ListOperationsPagedResponse listOperations(ListOperationsRequest request) { - return listOperationsPagedCallable().call(request); - } - - /** - * Lists operations that match the specified filter in the request. If the server doesn't support - * this method, it returns `UNIMPLEMENTED`. - * - *

NOTE: the `name` binding below allows API services to override the binding to use different - * resource name schemes, such as `users/*/operations`. - * - *

Sample code: - * - *


-   * try (OperationsClient operationsClient = OperationsClient.create()) {
-   *   String name = "";
-   *   String filter = "";
-   *   ListOperationsRequest request = ListOperationsRequest.newBuilder()
-   *     .setName(name)
-   *     .setFilter(filter)
-   *     .build();
-   *   ApiFuture<ListOperationsPagedResponse> future = operationsClient.listOperationsPagedCallable().futureCall(request);
-   *   // Do something
-   *   for (Operation element : future.get().iterateAll()) {
-   *     // doThingsWith(element);
-   *   }
-   * }
-   * 
- */ - public final UnaryCallable - listOperationsPagedCallable() { - return stub.listOperationsPagedCallable(); - } - - /** - * Lists operations that match the specified filter in the request. If the server doesn't support - * this method, it returns `UNIMPLEMENTED`. - * - *

NOTE: the `name` binding below allows API services to override the binding to use different - * resource name schemes, such as `users/*/operations`. - * - *

Sample code: - * - *


-   * try (OperationsClient operationsClient = OperationsClient.create()) {
-   *   String name = "";
-   *   String filter = "";
-   *   ListOperationsRequest request = ListOperationsRequest.newBuilder()
-   *     .setName(name)
-   *     .setFilter(filter)
-   *     .build();
-   *   while (true) {
-   *     ListOperationsResponse response = operationsClient.listOperationsCallable().call(request);
-   *     for (Operation element : response.getOperationsList()) {
-   *       // doThingsWith(element);
-   *     }
-   *     String nextPageToken = response.getNextPageToken();
-   *     if (!Strings.isNullOrEmpty(nextPageToken)) {
-   *       request = request.toBuilder().setPageToken(nextPageToken).build();
-   *     } else {
-   *       break;
-   *     }
-   *   }
-   * }
-   * 
- */ - public final UnaryCallable - listOperationsCallable() { - return stub.listOperationsCallable(); - } - - /** - * Starts asynchronous cancellation on a long-running operation. The server makes a best effort to - * cancel the operation, but success is not guaranteed. If the server doesn't support this method, - * it returns `google.rpc.Code.UNIMPLEMENTED`. Clients can use - * [Operations.GetOperation][google.longrunning.Operations.GetOperation] or other methods to check - * whether the cancellation succeeded or whether the operation completed despite cancellation. On - * successful cancellation, the operation is not deleted; instead, it becomes an operation with an - * [Operation.error][google.longrunning.Operation.error] value with a - * [google.rpc.Status.code][google.rpc.Status.code] of 1, corresponding to `Code.CANCELLED`. - * - *

Sample code: - * - *


-   * try (OperationsClient operationsClient = OperationsClient.create()) {
-   *   String name = "";
-   *   operationsClient.cancelOperation(name);
-   * }
-   * 
- * - * @param name The name of the operation resource to be cancelled. - * @throws com.google.api.gax.rpc.ApiException if the remote call fails - */ - public final void cancelOperation(String name) { - - CancelOperationRequest request = CancelOperationRequest.newBuilder().setName(name).build(); - cancelOperation(request); - } - - /** - * Starts asynchronous cancellation on a long-running operation. The server makes a best effort to - * cancel the operation, but success is not guaranteed. If the server doesn't support this method, - * it returns `google.rpc.Code.UNIMPLEMENTED`. Clients can use - * [Operations.GetOperation][google.longrunning.Operations.GetOperation] or other methods to check - * whether the cancellation succeeded or whether the operation completed despite cancellation. On - * successful cancellation, the operation is not deleted; instead, it becomes an operation with an - * [Operation.error][google.longrunning.Operation.error] value with a - * [google.rpc.Status.code][google.rpc.Status.code] of 1, corresponding to `Code.CANCELLED`. - * - *

Sample code: - * - *


-   * try (OperationsClient operationsClient = OperationsClient.create()) {
-   *   String name = "";
-   *   CancelOperationRequest request = CancelOperationRequest.newBuilder()
-   *     .setName(name)
-   *     .build();
-   *   operationsClient.cancelOperation(request);
-   * }
-   * 
- * - * @param request The request object containing all of the parameters for the API call. - * @throws com.google.api.gax.rpc.ApiException if the remote call fails - */ - private final void cancelOperation(CancelOperationRequest request) { - cancelOperationCallable().call(request); - } - - /** - * Starts asynchronous cancellation on a long-running operation. The server makes a best effort to - * cancel the operation, but success is not guaranteed. If the server doesn't support this method, - * it returns `google.rpc.Code.UNIMPLEMENTED`. Clients can use - * [Operations.GetOperation][google.longrunning.Operations.GetOperation] or other methods to check - * whether the cancellation succeeded or whether the operation completed despite cancellation. On - * successful cancellation, the operation is not deleted; instead, it becomes an operation with an - * [Operation.error][google.longrunning.Operation.error] value with a - * [google.rpc.Status.code][google.rpc.Status.code] of 1, corresponding to `Code.CANCELLED`. - * - *

Sample code: - * - *


-   * try (OperationsClient operationsClient = OperationsClient.create()) {
-   *   String name = "";
-   *   CancelOperationRequest request = CancelOperationRequest.newBuilder()
-   *     .setName(name)
-   *     .build();
-   *   ApiFuture<Void> future = operationsClient.cancelOperationCallable().futureCall(request);
-   *   // Do something
-   *   future.get();
-   * }
-   * 
- */ - public final UnaryCallable cancelOperationCallable() { - return stub.cancelOperationCallable(); - } - - /** - * Deletes a long-running operation. This method indicates that the client is no longer interested - * in the operation result. It does not cancel the operation. If the server doesn't support this - * method, it returns `google.rpc.Code.UNIMPLEMENTED`. - * - *

Sample code: - * - *


-   * try (OperationsClient operationsClient = OperationsClient.create()) {
-   *   String name = "";
-   *   operationsClient.deleteOperation(name);
-   * }
-   * 
- * - * @param name The name of the operation resource to be deleted. - * @throws com.google.api.gax.rpc.ApiException if the remote call fails - */ - public final void deleteOperation(String name) { - - DeleteOperationRequest request = DeleteOperationRequest.newBuilder().setName(name).build(); - deleteOperation(request); - } - - /** - * Deletes a long-running operation. This method indicates that the client is no longer interested - * in the operation result. It does not cancel the operation. If the server doesn't support this - * method, it returns `google.rpc.Code.UNIMPLEMENTED`. - * - *

Sample code: - * - *


-   * try (OperationsClient operationsClient = OperationsClient.create()) {
-   *   String name = "";
-   *   DeleteOperationRequest request = DeleteOperationRequest.newBuilder()
-   *     .setName(name)
-   *     .build();
-   *   operationsClient.deleteOperation(request);
-   * }
-   * 
- * - * @param request The request object containing all of the parameters for the API call. - * @throws com.google.api.gax.rpc.ApiException if the remote call fails - */ - private final void deleteOperation(DeleteOperationRequest request) { - deleteOperationCallable().call(request); - } - - /** - * Deletes a long-running operation. This method indicates that the client is no longer interested - * in the operation result. It does not cancel the operation. If the server doesn't support this - * method, it returns `google.rpc.Code.UNIMPLEMENTED`. - * - *

Sample code: - * - *


-   * try (OperationsClient operationsClient = OperationsClient.create()) {
-   *   String name = "";
-   *   DeleteOperationRequest request = DeleteOperationRequest.newBuilder()
-   *     .setName(name)
-   *     .build();
-   *   ApiFuture<Void> future = operationsClient.deleteOperationCallable().futureCall(request);
-   *   // Do something
-   *   future.get();
-   * }
-   * 
- */ - public final UnaryCallable deleteOperationCallable() { - return stub.deleteOperationCallable(); - } - - /** - * Waits until the specified long-running operation is done or reaches at most a specified - * timeout, returning the latest state. If the operation is already done, the latest state is - * immediately returned. If the timeout specified is greater than the default HTTP/RPC timeout, - * the HTTP/RPC timeout is used. If the server does not support this method, it returns - * `google.rpc.Code.UNIMPLEMENTED`. Note that this method is on a best-effort basis. It may return - * the latest state before the specified timeout (including immediately), meaning even an - * immediate response is no guarantee that the operation is done. - * - *

Sample code: - * - *


-   * try (OperationsClient operationsClient = OperationsClient.create()) {
-   *   String name = "";
-   *   WaitOperationRequest request = WaitOperationRequest.newBuilder()
-   *     .setName(name)
-   *     .setTimeout(Duration.ofMillis(100))
-   *     .build();
-   *   Operation response = operationsClient.waitOperation(request);
-   * }
-   * 
- * - * @param request the request object containing all of the parameters for the API call. - * @throws com.google.api.gax.rpc.ApiException if the remote call fails - */ - public final Operation waitOperation(WaitOperationRequest request) { - return waitOperationCallable().call(request); - } - - /** - * Waits until the specified long-running operation is done or reaches at most a specified - * timeout, returning the latest state. If the operation is already done, the latest state is - * immediately returned. If the timeout specified is greater than the default HTTP/RPC timeout, - * the HTTP/RPC timeout is used. If the server does not support this method, it returns - * `google.rpc.Code.UNIMPLEMENTED`. Note that this method is on a best-effort basis. It may return - * the latest state before the specified timeout (including immediately), meaning even an - * immediate response is no guarantee that the operation is done. - * - *

Sample code: - * - *


-   * try (OperationsClient operationsClient = OperationsClient.create()) {
-   *   String name = "";
-   *   WaitOperationRequest request = WaitOperationRequest.newBuilder()
-   *     .setName(name)
-   *     .setTimeout(Duration.ofMillis(100))
-   *     .build();
-   *   ApiFuture<Operation> future = operationsClient.waitOperationCallable().futureCall(request);
-   * }
-   * 
- */ - public final UnaryCallable waitOperationCallable() { - return stub.waitOperationCallable(); - } - - @Override - public final void close() { - stub.close(); - } - - @Override - public void shutdown() { - stub.shutdown(); - } - - @Override - public boolean isShutdown() { - return stub.isShutdown(); - } - - @Override - public boolean isTerminated() { - return stub.isTerminated(); - } - - @Override - public void shutdownNow() { - stub.shutdownNow(); - } - - @Override - public boolean awaitTermination(long duration, TimeUnit unit) throws InterruptedException { - return stub.awaitTermination(duration, unit); - } - - public static class ListOperationsPagedResponse - extends AbstractPagedListResponse< - ListOperationsRequest, - ListOperationsResponse, - Operation, - ListOperationsPage, - ListOperationsFixedSizeCollection> { - - public static ApiFuture createAsync( - PageContext context, - ApiFuture futureResponse) { - ApiFuture futurePage = - ListOperationsPage.createEmptyPage().createPageAsync(context, futureResponse); - return ApiFutures.transform( - futurePage, - new ApiFunction() { - @Override - public ListOperationsPagedResponse apply(ListOperationsPage input) { - return new ListOperationsPagedResponse(input); - } - }, - directExecutor()); - } - - private ListOperationsPagedResponse(ListOperationsPage page) { - super(page, ListOperationsFixedSizeCollection.createEmptyCollection()); - } - } - - public static class ListOperationsPage - extends AbstractPage< - ListOperationsRequest, ListOperationsResponse, Operation, ListOperationsPage> { - - private ListOperationsPage( - PageContext context, - ListOperationsResponse response) { - super(context, response); - } - - private static ListOperationsPage createEmptyPage() { - return new ListOperationsPage(null, null); - } - - @Override - protected ListOperationsPage createPage( - PageContext context, - ListOperationsResponse response) { - return new ListOperationsPage(context, response); - } - - @Override - public ApiFuture createPageAsync( - PageContext context, - ApiFuture futureResponse) { - return super.createPageAsync(context, futureResponse); - } - } - - public static class ListOperationsFixedSizeCollection - extends AbstractFixedSizeCollection< - ListOperationsRequest, - ListOperationsResponse, - Operation, - ListOperationsPage, - ListOperationsFixedSizeCollection> { - - private ListOperationsFixedSizeCollection(List pages, int collectionSize) { - super(pages, collectionSize); - } - - private static ListOperationsFixedSizeCollection createEmptyCollection() { - return new ListOperationsFixedSizeCollection(null, 0); - } - - @Override - protected ListOperationsFixedSizeCollection createCollection( - List pages, int collectionSize) { - return new ListOperationsFixedSizeCollection(pages, collectionSize); - } - } -} diff --git a/gax-grpc/src/main/java/com/google/longrunning/OperationsSettings.java b/gax-grpc/src/main/java/com/google/longrunning/OperationsSettings.java deleted file mode 100644 index 22ea7e5a1..000000000 --- a/gax-grpc/src/main/java/com/google/longrunning/OperationsSettings.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.longrunning; - -import com.google.api.core.ApiFunction; -import com.google.api.gax.core.GoogleCredentialsProvider; -import com.google.api.gax.core.InstantiatingExecutorProvider; -import com.google.api.gax.rpc.ApiClientHeaderProvider; -import com.google.api.gax.rpc.ClientContext; -import com.google.api.gax.rpc.ClientSettings; -import com.google.api.gax.rpc.PagedCallSettings; -import com.google.api.gax.rpc.UnaryCallSettings; -import com.google.longrunning.OperationsClient.ListOperationsPagedResponse; -import com.google.longrunning.stub.OperationsStubSettings; -import com.google.protobuf.Empty; -import java.io.IOException; - -/** Settings class to configure an instance of {@link OperationsClient}. */ -public class OperationsSettings extends ClientSettings { - /** Returns the object with the settings used for calls to getOperation. */ - public UnaryCallSettings getOperationSettings() { - return ((OperationsStubSettings) getStubSettings()).getOperationSettings(); - } - - /** Returns the object with the settings used for calls to listOperations. */ - public PagedCallSettings< - ListOperationsRequest, ListOperationsResponse, ListOperationsPagedResponse> - listOperationsSettings() { - return ((OperationsStubSettings) getStubSettings()).listOperationsSettings(); - } - - /** Returns the object with the settings used for calls to cancelOperation. */ - public UnaryCallSettings cancelOperationSettings() { - return ((OperationsStubSettings) getStubSettings()).cancelOperationSettings(); - } - - /** Returns the object with the settings used for calls to deleteOperation. */ - public UnaryCallSettings deleteOperationSettings() { - return ((OperationsStubSettings) getStubSettings()).deleteOperationSettings(); - } - - /** Returns the object with the settings used for calls to waitOperation. */ - public UnaryCallSettings waitOperationSettings() { - return ((OperationsStubSettings) getStubSettings()).waitOperationSettings(); - } - - public static final OperationsSettings create(OperationsStubSettings stub) throws IOException { - return new OperationsSettings.Builder(stub.toBuilder()).build(); - } - - /** Returns a builder for the default ExecutorProvider for this service. */ - public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuilder() { - return OperationsStubSettings.defaultExecutorProviderBuilder(); - } - - /** Returns a builder for the default credentials for this service. */ - public static GoogleCredentialsProvider.Builder defaultCredentialsProviderBuilder() { - return OperationsStubSettings.defaultCredentialsProviderBuilder(); - } - - public static ApiClientHeaderProvider.Builder defaultApiClientHeaderProviderBuilder() { - return OperationsStubSettings.defaultApiClientHeaderProviderBuilder(); - } - - /** Returns a new builder for this class. */ - public static Builder newBuilder() { - return Builder.createDefault(); - } - - /** Returns a new builder for this class. */ - public static Builder newBuilder(ClientContext clientContext) { - return new Builder(clientContext); - } - - /** Returns a builder containing all the values of this settings class. */ - @Override - public Builder toBuilder() { - return new Builder(this); - } - - protected OperationsSettings(Builder settingsBuilder) throws IOException { - super(settingsBuilder); - } - - /** Builder for OperationsSettings. */ - public static class Builder extends ClientSettings.Builder { - protected Builder() throws IOException { - this((ClientContext) null); - } - - protected Builder(ClientContext clientContext) { - super(OperationsStubSettings.newBuilder(clientContext)); - } - - private static Builder createDefault() { - return new Builder(OperationsStubSettings.newBuilder()); - } - - protected Builder(OperationsSettings settings) { - super(settings.getStubSettings().toBuilder()); - } - - protected Builder(OperationsStubSettings.Builder stubSettings) { - super(stubSettings); - } - - public OperationsStubSettings.Builder getStubSettingsBuilder() { - return ((OperationsStubSettings.Builder) getStubSettings()); - } - - /** - * Applies the given settings updater function to all of the unary API methods in this service. - * - *

Note: This method does not support applying settings to streaming methods. - */ - public Builder applyToAllUnaryMethods( - ApiFunction, Void> settingsUpdater) throws Exception { - super.applyToAllUnaryMethods( - getStubSettingsBuilder().unaryMethodSettingsBuilders(), settingsUpdater); - return this; - } - - /** Returns the builder for the settings used for calls to getOperation. */ - public UnaryCallSettings.Builder getOperationSettings() { - return getStubSettingsBuilder().getOperationSettings(); - } - - /** Returns the builder for the settings used for calls to listOperations. */ - public PagedCallSettings.Builder< - ListOperationsRequest, ListOperationsResponse, ListOperationsPagedResponse> - listOperationsSettings() { - return getStubSettingsBuilder().listOperationsSettings(); - } - - /** Returns the builder for the settings used for calls to cancelOperation. */ - public UnaryCallSettings.Builder cancelOperationSettings() { - return getStubSettingsBuilder().cancelOperationSettings(); - } - - /** Returns the builder for the settings used for calls to deleteOperation. */ - public UnaryCallSettings.Builder deleteOperationSettings() { - return getStubSettingsBuilder().deleteOperationSettings(); - } - - /** Returns the builder for the settings used for calls to deleteOperation. */ - public UnaryCallSettings.Builder waitOperationSettings() { - return getStubSettingsBuilder().waitOperationSettings(); - } - - @Override - public OperationsSettings build() throws IOException { - return new OperationsSettings(this); - } - } -} diff --git a/gax-grpc/src/main/java/com/google/longrunning/package-info.java b/gax-grpc/src/main/java/com/google/longrunning/package-info.java deleted file mode 100644 index 7e509fca0..000000000 --- a/gax-grpc/src/main/java/com/google/longrunning/package-info.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * A client to Google Long Running Operations API. - * - *

The interfaces provided are listed below, along with usage samples. - * - *

================ OperationsClient ================ - * - *

Service Description: Manages long-running operations with an API service. - * - *

When an API method normally takes long time to complete, it can be designed to return - * [Operation][google.longrunning.Operation] to the client, and the client can use this interface to - * receive the real response asynchronously by polling the operation resource, or pass the operation - * resource to another API (such as Google Cloud Pub/Sub API) to receive the response. Any API - * service that returns long-running operations should implement the `Operations` interface so - * developers can have a consistent client experience. - */ -package com.google.longrunning; diff --git a/gax-grpc/src/main/java/com/google/longrunning/stub/GrpcOperationsCallableFactory.java b/gax-grpc/src/main/java/com/google/longrunning/stub/GrpcOperationsCallableFactory.java deleted file mode 100644 index 8a18008c0..000000000 --- a/gax-grpc/src/main/java/com/google/longrunning/stub/GrpcOperationsCallableFactory.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.longrunning.stub; - -import com.google.api.gax.grpc.GrpcCallSettings; -import com.google.api.gax.grpc.GrpcCallableFactory; -import com.google.api.gax.grpc.GrpcStubCallableFactory; -import com.google.api.gax.rpc.BatchingCallSettings; -import com.google.api.gax.rpc.BidiStreamingCallable; -import com.google.api.gax.rpc.ClientContext; -import com.google.api.gax.rpc.ClientStreamingCallable; -import com.google.api.gax.rpc.OperationCallSettings; -import com.google.api.gax.rpc.OperationCallable; -import com.google.api.gax.rpc.PagedCallSettings; -import com.google.api.gax.rpc.ServerStreamingCallSettings; -import com.google.api.gax.rpc.ServerStreamingCallable; -import com.google.api.gax.rpc.StreamingCallSettings; -import com.google.api.gax.rpc.UnaryCallSettings; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.longrunning.Operation; - -/** - * gRPC callable factory implementation for Google Long Running Operations API. - * - *

This class is for advanced usage. - */ -public class GrpcOperationsCallableFactory implements GrpcStubCallableFactory { - @Override - public UnaryCallable createUnaryCallable( - GrpcCallSettings grpcCallSettings, - UnaryCallSettings callSettings, - ClientContext clientContext) { - return GrpcCallableFactory.createUnaryCallable(grpcCallSettings, callSettings, clientContext); - } - - @Override - public - UnaryCallable createPagedCallable( - GrpcCallSettings grpcCallSettings, - PagedCallSettings pagedCallSettings, - ClientContext clientContext) { - return GrpcCallableFactory.createPagedCallable( - grpcCallSettings, pagedCallSettings, clientContext); - } - - @Override - public UnaryCallable createBatchingCallable( - GrpcCallSettings grpcCallSettings, - BatchingCallSettings batchingCallSettings, - ClientContext clientContext) { - return GrpcCallableFactory.createBatchingCallable( - grpcCallSettings, batchingCallSettings, clientContext); - } - - @Override - public - OperationCallable createOperationCallable( - GrpcCallSettings grpcCallSettings, - OperationCallSettings operationCallSettings, - ClientContext clientContext, - OperationsStub operationsStub) { - return GrpcCallableFactory.createOperationCallable( - grpcCallSettings, operationCallSettings, clientContext, operationsStub); - } - - @Override - public - BidiStreamingCallable createBidiStreamingCallable( - GrpcCallSettings grpcCallSettings, - StreamingCallSettings streamingCallSettings, - ClientContext clientContext) { - return GrpcCallableFactory.createBidiStreamingCallable( - grpcCallSettings, streamingCallSettings, clientContext); - } - - @Override - public - ServerStreamingCallable createServerStreamingCallable( - GrpcCallSettings grpcCallSettings, - ServerStreamingCallSettings streamingCallSettings, - ClientContext clientContext) { - return GrpcCallableFactory.createServerStreamingCallable( - grpcCallSettings, streamingCallSettings, clientContext); - } - - @Override - public - ClientStreamingCallable createClientStreamingCallable( - GrpcCallSettings grpcCallSettings, - StreamingCallSettings streamingCallSettings, - ClientContext clientContext) { - return GrpcCallableFactory.createClientStreamingCallable( - grpcCallSettings, streamingCallSettings, clientContext); - } -} diff --git a/gax-grpc/src/main/java/com/google/longrunning/stub/GrpcOperationsStub.java b/gax-grpc/src/main/java/com/google/longrunning/stub/GrpcOperationsStub.java deleted file mode 100644 index c00574e88..000000000 --- a/gax-grpc/src/main/java/com/google/longrunning/stub/GrpcOperationsStub.java +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.longrunning.stub; - -import static com.google.longrunning.OperationsClient.ListOperationsPagedResponse; - -import com.google.api.gax.core.BackgroundResource; -import com.google.api.gax.core.BackgroundResourceAggregation; -import com.google.api.gax.grpc.GrpcCallSettings; -import com.google.api.gax.grpc.GrpcStubCallableFactory; -import com.google.api.gax.rpc.ClientContext; -import com.google.api.gax.rpc.RequestParamsExtractor; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.common.collect.ImmutableMap; -import com.google.longrunning.CancelOperationRequest; -import com.google.longrunning.DeleteOperationRequest; -import com.google.longrunning.GetOperationRequest; -import com.google.longrunning.ListOperationsRequest; -import com.google.longrunning.ListOperationsResponse; -import com.google.longrunning.Operation; -import com.google.longrunning.WaitOperationRequest; -import com.google.protobuf.Empty; -import io.grpc.MethodDescriptor; -import io.grpc.protobuf.ProtoUtils; -import java.io.IOException; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -/** - * gRPC stub implementation for Google Long Running Operations API. - * - *

This class is for advanced usage and reflects the underlying API directly. - */ -public class GrpcOperationsStub extends OperationsStub { - - private static final MethodDescriptor - getOperationMethodDescriptor = - MethodDescriptor.newBuilder() - .setType(MethodDescriptor.MethodType.UNARY) - .setFullMethodName("google.longrunning.Operations/GetOperation") - .setRequestMarshaller(ProtoUtils.marshaller(GetOperationRequest.getDefaultInstance())) - .setResponseMarshaller(ProtoUtils.marshaller(Operation.getDefaultInstance())) - .build(); - private static final MethodDescriptor - listOperationsMethodDescriptor = - MethodDescriptor.newBuilder() - .setType(MethodDescriptor.MethodType.UNARY) - .setFullMethodName("google.longrunning.Operations/ListOperations") - .setRequestMarshaller( - ProtoUtils.marshaller(ListOperationsRequest.getDefaultInstance())) - .setResponseMarshaller( - ProtoUtils.marshaller(ListOperationsResponse.getDefaultInstance())) - .build(); - private static final MethodDescriptor - cancelOperationMethodDescriptor = - MethodDescriptor.newBuilder() - .setType(MethodDescriptor.MethodType.UNARY) - .setFullMethodName("google.longrunning.Operations/CancelOperation") - .setRequestMarshaller( - ProtoUtils.marshaller(CancelOperationRequest.getDefaultInstance())) - .setResponseMarshaller(ProtoUtils.marshaller(Empty.getDefaultInstance())) - .build(); - private static final MethodDescriptor - deleteOperationMethodDescriptor = - MethodDescriptor.newBuilder() - .setType(MethodDescriptor.MethodType.UNARY) - .setFullMethodName("google.longrunning.Operations/DeleteOperation") - .setRequestMarshaller( - ProtoUtils.marshaller(DeleteOperationRequest.getDefaultInstance())) - .setResponseMarshaller(ProtoUtils.marshaller(Empty.getDefaultInstance())) - .build(); - private static final MethodDescriptor - waitOperationMethodDescriptor = - MethodDescriptor.newBuilder() - .setType(MethodDescriptor.MethodType.UNARY) - .setFullMethodName("google.longrunning.Operations/WaitOperation") - .setRequestMarshaller( - ProtoUtils.marshaller(WaitOperationRequest.getDefaultInstance())) - .setResponseMarshaller(ProtoUtils.marshaller(Operation.getDefaultInstance())) - .build(); - - private final BackgroundResource backgroundResources; - - private final UnaryCallable getOperationCallable; - private final UnaryCallable listOperationsCallable; - private final UnaryCallable - listOperationsPagedCallable; - private final UnaryCallable cancelOperationCallable; - private final UnaryCallable deleteOperationCallable; - private final UnaryCallable waitOperationCallable; - - private final GrpcStubCallableFactory callableFactory; - - public static final GrpcOperationsStub create(OperationsStubSettings settings) - throws IOException { - return new GrpcOperationsStub(settings, ClientContext.create(settings)); - } - - public static final GrpcOperationsStub create(ClientContext clientContext) throws IOException { - return new GrpcOperationsStub(OperationsStubSettings.newBuilder().build(), clientContext); - } - - public static final GrpcOperationsStub create( - ClientContext clientContext, GrpcStubCallableFactory callableFactory) throws IOException { - return new GrpcOperationsStub( - OperationsStubSettings.newBuilder().build(), clientContext, callableFactory); - } - - /** - * Constructs an instance of GrpcOperationsStub, using the given settings. This is protected so - * that it is easy to make a subclass, but otherwise, the static factory methods should be - * preferred. - */ - protected GrpcOperationsStub(OperationsStubSettings settings, ClientContext clientContext) - throws IOException { - this(settings, clientContext, new GrpcOperationsCallableFactory()); - } - - /** - * Constructs an instance of GrpcOperationsStub, using the given settings. This is protected so - * that it is easy to make a subclass, but otherwise, the static factory methods should be - * preferred. - */ - protected GrpcOperationsStub( - OperationsStubSettings settings, - ClientContext clientContext, - GrpcStubCallableFactory callableFactory) - throws IOException { - this.callableFactory = callableFactory; - - GrpcCallSettings getOperationTransportSettings = - GrpcCallSettings.newBuilder() - .setMethodDescriptor(getOperationMethodDescriptor) - .setParamsExtractor( - new RequestParamsExtractor() { - @Override - public Map extract(GetOperationRequest request) { - ImmutableMap.Builder params = ImmutableMap.builder(); - params.put("name", String.valueOf(request.getName())); - return params.build(); - } - }) - .build(); - GrpcCallSettings - listOperationsTransportSettings = - GrpcCallSettings.newBuilder() - .setMethodDescriptor(listOperationsMethodDescriptor) - .setParamsExtractor( - new RequestParamsExtractor() { - @Override - public Map extract(ListOperationsRequest request) { - ImmutableMap.Builder params = ImmutableMap.builder(); - params.put("name", String.valueOf(request.getName())); - return params.build(); - } - }) - .build(); - GrpcCallSettings cancelOperationTransportSettings = - GrpcCallSettings.newBuilder() - .setMethodDescriptor(cancelOperationMethodDescriptor) - .setParamsExtractor( - new RequestParamsExtractor() { - @Override - public Map extract(CancelOperationRequest request) { - ImmutableMap.Builder params = ImmutableMap.builder(); - params.put("name", String.valueOf(request.getName())); - return params.build(); - } - }) - .build(); - GrpcCallSettings deleteOperationTransportSettings = - GrpcCallSettings.newBuilder() - .setMethodDescriptor(deleteOperationMethodDescriptor) - .setParamsExtractor( - new RequestParamsExtractor() { - @Override - public Map extract(DeleteOperationRequest request) { - ImmutableMap.Builder params = ImmutableMap.builder(); - params.put("name", String.valueOf(request.getName())); - return params.build(); - } - }) - .build(); - GrpcCallSettings waitOperationTransportSettings = - GrpcCallSettings.newBuilder() - .setMethodDescriptor(waitOperationMethodDescriptor) - .setParamsExtractor( - new RequestParamsExtractor() { - @Override - public Map extract(WaitOperationRequest request) { - ImmutableMap.Builder params = ImmutableMap.builder(); - params.put("name", String.valueOf(request.getName())); - return params.build(); - } - }) - .build(); - - this.getOperationCallable = - callableFactory.createUnaryCallable( - getOperationTransportSettings, settings.getOperationSettings(), clientContext); - this.listOperationsCallable = - callableFactory.createUnaryCallable( - listOperationsTransportSettings, settings.listOperationsSettings(), clientContext); - this.listOperationsPagedCallable = - callableFactory.createPagedCallable( - listOperationsTransportSettings, settings.listOperationsSettings(), clientContext); - this.cancelOperationCallable = - callableFactory.createUnaryCallable( - cancelOperationTransportSettings, settings.cancelOperationSettings(), clientContext); - this.deleteOperationCallable = - callableFactory.createUnaryCallable( - deleteOperationTransportSettings, settings.deleteOperationSettings(), clientContext); - this.waitOperationCallable = - callableFactory.createUnaryCallable( - waitOperationTransportSettings, settings.waitOperationSettings(), clientContext); - - backgroundResources = new BackgroundResourceAggregation(clientContext.getBackgroundResources()); - } - - @Override - public UnaryCallable getOperationCallable() { - return getOperationCallable; - } - - @Override - public UnaryCallable - listOperationsPagedCallable() { - return listOperationsPagedCallable; - } - - @Override - public UnaryCallable listOperationsCallable() { - return listOperationsCallable; - } - - @Override - public UnaryCallable cancelOperationCallable() { - return cancelOperationCallable; - } - - @Override - public UnaryCallable deleteOperationCallable() { - return deleteOperationCallable; - } - - @Override - public UnaryCallable waitOperationCallable() { - return waitOperationCallable; - } - - @Override - public final void close() { - shutdown(); - } - - @Override - public void shutdown() { - backgroundResources.shutdown(); - } - - @Override - public boolean isShutdown() { - return backgroundResources.isShutdown(); - } - - @Override - public boolean isTerminated() { - return backgroundResources.isTerminated(); - } - - @Override - public void shutdownNow() { - backgroundResources.shutdownNow(); - } - - @Override - public boolean awaitTermination(long duration, TimeUnit unit) throws InterruptedException { - return backgroundResources.awaitTermination(duration, unit); - } -} diff --git a/gax-grpc/src/main/java/com/google/longrunning/stub/OperationsStub.java b/gax-grpc/src/main/java/com/google/longrunning/stub/OperationsStub.java deleted file mode 100644 index 467572b00..000000000 --- a/gax-grpc/src/main/java/com/google/longrunning/stub/OperationsStub.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.longrunning.stub; - -import static com.google.longrunning.OperationsClient.ListOperationsPagedResponse; - -import com.google.api.gax.core.BackgroundResource; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.longrunning.CancelOperationRequest; -import com.google.longrunning.DeleteOperationRequest; -import com.google.longrunning.GetOperationRequest; -import com.google.longrunning.ListOperationsRequest; -import com.google.longrunning.ListOperationsResponse; -import com.google.longrunning.Operation; -import com.google.longrunning.WaitOperationRequest; -import com.google.protobuf.Empty; - -/** - * Base stub class for Google Long Running Operations API. - * - *

This class is for advanced usage and reflects the underlying API directly. - */ -public abstract class OperationsStub implements BackgroundResource { - - public UnaryCallable getOperationCallable() { - throw new UnsupportedOperationException("Not implemented: getOperationCallable()"); - } - - public UnaryCallable - listOperationsPagedCallable() { - throw new UnsupportedOperationException("Not implemented: listOperationsPagedCallable()"); - } - - public UnaryCallable listOperationsCallable() { - throw new UnsupportedOperationException("Not implemented: listOperationsCallable()"); - } - - public UnaryCallable cancelOperationCallable() { - throw new UnsupportedOperationException("Not implemented: cancelOperationCallable()"); - } - - public UnaryCallable deleteOperationCallable() { - throw new UnsupportedOperationException("Not implemented: deleteOperationCallable()"); - } - - public UnaryCallable waitOperationCallable() { - throw new UnsupportedOperationException("Not implemented: waitOperationCallable()"); - } - - @Override - public abstract void close(); -} diff --git a/gax-grpc/src/main/java/com/google/longrunning/stub/OperationsStubSettings.java b/gax-grpc/src/main/java/com/google/longrunning/stub/OperationsStubSettings.java deleted file mode 100644 index 85da6db5c..000000000 --- a/gax-grpc/src/main/java/com/google/longrunning/stub/OperationsStubSettings.java +++ /dev/null @@ -1,385 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.longrunning.stub; - -import static com.google.longrunning.OperationsClient.ListOperationsPagedResponse; - -import com.google.api.core.ApiFunction; -import com.google.api.core.ApiFuture; -import com.google.api.gax.core.GaxProperties; -import com.google.api.gax.core.GoogleCredentialsProvider; -import com.google.api.gax.core.InstantiatingExecutorProvider; -import com.google.api.gax.grpc.GaxGrpcProperties; -import com.google.api.gax.grpc.GrpcTransportChannel; -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.ApiClientHeaderProvider; -import com.google.api.gax.rpc.ClientContext; -import com.google.api.gax.rpc.PageContext; -import com.google.api.gax.rpc.PagedCallSettings; -import com.google.api.gax.rpc.PagedListDescriptor; -import com.google.api.gax.rpc.PagedListResponseFactory; -import com.google.api.gax.rpc.StatusCode; -import com.google.api.gax.rpc.StubSettings; -import com.google.api.gax.rpc.UnaryCallSettings; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Lists; -import com.google.longrunning.CancelOperationRequest; -import com.google.longrunning.DeleteOperationRequest; -import com.google.longrunning.GetOperationRequest; -import com.google.longrunning.ListOperationsRequest; -import com.google.longrunning.ListOperationsResponse; -import com.google.longrunning.Operation; -import com.google.longrunning.WaitOperationRequest; -import com.google.protobuf.Empty; -import java.io.IOException; -import org.threeten.bp.Duration; - -/** Settings class to configure an instance of {@link OperationsStub}. */ -public class OperationsStubSettings extends StubSettings { - - private final UnaryCallSettings getOperationSettings; - private final PagedCallSettings< - ListOperationsRequest, ListOperationsResponse, ListOperationsPagedResponse> - listOperationsSettings; - private final UnaryCallSettings cancelOperationSettings; - private final UnaryCallSettings deleteOperationSettings; - private final UnaryCallSettings waitOperationSettings; - - /** Returns the object with the settings used for calls to getOperation. */ - public UnaryCallSettings getOperationSettings() { - return getOperationSettings; - } - - /** Returns the object with the settings used for calls to listOperations. */ - public PagedCallSettings< - ListOperationsRequest, ListOperationsResponse, ListOperationsPagedResponse> - listOperationsSettings() { - return listOperationsSettings; - } - - /** Returns the object with the settings used for calls to cancelOperation. */ - public UnaryCallSettings cancelOperationSettings() { - return cancelOperationSettings; - } - - /** Returns the object with the settings used for calls to deleteOperation. */ - public UnaryCallSettings deleteOperationSettings() { - return deleteOperationSettings; - } - - /** Returns the object with the settings used for calls to waitOperation. */ - public UnaryCallSettings waitOperationSettings() { - return waitOperationSettings; - } - - public OperationsStub createStub() throws IOException { - if (getTransportChannelProvider() - .getTransportName() - .equals(GrpcTransportChannel.getGrpcTransportName())) { - return GrpcOperationsStub.create(this); - } else { - throw new UnsupportedOperationException( - "Transport not supported: " + getTransportChannelProvider().getTransportName()); - } - } - - /** Returns a builder for the default ExecutorProvider for this service. */ - public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuilder() { - return InstantiatingExecutorProvider.newBuilder(); - } - - /** Returns a builder for the default credentials for this service. */ - public static GoogleCredentialsProvider.Builder defaultCredentialsProviderBuilder() { - return GoogleCredentialsProvider.newBuilder(); - } - - public static ApiClientHeaderProvider.Builder defaultApiClientHeaderProviderBuilder() { - return ApiClientHeaderProvider.newBuilder() - .setGeneratedLibToken( - "gapic", GaxProperties.getLibraryVersion(OperationsStubSettings.class)) - .setTransportToken( - GaxGrpcProperties.getGrpcTokenName(), GaxGrpcProperties.getGrpcVersion()); - } - - /** Returns a new builder for this class. */ - public static Builder newBuilder() { - return Builder.createDefault(); - } - - /** Returns a new builder for this class. */ - public static Builder newBuilder(ClientContext clientContext) { - return new Builder(clientContext); - } - - /** Returns a builder containing all the values of this settings class. */ - public Builder toBuilder() { - return new Builder(this); - } - - protected OperationsStubSettings(Builder settingsBuilder) throws IOException { - super(settingsBuilder); - - getOperationSettings = settingsBuilder.getOperationSettings().build(); - listOperationsSettings = settingsBuilder.listOperationsSettings().build(); - cancelOperationSettings = settingsBuilder.cancelOperationSettings().build(); - deleteOperationSettings = settingsBuilder.deleteOperationSettings().build(); - waitOperationSettings = settingsBuilder.waitOperationSettings().build(); - } - - private static final PagedListDescriptor - LIST_OPERATIONS_PAGE_STR_DESC = - new PagedListDescriptor() { - @Override - public String emptyToken() { - return ""; - } - - @Override - public ListOperationsRequest injectToken(ListOperationsRequest payload, String token) { - return ListOperationsRequest.newBuilder(payload).setPageToken(token).build(); - } - - @Override - public ListOperationsRequest injectPageSize( - ListOperationsRequest payload, int pageSize) { - return ListOperationsRequest.newBuilder(payload).setPageSize(pageSize).build(); - } - - @Override - public Integer extractPageSize(ListOperationsRequest payload) { - return payload.getPageSize(); - } - - @Override - public String extractNextToken(ListOperationsResponse payload) { - return payload.getNextPageToken(); - } - - @Override - public Iterable extractResources(ListOperationsResponse payload) { - return payload.getOperationsList(); - } - }; - - private static final PagedListResponseFactory< - ListOperationsRequest, ListOperationsResponse, ListOperationsPagedResponse> - LIST_OPERATIONS_PAGE_STR_FACT = - new PagedListResponseFactory< - ListOperationsRequest, ListOperationsResponse, ListOperationsPagedResponse>() { - @Override - public ApiFuture getFuturePagedResponse( - UnaryCallable callable, - ListOperationsRequest request, - ApiCallContext context, - ApiFuture futureResponse) { - PageContext pageContext = - PageContext.create(callable, LIST_OPERATIONS_PAGE_STR_DESC, request, context); - return ListOperationsPagedResponse.createAsync(pageContext, futureResponse); - } - }; - - /** Builder for OperationsStubSettings. */ - public static class Builder extends StubSettings.Builder { - private final ImmutableList> unaryMethodSettingsBuilders; - - private final UnaryCallSettings.Builder getOperationSettings; - private final PagedCallSettings.Builder< - ListOperationsRequest, ListOperationsResponse, ListOperationsPagedResponse> - listOperationsSettings; - private final UnaryCallSettings.Builder cancelOperationSettings; - private final UnaryCallSettings.Builder deleteOperationSettings; - private final UnaryCallSettings.Builder waitOperationSettings; - - private static final ImmutableMap> - RETRYABLE_CODE_DEFINITIONS; - - static { - ImmutableMap.Builder> definitions = - ImmutableMap.builder(); - definitions.put( - "idempotent", - ImmutableSet.copyOf( - Lists.newArrayList( - StatusCode.Code.DEADLINE_EXCEEDED, StatusCode.Code.UNAVAILABLE))); - definitions.put("non_idempotent", ImmutableSet.copyOf(Lists.newArrayList())); - RETRYABLE_CODE_DEFINITIONS = definitions.build(); - } - - private static final ImmutableMap RETRY_PARAM_DEFINITIONS; - - static { - ImmutableMap.Builder definitions = ImmutableMap.builder(); - RetrySettings settings = null; - settings = - RetrySettings.newBuilder() - .setInitialRetryDelay(Duration.ofMillis(100L)) - .setRetryDelayMultiplier(1.3) - .setMaxRetryDelay(Duration.ofMillis(60000L)) - .setInitialRpcTimeout(Duration.ofMillis(90000L)) - .setRpcTimeoutMultiplier(1.0) - .setMaxRpcTimeout(Duration.ofMillis(90000L)) - .setTotalTimeout(Duration.ofMillis(600000L)) - .build(); - definitions.put("default", settings); - RETRY_PARAM_DEFINITIONS = definitions.build(); - } - - protected Builder() { - this((ClientContext) null); - } - - protected Builder(ClientContext clientContext) { - super(clientContext); - - getOperationSettings = UnaryCallSettings.newUnaryCallSettingsBuilder(); - - listOperationsSettings = PagedCallSettings.newBuilder(LIST_OPERATIONS_PAGE_STR_FACT); - - cancelOperationSettings = UnaryCallSettings.newUnaryCallSettingsBuilder(); - - deleteOperationSettings = UnaryCallSettings.newUnaryCallSettingsBuilder(); - - waitOperationSettings = UnaryCallSettings.newUnaryCallSettingsBuilder(); - - unaryMethodSettingsBuilders = - ImmutableList.>of( - getOperationSettings, - listOperationsSettings, - cancelOperationSettings, - deleteOperationSettings); - - initDefaults(this); - } - - private static Builder createDefault() { - Builder builder = new Builder((ClientContext) null); - return initDefaults(builder); - } - - private static Builder initDefaults(Builder builder) { - - builder - .getOperationSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) - .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("default")); - - builder - .listOperationsSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) - .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("default")); - - builder - .cancelOperationSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) - .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("default")); - - builder - .deleteOperationSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) - .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("default")); - - builder - .waitOperationSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) - .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("default")); - - return builder; - } - - protected Builder(OperationsStubSettings settings) { - super(settings); - - getOperationSettings = settings.getOperationSettings.toBuilder(); - listOperationsSettings = settings.listOperationsSettings.toBuilder(); - cancelOperationSettings = settings.cancelOperationSettings.toBuilder(); - deleteOperationSettings = settings.deleteOperationSettings.toBuilder(); - waitOperationSettings = settings.waitOperationSettings.toBuilder(); - - unaryMethodSettingsBuilders = - ImmutableList.>of( - getOperationSettings, - listOperationsSettings, - cancelOperationSettings, - deleteOperationSettings, - waitOperationSettings); - } - - /** - * Applies the given settings updater function to all of the unary API methods in this service. - * - *

Note: This method does not support applying settings to streaming methods. - */ - public Builder applyToAllUnaryMethods( - ApiFunction, Void> settingsUpdater) throws Exception { - super.applyToAllUnaryMethods(unaryMethodSettingsBuilders, settingsUpdater); - return this; - } - - public ImmutableList> unaryMethodSettingsBuilders() { - return unaryMethodSettingsBuilders; - } - - /** Returns the builder for the settings used for calls to getOperation. */ - public UnaryCallSettings.Builder getOperationSettings() { - return getOperationSettings; - } - - /** Returns the builder for the settings used for calls to listOperations. */ - public PagedCallSettings.Builder< - ListOperationsRequest, ListOperationsResponse, ListOperationsPagedResponse> - listOperationsSettings() { - return listOperationsSettings; - } - - /** Returns the builder for the settings used for calls to cancelOperation. */ - public UnaryCallSettings.Builder cancelOperationSettings() { - return cancelOperationSettings; - } - - /** Returns the builder for the settings used for calls to deleteOperation. */ - public UnaryCallSettings.Builder deleteOperationSettings() { - return deleteOperationSettings; - } - - /** Returns the builder for the settings used for calls to waitOperation. */ - public UnaryCallSettings.Builder waitOperationSettings() { - return waitOperationSettings; - } - - @Override - public OperationsStubSettings build() throws IOException { - return new OperationsStubSettings(this); - } - } -} diff --git a/gax-grpc/src/main/resources/META-INF/native-image/com.google.api/gax-grpc/native-image.properties b/gax-grpc/src/main/resources/META-INF/native-image/com.google.api/gax-grpc/native-image.properties deleted file mode 100644 index f8c0ada53..000000000 --- a/gax-grpc/src/main/resources/META-INF/native-image/com.google.api/gax-grpc/native-image.properties +++ /dev/null @@ -1,14 +0,0 @@ -Args = --initialize-at-run-time=io.grpc.netty.shaded.io.netty.handler.ssl.OpenSsl,\ - io.grpc.netty.shaded.io.netty.internal.tcnative.SSL,\ - io.grpc.netty.shaded.io.netty.internal.tcnative.CertificateVerifier,\ - io.grpc.netty.shaded.io.netty.internal.tcnative.SSLPrivateKeyMethod,\ - io.grpc.netty.shaded.io.netty.internal.tcnative.AsyncSSLPrivateKeyMethod,\ - io.grpc.netty.shaded.io.netty.internal.tcnative.CertificateCompressionAlgo,\ - io.grpc.netty.shaded.io.grpc.netty,\ - io.grpc.netty.shaded.io.netty.channel.epoll,\ - io.grpc.netty.shaded.io.netty.channel.unix,\ - io.grpc.netty.shaded.io.netty.handler.ssl,\ - io.grpc.internal.RetriableStream \ - --features=com.google.api.gax.grpc.nativeimage.ProtobufMessageFeature,\ - com.google.api.gax.grpc.nativeimage.GrpcNettyFeature \ - -H:-RunReachabilityHandlersConcurrently \ No newline at end of file diff --git a/gax-grpc/src/main/resources/META-INF/native-image/com.google.api/gax-grpc/resource-config.json b/gax-grpc/src/main/resources/META-INF/native-image/com.google.api/gax-grpc/resource-config.json deleted file mode 100644 index 08e0ea0c5..000000000 --- a/gax-grpc/src/main/resources/META-INF/native-image/com.google.api/gax-grpc/resource-config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "resources":[ - {"pattern":"\\QMETA-INF/native/libio_grpc_netty_shaded_netty_tcnative_linux_x86_64.so\\E"}, - {"pattern":"\\QMETA-INF/native/libio_grpc_netty_shaded_netty_transport_native_epoll_x86_64.so\\E"}, - {"pattern":"\\QMETA-INF/services/io.grpc.LoadBalancerProvider\\E"}, - {"pattern":"\\QMETA-INF/services/io.grpc.ManagedChannelProvider\\E"}, - {"pattern":"\\QMETA-INF/services/io.grpc.NameResolverProvider\\E"}], - "bundles":[] -} \ No newline at end of file diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/CallOptionsUtilTest.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/CallOptionsUtilTest.java deleted file mode 100644 index 26a6b925f..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/CallOptionsUtilTest.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; - -import com.google.common.collect.ImmutableMap; -import io.grpc.CallOptions; -import io.grpc.Metadata.Key; -import java.util.Map; -import org.junit.Test; - -public class CallOptionsUtilTest { - @Test - public void testPutAndGetDynamicHeaderOption() { - String encodedRequestParams = "param1=value¶m2.param3=value23"; - CallOptions options = - CallOptionsUtil.putRequestParamsDynamicHeaderOption( - CallOptions.DEFAULT, encodedRequestParams); - - Map, String> headers = CallOptionsUtil.getDynamicHeadersOption(options); - - assertEquals( - ImmutableMap.of(CallOptionsUtil.REQUEST_PARAMS_HEADER_KEY, encodedRequestParams), headers); - } - - @Test - public void testPutAndGetDynamicHeaderOptionEmpty() { - CallOptions options = - CallOptionsUtil.putRequestParamsDynamicHeaderOption(CallOptions.DEFAULT, ""); - assertSame(CallOptions.DEFAULT, options); - Map, String> headers = CallOptionsUtil.getDynamicHeadersOption(options); - assertTrue(headers.isEmpty()); - } - - @Test(expected = NullPointerException.class) - public void testPutAndGetHeaderOptionNull() { - CallOptionsUtil.putRequestParamsDynamicHeaderOption(CallOptions.DEFAULT, null); - } -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/ChannelPoolTest.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/ChannelPoolTest.java deleted file mode 100644 index 1bf472653..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/ChannelPoolTest.java +++ /dev/null @@ -1,598 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.api.gax.grpc.testing.FakeChannelFactory; -import com.google.api.gax.grpc.testing.FakeMethodDescriptor; -import com.google.api.gax.grpc.testing.FakeServiceGrpc; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; -import com.google.type.Color; -import com.google.type.Money; -import io.grpc.CallOptions; -import io.grpc.ClientCall; -import io.grpc.ManagedChannel; -import io.grpc.Metadata; -import io.grpc.MethodDescriptor; -import io.grpc.Status; -import io.grpc.stub.ClientCalls; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; -import org.mockito.stubbing.Answer; - -@RunWith(JUnit4.class) -public class ChannelPoolTest { - @Test - public void testAuthority() throws IOException { - ManagedChannel sub1 = Mockito.mock(ManagedChannel.class); - ManagedChannel sub2 = Mockito.mock(ManagedChannel.class); - - Mockito.when(sub1.authority()).thenReturn("myAuth"); - - ChannelPool pool = - ChannelPool.create( - ChannelPoolSettings.staticallySized(2), - new FakeChannelFactory(Arrays.asList(sub1, sub2))); - assertThat(pool.authority()).isEqualTo("myAuth"); - } - - @Test - public void testRoundRobin() throws IOException { - ManagedChannel sub1 = Mockito.mock(ManagedChannel.class); - ManagedChannel sub2 = Mockito.mock(ManagedChannel.class); - - Mockito.when(sub1.authority()).thenReturn("myAuth"); - - ArrayList channels = Lists.newArrayList(sub1, sub2); - ChannelPool pool = - ChannelPool.create( - ChannelPoolSettings.staticallySized(channels.size()), new FakeChannelFactory(channels)); - - verifyTargetChannel(pool, channels, sub1); - verifyTargetChannel(pool, channels, sub2); - verifyTargetChannel(pool, channels, sub1); - } - - private void verifyTargetChannel( - ChannelPool pool, List channels, ManagedChannel targetChannel) { - MethodDescriptor methodDescriptor = FakeServiceGrpc.METHOD_RECOGNIZE; - CallOptions callOptions = CallOptions.DEFAULT; - @SuppressWarnings("unchecked") - ClientCall expectedClientCall = Mockito.mock(ClientCall.class); - - channels.forEach(Mockito::reset); - Mockito.doReturn(expectedClientCall).when(targetChannel).newCall(methodDescriptor, callOptions); - - ClientCall actualCall = pool.newCall(methodDescriptor, callOptions); - Mockito.verify(targetChannel, Mockito.times(1)).newCall(methodDescriptor, callOptions); - actualCall.start(null, null); - Mockito.verify(expectedClientCall, Mockito.times(1)).start(Mockito.any(), Mockito.any()); - - for (ManagedChannel otherChannel : channels) { - if (otherChannel != targetChannel) { - Mockito.verify(otherChannel, Mockito.never()).newCall(methodDescriptor, callOptions); - } - } - } - - @Test - public void ensureEvenDistribution() throws InterruptedException, IOException { - int numChannels = 10; - final ManagedChannel[] channels = new ManagedChannel[numChannels]; - final AtomicInteger[] counts = new AtomicInteger[numChannels]; - - final MethodDescriptor methodDescriptor = FakeServiceGrpc.METHOD_RECOGNIZE; - final CallOptions callOptions = CallOptions.DEFAULT; - @SuppressWarnings("unchecked") - final ClientCall clientCall = Mockito.mock(ClientCall.class); - - for (int i = 0; i < numChannels; i++) { - final int index = i; - - counts[i] = new AtomicInteger(); - - channels[i] = Mockito.mock(ManagedChannel.class); - Mockito.when(channels[i].newCall(methodDescriptor, callOptions)) - .thenAnswer( - (ignored) -> { - counts[index].incrementAndGet(); - return clientCall; - }); - } - - final ChannelPool pool = - ChannelPool.create( - ChannelPoolSettings.staticallySized(numChannels), - new FakeChannelFactory(Arrays.asList(channels))); - - int numThreads = 20; - final int numPerThread = 1000; - - ExecutorService executor = Executors.newFixedThreadPool(numThreads); - for (int i = 0; i < numThreads; i++) { - executor.submit( - () -> { - for (int j = 0; j < numPerThread; j++) { - pool.newCall(methodDescriptor, callOptions); - } - }); - } - executor.shutdown(); - boolean shutdown = executor.awaitTermination(1, TimeUnit.MINUTES); - assertThat(shutdown).isTrue(); - - int expectedCount = (numThreads * numPerThread) / numChannels; - for (AtomicInteger count : counts) { - assertThat(count.get()).isAnyOf(expectedCount, expectedCount + 1); - } - } - - // Test channelPrimer is called same number of times as poolSize if executorService is set to null - @Test - public void channelPrimerShouldCallPoolConstruction() throws IOException { - ChannelPrimer mockChannelPrimer = Mockito.mock(ChannelPrimer.class); - ManagedChannel channel1 = Mockito.mock(ManagedChannel.class); - ManagedChannel channel2 = Mockito.mock(ManagedChannel.class); - - ChannelPool.create( - ChannelPoolSettings.staticallySized(2) - .toBuilder() - .setPreemptiveRefreshEnabled(true) - .build(), - new FakeChannelFactory(Arrays.asList(channel1, channel2), mockChannelPrimer)); - Mockito.verify(mockChannelPrimer, Mockito.times(2)) - .primeChannel(Mockito.any(ManagedChannel.class)); - } - - // Test channelPrimer is called periodically, if there's an executorService - @Test - public void channelPrimerIsCalledPeriodically() throws IOException { - ChannelPrimer mockChannelPrimer = Mockito.mock(ChannelPrimer.class); - ManagedChannel channel1 = Mockito.mock(ManagedChannel.class); - ManagedChannel channel2 = Mockito.mock(ManagedChannel.class); - ManagedChannel channel3 = Mockito.mock(ManagedChannel.class); - - List channelRefreshers = new ArrayList<>(); - - ScheduledExecutorService scheduledExecutorService = - Mockito.mock(ScheduledExecutorService.class); - - Answer extractChannelRefresher = - invocation -> { - channelRefreshers.add(invocation.getArgument(0)); - return Mockito.mock(ScheduledFuture.class); - }; - - Mockito.doAnswer(extractChannelRefresher) - .when(scheduledExecutorService) - .scheduleAtFixedRate( - Mockito.any(Runnable.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.any()); - - FakeChannelFactory channelFactory = - new FakeChannelFactory(Arrays.asList(channel1, channel2, channel3), mockChannelPrimer); - - new ChannelPool( - ChannelPoolSettings.staticallySized(1) - .toBuilder() - .setPreemptiveRefreshEnabled(true) - .build(), - channelFactory, - scheduledExecutorService); - // 1 call during the creation - Mockito.verify(mockChannelPrimer, Mockito.times(1)) - .primeChannel(Mockito.any(ManagedChannel.class)); - - channelRefreshers.get(0).run(); - // 1 more call during channel refresh - Mockito.verify(mockChannelPrimer, Mockito.times(2)) - .primeChannel(Mockito.any(ManagedChannel.class)); - - channelRefreshers.get(0).run(); - // 1 more call during channel refresh - Mockito.verify(mockChannelPrimer, Mockito.times(3)) - .primeChannel(Mockito.any(ManagedChannel.class)); - } - - // ---- - // call should be allowed to complete and the channel should not be shutdown - @Test - public void callShouldCompleteAfterCreation() throws IOException { - ManagedChannel underlyingChannel = Mockito.mock(ManagedChannel.class); - ManagedChannel replacementChannel = Mockito.mock(ManagedChannel.class); - FakeChannelFactory channelFactory = - new FakeChannelFactory(ImmutableList.of(underlyingChannel, replacementChannel)); - ChannelPool pool = ChannelPool.create(ChannelPoolSettings.staticallySized(1), channelFactory); - - // create a mock call when new call comes to the underlying channel - MockClientCall mockClientCall = new MockClientCall<>(1, Status.OK); - MockClientCall spyClientCall = Mockito.spy(mockClientCall); - Mockito.when( - underlyingChannel.newCall( - Mockito.>any(), Mockito.any(CallOptions.class))) - .thenReturn(spyClientCall); - - Answer verifyChannelNotShutdown = - invocation -> { - Mockito.verify(underlyingChannel, Mockito.never()).shutdown(); - return invocation.callRealMethod(); - }; - - // verify that underlying channel is not shutdown when clientCall is still sending message - Mockito.doAnswer(verifyChannelNotShutdown).when(spyClientCall).sendMessage(Mockito.anyString()); - - // create a new call on entry - @SuppressWarnings("unchecked") - ClientCall.Listener listener = Mockito.mock(ClientCall.Listener.class); - ClientCall call = - pool.newCall(FakeMethodDescriptor.create(), CallOptions.DEFAULT); - - pool.refresh(); - // shutdown is not called because there is still an outstanding call, even if it hasn't started - Mockito.verify(underlyingChannel, Mockito.after(200).never()).shutdown(); - - // start clientCall - call.start(listener, new Metadata()); - // send message and end the call - call.sendMessage("message"); - // shutdown is called because the outstanding call has completed - Mockito.verify(underlyingChannel, Mockito.atLeastOnce()).shutdown(); - - // Replacement channel shouldn't be touched - Mockito.verify(replacementChannel, Mockito.never()).shutdown(); - Mockito.verify(replacementChannel, Mockito.never()).newCall(Mockito.any(), Mockito.any()); - } - - // call should be allowed to complete and the channel should not be shutdown - @Test - public void callShouldCompleteAfterStarted() throws IOException { - final ManagedChannel underlyingChannel = Mockito.mock(ManagedChannel.class); - ManagedChannel replacementChannel = Mockito.mock(ManagedChannel.class); - - FakeChannelFactory channelFactory = - new FakeChannelFactory(ImmutableList.of(underlyingChannel, replacementChannel)); - ChannelPool pool = ChannelPool.create(ChannelPoolSettings.staticallySized(1), channelFactory); - - // create a mock call when new call comes to the underlying channel - MockClientCall mockClientCall = new MockClientCall<>(1, Status.OK); - MockClientCall spyClientCall = Mockito.spy(mockClientCall); - Mockito.when( - underlyingChannel.newCall( - Mockito.>any(), Mockito.any(CallOptions.class))) - .thenReturn(spyClientCall); - - Answer verifyChannelNotShutdown = - invocation -> { - Mockito.verify(underlyingChannel, Mockito.never()).shutdown(); - return invocation.callRealMethod(); - }; - - // verify that underlying channel is not shutdown when clientCall is still sending message - Mockito.doAnswer(verifyChannelNotShutdown).when(spyClientCall).sendMessage(Mockito.anyString()); - - // create a new call on safeShutdownManagedChannel - @SuppressWarnings("unchecked") - ClientCall.Listener listener = Mockito.mock(ClientCall.Listener.class); - ClientCall call = - pool.newCall(FakeMethodDescriptor.create(), CallOptions.DEFAULT); - - // start clientCall - call.start(listener, new Metadata()); - pool.refresh(); - - // shutdown is not called because there is still an outstanding call - Mockito.verify(underlyingChannel, Mockito.after(200).never()).shutdown(); - // send message and end the call - call.sendMessage("message"); - // shutdown is called because the outstanding call has completed - Mockito.verify(underlyingChannel, Mockito.atLeastOnce()).shutdown(); - } - - // Channel should be shutdown after a refresh all the calls have completed - @Test - public void channelShouldShutdown() throws IOException { - ManagedChannel underlyingChannel = Mockito.mock(ManagedChannel.class); - ManagedChannel replacementChannel = Mockito.mock(ManagedChannel.class); - - FakeChannelFactory channelFactory = - new FakeChannelFactory(ImmutableList.of(underlyingChannel, replacementChannel)); - ChannelPool pool = ChannelPool.create(ChannelPoolSettings.staticallySized(1), channelFactory); - - // create a mock call when new call comes to the underlying channel - MockClientCall mockClientCall = new MockClientCall<>(1, Status.OK); - MockClientCall spyClientCall = Mockito.spy(mockClientCall); - Mockito.when( - underlyingChannel.newCall( - Mockito.>any(), Mockito.any(CallOptions.class))) - .thenReturn(spyClientCall); - - Answer verifyChannelNotShutdown = - invocation -> { - Mockito.verify(underlyingChannel, Mockito.never()).shutdown(); - return invocation.callRealMethod(); - }; - - // verify that underlying channel is not shutdown when clientCall is still sending message - Mockito.doAnswer(verifyChannelNotShutdown).when(spyClientCall).sendMessage(Mockito.anyString()); - - // create a new call on safeShutdownManagedChannel - @SuppressWarnings("unchecked") - ClientCall.Listener listener = Mockito.mock(ClientCall.Listener.class); - ClientCall call = - pool.newCall(FakeMethodDescriptor.create(), CallOptions.DEFAULT); - - // start clientCall - call.start(listener, new Metadata()); - // send message and end the call - call.sendMessage("message"); - // shutdown is not called because it has not been shutdown yet - Mockito.verify(underlyingChannel, Mockito.after(200).never()).shutdown(); - pool.refresh(); - // shutdown is called because the outstanding call has completed - Mockito.verify(underlyingChannel, Mockito.atLeastOnce()).shutdown(); - } - - @Test - public void channelRefreshShouldSwapChannels() throws IOException { - ManagedChannel underlyingChannel1 = Mockito.mock(ManagedChannel.class); - ManagedChannel underlyingChannel2 = Mockito.mock(ManagedChannel.class); - - // mock executor service to capture the runnable scheduled, so we can invoke it when we want to - ScheduledExecutorService scheduledExecutorService = - Mockito.mock(ScheduledExecutorService.class); - - Mockito.doReturn(null) - .when(scheduledExecutorService) - .schedule( - Mockito.any(Runnable.class), Mockito.anyLong(), Mockito.eq(TimeUnit.MILLISECONDS)); - - FakeChannelFactory channelFactory = - new FakeChannelFactory(ImmutableList.of(underlyingChannel1, underlyingChannel2)); - ChannelPool pool = - new ChannelPool( - ChannelPoolSettings.staticallySized(1) - .toBuilder() - .setPreemptiveRefreshEnabled(true) - .build(), - channelFactory, - scheduledExecutorService); - Mockito.reset(underlyingChannel1); - - pool.newCall(FakeMethodDescriptor.create(), CallOptions.DEFAULT); - - Mockito.verify(underlyingChannel1, Mockito.only()) - .newCall(Mockito.>any(), Mockito.any(CallOptions.class)); - - // swap channel - pool.refresh(); - - pool.newCall(FakeMethodDescriptor.create(), CallOptions.DEFAULT); - - Mockito.verify(underlyingChannel2, Mockito.only()) - .newCall(Mockito.>any(), Mockito.any(CallOptions.class)); - } - - @Test - public void channelCountShouldNotChangeWhenOutstandingRpcsAreWithinLimits() throws Exception { - ScheduledExecutorService executor = Mockito.mock(ScheduledExecutorService.class); - - List channels = new ArrayList<>(); - List> startedCalls = new ArrayList<>(); - - ChannelFactory channelFactory = - () -> { - ManagedChannel channel = Mockito.mock(ManagedChannel.class); - Mockito.when(channel.newCall(Mockito.any(), Mockito.any())) - .thenAnswer( - invocation -> { - @SuppressWarnings("unchecked") - ClientCall clientCall = Mockito.mock(ClientCall.class); - startedCalls.add(clientCall); - return clientCall; - }); - - channels.add(channel); - return channel; - }; - - ChannelPool pool = - new ChannelPool( - ChannelPoolSettings.builder() - .setInitialChannelCount(2) - .setMinRpcsPerChannel(1) - .setMaxRpcsPerChannel(2) - .build(), - channelFactory, - executor); - assertThat(pool.entries.get()).hasSize(2); - - // Start the minimum number of - for (int i = 0; i < 2; i++) { - ClientCalls.futureUnaryCall( - pool.newCall(FakeServiceGrpc.METHOD_RECOGNIZE, CallOptions.DEFAULT), - Color.getDefaultInstance()); - } - pool.resize(); - assertThat(pool.entries.get()).hasSize(2); - - // Add enough RPCs to be just at the brink of expansion - for (int i = startedCalls.size(); i < 4; i++) { - ClientCalls.futureUnaryCall( - pool.newCall(FakeServiceGrpc.METHOD_RECOGNIZE, CallOptions.DEFAULT), - Color.getDefaultInstance()); - } - pool.resize(); - assertThat(pool.entries.get()).hasSize(2); - - // Add another RPC to push expansion - pool.newCall(FakeServiceGrpc.METHOD_RECOGNIZE, CallOptions.DEFAULT); - pool.resize(); - assertThat(pool.entries.get()).hasSize(4); // += ChannelPool::MAX_RESIZE_DELTA - assertThat(startedCalls).hasSize(5); - - // Complete RPCs to the brink of shrinking - @SuppressWarnings("unchecked") - ArgumentCaptor> captor = - ArgumentCaptor.forClass(ClientCall.Listener.class); - Mockito.verify(startedCalls.remove(0)).start(captor.capture(), Mockito.any()); - captor.getValue().onClose(Status.ABORTED, new Metadata()); - // Resize twice: the first round maintains the peak from the last cycle - pool.resize(); - pool.resize(); - assertThat(pool.entries.get()).hasSize(4); - assertThat(startedCalls).hasSize(4); - - // Complete another RPC to trigger shrinking - Mockito.verify(startedCalls.remove(0)).start(captor.capture(), Mockito.any()); - captor.getValue().onClose(Status.ABORTED, new Metadata()); - // Resize twice: the first round maintains the peak from the last cycle - pool.resize(); - pool.resize(); - assertThat(startedCalls).hasSize(3); - // range of channels is [2-3] rounded down average is 2 - assertThat(pool.entries.get()).hasSize(2); - } - - @Test - public void removedIdleChannelsAreShutdown() throws Exception { - ScheduledExecutorService executor = Mockito.mock(ScheduledExecutorService.class); - - List channels = new ArrayList<>(); - List> startedCalls = new ArrayList<>(); - - ChannelFactory channelFactory = - () -> { - ManagedChannel channel = Mockito.mock(ManagedChannel.class); - Mockito.when(channel.newCall(Mockito.any(), Mockito.any())) - .thenAnswer( - invocation -> { - @SuppressWarnings("unchecked") - ClientCall clientCall = Mockito.mock(ClientCall.class); - startedCalls.add(clientCall); - return clientCall; - }); - - channels.add(channel); - return channel; - }; - - ChannelPool pool = - new ChannelPool( - ChannelPoolSettings.builder() - .setInitialChannelCount(2) - .setMinRpcsPerChannel(1) - .setMaxRpcsPerChannel(2) - .build(), - channelFactory, - executor); - assertThat(pool.entries.get()).hasSize(2); - - // With no outstanding RPCs, the pool should shrink - pool.resize(); - assertThat(pool.entries.get()).hasSize(1); - Mockito.verify(channels.get(1), Mockito.times(1)).shutdown(); - } - - @Test - public void removedActiveChannelsAreShutdown() throws Exception { - ScheduledExecutorService executor = Mockito.mock(ScheduledExecutorService.class); - - List channels = new ArrayList<>(); - List> startedCalls = new ArrayList<>(); - - ChannelFactory channelFactory = - () -> { - ManagedChannel channel = Mockito.mock(ManagedChannel.class); - Mockito.when(channel.newCall(Mockito.any(), Mockito.any())) - .thenAnswer( - invocation -> { - @SuppressWarnings("unchecked") - ClientCall clientCall = Mockito.mock(ClientCall.class); - startedCalls.add(clientCall); - return clientCall; - }); - - channels.add(channel); - return channel; - }; - - ChannelPool pool = - new ChannelPool( - ChannelPoolSettings.builder() - .setInitialChannelCount(2) - .setMinRpcsPerChannel(1) - .setMaxRpcsPerChannel(2) - .build(), - channelFactory, - executor); - assertThat(pool.entries.get()).hasSize(2); - - // Start 2 RPCs - for (int i = 0; i < 2; i++) { - ClientCalls.futureUnaryCall( - pool.newCall(FakeServiceGrpc.METHOD_RECOGNIZE, CallOptions.DEFAULT), - Color.getDefaultInstance()); - } - // Complete the first one - @SuppressWarnings("unchecked") - ArgumentCaptor> captor = - ArgumentCaptor.forClass(ClientCall.Listener.class); - Mockito.verify(startedCalls.get(0)).start(captor.capture(), Mockito.any()); - captor.getValue().onClose(Status.ABORTED, new Metadata()); - - // With a single RPC, the pool should shrink - pool.resize(); - pool.resize(); - assertThat(pool.entries.get()).hasSize(1); - - // While the RPC is outstanding, the channel should still be open - Mockito.verify(channels.get(1), Mockito.never()).shutdown(); - - // Complete the RPC - Mockito.verify(startedCalls.get(1)).start(captor.capture(), Mockito.any()); - captor.getValue().onClose(Status.ABORTED, new Metadata()); - // Now the channel should be closed - Mockito.verify(channels.get(1), Mockito.times(1)).shutdown(); - } -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/GaxGrpcPropertiesTest.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/GaxGrpcPropertiesTest.java deleted file mode 100644 index 417431227..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/GaxGrpcPropertiesTest.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.util.regex.Pattern; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class GaxGrpcPropertiesTest { - - @Test - public void testGrpcVersion() { - String grpcVersion = GaxGrpcProperties.getGrpcVersion(); - assertTrue(Pattern.compile("^\\d+\\.\\d+\\.\\d+").matcher(grpcVersion).find()); - } - - @Test - public void testGaxGrpcVersion() { - String gaxGrpcVersion = GaxGrpcProperties.getGaxGrpcVersion(); - assertNotNull(gaxGrpcVersion); - } - - @Test - public void testDefaultHeaderPattern() { - assertTrue( - GaxGrpcProperties.getDefaultApiClientHeaderPattern() - .matcher("gl-java/1.8_00 gapic/1.2.3-alpha gax/1.5.0 grpc/1.7.0") - .matches()); - } -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcApiExceptionFactoryTest.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcApiExceptionFactoryTest.java deleted file mode 100644 index bb8febef5..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcApiExceptionFactoryTest.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import static com.google.api.gax.grpc.GrpcApiExceptionFactory.ERROR_DETAIL_KEY; - -import com.google.api.gax.rpc.ApiException; -import com.google.api.gax.rpc.ErrorDetails; -import com.google.common.collect.ImmutableList; -import com.google.common.truth.Truth; -import com.google.protobuf.Any; -import com.google.protobuf.Duration; -import com.google.rpc.ErrorInfo; -import com.google.rpc.RetryInfo; -import com.google.rpc.Status; -import io.grpc.Metadata; -import io.grpc.StatusException; -import io.grpc.StatusRuntimeException; -import java.util.Collections; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class GrpcApiExceptionFactoryTest { - - private static final ErrorInfo ERROR_INFO = - ErrorInfo.newBuilder() - .setDomain("googleapis.com") - .setReason("SERVICE_DISABLED") - .putAllMetadata(Collections.emptyMap()) - .build(); - - private static final RetryInfo RETRY_INFO = - RetryInfo.newBuilder().setRetryDelay(Duration.newBuilder().setSeconds(213).build()).build(); - - private static final ImmutableList RAW_ERROR_MESSAGES = - ImmutableList.of(Any.pack(ERROR_INFO), Any.pack(RETRY_INFO)); - - private static final ErrorDetails ERROR_DETAILS = - ErrorDetails.builder().setRawErrorMessages(RAW_ERROR_MESSAGES).build(); - - private static final io.grpc.Status GRPC_STATUS = io.grpc.Status.CANCELLED; - - private GrpcApiExceptionFactory factory; - - @Before - public void setUp() throws Exception { - factory = new GrpcApiExceptionFactory(Collections.emptySet()); - } - - @Test - public void create_shouldCreateApiExceptionWithErrorDetailsForStatusException() { - Metadata trailers = new Metadata(); - Status status = Status.newBuilder().addAllDetails(RAW_ERROR_MESSAGES).build(); - trailers.put( - Metadata.Key.of(ERROR_DETAIL_KEY, Metadata.BINARY_BYTE_MARSHALLER), status.toByteArray()); - StatusException statusException = new StatusException(GRPC_STATUS, trailers); - - ApiException actual = factory.create(statusException); - - Truth.assertThat(actual.getErrorDetails()).isEqualTo(ERROR_DETAILS); - } - - @Test - public void create_shouldCreateApiExceptionWithErrorDetailsForStatusRuntimeException() { - Metadata trailers = new Metadata(); - Status status = Status.newBuilder().addAllDetails(RAW_ERROR_MESSAGES).build(); - trailers.put( - Metadata.Key.of(ERROR_DETAIL_KEY, Metadata.BINARY_BYTE_MARSHALLER), status.toByteArray()); - StatusRuntimeException statusException = new StatusRuntimeException(GRPC_STATUS, trailers); - - ApiException actual = factory.create(statusException); - - Truth.assertThat(actual.getErrorDetails()).isEqualTo(ERROR_DETAILS); - } - - @Test - public void create_shouldCreateApiExceptionWithNoErrorDetailsIfMetadataIsNull() { - StatusRuntimeException statusException = new StatusRuntimeException(GRPC_STATUS, null); - - ApiException actual = factory.create(statusException); - - Truth.assertThat(actual.getErrorDetails()).isNull(); - } - - @Test - public void create_shouldCreateApiExceptionWithNoErrorDetailsIfMetadataDoesNotHaveErrorDetails() { - StatusRuntimeException statusException = - new StatusRuntimeException(GRPC_STATUS, new Metadata()); - - ApiException actual = factory.create(statusException); - - Truth.assertThat(actual.getErrorDetails()).isNull(); - } - - @Test - public void create_shouldCreateApiExceptionWithNoErrorDetailsIfStatusIsMalformed() { - Metadata trailers = new Metadata(); - Status status = Status.newBuilder().addDetails(Any.pack(ERROR_INFO)).build(); - byte[] bytes = status.toByteArray(); - // manually manipulate status bytes array - bytes[0] = 123; - trailers.put(Metadata.Key.of(ERROR_DETAIL_KEY, Metadata.BINARY_BYTE_MARSHALLER), bytes); - StatusRuntimeException statusException = new StatusRuntimeException(GRPC_STATUS, trailers); - - ApiException actual = factory.create(statusException); - - Truth.assertThat(actual.getErrorDetails()).isNull(); - } -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcCallContextTest.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcCallContextTest.java deleted file mode 100644 index 4e563225e..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcCallContextTest.java +++ /dev/null @@ -1,411 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.StatusCode; -import com.google.api.gax.rpc.testing.FakeCallContext; -import com.google.api.gax.rpc.testing.FakeChannel; -import com.google.api.gax.rpc.testing.FakeTransportChannel; -import com.google.api.gax.tracing.ApiTracer; -import com.google.auth.Credentials; -import com.google.common.collect.ImmutableMap; -import com.google.common.truth.Truth; -import io.grpc.CallOptions; -import io.grpc.ManagedChannel; -import io.grpc.Metadata.Key; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class GrpcCallContextTest { - - @Test - public void testNullToSelfWrongType() { - try { - GrpcCallContext.createDefault().nullToSelf(FakeCallContext.createDefault()); - Assert.fail("GrpcCallContext should have thrown an exception"); - } catch (IllegalArgumentException expected) { - Truth.assertThat(expected) - .hasMessageThat() - .contains("context must be an instance of GrpcCallContext"); - } - } - - @Test - public void testWithCredentials() { - Credentials credentials = Mockito.mock(Credentials.class); - GrpcCallContext emptyContext = GrpcCallContext.createDefault(); - assertNull(emptyContext.getCallOptions().getCredentials()); - GrpcCallContext context = emptyContext.withCredentials(credentials); - assertNotNull(context.getCallOptions().getCredentials()); - } - - @Test - public void testWithTransportChannel() { - ManagedChannel channel = Mockito.mock(ManagedChannel.class); - GrpcCallContext context = - GrpcCallContext.createDefault().withTransportChannel(GrpcTransportChannel.create(channel)); - Truth.assertThat(context.getChannel()).isSameInstanceAs(channel); - } - - @Test - public void testWithTransportChannelWrongType() { - FakeChannel channel = new FakeChannel(); - try { - GrpcCallContext.createDefault().withTransportChannel(FakeTransportChannel.create(channel)); - Assert.fail("GrpcCallContext should have thrown an exception"); - } catch (IllegalArgumentException expected) { - Truth.assertThat(expected).hasMessageThat().contains("Expected GrpcTransportChannel"); - } - } - - @Test - public void testMergeWrongType() { - try { - GrpcCallContext.createDefault().merge(FakeCallContext.createDefault()); - Assert.fail("GrpcCallContext should have thrown an exception"); - } catch (IllegalArgumentException expected) { - Truth.assertThat(expected) - .hasMessageThat() - .contains("context must be an instance of " + "GrpcCallContext"); - } - } - - @Test - public void testWithRequestParamsDynamicHeaderOption() { - String encodedRequestParams = "param1=value¶m2.param3=value23"; - GrpcCallContext context = - GrpcCallContext.createDefault().withRequestParamsDynamicHeaderOption(encodedRequestParams); - - Map, String> headers = - CallOptionsUtil.getDynamicHeadersOption(context.getCallOptions()); - - assertEquals( - ImmutableMap.of(CallOptionsUtil.REQUEST_PARAMS_HEADER_KEY, encodedRequestParams), headers); - } - - @Test - public void testWithTimeout() { - assertNull(GrpcCallContext.createDefault().withTimeout(null).getTimeout()); - } - - @Test - public void testWithNegativeTimeout() { - assertNull(GrpcCallContext.createDefault().withTimeout(Duration.ofSeconds(-1L)).getTimeout()); - } - - @Test - public void testWithZeroTimeout() { - assertNull(GrpcCallContext.createDefault().withTimeout(Duration.ofSeconds(0L)).getTimeout()); - } - - @Test - public void testWithShorterTimeout() { - GrpcCallContext ctxWithLongTimeout = - GrpcCallContext.createDefault().withTimeout(Duration.ofSeconds(10)); - - // Sanity check - Truth.assertThat(ctxWithLongTimeout.getTimeout()).isEqualTo(Duration.ofSeconds(10)); - - // Shorten the timeout and make sure it changed - GrpcCallContext ctxWithShorterTimeout = ctxWithLongTimeout.withTimeout(Duration.ofSeconds(5)); - Truth.assertThat(ctxWithShorterTimeout.getTimeout()).isEqualTo(Duration.ofSeconds(5)); - } - - @Test - public void testWithLongerTimeout() { - GrpcCallContext ctxWithShortTimeout = - GrpcCallContext.createDefault().withTimeout(Duration.ofSeconds(5)); - - // Sanity check - Truth.assertThat(ctxWithShortTimeout.getTimeout()).isEqualTo(Duration.ofSeconds(5)); - - // Try to extend the timeout and verify that it was ignored - GrpcCallContext ctxWithUnchangedTimeout = - ctxWithShortTimeout.withTimeout(Duration.ofSeconds(10)); - Truth.assertThat(ctxWithUnchangedTimeout.getTimeout()).isEqualTo(Duration.ofSeconds(5)); - } - - @Test - public void testMergeWithNullTimeout() { - Duration timeout = Duration.ofSeconds(10); - GrpcCallContext baseContext = GrpcCallContext.createDefault().withTimeout(timeout); - - GrpcCallContext defaultOverlay = GrpcCallContext.createDefault(); - Truth.assertThat(baseContext.merge(defaultOverlay).getTimeout()).isEqualTo(timeout); - - GrpcCallContext explicitNullOverlay = GrpcCallContext.createDefault().withTimeout(null); - Truth.assertThat(baseContext.merge(explicitNullOverlay).getTimeout()).isEqualTo(timeout); - } - - @Test - public void testMergeWithTimeout() { - Duration timeout = Duration.ofSeconds(19); - GrpcCallContext ctx1 = GrpcCallContext.createDefault(); - GrpcCallContext ctx2 = GrpcCallContext.createDefault().withTimeout(timeout); - - Truth.assertThat(ctx1.merge(ctx2).getTimeout()).isEqualTo(timeout); - } - - @Test - public void testWithStreamingWaitTimeout() { - Duration timeout = Duration.ofSeconds(15); - GrpcCallContext context = GrpcCallContext.createDefault().withStreamWaitTimeout(timeout); - Truth.assertThat(context.getStreamWaitTimeout()).isEqualTo(timeout); - } - - @Test - public void testMergeWithNullStreamingWaitTimeout() { - Duration timeout = Duration.ofSeconds(10); - GrpcCallContext baseContext = GrpcCallContext.createDefault().withStreamWaitTimeout(timeout); - - GrpcCallContext defaultOverlay = GrpcCallContext.createDefault(); - Truth.assertThat(baseContext.merge(defaultOverlay).getStreamWaitTimeout()).isEqualTo(timeout); - - GrpcCallContext explicitNullOverlay = - GrpcCallContext.createDefault().withStreamWaitTimeout(null); - Truth.assertThat(baseContext.merge(explicitNullOverlay).getStreamWaitTimeout()) - .isEqualTo(timeout); - } - - @Test - public void testWithZeroStreamingWaitTimeout() { - Duration timeout = Duration.ZERO; - Truth.assertThat( - GrpcCallContext.createDefault().withStreamWaitTimeout(timeout).getStreamWaitTimeout()) - .isEqualTo(timeout); - } - - @Test - public void testMergeWithStreamingWaitTimeout() { - Duration timeout = Duration.ofSeconds(19); - GrpcCallContext ctx1 = GrpcCallContext.createDefault(); - GrpcCallContext ctx2 = GrpcCallContext.createDefault().withStreamWaitTimeout(timeout); - - Truth.assertThat(ctx1.merge(ctx2).getStreamWaitTimeout()).isEqualTo(timeout); - } - - @Test - public void testWithStreamingIdleTimeout() { - Duration timeout = Duration.ofSeconds(15); - GrpcCallContext context = GrpcCallContext.createDefault().withStreamIdleTimeout(timeout); - Truth.assertThat(context.getStreamIdleTimeout()).isEqualTo(timeout); - } - - @Test - public void testMergeWithNullStreamingIdleTimeout() { - Duration timeout = Duration.ofSeconds(10); - GrpcCallContext baseContext = GrpcCallContext.createDefault().withStreamIdleTimeout(timeout); - - GrpcCallContext defaultOverlay = GrpcCallContext.createDefault(); - Truth.assertThat(baseContext.merge(defaultOverlay).getStreamIdleTimeout()).isEqualTo(timeout); - - GrpcCallContext explicitNullOverlay = - GrpcCallContext.createDefault().withStreamIdleTimeout(null); - Truth.assertThat(baseContext.merge(explicitNullOverlay).getStreamIdleTimeout()) - .isEqualTo(timeout); - } - - @Test - public void testWithZeroStreamingIdleTimeout() { - Duration timeout = Duration.ZERO; - Truth.assertThat( - GrpcCallContext.createDefault().withStreamIdleTimeout(timeout).getStreamIdleTimeout()) - .isEqualTo(timeout); - } - - @Test - public void testMergeWithStreamingIdleTimeout() { - Duration timeout = Duration.ofSeconds(19); - GrpcCallContext ctx1 = GrpcCallContext.createDefault(); - GrpcCallContext ctx2 = GrpcCallContext.createDefault().withStreamIdleTimeout(timeout); - - Truth.assertThat(ctx1.merge(ctx2).getStreamIdleTimeout()).isEqualTo(timeout); - } - - @Test - public void testMergeWithCustomCallOptions() { - CallOptions.Key key = CallOptions.Key.createWithDefault("somekey", "somedefault"); - GrpcCallContext ctx1 = GrpcCallContext.createDefault(); - GrpcCallContext ctx2 = - GrpcCallContext.createDefault() - .withCallOptions(CallOptions.DEFAULT.withOption(key, "somevalue")); - - GrpcCallContext merged = (GrpcCallContext) ctx1.merge(ctx2); - Truth.assertThat(merged.getCallOptions().getOption(key)) - .isNotEqualTo(ctx1.getCallOptions().getOption(key)); - Truth.assertThat(merged.getCallOptions().getOption(key)) - .isEqualTo(ctx2.getCallOptions().getOption(key)); - } - - @Test - public void testWithExtraHeaders() { - Map> extraHeaders = - createTestExtraHeaders("key1", "value1", "key1", "value2"); - GrpcCallContext ctx = GrpcCallContext.createDefault().withExtraHeaders(extraHeaders); - Map> moreExtraHeaders = - createTestExtraHeaders("key1", "value2", "key2", "value2"); - ctx = ctx.withExtraHeaders(moreExtraHeaders); - Map> gotExtraHeaders = ctx.getExtraHeaders(); - Map> expectedExtraHeaders = - createTestExtraHeaders( - "key1", "value1", "key1", "value2", "key1", "value2", "key2", "value2"); - Truth.assertThat(gotExtraHeaders).containsExactlyEntriesIn(expectedExtraHeaders); - } - - @Test - public void testMergeWithExtraHeaders() { - Map> extraHeaders1 = - createTestExtraHeaders("key1", "value1", "key1", "value2"); - GrpcCallContext ctx1 = GrpcCallContext.createDefault().withExtraHeaders(extraHeaders1); - Map> extraHeaders2 = - createTestExtraHeaders("key1", "value2", "key2", "value2"); - GrpcCallContext ctx2 = GrpcCallContext.createDefault().withExtraHeaders(extraHeaders2); - ApiCallContext mergedApiCallContext = ctx1.merge(ctx2); - Truth.assertThat(mergedApiCallContext).isInstanceOf(GrpcCallContext.class); - GrpcCallContext mergedGrpcCallContext = (GrpcCallContext) mergedApiCallContext; - Map> gotExtraHeaders = mergedGrpcCallContext.getExtraHeaders(); - Map> expectedExtraHeaders = - createTestExtraHeaders( - "key1", "value1", "key1", "value2", "key1", "value2", "key2", "value2"); - Truth.assertThat(gotExtraHeaders).containsExactlyEntriesIn(expectedExtraHeaders); - } - - @Test - public void testMergeWithTracer() { - ApiTracer explicitTracer = Mockito.mock(ApiTracer.class); - GrpcCallContext ctxWithExplicitTracer = - GrpcCallContext.createDefault().withTracer(explicitTracer); - - GrpcCallContext ctxWithDefaultTracer = GrpcCallContext.createDefault(); - ApiTracer defaultTracer = ctxWithDefaultTracer.getTracer(); - - // Explicit tracer overrides the default tracer. - Truth.assertThat(ctxWithDefaultTracer.merge(ctxWithExplicitTracer).getTracer()) - .isSameInstanceAs(explicitTracer); - - // Default tracer does not override an explicit tracer. - Truth.assertThat(ctxWithExplicitTracer.merge(ctxWithDefaultTracer).getTracer()) - .isSameInstanceAs(explicitTracer); - - // Default tracer does not override another default tracer. - Truth.assertThat(ctxWithDefaultTracer.merge(GrpcCallContext.createDefault()).getTracer()) - .isSameInstanceAs(defaultTracer); - } - - @Test - public void testWithRetrySettings() { - RetrySettings retrySettings = Mockito.mock(RetrySettings.class); - GrpcCallContext emptyContext = GrpcCallContext.createDefault(); - assertNull(emptyContext.getRetrySettings()); - GrpcCallContext context = emptyContext.withRetrySettings(retrySettings); - assertNotNull(context.getRetrySettings()); - } - - @Test - public void testWithRetryableCodes() { - Set codes = Collections.singleton(StatusCode.Code.UNAVAILABLE); - GrpcCallContext emptyContext = GrpcCallContext.createDefault(); - assertNull(emptyContext.getRetryableCodes()); - GrpcCallContext context = emptyContext.withRetryableCodes(codes); - assertNotNull(context.getRetryableCodes()); - } - - @Test - public void testWithOptions() { - GrpcCallContext emptyCallContext = GrpcCallContext.createDefault(); - ApiCallContext.Key contextKey1 = ApiCallContext.Key.create("testKey1"); - ApiCallContext.Key contextKey2 = ApiCallContext.Key.create("testKey2"); - String testContext1 = "test1"; - String testContext2 = "test2"; - String testContextOverwrite = "test1Overwrite"; - GrpcCallContext context = - emptyCallContext - .withOption(contextKey1, testContext1) - .withOption(contextKey2, testContext2); - assertEquals(testContext1, context.getOption(contextKey1)); - assertEquals(testContext2, context.getOption(contextKey2)); - GrpcCallContext newContext = context.withOption(contextKey1, testContextOverwrite); - assertEquals(testContextOverwrite, newContext.getOption(contextKey1)); - } - - @Test - public void testMergeOptions() { - GrpcCallContext emptyCallContext = GrpcCallContext.createDefault(); - ApiCallContext.Key contextKey1 = ApiCallContext.Key.create("testKey1"); - ApiCallContext.Key contextKey2 = ApiCallContext.Key.create("testKey2"); - ApiCallContext.Key contextKey3 = ApiCallContext.Key.create("testKey3"); - String testContext1 = "test1"; - String testContext2 = "test2"; - String testContext3 = "test3"; - String testContextOverwrite = "test1Overwrite"; - GrpcCallContext context1 = - emptyCallContext - .withOption(contextKey1, testContext1) - .withOption(contextKey2, testContext2); - GrpcCallContext context2 = - emptyCallContext - .withOption(contextKey1, testContextOverwrite) - .withOption(contextKey3, testContext3); - ApiCallContext mergedContext = context1.merge(context2); - assertEquals(testContextOverwrite, mergedContext.getOption(contextKey1)); - assertEquals(testContext2, mergedContext.getOption(contextKey2)); - assertEquals(testContext3, mergedContext.getOption(contextKey3)); - } - - private static Map> createTestExtraHeaders(String... keyValues) { - Map> extraHeaders = new HashMap<>(); - for (int i = 0; i < keyValues.length; i += 2) { - String key = keyValues[i]; - String value = keyValues[i + 1]; - if (!extraHeaders.containsKey(key)) { - extraHeaders.put(key, new ArrayList()); - } - extraHeaders.get(key).add(value); - } - return extraHeaders; - } -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcCallableFactoryTest.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcCallableFactoryTest.java deleted file mode 100644 index 2ebe93b7f..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcCallableFactoryTest.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.api.gax.grpc.testing.FakeServiceGrpc; -import com.google.api.gax.grpc.testing.FakeServiceImpl; -import com.google.api.gax.grpc.testing.InProcessServer; -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.rpc.ClientContext; -import com.google.api.gax.rpc.InvalidArgumentException; -import com.google.api.gax.rpc.ServerStreamingCallSettings; -import com.google.api.gax.rpc.ServerStreamingCallable; -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.api.gax.tracing.SpanName; -import com.google.common.collect.ImmutableList; -import com.google.common.truth.Truth; -import com.google.type.Color; -import com.google.type.Money; -import io.grpc.CallOptions; -import io.grpc.ManagedChannel; -import io.grpc.MethodDescriptor; -import io.grpc.MethodDescriptor.Marshaller; -import io.grpc.MethodDescriptor.MethodType; -import io.grpc.inprocess.InProcessChannelBuilder; -import java.util.List; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class GrpcCallableFactoryTest { - private InProcessServer inprocessServer; - private ManagedChannel channel; - private ClientContext clientContext; - - @Before - public void setUp() throws Exception { - String serverName = "fakeservice"; - FakeServiceImpl serviceImpl = new FakeServiceImpl(); - inprocessServer = new InProcessServer<>(serviceImpl, serverName); - inprocessServer.start(); - - channel = InProcessChannelBuilder.forName(serverName).directExecutor().usePlaintext().build(); - clientContext = - ClientContext.newBuilder() - .setTransportChannel(GrpcTransportChannel.create(channel)) - .setDefaultCallContext(GrpcCallContext.of(channel, CallOptions.DEFAULT)) - .build(); - } - - @After - public void tearDown() { - channel.shutdown(); - inprocessServer.stop(); - } - - @Test - public void createServerStreamingCallableRetryableExceptions() { - GrpcCallSettings grpcCallSettings = - GrpcCallSettings.create(FakeServiceGrpc.METHOD_STREAMING_RECOGNIZE_ERROR); - - // Base case: without config, invalid argument errors are not retryable. - ServerStreamingCallSettings nonRetryableSettings = - ServerStreamingCallSettings.newBuilder() - .setRetrySettings( - RetrySettings.newBuilder() - .setTotalTimeout(Duration.ofSeconds(1)) - .setMaxAttempts(1) - .build()) - .build(); - - ServerStreamingCallable nonRetryableCallable = - GrpcCallableFactory.createServerStreamingCallable( - grpcCallSettings, nonRetryableSettings, clientContext); - - Throwable actualError = null; - try { - nonRetryableCallable - .first() - .call(Color.getDefaultInstance(), clientContext.getDefaultCallContext()); - } catch (Throwable e) { - actualError = e; - } - assertThat(actualError).isInstanceOf(InvalidArgumentException.class); - assertThat(((InvalidArgumentException) actualError).isRetryable()).isFalse(); - - // Actual test: with config, invalid argument errors are retryable. - ServerStreamingCallSettings retryableSettings = - ServerStreamingCallSettings.newBuilder() - .setRetryableCodes(Code.INVALID_ARGUMENT) - .setRetrySettings( - RetrySettings.newBuilder() - .setTotalTimeout(Duration.ofSeconds(1)) - .setMaxAttempts(1) - .build()) - .build(); - - ServerStreamingCallable retryableCallable = - GrpcCallableFactory.createServerStreamingCallable( - grpcCallSettings, retryableSettings, clientContext); - - Throwable actualError2 = null; - try { - retryableCallable - .first() - .call(Color.getDefaultInstance(), clientContext.getDefaultCallContext()); - } catch (Throwable e) { - actualError2 = e; - } - assertThat(actualError2).isInstanceOf(InvalidArgumentException.class); - assertThat(((InvalidArgumentException) actualError2).isRetryable()).isTrue(); - } - - @Test - public void testGetSpanName() { - @SuppressWarnings("unchecked") - MethodDescriptor descriptor = - MethodDescriptor.newBuilder() - .setType(MethodType.SERVER_STREAMING) - .setFullMethodName("google.bigtable.v2.Bigtable/ReadRows") - .setRequestMarshaller(Mockito.mock(Marshaller.class)) - .setResponseMarshaller(Mockito.mock(Marshaller.class)) - .build(); - - SpanName actualSpanName = GrpcCallableFactory.getSpanName(descriptor); - assertThat(actualSpanName).isEqualTo(SpanName.of("Bigtable", "ReadRows")); - } - - @Test - public void testGetSpanNameUnqualified() { - @SuppressWarnings("unchecked") - MethodDescriptor descriptor = - MethodDescriptor.newBuilder() - .setType(MethodType.SERVER_STREAMING) - .setFullMethodName("UnqualifiedService/ReadRows") - .setRequestMarshaller(Mockito.mock(Marshaller.class)) - .setResponseMarshaller(Mockito.mock(Marshaller.class)) - .build(); - - SpanName actualSpanName = GrpcCallableFactory.getSpanName(descriptor); - assertThat(actualSpanName).isEqualTo(SpanName.of("UnqualifiedService", "ReadRows")); - } - - @Test - public void testGetSpanNameInvalid() { - List invalidNames = ImmutableList.of("BareMethod", "/MethodWithoutService"); - - for (String invalidName : invalidNames) { - @SuppressWarnings("unchecked") - MethodDescriptor descriptor = - MethodDescriptor.newBuilder() - .setType(MethodType.SERVER_STREAMING) - .setFullMethodName(invalidName) - .setRequestMarshaller(Mockito.mock(Marshaller.class)) - .setResponseMarshaller(Mockito.mock(Marshaller.class)) - .build(); - - IllegalArgumentException actualError = null; - try { - SpanName spanName = GrpcCallableFactory.getSpanName(descriptor); - Truth.assertWithMessage( - "Invalid method descriptor should not have a valid span name: %s should not generate the spanName: %s", - invalidName, spanName) - .fail(); - } catch (IllegalArgumentException e) { - actualError = e; - } - - assertThat(actualError).isNotNull(); - } - } -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcClientCallsTest.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcClientCallsTest.java deleted file mode 100644 index fcdea5afe..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcClientCallsTest.java +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.verify; - -import com.google.api.gax.grpc.testing.FakeChannelFactory; -import com.google.api.gax.grpc.testing.FakeServiceGrpc; -import com.google.common.collect.ImmutableList; -import com.google.common.truth.Truth; -import com.google.type.Color; -import com.google.type.Money; -import io.grpc.CallOptions; -import io.grpc.Channel; -import io.grpc.ClientCall; -import io.grpc.Deadline; -import io.grpc.ManagedChannel; -import io.grpc.Metadata; -import io.grpc.MethodDescriptor; -import java.io.IOException; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; -import org.threeten.bp.Duration; - -public class GrpcClientCallsTest { - @Test - public void testAffinity() throws IOException { - MethodDescriptor descriptor = FakeServiceGrpc.METHOD_RECOGNIZE; - - @SuppressWarnings("unchecked") - ClientCall clientCall0 = Mockito.mock(ClientCall.class); - - @SuppressWarnings("unchecked") - ClientCall clientCall1 = Mockito.mock(ClientCall.class); - - ManagedChannel channel0 = Mockito.mock(ManagedChannel.class); - ManagedChannel channel1 = Mockito.mock(ManagedChannel.class); - - Mockito.when(channel0.newCall(Mockito.eq(descriptor), Mockito.any())) - .thenReturn(clientCall0); - Mockito.when(channel1.newCall(Mockito.eq(descriptor), Mockito.any())) - .thenReturn(clientCall1); - Channel pool = - ChannelPool.create( - ChannelPoolSettings.staticallySized(2), - new FakeChannelFactory(Arrays.asList(channel0, channel1))); - GrpcCallContext context = GrpcCallContext.createDefault().withChannel(pool); - - ClientCall gotCallA = - GrpcClientCalls.newCall(descriptor, context.withChannelAffinity(0)); - ClientCall gotCallB = - GrpcClientCalls.newCall(descriptor, context.withChannelAffinity(0)); - ClientCall gotCallC = - GrpcClientCalls.newCall(descriptor, context.withChannelAffinity(1)); - - verify(channel0, Mockito.times(2)).newCall(Mockito.eq(descriptor), Mockito.any()); - verify(channel1, Mockito.times(1)).newCall(Mockito.eq(descriptor), Mockito.any()); - } - - @Test - public void testExtraHeaders() { - Metadata emptyHeaders = new Metadata(); - final Map> extraHeaders = new HashMap<>(); - extraHeaders.put( - "header-key-1", ImmutableList.of("header-value-11", "header-value-12")); - extraHeaders.put("header-key-2", ImmutableList.of("header-value-21")); - - MethodDescriptor descriptor = FakeServiceGrpc.METHOD_RECOGNIZE; - - @SuppressWarnings("unchecked") - ClientCall mockClientCall = Mockito.mock(ClientCall.class); - - @SuppressWarnings("unchecked") - ClientCall.Listener mockListener = Mockito.mock(ClientCall.Listener.class); - - Channel mockChannel = Mockito.mock(ManagedChannel.class); - - Mockito.doAnswer( - invocation -> { - Metadata clientCallHeaders = (Metadata) invocation.getArguments()[1]; - Metadata.Key key1 = - Metadata.Key.of("header-key-1", Metadata.ASCII_STRING_MARSHALLER); - Metadata.Key key2 = - Metadata.Key.of("header-key-2", Metadata.ASCII_STRING_MARSHALLER); - assertThat(clientCallHeaders.getAll(key1)) - .containsExactly("header-value-11", "header-value-12"); - assertThat(clientCallHeaders.getAll(key2)).containsExactly("header-value-21"); - return null; - }) - .when(mockClientCall) - .start(Mockito.>any(), Mockito.any()); - - Mockito.when(mockChannel.newCall(Mockito.eq(descriptor), Mockito.any())) - .thenReturn(mockClientCall); - - GrpcCallContext context = - GrpcCallContext.createDefault().withChannel(mockChannel).withExtraHeaders(extraHeaders); - GrpcClientCalls.newCall(descriptor, context).start(mockListener, emptyHeaders); - } - - @Test - public void testTimeoutToDeadlineConversion() { - MethodDescriptor descriptor = FakeServiceGrpc.METHOD_RECOGNIZE; - - @SuppressWarnings("unchecked") - ClientCall mockClientCall = Mockito.mock(ClientCall.class); - - @SuppressWarnings("unchecked") - ClientCall.Listener mockListener = Mockito.mock(ClientCall.Listener.class); - - Channel mockChannel = Mockito.mock(ManagedChannel.class); - - ArgumentCaptor capturedCallOptions = ArgumentCaptor.forClass(CallOptions.class); - - Mockito.when(mockChannel.newCall(Mockito.eq(descriptor), capturedCallOptions.capture())) - .thenReturn(mockClientCall); - - Duration timeout = Duration.ofSeconds(10); - Deadline minExpectedDeadline = Deadline.after(timeout.getSeconds(), TimeUnit.SECONDS); - - GrpcCallContext context = - GrpcCallContext.createDefault().withChannel(mockChannel).withTimeout(timeout); - - GrpcClientCalls.newCall(descriptor, context).start(mockListener, new Metadata()); - - Deadline maxExpectedDeadline = Deadline.after(timeout.getSeconds(), TimeUnit.SECONDS); - - Truth.assertThat(capturedCallOptions.getValue().getDeadline()).isAtLeast(minExpectedDeadline); - Truth.assertThat(capturedCallOptions.getValue().getDeadline()).isAtMost(maxExpectedDeadline); - } - - @Test - public void testTimeoutAfterDeadline() { - MethodDescriptor descriptor = FakeServiceGrpc.METHOD_RECOGNIZE; - - @SuppressWarnings("unchecked") - ClientCall mockClientCall = Mockito.mock(ClientCall.class); - - @SuppressWarnings("unchecked") - ClientCall.Listener mockListener = Mockito.mock(ClientCall.Listener.class); - - Channel mockChannel = Mockito.mock(ManagedChannel.class); - - ArgumentCaptor capturedCallOptions = ArgumentCaptor.forClass(CallOptions.class); - - Mockito.when(mockChannel.newCall(Mockito.eq(descriptor), capturedCallOptions.capture())) - .thenReturn(mockClientCall); - - // Configure a timeout that occurs after the grpc deadline - Deadline priorDeadline = Deadline.after(5, TimeUnit.SECONDS); - Duration timeout = Duration.ofSeconds(10); - - GrpcCallContext context = - GrpcCallContext.createDefault() - .withChannel(mockChannel) - .withCallOptions(CallOptions.DEFAULT.withDeadline(priorDeadline)) - .withTimeout(timeout); - - GrpcClientCalls.newCall(descriptor, context).start(mockListener, new Metadata()); - - // Verify that the timeout is ignored - Truth.assertThat(capturedCallOptions.getValue().getDeadline()).isEqualTo(priorDeadline); - } - - @Test - public void testTimeoutBeforeDeadline() { - MethodDescriptor descriptor = FakeServiceGrpc.METHOD_RECOGNIZE; - - @SuppressWarnings("unchecked") - ClientCall mockClientCall = Mockito.mock(ClientCall.class); - - @SuppressWarnings("unchecked") - ClientCall.Listener mockListener = Mockito.mock(ClientCall.Listener.class); - - Channel mockChannel = Mockito.mock(ManagedChannel.class); - - ArgumentCaptor capturedCallOptions = ArgumentCaptor.forClass(CallOptions.class); - - Mockito.when(mockChannel.newCall(Mockito.eq(descriptor), capturedCallOptions.capture())) - .thenReturn(mockClientCall); - - // Configure a timeout that occurs before the grpc deadline - Duration timeout = Duration.ofSeconds(5); - Deadline subsequentDeadline = Deadline.after(10, TimeUnit.SECONDS); - Deadline minExpectedDeadline = Deadline.after(timeout.getSeconds(), TimeUnit.SECONDS); - - GrpcCallContext context = - GrpcCallContext.createDefault() - .withChannel(mockChannel) - .withCallOptions(CallOptions.DEFAULT.withDeadline(subsequentDeadline)) - .withTimeout(timeout); - - GrpcClientCalls.newCall(descriptor, context).start(mockListener, new Metadata()); - - // Verify that the timeout is ignored - Deadline maxExpectedDeadline = Deadline.after(timeout.getSeconds(), TimeUnit.SECONDS); - - Truth.assertThat(capturedCallOptions.getValue().getDeadline()).isAtLeast(minExpectedDeadline); - Truth.assertThat(capturedCallOptions.getValue().getDeadline()).isAtMost(maxExpectedDeadline); - } -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcDirectServerStreamingCallableTest.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcDirectServerStreamingCallableTest.java deleted file mode 100644 index e5084b753..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcDirectServerStreamingCallableTest.java +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import static com.google.api.gax.grpc.testing.FakeServiceGrpc.METHOD_SERVER_STREAMING_RECOGNIZE; - -import com.google.api.core.SettableApiFuture; -import com.google.api.gax.grpc.testing.FakeServiceImpl; -import com.google.api.gax.grpc.testing.InProcessServer; -import com.google.api.gax.rpc.ApiException; -import com.google.api.gax.rpc.ClientContext; -import com.google.api.gax.rpc.ResponseObserver; -import com.google.api.gax.rpc.ServerStream; -import com.google.api.gax.rpc.ServerStreamingCallSettings; -import com.google.api.gax.rpc.ServerStreamingCallable; -import com.google.api.gax.rpc.StateCheckingResponseObserver; -import com.google.api.gax.rpc.StatusCode; -import com.google.api.gax.rpc.StreamController; -import com.google.api.gax.rpc.testing.FakeCallContext; -import com.google.common.collect.Lists; -import com.google.common.truth.Truth; -import com.google.type.Color; -import com.google.type.Money; -import io.grpc.CallOptions; -import io.grpc.ManagedChannel; -import io.grpc.StatusRuntimeException; -import io.grpc.inprocess.InProcessChannelBuilder; -import java.io.IOException; -import java.util.List; -import java.util.concurrent.CancellationException; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class GrpcDirectServerStreamingCallableTest { - private static final Color DEFAULT_REQUEST = Color.newBuilder().setRed(0.5f).build(); - private static final Color ASYNC_REQUEST = DEFAULT_REQUEST.toBuilder().setGreen(1000).build(); - private static final Color ERROR_REQUEST = Color.newBuilder().setRed(-1).build(); - private static final Money DEFAULT_RESPONSE = - Money.newBuilder().setCurrencyCode("USD").setUnits(127).build(); - - private InProcessServer inprocessServer; - private ManagedChannel channel; - private ClientContext clientContext; - private ServerStreamingCallSettings streamingCallSettings; - private ServerStreamingCallable streamingCallable; - - @Before - public void setUp() throws InstantiationException, IllegalAccessException, IOException { - String serverName = "fakeservice"; - FakeServiceImpl serviceImpl = new FakeServiceImpl(); - inprocessServer = new InProcessServer<>(serviceImpl, serverName); - inprocessServer.start(); - - channel = InProcessChannelBuilder.forName(serverName).directExecutor().usePlaintext().build(); - clientContext = - ClientContext.newBuilder() - .setTransportChannel(GrpcTransportChannel.create(channel)) - .setDefaultCallContext(GrpcCallContext.of(channel, CallOptions.DEFAULT)) - .build(); - streamingCallSettings = ServerStreamingCallSettings.newBuilder().build(); - streamingCallable = - GrpcCallableFactory.createServerStreamingCallable( - GrpcCallSettings.create(METHOD_SERVER_STREAMING_RECOGNIZE), - streamingCallSettings, - clientContext); - } - - @After - public void tearDown() { - channel.shutdown(); - inprocessServer.stop(); - } - - @Test - public void testBadContext() { - streamingCallable = - GrpcCallableFactory.createServerStreamingCallable( - GrpcCallSettings.create(METHOD_SERVER_STREAMING_RECOGNIZE), - streamingCallSettings, - clientContext - .toBuilder() - .setDefaultCallContext(FakeCallContext.createDefault()) - .build()); - - CountDownLatch latch = new CountDownLatch(1); - MoneyObserver observer = new MoneyObserver(true, latch); - try { - streamingCallable.call(DEFAULT_REQUEST, observer); - Assert.fail("Callable should have thrown an exception"); - } catch (IllegalArgumentException expected) { - Truth.assertThat(expected) - .hasMessageThat() - .contains("context must be an instance of GrpcCallContext"); - } - } - - @Test - public void testServerStreamingStart() { - CountDownLatch latch = new CountDownLatch(1); - MoneyObserver moneyObserver = new MoneyObserver(true, latch); - - streamingCallable.call(DEFAULT_REQUEST, moneyObserver); - - Truth.assertThat(moneyObserver.controller).isNotNull(); - } - - @Test - public void testServerStreaming() throws Exception { - CountDownLatch latch = new CountDownLatch(2); - MoneyObserver moneyObserver = new MoneyObserver(true, latch); - - streamingCallable.call(DEFAULT_REQUEST, moneyObserver); - - Truth.assertThat(latch.await(20, TimeUnit.SECONDS)).isTrue(); - Truth.assertThat(moneyObserver.error).isNull(); - Truth.assertThat(moneyObserver.response).isEqualTo(DEFAULT_RESPONSE); - } - - @Test - public void testManualFlowControl() throws Exception { - CountDownLatch latch = new CountDownLatch(2); - MoneyObserver moneyObserver = new MoneyObserver(false, latch); - - streamingCallable.call(DEFAULT_REQUEST, moneyObserver); - - Truth.assertThat(latch.await(500, TimeUnit.MILLISECONDS)).isFalse(); - Truth.assertWithMessage("Received response before requesting it") - .that(moneyObserver.response) - .isNull(); - - moneyObserver.controller.request(1); - Truth.assertThat(latch.await(500, TimeUnit.MILLISECONDS)).isTrue(); - - Truth.assertThat(moneyObserver.response).isEqualTo(DEFAULT_RESPONSE); - Truth.assertThat(moneyObserver.completed).isTrue(); - } - - @Test - public void testCancelClientCall() throws Exception { - CountDownLatch latch = new CountDownLatch(1); - MoneyObserver moneyObserver = new MoneyObserver(false, latch); - - streamingCallable.call(ASYNC_REQUEST, moneyObserver); - - moneyObserver.controller.cancel(); - moneyObserver.controller.request(1); - Truth.assertThat(latch.await(500, TimeUnit.MILLISECONDS)).isTrue(); - - Truth.assertThat(moneyObserver.error).isInstanceOf(CancellationException.class); - Truth.assertThat(moneyObserver.error).hasMessageThat().isEqualTo("User cancelled stream"); - } - - @Test - public void testOnResponseError() throws Throwable { - CountDownLatch latch = new CountDownLatch(1); - MoneyObserver moneyObserver = new MoneyObserver(true, latch); - - streamingCallable.call(ERROR_REQUEST, moneyObserver); - Truth.assertThat(latch.await(500, TimeUnit.MILLISECONDS)).isTrue(); - - Truth.assertThat(moneyObserver.error).isInstanceOf(ApiException.class); - Truth.assertThat(((ApiException) moneyObserver.error).getStatusCode().getCode()) - .isEqualTo(StatusCode.Code.INVALID_ARGUMENT); - Truth.assertThat(moneyObserver.error) - .hasMessageThat() - .isEqualTo("io.grpc.StatusRuntimeException: INVALID_ARGUMENT: red must be positive"); - } - - @Test - public void testObserverErrorCancelsCall() throws Throwable { - final RuntimeException expectedCause = new RuntimeException("some error"); - final SettableApiFuture actualErrorF = SettableApiFuture.create(); - - ResponseObserver moneyObserver = - new StateCheckingResponseObserver() { - @Override - protected void onStartImpl(StreamController controller) {} - - @Override - protected void onResponseImpl(Money response) { - throw expectedCause; - } - - @Override - protected void onErrorImpl(Throwable t) { - actualErrorF.set(t); - } - - @Override - protected void onCompleteImpl() { - actualErrorF.set(null); - } - }; - - streamingCallable.call(DEFAULT_REQUEST, moneyObserver); - Throwable actualError = actualErrorF.get(500, TimeUnit.MILLISECONDS); - - Truth.assertThat(actualError).isInstanceOf(ApiException.class); - Truth.assertThat(((ApiException) actualError).getStatusCode().getCode()) - .isEqualTo(StatusCode.Code.CANCELLED); - - // grpc is responsible for the immediate cancellation - Truth.assertThat(actualError.getCause()).isInstanceOf(StatusRuntimeException.class); - // and the client error is cause for grpc to cancel it - Truth.assertThat(actualError.getCause().getCause()).isSameInstanceAs(expectedCause); - } - - @Test - public void testBlockingServerStreaming() { - Color request = Color.newBuilder().setRed(0.5f).build(); - ServerStream response = streamingCallable.call(request); - List responseData = Lists.newArrayList(response); - - Money expected = Money.newBuilder().setCurrencyCode("USD").setUnits(127).build(); - Truth.assertThat(responseData).containsExactly(expected); - } - - static class MoneyObserver extends StateCheckingResponseObserver { - private final boolean autoFlowControl; - private final CountDownLatch latch; - - volatile StreamController controller; - volatile Money response; - volatile Throwable error; - volatile boolean completed; - - MoneyObserver(boolean autoFlowControl, CountDownLatch latch) { - this.autoFlowControl = autoFlowControl; - this.latch = latch; - } - - @Override - protected void onStartImpl(StreamController controller) { - this.controller = controller; - if (!autoFlowControl) { - controller.disableAutoInboundFlowControl(); - } - } - - @Override - protected void onResponseImpl(Money value) { - response = value; - latch.countDown(); - } - - @Override - protected void onErrorImpl(Throwable t) { - error = t; - latch.countDown(); - } - - @Override - protected void onCompleteImpl() { - completed = true; - latch.countDown(); - } - } -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcDirectStreamingCallableTest.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcDirectStreamingCallableTest.java deleted file mode 100644 index 95d4550b0..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcDirectStreamingCallableTest.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import static com.google.api.gax.grpc.testing.FakeServiceGrpc.METHOD_CLIENT_STREAMING_RECOGNIZE; -import static com.google.api.gax.grpc.testing.FakeServiceGrpc.METHOD_STREAMING_RECOGNIZE; -import static com.google.api.gax.grpc.testing.FakeServiceGrpc.METHOD_STREAMING_RECOGNIZE_ERROR; -import static com.google.common.truth.Truth.assertThat; - -import com.google.api.gax.grpc.testing.FakeServiceImpl; -import com.google.api.gax.grpc.testing.InProcessServer; -import com.google.api.gax.rpc.ApiException; -import com.google.api.gax.rpc.ApiStreamObserver; -import com.google.api.gax.rpc.BidiStreamingCallable; -import com.google.api.gax.rpc.ClientContext; -import com.google.api.gax.rpc.ClientStream; -import com.google.api.gax.rpc.ClientStreamingCallable; -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.type.Color; -import com.google.type.Money; -import io.grpc.CallOptions; -import io.grpc.ManagedChannel; -import io.grpc.Status; -import io.grpc.StatusRuntimeException; -import io.grpc.inprocess.InProcessChannelBuilder; -import java.io.IOException; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class GrpcDirectStreamingCallableTest { - private InProcessServer inprocessServer; - private ManagedChannel channel; - private FakeServiceImpl serviceImpl; - private ClientContext clientContext; - - @Before - public void setUp() throws InstantiationException, IllegalAccessException, IOException { - String serverName = "fakeservice"; - serviceImpl = new FakeServiceImpl(); - inprocessServer = new InProcessServer<>(serviceImpl, serverName); - inprocessServer.start(); - channel = InProcessChannelBuilder.forName(serverName).directExecutor().usePlaintext().build(); - clientContext = - ClientContext.newBuilder() - .setTransportChannel(GrpcTransportChannel.create(channel)) - .setDefaultCallContext(GrpcCallContext.of(channel, CallOptions.DEFAULT)) - .build(); - } - - @After - public void tearDown() { - channel.shutdown(); - inprocessServer.stop(); - } - - @Test - public void testBidiStreaming() throws Exception { - BidiStreamingCallable streamingCallable = - GrpcCallableFactory.createBidiStreamingCallable( - GrpcCallSettings.create(METHOD_STREAMING_RECOGNIZE), null, clientContext); - - CountDownLatch latch = new CountDownLatch(1); - GrpcDirectServerStreamingCallableTest.MoneyObserver moneyObserver = - new GrpcDirectServerStreamingCallableTest.MoneyObserver(true, latch); - - Color request = Color.newBuilder().setRed(0.5f).build(); - ClientStream stream = streamingCallable.splitCall(moneyObserver); - stream.send(request); - stream.closeSend(); - - latch.await(20, TimeUnit.SECONDS); - assertThat(moneyObserver.error).isNull(); - Money expected = Money.newBuilder().setCurrencyCode("USD").setUnits(127).build(); - assertThat(moneyObserver.response).isEqualTo(expected); - assertThat(moneyObserver.completed).isTrue(); - } - - @Test - public void testBidiStreamingServerError() throws Exception { - BidiStreamingCallable streamingCallable = - GrpcCallableFactory.createBidiStreamingCallable( - GrpcCallSettings.create(METHOD_STREAMING_RECOGNIZE_ERROR), null, clientContext); - - CountDownLatch latch = new CountDownLatch(1); - GrpcDirectServerStreamingCallableTest.MoneyObserver moneyObserver = - new GrpcDirectServerStreamingCallableTest.MoneyObserver(true, latch); - - Color request = Color.newBuilder().setRed(0.5f).build(); - ClientStream stream = streamingCallable.splitCall(moneyObserver); - stream.send(request); - - latch.await(20, TimeUnit.SECONDS); - assertThat(moneyObserver.error).isNotNull(); - assertThat(moneyObserver.error).isInstanceOf(ApiException.class); - assertThat(moneyObserver.error.getCause()).isInstanceOf(StatusRuntimeException.class); - assertThat(((StatusRuntimeException) moneyObserver.error.getCause()).getStatus()) - .isEqualTo(Status.INVALID_ARGUMENT); - assertThat(moneyObserver.response).isNull(); - } - - @Test - public void testBidiStreamingClientError() throws Exception { - BidiStreamingCallable streamingCallable = - GrpcCallableFactory.createBidiStreamingCallable( - GrpcCallSettings.create(METHOD_STREAMING_RECOGNIZE_ERROR), null, clientContext); - - CountDownLatch latch = new CountDownLatch(1); - GrpcDirectServerStreamingCallableTest.MoneyObserver moneyObserver = - new GrpcDirectServerStreamingCallableTest.MoneyObserver(true, latch); - - ClientStream stream = streamingCallable.splitCall(moneyObserver); - Throwable clientError = new StatusRuntimeException(Status.CANCELLED); - stream.closeSendWithError(clientError); - - latch.await(20, TimeUnit.SECONDS); - assertThat(moneyObserver.error).isNotNull(); - assertThat(moneyObserver.error).isInstanceOf(ApiException.class); - assertThat(((ApiException) moneyObserver.error).getStatusCode().getCode()) - .isEqualTo(Code.CANCELLED); - assertThat(moneyObserver.response).isNull(); - - // As of gRPC 1.8, when the client closes, the server gRPC issues - // io.grpc.StatusRuntimeException: CANCELLED: cancelled before receiving half close - // to the server application, and our error is not propagated. - // We don't check the error received by the server; we can't round-trip it. - } - - @Test - public void testClientStreaming() throws Exception { - ClientStreamingCallable streamingCallable = - GrpcCallableFactory.createClientStreamingCallable( - GrpcCallSettings.create(METHOD_CLIENT_STREAMING_RECOGNIZE), null, clientContext); - - CountDownLatch latch = new CountDownLatch(1); - MoneyObserver moneyObserver = new MoneyObserver(latch); - - Color request = Color.newBuilder().setRed(0.5f).build(); - ApiStreamObserver requestObserver = streamingCallable.clientStreamingCall(moneyObserver); - requestObserver.onNext(request); - requestObserver.onCompleted(); - - latch.await(20, TimeUnit.SECONDS); - assertThat(moneyObserver.error).isNull(); - Money expected = Money.newBuilder().setCurrencyCode("USD").setUnits(127).build(); - assertThat(moneyObserver.response).isEqualTo(expected); - assertThat(moneyObserver.completed).isTrue(); - } - - private static class MoneyObserver implements ApiStreamObserver { - volatile Money response; - volatile Throwable error; - volatile boolean completed; - CountDownLatch latch; - - MoneyObserver(CountDownLatch latch) { - this.latch = latch; - } - - @Override - public void onNext(Money value) { - response = value; - latch.countDown(); - } - - @Override - public void onError(Throwable t) { - error = t; - latch.countDown(); - } - - @Override - public void onCompleted() { - completed = true; - } - }; -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcHeaderInterceptorTest.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcHeaderInterceptorTest.java deleted file mode 100644 index cf49ddbcb..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcHeaderInterceptorTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import static org.junit.Assert.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.same; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.api.gax.grpc.testing.FakeMethodDescriptor; -import com.google.common.collect.ImmutableMap; -import io.grpc.CallOptions; -import io.grpc.Channel; -import io.grpc.ClientCall; -import io.grpc.ClientInterceptors; -import io.grpc.Metadata; -import io.grpc.MethodDescriptor; -import java.util.Map; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; - -/** Tests for {@link GrpcHeaderInterceptor}. */ -@RunWith(JUnit4.class) -public class GrpcHeaderInterceptorTest { - - @Mock private Channel channel; - - @Mock private ClientCall call; - - private static final MethodDescriptor method = FakeMethodDescriptor.create(); - - /** Sets up mocks. */ - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - when(channel.newCall(Mockito.>any(), any(CallOptions.class))) - .thenReturn(call); - } - - @Test - public void testInterceptor() { - Map data = ImmutableMap.of("x-goog-api-client", "abcd", "user-agent", "defg"); - GrpcHeaderInterceptor interceptor = new GrpcHeaderInterceptor(data); - Channel intercepted = ClientInterceptors.intercept(channel, interceptor); - @SuppressWarnings("unchecked") - ClientCall.Listener listener = mock(ClientCall.Listener.class); - ClientCall interceptedCall = intercepted.newCall(method, CallOptions.DEFAULT); - // start() on the intercepted call will eventually reach the call created by the real channel - interceptedCall.start(listener, new Metadata()); - // The headers passed to the real channel call will contain the information inserted by the - // interceptor. - ArgumentCaptor captor = ArgumentCaptor.forClass(Metadata.class); - verify(call).start(same(listener), captor.capture()); - final Metadata.Key headerKey = - Metadata.Key.of("x-goog-api-client", Metadata.ASCII_STRING_MARSHALLER); - assertEquals("abcd", captor.getValue().get(headerKey)); - assertEquals("defg", interceptor.getUserAgentHeader()); - } -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcLongRunningClientTest.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcLongRunningClientTest.java deleted file mode 100644 index dc3879505..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcLongRunningClientTest.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.LongRunningClient; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.common.truth.Truth; -import com.google.longrunning.CancelOperationRequest; -import com.google.longrunning.DeleteOperationRequest; -import com.google.longrunning.GetOperationRequest; -import com.google.longrunning.Operation; -import com.google.longrunning.stub.OperationsStub; -import com.google.protobuf.Empty; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class GrpcLongRunningClientTest { - - @Test - public void get() { - OperationsStub operationsStub = mock(OperationsStub.class); - when(operationsStub.getOperationCallable()) - .thenReturn( - new UnaryCallable() { - @Override - public ApiFuture futureCall( - GetOperationRequest request, ApiCallContext context) { - if (!request.getName().equals("poseidon")) { - return ApiFutures.immediateFailedFuture( - new IllegalStateException("Unexpected request: " + request)); - } else { - return ApiFutures.immediateFuture( - Operation.newBuilder().setName("greece").build()); - } - } - }); - LongRunningClient longRunningClient = new GrpcLongRunningClient(operationsStub); - Truth.assertThat(longRunningClient.getOperationCallable().call("poseidon").getName()) - .isEqualTo("greece"); - } - - @Test - public void cancel() { - OperationsStub operationsStub = mock(OperationsStub.class); - when(operationsStub.cancelOperationCallable()) - .thenReturn( - new UnaryCallable() { - @Override - public ApiFuture futureCall( - CancelOperationRequest request, ApiCallContext context) { - if (!request.getName().equals("poseidon")) { - return ApiFutures.immediateFailedFuture( - new IllegalStateException("Unexpected request: " + request)); - } else { - return ApiFutures.immediateFuture(Empty.getDefaultInstance()); - } - } - }); - LongRunningClient longRunningClient = new GrpcLongRunningClient(operationsStub); - Truth.assertThat(longRunningClient.cancelOperationCallable().call("poseidon")).isNull(); - } - - @Test - public void delete() { - OperationsStub operationsStub = mock(OperationsStub.class); - when(operationsStub.deleteOperationCallable()) - .thenReturn( - new UnaryCallable() { - @Override - public ApiFuture futureCall( - DeleteOperationRequest request, ApiCallContext context) { - if (!request.getName().equals("poseidon")) { - return ApiFutures.immediateFailedFuture( - new IllegalStateException("Unexpected request: " + request)); - } else { - return ApiFutures.immediateFuture(Empty.getDefaultInstance()); - } - } - }); - LongRunningClient longRunningClient = new GrpcLongRunningClient(operationsStub); - Truth.assertThat(longRunningClient.deleteOperationCallable().call("poseidon")).isNull(); - } -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcLongRunningTest.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcLongRunningTest.java deleted file mode 100644 index 7149f23ba..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcLongRunningTest.java +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import static com.google.common.truth.Truth.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import com.google.api.gax.core.FakeApiClock; -import com.google.api.gax.core.RecordingScheduler; -import com.google.api.gax.grpc.testing.FakeMethodDescriptor; -import com.google.api.gax.longrunning.OperationFuture; -import com.google.api.gax.longrunning.OperationSnapshot; -import com.google.api.gax.longrunning.OperationTimedPollAlgorithm; -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.rpc.ClientContext; -import com.google.api.gax.rpc.OperationCallSettings; -import com.google.api.gax.rpc.OperationCallable; -import com.google.api.gax.rpc.TransportChannel; -import com.google.api.gax.rpc.TransportChannelProvider; -import com.google.api.gax.rpc.UnaryCallSettings; -import com.google.longrunning.Operation; -import com.google.longrunning.OperationsSettings; -import com.google.longrunning.stub.GrpcOperationsStub; -import com.google.longrunning.stub.OperationsStub; -import com.google.longrunning.stub.OperationsStubSettings; -import com.google.protobuf.Any; -import com.google.protobuf.Message; -import com.google.type.Color; -import com.google.type.Money; -import io.grpc.CallOptions; -import io.grpc.ClientCall; -import io.grpc.ManagedChannel; -import io.grpc.MethodDescriptor; -import io.grpc.Status; -import io.grpc.Status.Code; -import java.io.IOException; -import java.util.concurrent.TimeUnit; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class GrpcLongRunningTest { - - private static final RetrySettings FAST_RETRY_SETTINGS = - RetrySettings.newBuilder() - .setInitialRetryDelay(Duration.ofMillis(1L)) - .setRetryDelayMultiplier(1) - .setMaxRetryDelay(Duration.ofMillis(1L)) - .setInitialRpcTimeout(Duration.ofMillis(1L)) - .setMaxAttempts(0) - .setJittered(false) - .setRpcTimeoutMultiplier(1) - .setMaxRpcTimeout(Duration.ofMillis(1L)) - .setTotalTimeout(Duration.ofMillis(5L)) - .build(); - - private ManagedChannel channel; - private OperationsStub operationsStub; - private RecordingScheduler executor; - private ClientContext initialContext; - private OperationCallSettings callSettings; - - private FakeApiClock clock; - private OperationTimedPollAlgorithm pollingAlgorithm; - - @Before - public void setUp() throws IOException { - channel = mock(ManagedChannel.class); - TransportChannelProvider operationsChannelProvider = mock(TransportChannelProvider.class); - TransportChannel transportChannel = - GrpcTransportChannel.newBuilder().setManagedChannel(channel).build(); - when(operationsChannelProvider.getTransportChannel()).thenReturn(transportChannel); - - clock = new FakeApiClock(0L); - executor = RecordingScheduler.create(clock); - pollingAlgorithm = OperationTimedPollAlgorithm.create(FAST_RETRY_SETTINGS, clock); - - OperationsSettings.Builder settingsBuilder = OperationsSettings.newBuilder(); - settingsBuilder - .getOperationSettings() - .setRetrySettings(FAST_RETRY_SETTINGS.toBuilder().setMaxAttempts(1).build()); - OperationsSettings settings = - OperationsSettings.newBuilder() - .setTransportChannelProvider(operationsChannelProvider) - .build(); - operationsStub = - GrpcOperationsStub.create(((OperationsStubSettings) settings.getStubSettings())); - - UnaryCallSettings initialCallSettings = - UnaryCallSettings.newUnaryCallSettingsBuilder() - .setRetrySettings(FAST_RETRY_SETTINGS.toBuilder().setMaxAttempts(1).build()) - .build(); - - callSettings = - OperationCallSettings.newBuilder() - .setInitialCallSettings(initialCallSettings) - .setResponseTransformer( - ProtoOperationTransformers.ResponseTransformer.create(Color.class)) - .setMetadataTransformer( - ProtoOperationTransformers.MetadataTransformer.create(Money.class)) - .setPollingAlgorithm(pollingAlgorithm) - .build(); - - initialContext = - ClientContext.newBuilder() - .setTransportChannel( - GrpcTransportChannel.newBuilder().setManagedChannel(channel).build()) - .setExecutor(executor) - .setDefaultCallContext(GrpcCallContext.of(channel, CallOptions.DEFAULT)) - .setClock(clock) - .build(); - } - - @Test - public void testCall() { - Color resp = getColor(1.0f); - Money meta = getMoney("UAH"); - Operation resultOperation = getOperation("testCall", resp, meta, true); - mockResponse(channel, Code.OK, resultOperation); - - OperationCallable callable = - GrpcCallableFactory.createOperationCallable( - createGrpcSettings(), callSettings, initialContext, operationsStub); - - Color response = callable.call(2, GrpcCallContext.createDefault()); - assertThat(response).isEqualTo(resp); - assertThat(executor.getIterationsCount()).isEqualTo(0); - } - - @Test - public void testFutureCallPollDoneOnFirst() throws Exception { - String opName = "testFutureCallPollDoneOnFirst"; - Color resp = getColor(0.5f); - Money meta = getMoney("UAH"); - Operation initialOperation = getOperation(opName, null, null, false); - Operation resultOperation = getOperation(opName, resp, meta, true); - mockResponse(channel, Code.OK, initialOperation, resultOperation); - - OperationCallable callable = - GrpcCallableFactory.createOperationCallable( - createGrpcSettings(), callSettings, initialContext, operationsStub); - - OperationFuture future = callable.futureCall(2); - - assertFutureSuccessMetaSuccess(opName, future, resp, meta); - assertThat(executor.getIterationsCount()).isEqualTo(0); - } - - private void assertFutureSuccessMetaSuccess( - String opName, OperationFuture future, Color resp, Money meta) - throws Exception { - assertThat(future.getName()).isEqualTo(opName); - assertThat(future.get(3, TimeUnit.SECONDS)).isEqualTo(resp); - assertThat(future.isDone()).isTrue(); - assertThat(future.isCancelled()).isFalse(); - assertThat(future.get()).isEqualTo(resp); - - assertThat(future.peekMetadata().get()).isEqualTo(meta); - assertThat(future.peekMetadata()).isSameInstanceAs(future.peekMetadata()); - assertThat(future.peekMetadata().isDone()).isTrue(); - assertThat(future.peekMetadata().isCancelled()).isFalse(); - - assertThat(future.getMetadata().get()).isEqualTo(meta); - assertThat(future.getMetadata()).isSameInstanceAs(future.getMetadata()); - assertThat(future.getMetadata().isDone()).isTrue(); - assertThat(future.getMetadata().isCancelled()).isFalse(); - } - - private Color getColor(float blueValue) { - return Color.newBuilder().setBlue(blueValue).build(); - } - - private Money getMoney(String currencyCode) { - return Money.newBuilder().setCurrencyCode(currencyCode).build(); - } - - private Operation getOperation(String name, Message response, Message metadata, boolean done) { - Operation.Builder builder = Operation.newBuilder().setName(name).setDone(done); - if (response instanceof com.google.rpc.Status) { - builder.setError((com.google.rpc.Status) response); - } else if (response != null) { - builder.setResponse(Any.pack(response)); - } - if (metadata != null) { - builder.setMetadata(Any.pack(metadata)); - } - return builder.build(); - } - - @SuppressWarnings("unchecked") - private void mockResponse(ManagedChannel channel, Code statusCode, Object... results) { - Status status = statusCode.toStatus(); - ClientCall clientCall = new MockClientCall<>(results[0], status); - ClientCall[] moreCalls = new ClientCall[results.length - 1]; - for (int i = 0; i < results.length - 1; i++) { - moreCalls[i] = new MockClientCall<>(results[i + 1], status); - } - when(channel.newCall(any(MethodDescriptor.class), any(CallOptions.class))) - .thenReturn(clientCall, moreCalls); - } - - private GrpcCallSettings createGrpcSettings() { - return GrpcCallSettings.create(FakeMethodDescriptor.create()); - } -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcMetadataHandlerInterceptorTest.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcMetadataHandlerInterceptorTest.java deleted file mode 100644 index f8306fddf..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcMetadataHandlerInterceptorTest.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.api.gax.grpc.testing.FakeMethodDescriptor; -import io.grpc.CallOptions; -import io.grpc.Channel; -import io.grpc.ClientCall; -import io.grpc.ClientInterceptors; -import io.grpc.Metadata; -import io.grpc.MethodDescriptor; -import io.grpc.Status; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; - -/** Tests for {@link GrpcHeaderInterceptor}. */ -@RunWith(JUnit4.class) -public class GrpcMetadataHandlerInterceptorTest { - - private static class MutableBoolean { - private volatile boolean value = false; - } - - @Mock private Channel channel; - @Mock private ClientCall call; - - private static final MethodDescriptor method = FakeMethodDescriptor.create(); - - /** Sets up mocks. */ - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - when(channel.newCall(Mockito.>any(), any(CallOptions.class))) - .thenReturn(call); - } - - @Test - public void testInterceptor() { - final MutableBoolean metadataHandlerCalled = new MutableBoolean(); - final MutableBoolean trailingMetadataHandlerCalled = new MutableBoolean(); - - CallOptions callOptions = - CallOptionsUtil.putMetadataHandlerOption( - CallOptions.DEFAULT, - new ResponseMetadataHandler() { - @Override - public void onHeaders(Metadata metadata) { - metadataHandlerCalled.value = true; - } - - @Override - public void onTrailers(Metadata metadata) { - trailingMetadataHandlerCalled.value = true; - } - }); - - GrpcMetadataHandlerInterceptor interceptor = new GrpcMetadataHandlerInterceptor(); - Channel intercepted = ClientInterceptors.intercept(channel, interceptor); - @SuppressWarnings("unchecked") - ClientCall.Listener listener = mock(ClientCall.Listener.class); - - ClientCall interceptedCall = intercepted.newCall(method, callOptions); - - // Confirm false - assertFalse(metadataHandlerCalled.value); - assertFalse(trailingMetadataHandlerCalled.value); - - // start() on the intercepted call will eventually reach the call created by the real channel - interceptedCall.start(listener, new Metadata()); - ArgumentCaptor captor = ArgumentCaptor.forClass(ClientCall.Listener.class); - ArgumentCaptor metadataCaptor = ArgumentCaptor.forClass(Metadata.class); - verify(call).start(captor.capture(), metadataCaptor.capture()); - - // Confirm false before calling functions on listener - assertFalse(metadataHandlerCalled.value); - assertFalse(trailingMetadataHandlerCalled.value); - - captor.getValue().onHeaders(new Metadata()); - - // Confirm values after headers but before close - assertTrue(metadataHandlerCalled.value); - assertFalse(trailingMetadataHandlerCalled.value); - - captor.getValue().onClose(Status.fromCodeValue(0), new Metadata()); - - // Confirm values after close - assertTrue(metadataHandlerCalled.value); - assertTrue(trailingMetadataHandlerCalled.value); - } -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcResponseMetadataTest.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcResponseMetadataTest.java deleted file mode 100644 index 80b041a37..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcResponseMetadataTest.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.gax.grpc.testing.FakeServiceGrpc; -import com.google.api.gax.grpc.testing.FakeServiceGrpc.FakeServiceImplBase; -import com.google.api.gax.grpc.testing.InProcessServer; -import com.google.api.gax.rpc.ClientContext; -import com.google.api.gax.rpc.UnaryCallSettings; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.type.Color; -import com.google.type.Money; -import io.grpc.CallOptions; -import io.grpc.ForwardingServerCall.SimpleForwardingServerCall; -import io.grpc.ManagedChannel; -import io.grpc.Metadata; -import io.grpc.Metadata.Key; -import io.grpc.ServerCall; -import io.grpc.ServerCall.Listener; -import io.grpc.ServerCallHandler; -import io.grpc.ServerInterceptor; -import io.grpc.Status; -import io.grpc.inprocess.InProcessChannelBuilder; -import io.grpc.stub.StreamObserver; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -@RunWith(JUnit4.class) -public class GrpcResponseMetadataTest { - - private static final String HEADER_KEY = "inprocessheaderkey"; - private static final String HEADER_VALUE = "inprocessheadervalue"; - private static final String TRAILER_KEY = "inprocesstrailerkey"; - private static final String TRAILER_VALUE = "inprocesstrailervalue"; - - private InProcessServer inprocessServer; - private ManagedChannel channel; - private ClientContext clientContext; - - private Metadata requestHeaders = null; - - @Before - public void setUp() throws Exception { - String serverName = "fakeservice"; - FakeServiceImplBase serviceImpl = Mockito.mock(FakeServiceImplBase.class); - Mockito.doAnswer( - new Answer() { - @Override - public Void answer(InvocationOnMock invocation) { - Color color = invocation.getArgument(0); - StreamObserver observer = invocation.getArgument(1); - observer.onNext( - Money.newBuilder() - .setCurrencyCode("USD") - .setUnits((long) (color.getRed() * 255)) - .build()); - observer.onCompleted(); - return null; - } - }) - .when(serviceImpl) - .recognize(Mockito.any(), Mockito.>any()); - requestHeaders = null; - inprocessServer = - new InProcessServer<>( - serviceImpl, - serverName, - new ServerInterceptor() { - @Override - public Listener interceptCall( - ServerCall call, - Metadata headers, - ServerCallHandler next) { - requestHeaders = headers; - return next.startCall( - new SimpleForwardingServerCall(call) { - @Override - public void sendHeaders(Metadata responseHeaders) { - responseHeaders.put( - Key.of(HEADER_KEY, Metadata.ASCII_STRING_MARSHALLER), HEADER_VALUE); - super.sendHeaders(responseHeaders); - } - - @Override - public void close(Status status, Metadata trailers) { - trailers.put( - Key.of(TRAILER_KEY, Metadata.ASCII_STRING_MARSHALLER), TRAILER_VALUE); - super.close(status, trailers); - } - }, - headers); - } - }); - inprocessServer.start(); - - channel = - InProcessChannelBuilder.forName(serverName) - .directExecutor() - .usePlaintext() - .intercept(new GrpcMetadataHandlerInterceptor()) - .build(); - clientContext = - ClientContext.newBuilder() - .setTransportChannel(GrpcTransportChannel.create(channel)) - .setDefaultCallContext(GrpcCallContext.of(channel, CallOptions.DEFAULT)) - .build(); - } - - @After - public void tearDown() { - channel.shutdown(); - inprocessServer.stop(); - } - - @Test - public void testResponseMetadataUnaryCall() { - GrpcCallSettings grpcCallSettings = - GrpcCallSettings.create(FakeServiceGrpc.METHOD_RECOGNIZE); - - UnaryCallSettings callSettings = - UnaryCallSettings.newUnaryCallSettingsBuilder().build(); - - UnaryCallable callable = - GrpcCallableFactory.createUnaryCallable(grpcCallSettings, callSettings, clientContext); - - Assert.assertNull(requestHeaders); - - GrpcResponseMetadata responseMetadata = new GrpcResponseMetadata(); - callable.call(Color.getDefaultInstance(), responseMetadata.createContextWithHandlers()); - - Assert.assertNotNull(requestHeaders); - - Metadata metadata = responseMetadata.getMetadata(); - Metadata trailingMetadata = responseMetadata.getTrailingMetadata(); - - Assert.assertEquals( - metadata.get(Key.of(HEADER_KEY, Metadata.ASCII_STRING_MARSHALLER)), HEADER_VALUE); - Assert.assertEquals( - trailingMetadata.get(Key.of(TRAILER_KEY, Metadata.ASCII_STRING_MARSHALLER)), TRAILER_VALUE); - } -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcStatusCodeTest.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcStatusCodeTest.java deleted file mode 100644 index f078a4a92..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcStatusCodeTest.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.gax.rpc.StatusCode; -import com.google.common.truth.Truth; -import io.grpc.Status; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class GrpcStatusCodeTest { - @Test - public void testGrpcCodeToStatusCode() { - testCodes(StatusCode.Code.OK, Status.Code.OK); - testCodes(StatusCode.Code.CANCELLED, Status.Code.CANCELLED); - testCodes(StatusCode.Code.UNKNOWN, Status.Code.UNKNOWN); - testCodes(StatusCode.Code.INVALID_ARGUMENT, Status.Code.INVALID_ARGUMENT); - testCodes(StatusCode.Code.DEADLINE_EXCEEDED, Status.Code.DEADLINE_EXCEEDED); - testCodes(StatusCode.Code.NOT_FOUND, Status.Code.NOT_FOUND); - testCodes(StatusCode.Code.ALREADY_EXISTS, Status.Code.ALREADY_EXISTS); - testCodes(StatusCode.Code.PERMISSION_DENIED, Status.Code.PERMISSION_DENIED); - testCodes(StatusCode.Code.RESOURCE_EXHAUSTED, Status.Code.RESOURCE_EXHAUSTED); - testCodes(StatusCode.Code.FAILED_PRECONDITION, Status.Code.FAILED_PRECONDITION); - testCodes(StatusCode.Code.ABORTED, Status.Code.ABORTED); - testCodes(StatusCode.Code.OUT_OF_RANGE, Status.Code.OUT_OF_RANGE); - testCodes(StatusCode.Code.UNIMPLEMENTED, Status.Code.UNIMPLEMENTED); - testCodes(StatusCode.Code.INTERNAL, Status.Code.INTERNAL); - testCodes(StatusCode.Code.UNAVAILABLE, Status.Code.UNAVAILABLE); - testCodes(StatusCode.Code.DATA_LOSS, Status.Code.DATA_LOSS); - testCodes(StatusCode.Code.UNAUTHENTICATED, Status.Code.UNAUTHENTICATED); - } - - private void testCodes(StatusCode.Code gaxCode, Status.Code grpcCode) { - Truth.assertThat(GrpcStatusCode.grpcCodeToStatusCode(grpcCode)).isEqualTo(gaxCode); - } -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcTransportDescriptorTest.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcTransportDescriptorTest.java deleted file mode 100644 index 456d4e73b..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcTransportDescriptorTest.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import static org.junit.Assert.fail; - -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.api.core.SettableApiFuture; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.ApiException; -import com.google.api.gax.rpc.DataLossException; -import com.google.api.gax.rpc.InvalidArgumentException; -import com.google.api.gax.rpc.StatusCode; -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.api.gax.rpc.UnavailableException; -import com.google.api.gax.rpc.UnknownException; -import com.google.common.truth.Truth; -import io.grpc.Status; -import io.grpc.StatusException; -import io.grpc.StatusRuntimeException; -import java.util.Collections; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class GrpcTransportDescriptorTest { - private static boolean NOT_RETRYABLE = false; - private static boolean IS_RETRYABLE = true; - - @Test - public void translateException_StatusException_noRetry() { - Throwable originalException = new StatusException(Status.INVALID_ARGUMENT); - GrpcExceptionCallable exceptionCallable = - new GrpcExceptionCallable<>( - failingCallable(originalException), Collections.emptySet()); - try { - exceptionCallable.call(0); - fail("Expected exception to be thrown"); - } catch (Throwable throwable) { - assertInnerExceptionIsInstanceOf( - throwable, InvalidArgumentException.class, NOT_RETRYABLE, originalException); - } - } - - @Test - public void translateException_StatusException_withRetry() { - Throwable originalException = new StatusException(Status.UNAVAILABLE); - GrpcExceptionCallable exceptionCallable = - new GrpcExceptionCallable<>( - failingCallable(originalException), Collections.singleton(Code.UNAVAILABLE)); - try { - exceptionCallable.call(0); - fail("Expected exception to be thrown"); - } catch (Throwable throwable) { - assertInnerExceptionIsInstanceOf( - throwable, UnavailableException.class, IS_RETRYABLE, originalException); - } - } - - @Test - public void translateException_StatusRuntimeException_noRetry() { - Throwable originalException = new StatusRuntimeException(Status.INVALID_ARGUMENT); - GrpcExceptionCallable exceptionCallable = - new GrpcExceptionCallable<>( - failingCallable(originalException), Collections.emptySet()); - try { - exceptionCallable.call(0); - fail("Expected exception to be thrown"); - } catch (Throwable throwable) { - assertInnerExceptionIsInstanceOf( - throwable, InvalidArgumentException.class, NOT_RETRYABLE, originalException); - } - } - - @Test - public void translateException_StatusRuntimeException_withRetry() { - Throwable originalException = new StatusRuntimeException(Status.UNAVAILABLE); - GrpcExceptionCallable exceptionCallable = - new GrpcExceptionCallable<>( - failingCallable(originalException), Collections.singleton(Code.UNAVAILABLE)); - try { - exceptionCallable.call(0); - fail("Expected exception to be thrown"); - } catch (Throwable throwable) { - assertInnerExceptionIsInstanceOf( - throwable, UnavailableException.class, IS_RETRYABLE, originalException); - } - } - - @Test - public void translateException_cancelled() { - GrpcExceptionCallable exceptionCallable = - new GrpcExceptionCallable<>(inactiveCallable(), Collections.emptySet()); - ApiFuture result = exceptionCallable.futureCall(0); - Truth.assertThat(result.isDone()).isFalse(); - result.cancel(true); - Truth.assertThat(result.isCancelled()).isTrue(); - Truth.assertThat(result.isDone()).isTrue(); - } - - @Test - public void translateException_ApiException() { - Throwable originalException = new RuntimeException("stuff went wrong"); - Throwable apiException = - new DataLossException( - originalException, GrpcStatusCode.of(Status.Code.UNKNOWN), IS_RETRYABLE); - GrpcExceptionCallable exceptionCallable = - new GrpcExceptionCallable<>( - failingCallable(apiException), Collections.emptySet()); - try { - exceptionCallable.call(0); - fail("Expected exception to be thrown"); - } catch (Throwable throwable) { - assertInnerExceptionIsInstanceOf( - throwable, DataLossException.class, IS_RETRYABLE, originalException); - } - } - - @Test - public void translateException_RuntimeException() { - Throwable originalException = new RuntimeException("stuff went wrong"); - GrpcExceptionCallable exceptionCallable = - new GrpcExceptionCallable<>( - failingCallable(originalException), Collections.emptySet()); - try { - exceptionCallable.call(0); - fail("Expected exception to be thrown"); - } catch (Throwable throwable) { - assertInnerExceptionIsInstanceOf( - throwable, UnknownException.class, NOT_RETRYABLE, originalException); - } - } - - private UnaryCallable failingCallable(final Throwable exception) { - return new UnaryCallable() { - @Override - public ApiFuture futureCall(Integer request, ApiCallContext context) { - return ApiFutures.immediateFailedFuture(exception); - } - }; - } - - private UnaryCallable inactiveCallable() { - return new UnaryCallable() { - @Override - public ApiFuture futureCall(Integer request, ApiCallContext context) { - return SettableApiFuture.create(); - } - }; - } - - public void assertInnerExceptionIsInstanceOf( - Throwable thrownException, Class clazz, boolean retryable, Throwable originalException) { - Truth.assertThat(thrownException).isInstanceOf(clazz); - ApiException apiException = (ApiException) thrownException; - Truth.assertThat(apiException.isRetryable()).isEqualTo(retryable); - } -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java deleted file mode 100644 index 654fc57b8..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java +++ /dev/null @@ -1,487 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.assertEquals; - -import com.google.api.core.ApiFunction; -import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider.Builder; -import com.google.api.gax.rpc.HeaderProvider; -import com.google.api.gax.rpc.TransportChannelProvider; -import com.google.api.gax.rpc.mtls.AbstractMtlsTransportChannelTest; -import com.google.api.gax.rpc.mtls.MtlsProvider; -import com.google.auth.oauth2.CloudShellCredentials; -import com.google.auth.oauth2.ComputeEngineCredentials; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import io.grpc.alts.ComputeEngineChannelBuilder; -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Executor; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import javax.annotation.Nullable; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class InstantiatingGrpcChannelProviderTest extends AbstractMtlsTransportChannelTest { - - @Test - public void testEndpoint() { - String endpoint = "localhost:8080"; - InstantiatingGrpcChannelProvider.Builder builder = - InstantiatingGrpcChannelProvider.newBuilder(); - builder.setEndpoint(endpoint); - assertEquals(builder.getEndpoint(), endpoint); - - InstantiatingGrpcChannelProvider provider = builder.build(); - assertEquals(provider.getEndpoint(), endpoint); - } - - @Test(expected = IllegalArgumentException.class) - public void testEndpointNoPort() { - InstantiatingGrpcChannelProvider.newBuilder().setEndpoint("localhost"); - } - - @Test(expected = IllegalArgumentException.class) - public void testEndpointBadPort() { - InstantiatingGrpcChannelProvider.newBuilder().setEndpoint("localhost:abcd"); - } - - @Test - public void testKeepAlive() { - Duration keepaliveTime = Duration.ofSeconds(1); - Duration keepaliveTimeout = Duration.ofSeconds(2); - boolean keepaliveWithoutCalls = true; - - InstantiatingGrpcChannelProvider provider = - InstantiatingGrpcChannelProvider.newBuilder() - .setKeepAliveTime(keepaliveTime) - .setKeepAliveTimeout(keepaliveTimeout) - .setKeepAliveWithoutCalls(keepaliveWithoutCalls) - .build(); - - assertEquals(provider.getKeepAliveTime(), keepaliveTime); - assertEquals(provider.getKeepAliveTimeout(), keepaliveTimeout); - assertEquals(provider.getKeepAliveWithoutCalls(), keepaliveWithoutCalls); - } - - @Test - public void testMaxInboundMetadataSize() { - InstantiatingGrpcChannelProvider provider = - InstantiatingGrpcChannelProvider.newBuilder().setMaxInboundMetadataSize(4096).build(); - assertThat(provider.getMaxInboundMetadataSize()).isEqualTo(4096); - } - - @Test - public void testCpuPoolSize() { - // happy path - Builder builder = InstantiatingGrpcChannelProvider.newBuilder().setProcessorCount(2); - builder.setChannelsPerCpu(2.5); - assertEquals(5, builder.getPoolSize()); - - // User specified max - builder = builder.setProcessorCount(50); - builder.setChannelsPerCpu(100, 10); - assertEquals(10, builder.getPoolSize()); - - // Sane default maximum - builder.setChannelsPerCpu(200); - assertEquals(100, builder.getPoolSize()); - } - - @Test - public void testWithPoolSize() throws IOException { - ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(1); - executor.shutdown(); - - TransportChannelProvider provider = - InstantiatingGrpcChannelProvider.newBuilder() - .build() - .withExecutor((Executor) executor) - .withHeaders(Collections.emptyMap()) - .withEndpoint("localhost:8080"); - assertThat(provider.acceptsPoolSize()).isTrue(); - - // Make sure we can create channels OK. - provider.getTransportChannel().shutdownNow(); - - provider = provider.withPoolSize(2); - provider.getTransportChannel().shutdownNow(); - } - - @Test - public void testToBuilder() { - Duration keepaliveTime = Duration.ofSeconds(1); - Duration keepaliveTimeout = Duration.ofSeconds(2); - ApiFunction channelConfigurator = - builder -> { - throw new UnsupportedOperationException(); - }; - Map directPathServiceConfig = ImmutableMap.of("loadbalancingConfig", "grpclb"); - - InstantiatingGrpcChannelProvider provider = - InstantiatingGrpcChannelProvider.newBuilder() - .setProcessorCount(2) - .setEndpoint("fake.endpoint:443") - .setMaxInboundMessageSize(12345678) - .setMaxInboundMetadataSize(4096) - .setKeepAliveTime(keepaliveTime) - .setKeepAliveTimeout(keepaliveTimeout) - .setKeepAliveWithoutCalls(true) - .setChannelConfigurator(channelConfigurator) - .setChannelsPerCpu(2.5) - .setDirectPathServiceConfig(directPathServiceConfig) - .build(); - - InstantiatingGrpcChannelProvider.Builder builder = provider.toBuilder(); - - assertThat(builder.getEndpoint()).isEqualTo("fake.endpoint:443"); - assertThat(builder.getMaxInboundMessageSize()).isEqualTo(12345678); - assertThat(builder.getMaxInboundMetadataSize()).isEqualTo(4096); - assertThat(builder.getKeepAliveTime()).isEqualTo(keepaliveTime); - assertThat(builder.getKeepAliveTimeout()).isEqualTo(keepaliveTimeout); - assertThat(builder.getChannelConfigurator()).isEqualTo(channelConfigurator); - assertThat(builder.getPoolSize()).isEqualTo(5); - assertThat(builder.build().directPathServiceConfig).isEqualTo(directPathServiceConfig); - } - - @Test - public void testWithInterceptors() throws Exception { - testWithInterceptors(1); - } - - @Test - public void testWithInterceptorsAndMultipleChannels() throws Exception { - testWithInterceptors(5); - } - - private void testWithInterceptors(int numChannels) throws Exception { - final GrpcInterceptorProvider interceptorProvider = Mockito.mock(GrpcInterceptorProvider.class); - - InstantiatingGrpcChannelProvider channelProvider = - InstantiatingGrpcChannelProvider.newBuilder() - .setEndpoint("localhost:8080") - .setPoolSize(numChannels) - .setHeaderProvider(Mockito.mock(HeaderProvider.class)) - .setExecutor(Mockito.mock(Executor.class)) - .setInterceptorProvider(interceptorProvider) - .build(); - - Mockito.verify(interceptorProvider, Mockito.never()).getInterceptors(); - channelProvider.getTransportChannel().shutdownNow(); - Mockito.verify(interceptorProvider, Mockito.times(numChannels)).getInterceptors(); - } - - @Test - public void testChannelConfigurator() throws IOException { - final int numChannels = 5; - - // Create a mock configurator that will insert mock channels - @SuppressWarnings("unchecked") - ApiFunction channelConfigurator = - Mockito.mock(ApiFunction.class); - - ArgumentCaptor> channelBuilderCaptor = - ArgumentCaptor.forClass(ManagedChannelBuilder.class); - - ManagedChannelBuilder swappedBuilder = Mockito.mock(ManagedChannelBuilder.class); - ManagedChannel fakeChannel = Mockito.mock(ManagedChannel.class); - Mockito.when(swappedBuilder.build()).thenReturn(fakeChannel); - - Mockito.when(channelConfigurator.apply(channelBuilderCaptor.capture())) - .thenReturn(swappedBuilder); - - // Invoke the provider - InstantiatingGrpcChannelProvider.newBuilder() - .setEndpoint("localhost:8080") - .setHeaderProvider(Mockito.mock(HeaderProvider.class)) - .setExecutor(Mockito.mock(Executor.class)) - .setChannelConfigurator(channelConfigurator) - .setPoolSize(numChannels) - .build() - .getTransportChannel(); - - // Make sure that the provider passed in a configured channel - assertThat(channelBuilderCaptor.getValue()).isNotNull(); - // And that it was replaced with the mock - Mockito.verify(swappedBuilder, Mockito.times(numChannels)).build(); - } - - @Test - public void testWithGCECredentials() throws IOException { - ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(1); - executor.shutdown(); - - TransportChannelProvider provider = - InstantiatingGrpcChannelProvider.newBuilder() - .setAttemptDirectPath(true) - .build() - .withExecutor((Executor) executor) - .withHeaders(Collections.emptyMap()) - .withEndpoint("localhost:8080"); - - assertThat(provider.needsCredentials()).isTrue(); - if (InstantiatingGrpcChannelProvider.isOnComputeEngine()) { - provider = provider.withCredentials(ComputeEngineCredentials.create()); - } else { - provider = provider.withCredentials(CloudShellCredentials.create(3000)); - } - assertThat(provider.needsCredentials()).isFalse(); - - provider.getTransportChannel().shutdownNow(); - } - - @Test - public void testWithNonGCECredentials() throws IOException { - ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(1); - executor.shutdown(); - - ApiFunction channelConfigurator = - channelBuilder -> { - // Clients with non-GCE credentials will not attempt DirectPath. - assertThat(channelBuilder instanceof ComputeEngineChannelBuilder).isFalse(); - return channelBuilder; - }; - - TransportChannelProvider provider = - InstantiatingGrpcChannelProvider.newBuilder() - .setAttemptDirectPath(true) - .setChannelConfigurator(channelConfigurator) - .build() - .withExecutor((Executor) executor) - .withHeaders(Collections.emptyMap()) - .withEndpoint("localhost:8080"); - - assertThat(provider.needsCredentials()).isTrue(); - provider = provider.withCredentials(CloudShellCredentials.create(3000)); - assertThat(provider.needsCredentials()).isFalse(); - - provider.getTransportChannel().shutdownNow(); - } - - @Test - public void testWithDirectPathDisabled() throws IOException { - ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(1); - executor.shutdown(); - - ApiFunction channelConfigurator = - channelBuilder -> { - // Clients without setting attemptDirectPath flag will not attempt DirectPath - assertThat(channelBuilder instanceof ComputeEngineChannelBuilder).isFalse(); - return channelBuilder; - }; - - TransportChannelProvider provider = - InstantiatingGrpcChannelProvider.newBuilder() - .setAttemptDirectPath(false) - .setChannelConfigurator(channelConfigurator) - .build() - .withExecutor((Executor) executor) - .withHeaders(Collections.emptyMap()) - .withEndpoint("localhost:8080"); - - assertThat(provider.needsCredentials()).isTrue(); - provider = provider.withCredentials(ComputeEngineCredentials.create()); - assertThat(provider.needsCredentials()).isFalse(); - - provider.getTransportChannel().shutdownNow(); - } - - @Test - public void testWithNoDirectPathFlagSet() throws IOException { - ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(1); - executor.shutdown(); - - ApiFunction channelConfigurator = - channelBuilder -> { - // Clients without setting attemptDirectPath flag will not attempt DirectPath - assertThat(channelBuilder instanceof ComputeEngineChannelBuilder).isFalse(); - return channelBuilder; - }; - - TransportChannelProvider provider = - InstantiatingGrpcChannelProvider.newBuilder() - .setChannelConfigurator(channelConfigurator) - .build() - .withExecutor((Executor) executor) - .withHeaders(Collections.emptyMap()) - .withEndpoint("localhost:8080"); - - assertThat(provider.needsCredentials()).isTrue(); - provider = provider.withCredentials(ComputeEngineCredentials.create()); - assertThat(provider.needsCredentials()).isFalse(); - - provider.getTransportChannel().shutdownNow(); - } - - @Test - public void testWithIPv6Address() throws IOException { - ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(1); - executor.shutdown(); - - TransportChannelProvider provider = - InstantiatingGrpcChannelProvider.newBuilder() - .build() - .withExecutor((Executor) executor) - .withHeaders(Collections.emptyMap()) - .withEndpoint("[::1]:8080"); - assertThat(provider.needsEndpoint()).isFalse(); - - // Make sure we can create channels OK. - provider.getTransportChannel().shutdownNow(); - } - - // Test that if ChannelPrimer is provided, it is called during creation - @Test - public void testWithPrimeChannel() throws IOException { - // create channelProvider with different pool sizes to verify ChannelPrimer is called the - // correct number of times - for (int poolSize = 1; poolSize < 5; poolSize++) { - final ChannelPrimer mockChannelPrimer = Mockito.mock(ChannelPrimer.class); - - InstantiatingGrpcChannelProvider provider = - InstantiatingGrpcChannelProvider.newBuilder() - .setEndpoint("localhost:8080") - .setPoolSize(poolSize) - .setHeaderProvider(Mockito.mock(HeaderProvider.class)) - .setExecutor(Mockito.mock(Executor.class)) - .setChannelPrimer(mockChannelPrimer) - .build(); - - provider.getTransportChannel().shutdownNow(); - - // every channel in the pool should call primeChannel during creation. - Mockito.verify(mockChannelPrimer, Mockito.times(poolSize)) - .primeChannel(Mockito.any(ManagedChannel.class)); - } - } - - @Test - public void testWithDefaultDirectPathServiceConfig() { - InstantiatingGrpcChannelProvider provider = - InstantiatingGrpcChannelProvider.newBuilder().build(); - - ImmutableMap defaultServiceConfig = provider.directPathServiceConfig; - - List> lbConfigs = getAsObjectList(defaultServiceConfig, "loadBalancingConfig"); - assertThat(lbConfigs).hasSize(1); - Map lbConfig = lbConfigs.get(0); - Map grpclb = getAsObject(lbConfig, "grpclb"); - List> childPolicies = getAsObjectList(grpclb, "childPolicy"); - assertThat(childPolicies).hasSize(1); - Map childPolicy = childPolicies.get(0); - assertThat(childPolicy.keySet()).containsExactly("pick_first"); - } - - @Nullable - private static Map getAsObject(Map json, String key) { - Object mapObject = json.get(key); - if (mapObject == null) { - return null; - } - return checkObject(mapObject); - } - - @SuppressWarnings("unchecked") - private static Map checkObject(Object json) { - checkArgument(json instanceof Map, "Invalid json object representation: %s", json); - for (Map.Entry entry : ((Map) json).entrySet()) { - checkArgument(entry.getKey() instanceof String, "Key is not string"); - } - return (Map) json; - } - - private static List> getAsObjectList(Map json, String key) { - Object listObject = json.get(key); - if (listObject == null) { - return null; - } - return checkListOfObjects(listObject); - } - - @SuppressWarnings("unchecked") - private static List> checkListOfObjects(Object listObject) { - checkArgument(listObject instanceof List, "Passed object is not a list"); - List> list = new ArrayList<>(); - for (Object object : ((List) listObject)) { - list.add(checkObject(object)); - } - return list; - } - - @Test - public void testWithCustomDirectPathServiceConfig() { - ImmutableMap pickFirstStrategy = - ImmutableMap.of("round_robin", ImmutableMap.of()); - ImmutableMap childPolicy = - ImmutableMap.of( - "childPolicy", ImmutableList.of(pickFirstStrategy), "foo", "bar"); - ImmutableMap grpcLbPolicy = - ImmutableMap.of("grpclb", childPolicy); - Map passedServiceConfig = new HashMap<>(); - passedServiceConfig.put("loadBalancingConfig", ImmutableList.of(grpcLbPolicy)); - - InstantiatingGrpcChannelProvider provider = - InstantiatingGrpcChannelProvider.newBuilder() - .setDirectPathServiceConfig(passedServiceConfig) - .build(); - - ImmutableMap defaultServiceConfig = provider.directPathServiceConfig; - assertThat(defaultServiceConfig).isEqualTo(passedServiceConfig); - } - - @Override - protected Object getMtlsObjectFromTransportChannel(MtlsProvider provider) - throws IOException, GeneralSecurityException { - InstantiatingGrpcChannelProvider channelProvider = - InstantiatingGrpcChannelProvider.newBuilder() - .setEndpoint("localhost:8080") - .setMtlsProvider(provider) - .setHeaderProvider(Mockito.mock(HeaderProvider.class)) - .setExecutor(Mockito.mock(Executor.class)) - .build(); - return channelProvider.createMtlsChannelCredentials(); - } -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/MockClientCall.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/MockClientCall.java deleted file mode 100644 index a1720293f..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/MockClientCall.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import io.grpc.ClientCall; -import io.grpc.Metadata; -import io.grpc.Status; -import javax.annotation.Nullable; - -public class MockClientCall extends ClientCall { - - private ResponseT response; - private Listener responseListener; - private Metadata headers; - private Status status; - - public MockClientCall(ResponseT response, Status status) { - this.response = response; - this.status = status; - } - - @Override - public synchronized void start(Listener responseListener, Metadata headers) { - this.responseListener = responseListener; - this.headers = headers; - } - - @Override - public void request(int numMessages) {} - - @Override - public void cancel(@Nullable String message, @Nullable Throwable cause) {} - - @Override - public void halfClose() {} - - @Override - public void sendMessage(RequestT message) { - responseListener.onHeaders(headers); - responseListener.onMessage(response); - responseListener.onClose(status, headers); - } -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/MockOperationsEx.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/MockOperationsEx.java deleted file mode 100644 index 0f6c3fd8a..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/MockOperationsEx.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.core.BetaApi; -import com.google.api.gax.grpc.testing.MockGrpcService; -import com.google.protobuf.AbstractMessage; -import io.grpc.ServerServiceDefinition; -import java.util.List; - -/** A MockGrpcService for OperationsApi which uses MockOperationsExImpl. */ -@BetaApi -public class MockOperationsEx implements MockGrpcService { - private final MockOperationsExImpl serviceImpl; - - public MockOperationsEx() { - serviceImpl = new MockOperationsExImpl(); - } - - @Override - public List getRequests() { - return serviceImpl.getRequests(); - } - - @Override - public void addResponse(AbstractMessage response) { - serviceImpl.addGetOperationResponse(response); - } - - @Override - public void addException(Exception error) { - serviceImpl.addGetOperationError(error); - } - - @Override - public ServerServiceDefinition getServiceDefinition() { - return serviceImpl.bindService(); - } - - @Override - public void reset() { - serviceImpl.reset(); - } -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/MockOperationsExImpl.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/MockOperationsExImpl.java deleted file mode 100644 index 055e7cdca..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/MockOperationsExImpl.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import com.google.api.core.BetaApi; -import com.google.longrunning.CancelOperationRequest; -import com.google.longrunning.DeleteOperationRequest; -import com.google.longrunning.GetOperationRequest; -import com.google.longrunning.ListOperationsRequest; -import com.google.longrunning.ListOperationsResponse; -import com.google.longrunning.Operation; -import com.google.longrunning.OperationsGrpc.OperationsImplBase; -import com.google.protobuf.AbstractMessage; -import com.google.protobuf.Empty; -import io.grpc.stub.StreamObserver; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.Queue; - -/** A custom mock Operations service implementation which only mocks responses for GetOperation. */ -@BetaApi -public class MockOperationsExImpl extends OperationsImplBase { - private List requests; - private Queue getOperationResponses; - - public MockOperationsExImpl() { - requests = new ArrayList<>(); - getOperationResponses = new LinkedList<>(); - } - - public List getRequests() { - return requests; - } - - public void addGetOperationResponse(AbstractMessage response) { - this.getOperationResponses.add(response); - } - - public void addGetOperationError(Throwable error) { - this.getOperationResponses.add(error); - } - - public void reset() { - requests = new ArrayList<>(); - getOperationResponses = new LinkedList<>(); - } - - @Override - public void getOperation( - GetOperationRequest request, StreamObserver responseObserver) { - requests.add(request); - Object response = getOperationResponses.remove(); - if (response instanceof Throwable) { - responseObserver.onError((Throwable) response); - } else if (response instanceof AbstractMessage) { - responseObserver.onNext((Operation) response); - responseObserver.onCompleted(); - } - } - - @Override - public void listOperations( - ListOperationsRequest request, StreamObserver responseObserver) { - requests.add(request); - responseObserver.onError( - new UnsupportedOperationException( - "MockOperationsExImpl: listOperations not yet supported")); - } - - @Override - public void cancelOperation( - CancelOperationRequest request, StreamObserver responseObserver) { - requests.add(request); - responseObserver.onNext(Empty.getDefaultInstance()); - responseObserver.onCompleted(); - } - - @Override - public void deleteOperation( - DeleteOperationRequest request, StreamObserver responseObserver) { - requests.add(request); - responseObserver.onError( - new UnsupportedOperationException( - "MockOperationsExImpl: listOperations not yet supported")); - } -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/ProtoOperationTransformersTest.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/ProtoOperationTransformersTest.java deleted file mode 100644 index 5ac43f141..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/ProtoOperationTransformersTest.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import static org.junit.Assert.assertThrows; - -import com.google.api.gax.grpc.ProtoOperationTransformers.MetadataTransformer; -import com.google.api.gax.grpc.ProtoOperationTransformers.ResponseTransformer; -import com.google.api.gax.longrunning.OperationSnapshot; -import com.google.api.gax.rpc.UnavailableException; -import com.google.api.gax.rpc.UnknownException; -import com.google.common.truth.Truth; -import com.google.longrunning.Operation; -import com.google.protobuf.Any; -import com.google.rpc.Status; -import com.google.type.Color; -import com.google.type.Money; -import io.grpc.Status.Code; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class ProtoOperationTransformersTest { - @Test - public void testAnyResponseTransformer() { - ResponseTransformer transformer = ResponseTransformer.create(Money.class); - Money inputMoney = Money.newBuilder().setCurrencyCode("USD").build(); - OperationSnapshot operationSnapshot = - GrpcOperationSnapshot.create( - Operation.newBuilder().setResponse(Any.pack(inputMoney)).build()); - Truth.assertThat(transformer.apply(operationSnapshot)).isEqualTo(inputMoney); - } - - @Test - public void testAnyResponseTransformer_exception() { - ResponseTransformer transformer = ResponseTransformer.create(Money.class); - Money inputMoney = Money.newBuilder().setCurrencyCode("USD").build(); - Status status = Status.newBuilder().setCode(Code.UNAVAILABLE.value()).build(); - OperationSnapshot operationSnapshot = - GrpcOperationSnapshot.create( - Operation.newBuilder().setResponse(Any.pack(inputMoney)).setError(status).build()); - Exception exception = - assertThrows(UnavailableException.class, () -> transformer.apply(operationSnapshot)); - Truth.assertThat(exception) - .hasMessageThat() - .contains("failed with status = GrpcStatusCode{transportCode=UNAVAILABLE}"); - } - - @Test - public void testAnyResponseTransformer_mismatchedTypes() { - ResponseTransformer transformer = ResponseTransformer.create(Money.class); - Status status = Status.newBuilder().setCode(Code.OK.value()).build(); - OperationSnapshot operationSnapshot = - GrpcOperationSnapshot.create( - Operation.newBuilder() - .setResponse(Any.pack(Color.getDefaultInstance())) - .setError(status) - .build()); - Exception exception = - assertThrows(UnknownException.class, () -> transformer.apply(operationSnapshot)); - Truth.assertThat(exception).hasMessageThat().contains("encountered a problem unpacking it"); - } - - @Test - public void testAnyMetadataTransformer() { - MetadataTransformer transformer = MetadataTransformer.create(Money.class); - Money inputMoney = Money.newBuilder().setCurrencyCode("USD").build(); - OperationSnapshot operationSnapshot = - GrpcOperationSnapshot.create( - Operation.newBuilder().setMetadata(Any.pack(inputMoney)).build()); - Truth.assertThat(transformer.apply(operationSnapshot)).isEqualTo(inputMoney); - } - - @Test - public void testAnyMetadataTransformer_mismatchedTypes() { - MetadataTransformer transformer = MetadataTransformer.create(Money.class); - Status status = Status.newBuilder().setCode(Code.OK.value()).build(); - OperationSnapshot operationSnapshot = - GrpcOperationSnapshot.create( - Operation.newBuilder() - .setMetadata(Any.pack(Color.getDefaultInstance())) - .setError(status) - .build()); - Exception exception = - assertThrows(UnknownException.class, () -> transformer.apply(operationSnapshot)); - Truth.assertThat(exception).hasMessageThat().contains("encountered a problem unpacking it"); - } -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/SettingsTest.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/SettingsTest.java deleted file mode 100644 index e24e36c68..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/SettingsTest.java +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import static org.junit.Assert.assertEquals; - -import com.google.api.gax.batching.BatchingSettings; -import com.google.api.gax.core.CredentialsProvider; -import com.google.api.gax.core.FixedCredentialsProvider; -import com.google.api.gax.core.GoogleCredentialsProvider; -import com.google.api.gax.core.InstantiatingExecutorProvider; -import com.google.api.gax.paging.PagedListResponse; -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.rpc.ApiClientHeaderProvider; -import com.google.api.gax.rpc.BatchingCallSettings; -import com.google.api.gax.rpc.BatchingDescriptor; -import com.google.api.gax.rpc.ClientContext; -import com.google.api.gax.rpc.FixedWatchdogProvider; -import com.google.api.gax.rpc.NoHeaderProvider; -import com.google.api.gax.rpc.PagedCallSettings; -import com.google.api.gax.rpc.PagedListResponseFactory; -import com.google.api.gax.rpc.StatusCode; -import com.google.api.gax.rpc.StubSettings; -import com.google.api.gax.rpc.TransportChannelProvider; -import com.google.api.gax.rpc.UnaryCallSettings; -import com.google.api.gax.rpc.mtls.MtlsProvider; -import com.google.auth.Credentials; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Lists; -import com.google.common.truth.Truth; -import java.io.IOException; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class SettingsTest { - - interface FakePagedListResponse extends PagedListResponse {} - - private static class FakeStubSettings extends StubSettings { - - @SuppressWarnings("unchecked") - private static final PagedListResponseFactory - fakePagedListResponseFactory = Mockito.mock(PagedListResponseFactory.class); - - @SuppressWarnings("unchecked") - private static final BatchingDescriptor FAKE_BATCHING_DESCRIPTOR = - Mockito.mock(BatchingDescriptor.class); - - private static final String DEFAULT_GAPIC_NAME = "gapic"; - public static final String DEFAULT_SERVICE_ADDRESS = "pubsub-experimental.googleapis.com"; - public static final int DEFAULT_SERVICE_PORT = 443; - public static final String DEFAULT_SERVICE_ENDPOINT = - DEFAULT_SERVICE_ADDRESS + ':' + DEFAULT_SERVICE_PORT; - public static final MtlsProvider DEFAULT_MTLS_PROVIDER = new MtlsProvider(); - public static final ImmutableList DEFAULT_SERVICE_SCOPES = - ImmutableList.builder() - .add("https://www.googleapis.com/auth/pubsub") - .add("https://www.googleapis.com/auth/cloud-platform") - .build(); - - private static final ImmutableMap> - RETRYABLE_CODE_DEFINITIONS; - - static { - ImmutableMap.Builder> definitions = - ImmutableMap.builder(); - definitions.put( - "idempotent", - ImmutableSet.copyOf( - Lists.newArrayList(StatusCode.Code.DEADLINE_EXCEEDED, StatusCode.Code.UNAVAILABLE))); - definitions.put("non_idempotent", ImmutableSet.copyOf(Lists.newArrayList())); - RETRYABLE_CODE_DEFINITIONS = definitions.build(); - } - - private static final ImmutableMap RETRY_PARAM_DEFINITIONS; - - static { - ImmutableMap.Builder definitions = ImmutableMap.builder(); - RetrySettings settings = null; - settings = - RetrySettings.newBuilder() - .setInitialRetryDelay(Duration.ofMillis(100L)) - .setRetryDelayMultiplier(1.2) - .setMaxRetryDelay(Duration.ofMillis(1000L)) - .setInitialRpcTimeout(Duration.ofMillis(2000L)) - .setRpcTimeoutMultiplier(1.5) - .setMaxRpcTimeout(Duration.ofMillis(30000L)) - .setTotalTimeout(Duration.ofMillis(45000L)) - .build(); - definitions.put("default", settings); - RETRY_PARAM_DEFINITIONS = definitions.build(); - } - - private final UnaryCallSettings fakeMethodSimple; - private final PagedCallSettings fakePagedMethod; - private final BatchingCallSettings fakeMethodBatching; - - public UnaryCallSettings fakeMethodSimple() { - return fakeMethodSimple; - } - - public PagedCallSettings fakePagedMethod() { - return fakePagedMethod; - } - - public BatchingCallSettings fakeMethodBatching() { - return fakeMethodBatching; - } - - public static GoogleCredentialsProvider.Builder defaultCredentialsProviderBuilder() { - return GoogleCredentialsProvider.newBuilder().setScopesToApply(DEFAULT_SERVICE_SCOPES); - } - - public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuilder() { - return InstantiatingExecutorProvider.newBuilder(); - } - - /** Returns a builder for the default TransportChannelProvider for this service. */ - public static InstantiatingGrpcChannelProvider.Builder defaultGrpcChannelProviderBuilder() { - return InstantiatingGrpcChannelProvider.newBuilder() - .setEndpoint(DEFAULT_SERVICE_ENDPOINT) - .setMtlsProvider(DEFAULT_MTLS_PROVIDER); - } - - public static ApiClientHeaderProvider.Builder defaultGoogleServiceHeaderProviderBuilder() { - return ApiClientHeaderProvider.newBuilder() - .setGeneratedLibToken(DEFAULT_GAPIC_NAME, "0.10.0") - .setTransportToken( - GaxGrpcProperties.getGrpcTokenName(), GaxGrpcProperties.getGrpcVersion()); - } - - public static TransportChannelProvider defaultTransportChannelProvider() { - return defaultGrpcChannelProviderBuilder().build(); - } - - public static Builder newBuilder() { - return Builder.createDefault(); - } - - @Override - public Builder toBuilder() { - return new Builder(this); - } - - private FakeStubSettings(Builder settingsBuilder) { - super(settingsBuilder); - - fakeMethodSimple = settingsBuilder.fakeMethodSimple().build(); - fakePagedMethod = settingsBuilder.fakePagedMethod().build(); - fakeMethodBatching = settingsBuilder.fakeMethodBatching().build(); - } - - private static class Builder extends StubSettings.Builder { - - private UnaryCallSettings.Builder fakeMethodSimple; - private PagedCallSettings.Builder fakePagedMethod; - private BatchingCallSettings.Builder fakeMethodBatching; - - private Builder() { - super((ClientContext) null); - - fakeMethodSimple = UnaryCallSettings.newUnaryCallSettingsBuilder(); - fakePagedMethod = PagedCallSettings.newBuilder(fakePagedListResponseFactory); - fakeMethodBatching = - BatchingCallSettings.newBuilder(FAKE_BATCHING_DESCRIPTOR) - .setBatchingSettings(BatchingSettings.newBuilder().build()); - } - - private static Builder createDefault() { - Builder builder = new Builder(); - builder.setTransportChannelProvider(defaultTransportChannelProvider()); - builder.setExecutorProvider(defaultExecutorProviderBuilder().build()); - builder.setCredentialsProvider(defaultCredentialsProviderBuilder().build()); - builder.setHeaderProvider(new NoHeaderProvider()); - builder.setInternalHeaderProvider(defaultGoogleServiceHeaderProviderBuilder().build()); - builder.setStreamWatchdogProvider(FixedWatchdogProvider.create(null)); - - builder - .fakeMethodSimple() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) - .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("default")); - - builder - .fakePagedMethod() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) - .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("default")); - - builder - .fakeMethodBatching() - .setBatchingSettings( - BatchingSettings.newBuilder() - .setElementCountThreshold(800L) - .setRequestByteThreshold(8388608L) - .setDelayThreshold(Duration.ofMillis(100)) - .build()); - builder - .fakeMethodBatching() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) - .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("default")); - - return builder; - } - - private Builder(FakeStubSettings settings) { - super(settings); - - fakeMethodSimple = settings.fakeMethodSimple().toBuilder(); - fakePagedMethod = settings.fakePagedMethod().toBuilder(); - fakeMethodBatching = settings.fakeMethodBatching().toBuilder(); - } - - @Override - public FakeStubSettings build() throws IOException { - return new FakeStubSettings(this); - } - - public UnaryCallSettings.Builder fakeMethodSimple() { - return fakeMethodSimple; - } - - public PagedCallSettings.Builder fakePagedMethod() { - return fakePagedMethod; - } - - public BatchingCallSettings.Builder fakeMethodBatching() { - return fakeMethodBatching; - } - } - } - - // GrpcTransportProvider - // ==== - - @Test - public void customCredentials() throws IOException { - Credentials credentials = Mockito.mock(Credentials.class); - - FakeStubSettings settings = - FakeStubSettings.newBuilder() - .setCredentialsProvider(FixedCredentialsProvider.create(credentials)) - .build(); - - TransportChannelProvider actualChannelProvider = settings.getTransportChannelProvider(); - Truth.assertThat(actualChannelProvider).isInstanceOf(InstantiatingGrpcChannelProvider.class); - InstantiatingGrpcChannelProvider actualInstChPr = - (InstantiatingGrpcChannelProvider) actualChannelProvider; - - Truth.assertThat(actualInstChPr.getEndpoint()) - .isEqualTo(FakeStubSettings.DEFAULT_SERVICE_ENDPOINT); - // TODO(michaelbausor): create JSON with credentials and define GOOGLE_APPLICATION_CREDENTIALS - // environment variable to allow travis build to access application default credentials - Truth.assertThat(settings.getCredentialsProvider().getCredentials()) - .isSameInstanceAs(credentials); - } - - @Test - public void channelCustomCredentialScopes() throws IOException { - ImmutableList inputScopes = - ImmutableList.builder().add("https://www.googleapis.com/auth/fakeservice").build(); - - CredentialsProvider credentialsProvider = - FakeStubSettings.defaultCredentialsProviderBuilder().setScopesToApply(inputScopes).build(); - FakeStubSettings settings = - FakeStubSettings.newBuilder().setCredentialsProvider(credentialsProvider).build(); - - TransportChannelProvider actualChannelProvider = settings.getTransportChannelProvider(); - Truth.assertThat(actualChannelProvider).isInstanceOf(InstantiatingGrpcChannelProvider.class); - InstantiatingGrpcChannelProvider actualInstChPr = - (InstantiatingGrpcChannelProvider) actualChannelProvider; - - Truth.assertThat(actualInstChPr.getEndpoint()) - .isEqualTo(FakeStubSettings.DEFAULT_SERVICE_ENDPOINT); - - CredentialsProvider actualCredentialsProvider = settings.getCredentialsProvider(); - Truth.assertThat(actualCredentialsProvider).isInstanceOf(GoogleCredentialsProvider.class); - GoogleCredentialsProvider googCredProv = (GoogleCredentialsProvider) actualCredentialsProvider; - - Truth.assertThat(googCredProv.getScopesToApply()).isEqualTo(inputScopes); - - // TODO(michaelbausor): create JSON with credentials and define GOOGLE_APPLICATION_CREDENTIALS - // environment variable to allow travis build to access application default credentials - // Truth.assertThat(connSettings.getCredentials()).isNotNull(); - } - - // CallSettings - // ==== - - @Test - public void callSettingsToBuilder() { - UnaryCallSettings.Builder builderA = UnaryCallSettings.newUnaryCallSettingsBuilder(); - UnaryCallSettings settingsA = builderA.build(); - UnaryCallSettings.Builder builderB = settingsA.toBuilder(); - UnaryCallSettings settingsB = builderB.build(); - - assertEquals(settingsA, settingsB); - } - - @Test - public void unaryCallSettingsBuilderBuildDoesNotFailUnsetProperties() { - UnaryCallSettings.Builder builder = - UnaryCallSettings.newUnaryCallSettingsBuilder(); - builder.build(); - } - - @Test - public void callSettingsBuildFromTimeoutNoRetries() { - Duration timeout = Duration.ofMillis(60000); - - UnaryCallSettings.Builder builderA = - UnaryCallSettings.newUnaryCallSettingsBuilder(); - builderA.setSimpleTimeoutNoRetries(timeout); - UnaryCallSettings settingsA = builderA.build(); - - UnaryCallSettings.Builder builderB = - UnaryCallSettings.newUnaryCallSettingsBuilder(); - builderB - .setRetryableCodes() - .setRetrySettings( - RetrySettings.newBuilder() - .setTotalTimeout(timeout) - .setInitialRetryDelay(Duration.ZERO) - .setRetryDelayMultiplier(1) - .setMaxRetryDelay(Duration.ZERO) - .setInitialRpcTimeout(timeout) - .setRpcTimeoutMultiplier(1) - .setMaxRpcTimeout(timeout) - .setMaxAttempts(1) - .build()); - UnaryCallSettings settingsB = builderB.build(); - - assertEquals("UnaryCallSettings", settingsA, settingsB); - } -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/TimeoutTest.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/TimeoutTest.java deleted file mode 100644 index 3b0d8ebc5..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/TimeoutTest.java +++ /dev/null @@ -1,447 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc; - -import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.times; - -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.rpc.ApiException; -import com.google.api.gax.rpc.ClientContext; -import com.google.api.gax.rpc.RequestParamsExtractor; -import com.google.api.gax.rpc.ServerStreamingCallSettings; -import com.google.api.gax.rpc.ServerStreamingCallable; -import com.google.api.gax.rpc.StatusCode; -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.api.gax.rpc.UnaryCallSettings; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.api.gax.rpc.testing.FakeStatusCode; -import com.google.common.collect.ImmutableSet; -import io.grpc.CallOptions; -import io.grpc.ClientCall; -import io.grpc.Deadline; -import io.grpc.ManagedChannel; -import io.grpc.MethodDescriptor; -import io.grpc.MethodDescriptor.Marshaller; -import io.grpc.MethodDescriptor.MethodType; -import java.util.concurrent.TimeUnit; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.ArgumentCaptor; -import org.mockito.ArgumentMatchers; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.mockito.quality.Strictness; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class TimeoutTest { - private static final String CALL_OPTIONS_AUTHORITY = "RETRYING_TEST"; - private static final int DEADLINE_IN_DAYS = 7; - private static final int DEADLINE_IN_MINUTES = 10; - private static final int DEADLINE_IN_SECONDS = 20; - private static final ImmutableSet emptyRetryCodes = ImmutableSet.of(); - private static final ImmutableSet retryUnknownCode = - ImmutableSet.of(StatusCode.Code.UNKNOWN); - private static final Duration totalTimeout = Duration.ofDays(DEADLINE_IN_DAYS); - private static final Duration maxRpcTimeout = Duration.ofMinutes(DEADLINE_IN_MINUTES); - private static final Duration initialRpcTimeout = Duration.ofSeconds(DEADLINE_IN_SECONDS); - private static final GrpcCallContext defaultCallContext = GrpcCallContext.createDefault(); - - @Rule public MockitoRule mockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS); - @Mock private Marshaller stringMarshaller; - @Mock private RequestParamsExtractor paramsExtractor; - @Mock private ManagedChannel managedChannel; - - @Test - public void testNonRetryUnarySettings() { - RetrySettings retrySettings = - RetrySettings.newBuilder() - .setTotalTimeout(totalTimeout) - .setInitialRetryDelay(Duration.ZERO) - .setRetryDelayMultiplier(1.0) - .setMaxRetryDelay(Duration.ZERO) - .setMaxAttempts(1) - .setJittered(true) - .setInitialRpcTimeout(initialRpcTimeout) - .setRpcTimeoutMultiplier(1.0) - .setMaxRpcTimeout(maxRpcTimeout) - .build(); - CallOptions callOptionsUsed = - setupUnaryCallable(retrySettings, emptyRetryCodes, defaultCallContext); - - // Verify that the gRPC channel used the CallOptions with our custom timeout of ~2 Days. - assertThat(callOptionsUsed.getDeadline()).isNotNull(); - assertThat(callOptionsUsed.getDeadline()) - .isGreaterThan(Deadline.after(DEADLINE_IN_DAYS - 1, TimeUnit.DAYS)); - assertThat(callOptionsUsed.getDeadline()) - .isLessThan(Deadline.after(DEADLINE_IN_DAYS, TimeUnit.DAYS)); - assertThat(callOptionsUsed.getAuthority()).isEqualTo(CALL_OPTIONS_AUTHORITY); - } - - @Test - public void testNonRetryUnarySettingsContextWithRetry() { - RetrySettings retrySettings = - RetrySettings.newBuilder() - .setTotalTimeout(totalTimeout) - .setInitialRetryDelay(Duration.ZERO) - .setRetryDelayMultiplier(1.0) - .setMaxRetryDelay(Duration.ZERO) - .setMaxAttempts(1) - .setJittered(true) - .setInitialRpcTimeout(initialRpcTimeout) - .setRpcTimeoutMultiplier(1.0) - .setMaxRpcTimeout(maxRpcTimeout) - .build(); - Duration newTimeout = Duration.ofSeconds(5); - RetrySettings contextRetrySettings = - retrySettings - .toBuilder() - .setInitialRpcTimeout(newTimeout) - .setMaxRpcTimeout(newTimeout) - .setMaxAttempts(3) - .build(); - GrpcCallContext retryingContext = - defaultCallContext - .withRetrySettings(contextRetrySettings) - .withRetryableCodes(retryUnknownCode); - CallOptions callOptionsUsed = - setupUnaryCallable(retrySettings, emptyRetryCodes, retryingContext); - - // Verify that the gRPC channel used the CallOptions the initial timeout of ~5 seconds. - // This indicates that the context retry settings were used on a callable that was instantiated - // with non-retryable settings. - assertThat(callOptionsUsed.getDeadline()).isNotNull(); - assertThat(callOptionsUsed.getDeadline()) - .isGreaterThan(Deadline.after(toSecondsPart(newTimeout) - 1, TimeUnit.SECONDS)); - assertThat(callOptionsUsed.getDeadline()) - .isLessThan(Deadline.after(toSecondsPart(newTimeout), TimeUnit.SECONDS)); - assertThat(callOptionsUsed.getAuthority()).isEqualTo(CALL_OPTIONS_AUTHORITY); - } - - @Test - public void testNonRetryUnarySettingsWithoutInitialRpcTimeout() { - RetrySettings retrySettings = - RetrySettings.newBuilder() - .setTotalTimeout(totalTimeout) - .setInitialRetryDelay(Duration.ZERO) - .setRetryDelayMultiplier(1.0) - .setMaxRetryDelay(Duration.ZERO) - .setMaxAttempts(1) - .setJittered(true) - .setRpcTimeoutMultiplier(1.0) - .setMaxRpcTimeout(maxRpcTimeout) - .build(); - CallOptions callOptionsUsed = - setupUnaryCallable(retrySettings, emptyRetryCodes, defaultCallContext); - - // Verify that the gRPC channel used the CallOptions with our custom timeout of ~2 Days. - assertThat(callOptionsUsed.getDeadline()).isNotNull(); - assertThat(callOptionsUsed.getDeadline()) - .isGreaterThan(Deadline.after(DEADLINE_IN_DAYS - 1, TimeUnit.DAYS)); - assertThat(callOptionsUsed.getDeadline()) - .isLessThan(Deadline.after(DEADLINE_IN_DAYS, TimeUnit.DAYS)); - assertThat(callOptionsUsed.getAuthority()).isEqualTo(CALL_OPTIONS_AUTHORITY); - } - - @Test - public void testNonRetryUnarySettingsWithoutIndividualRpcTimeout() { - RetrySettings retrySettings = - RetrySettings.newBuilder() - .setTotalTimeout(totalTimeout) - .setInitialRetryDelay(Duration.ZERO) - .setRetryDelayMultiplier(1.0) - .setMaxRetryDelay(Duration.ZERO) - .setMaxAttempts(1) - .setJittered(true) - .setRpcTimeoutMultiplier(1.0) - .setRpcTimeoutMultiplier(1.0) - .build(); - CallOptions callOptionsUsed = - setupUnaryCallable(retrySettings, emptyRetryCodes, defaultCallContext); - - // Verify that the gRPC channel used the CallOptions with our custom timeout of ~2 Days. - assertThat(callOptionsUsed.getDeadline()).isNotNull(); - assertThat(callOptionsUsed.getDeadline()) - .isGreaterThan(Deadline.after(DEADLINE_IN_DAYS - 1, TimeUnit.DAYS)); - assertThat(callOptionsUsed.getDeadline()) - .isLessThan(Deadline.after(DEADLINE_IN_DAYS, TimeUnit.DAYS)); - assertThat(callOptionsUsed.getAuthority()).isEqualTo(CALL_OPTIONS_AUTHORITY); - } - - @Test - public void testNonRetryServerStreamingSettings() { - RetrySettings retrySettings = - RetrySettings.newBuilder() - .setTotalTimeout(totalTimeout) - .setInitialRetryDelay(Duration.ZERO) - .setRetryDelayMultiplier(1.0) - .setMaxRetryDelay(Duration.ZERO) - .setMaxAttempts(1) - .setJittered(true) - .setInitialRpcTimeout(initialRpcTimeout) - .setRpcTimeoutMultiplier(1.0) - .setMaxRpcTimeout(maxRpcTimeout) - .build(); - CallOptions callOptionsUsed = - setupServerStreamingCallable(retrySettings, emptyRetryCodes, defaultCallContext); - - // Verify that the gRPC channel used the CallOptions with our custom timeout of ~2 Days. - assertThat(callOptionsUsed.getDeadline()).isNotNull(); - assertThat(callOptionsUsed.getDeadline()) - .isGreaterThan(Deadline.after(DEADLINE_IN_DAYS - 1, TimeUnit.DAYS)); - assertThat(callOptionsUsed.getDeadline()) - .isLessThan(Deadline.after(DEADLINE_IN_DAYS, TimeUnit.DAYS)); - assertThat(callOptionsUsed.getAuthority()).isEqualTo(CALL_OPTIONS_AUTHORITY); - } - - @Test - public void testNonRetryServerStreamingSettingsContextWithRetry() { - RetrySettings retrySettings = - RetrySettings.newBuilder() - .setTotalTimeout(totalTimeout) - .setInitialRetryDelay(Duration.ZERO) - .setRetryDelayMultiplier(1.0) - .setMaxRetryDelay(Duration.ZERO) - .setMaxAttempts(1) - .setJittered(true) - .setInitialRpcTimeout(initialRpcTimeout) - .setRpcTimeoutMultiplier(1.0) - .setMaxRpcTimeout(maxRpcTimeout) - .build(); - Duration newTimeout = Duration.ofSeconds(5); - RetrySettings contextRetrySettings = - retrySettings.toBuilder().setTotalTimeout(newTimeout).setMaxAttempts(3).build(); - GrpcCallContext retryingContext = - defaultCallContext - .withRetrySettings(contextRetrySettings) - .withRetryableCodes(retryUnknownCode); - CallOptions callOptionsUsed = - setupServerStreamingCallable(retrySettings, emptyRetryCodes, retryingContext); - - // Verify that the gRPC channel used the CallOptions the total timeout of ~5 seconds. - // This indicates that the context retry settings were used on a callable that was instantiated - // with non-retryable settings. - assertThat(callOptionsUsed.getDeadline()).isNotNull(); - assertThat(callOptionsUsed.getDeadline()) - .isGreaterThan(Deadline.after(toSecondsPart(newTimeout) - 1, TimeUnit.SECONDS)); - assertThat(callOptionsUsed.getDeadline()) - .isLessThan(Deadline.after(toSecondsPart(newTimeout), TimeUnit.SECONDS)); - assertThat(callOptionsUsed.getAuthority()).isEqualTo(CALL_OPTIONS_AUTHORITY); - } - - @Test - public void testNonRetryServerStreamingSettingsWithoutInitialRpcTimeout() { - RetrySettings retrySettings = - RetrySettings.newBuilder() - .setTotalTimeout(totalTimeout) - .setInitialRetryDelay(Duration.ZERO) - .setRetryDelayMultiplier(1.0) - .setMaxRetryDelay(Duration.ZERO) - .setMaxAttempts(1) - .setJittered(true) - .setRpcTimeoutMultiplier(1.0) - .setMaxRpcTimeout(maxRpcTimeout) - .build(); - CallOptions callOptionsUsed = - setupServerStreamingCallable(retrySettings, emptyRetryCodes, defaultCallContext); - - // Verify that the gRPC channel used the CallOptions with our custom timeout of ~2 Days. - assertThat(callOptionsUsed.getDeadline()).isNotNull(); - assertThat(callOptionsUsed.getDeadline()) - .isGreaterThan(Deadline.after(DEADLINE_IN_DAYS - 1, TimeUnit.DAYS)); - assertThat(callOptionsUsed.getDeadline()) - .isLessThan(Deadline.after(DEADLINE_IN_DAYS, TimeUnit.DAYS)); - assertThat(callOptionsUsed.getAuthority()).isEqualTo(CALL_OPTIONS_AUTHORITY); - } - - @Test - public void testNonRetryServerStreamingSettingsWithoutIndividualRpcTimeout() { - RetrySettings retrySettings = - RetrySettings.newBuilder() - .setTotalTimeout(totalTimeout) - .setInitialRetryDelay(Duration.ZERO) - .setRetryDelayMultiplier(1.0) - .setMaxRetryDelay(Duration.ZERO) - .setMaxAttempts(1) - .setJittered(true) - .setRpcTimeoutMultiplier(1.0) - .setRpcTimeoutMultiplier(1.0) - .build(); - CallOptions callOptionsUsed = - setupServerStreamingCallable(retrySettings, emptyRetryCodes, defaultCallContext); - - // Verify that the gRPC channel used the CallOptions with our custom timeout of ~2 Days. - assertThat(callOptionsUsed.getDeadline()).isNotNull(); - assertThat(callOptionsUsed.getDeadline()) - .isGreaterThan(Deadline.after(DEADLINE_IN_DAYS - 1, TimeUnit.DAYS)); - assertThat(callOptionsUsed.getDeadline()) - .isLessThan(Deadline.after(DEADLINE_IN_DAYS, TimeUnit.DAYS)); - assertThat(callOptionsUsed.getAuthority()).isEqualTo(CALL_OPTIONS_AUTHORITY); - } - - private CallOptions setupUnaryCallable( - RetrySettings retrySettings, - ImmutableSet retryableCodes, - GrpcCallContext callContext) { - MethodDescriptor methodDescriptor = - MethodDescriptor.newBuilder() - .setSchemaDescriptor("yaml") - .setFullMethodName("fake.test/RingRing") - .setResponseMarshaller(stringMarshaller) - .setRequestMarshaller(stringMarshaller) - .setType(MethodType.UNARY) - .build(); - - @SuppressWarnings("unchecked") - ClientCall clientCall = Mockito.mock(ClientCall.class); - Mockito.doReturn(clientCall) - .when(managedChannel) - .newCall(ArgumentMatchers.eq(methodDescriptor), ArgumentMatchers.any(CallOptions.class)); - - // Clobber the "authority" property with an identifier that allows us to trace - // the use of this CallOptions variable. - CallOptions spyCallOptions = CallOptions.DEFAULT.withAuthority("RETRYING_TEST"); - GrpcCallContext context = - callContext.withChannel(managedChannel).withCallOptions(spyCallOptions); - - ArgumentCaptor callOptionsArgumentCaptor = - ArgumentCaptor.forClass(CallOptions.class); - - // Throw an exception during the gRPC channel business so we don't have to deal with - // processing the channel output. - Mockito.doThrow( - new ApiException(new RuntimeException(), FakeStatusCode.of(Code.UNAVAILABLE), false)) - .when(clientCall) - .halfClose(); - - GrpcCallSettings grpcCallSettings = - GrpcCallSettings.newBuilder() - .setMethodDescriptor(methodDescriptor) - .setParamsExtractor(paramsExtractor) - .build(); - UnaryCallSettings unaryCallSettings = - UnaryCallSettings.newUnaryCallSettingsBuilder() - .setRetrySettings(retrySettings) - .setRetryableCodes(retryableCodes) - .build(); - UnaryCallable callable = - GrpcCallableFactory.createUnaryCallable( - grpcCallSettings, - unaryCallSettings, - ClientContext.newBuilder().setDefaultCallContext(context).build()); - - try { - callable.futureCall("Is your refrigerator running?"); - } catch (ApiException e) { - } - - Mockito.verify(managedChannel, times(1)) - .newCall(ArgumentMatchers.eq(methodDescriptor), callOptionsArgumentCaptor.capture()); - return callOptionsArgumentCaptor.getValue(); - } - - private CallOptions setupServerStreamingCallable( - RetrySettings retrySettings, - ImmutableSet retryableCodes, - GrpcCallContext callContext) { - MethodDescriptor methodDescriptor = - MethodDescriptor.newBuilder() - .setSchemaDescriptor("yaml") - .setFullMethodName("fake.test/RingRing") - .setResponseMarshaller(stringMarshaller) - .setRequestMarshaller(stringMarshaller) - .setType(MethodType.SERVER_STREAMING) - .build(); - - @SuppressWarnings("unchecked") - ClientCall clientCall = Mockito.mock(ClientCall.class); - Mockito.doReturn(clientCall) - .when(managedChannel) - .newCall(ArgumentMatchers.eq(methodDescriptor), ArgumentMatchers.any(CallOptions.class)); - - // Clobber the "authority" property with an identifier that allows us to trace - // the use of this CallOptions variable. - CallOptions spyCallOptions = CallOptions.DEFAULT.withAuthority("RETRYING_TEST"); - GrpcCallContext context = - callContext.withChannel(managedChannel).withCallOptions(spyCallOptions); - - ArgumentCaptor callOptionsArgumentCaptor = - ArgumentCaptor.forClass(CallOptions.class); - - // Throw an exception during the gRPC channel business so we don't have to deal with - // processing the channel output. - Mockito.doThrow( - new ApiException(new RuntimeException(), FakeStatusCode.of(Code.UNAVAILABLE), false)) - .when(clientCall) - .halfClose(); - - GrpcCallSettings grpcCallSettings = - GrpcCallSettings.newBuilder() - .setMethodDescriptor(methodDescriptor) - .setParamsExtractor(paramsExtractor) - .build(); - ServerStreamingCallSettings serverStreamingCallSettings = - ServerStreamingCallSettings.newBuilder() - .setRetrySettings(retrySettings) - .setRetryableCodes(retryableCodes) - .build(); - ServerStreamingCallable callable = - GrpcCallableFactory.createServerStreamingCallable( - grpcCallSettings, - serverStreamingCallSettings, - ClientContext.newBuilder().setDefaultCallContext(context).build()); - - try { - callable.call("Is your refrigerator running?"); - } catch (ApiException e) { - } - - Mockito.verify(managedChannel, times(1)) - .newCall(ArgumentMatchers.eq(methodDescriptor), callOptionsArgumentCaptor.capture()); - return callOptionsArgumentCaptor.getValue(); - } - - /** - * Compatibility wrapper for Duration's toSecondsPart, which is not supported before Java 9. This - * codebase must continue to support Java 7 and up, in alignment with client libraries that depend - * on gax-java. - */ - private int toSecondsPart(Duration duration) { - return (int) - (duration.getSeconds() - - TimeUnit.MINUTES.toSeconds(1) - * (int) Math.floor(duration.getSeconds() / TimeUnit.MINUTES.toSeconds(1))); - } -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/testing/FakeChannelFactory.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/testing/FakeChannelFactory.java deleted file mode 100644 index 5a98d23d0..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/testing/FakeChannelFactory.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc.testing; - -import com.google.api.gax.grpc.ChannelFactory; -import com.google.api.gax.grpc.ChannelPrimer; -import io.grpc.ManagedChannel; -import java.util.List; - -public class FakeChannelFactory implements ChannelFactory { - private int called = 0; - private List channels; - private ChannelPrimer channelPrimer; - - public FakeChannelFactory(List channels) { - this.channels = channels; - } - - public FakeChannelFactory(List channels, ChannelPrimer channelPrimer) { - this.channels = channels; - this.channelPrimer = channelPrimer; - } - - public ManagedChannel createSingleChannel() { - ManagedChannel managedChannel = channels.get(called++); - if (this.channelPrimer != null) { - this.channelPrimer.primeChannel(managedChannel); - } - return managedChannel; - } -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/testing/FakeMethodDescriptor.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/testing/FakeMethodDescriptor.java deleted file mode 100644 index 0aca65ecf..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/testing/FakeMethodDescriptor.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc.testing; - -import com.google.api.core.BetaApi; -import io.grpc.MethodDescriptor; -import java.io.InputStream; - -@BetaApi -public class FakeMethodDescriptor { - // Utility class, uninstantiable. - private FakeMethodDescriptor() {} - - public static MethodDescriptor create() { - return create(MethodDescriptor.MethodType.UNARY, "FakeClient/fake-method"); - } - - public static MethodDescriptor create( - MethodDescriptor.MethodType type, String name) { - return MethodDescriptor.newBuilder() - .setType(MethodDescriptor.MethodType.UNARY) - .setFullMethodName(name) - .setRequestMarshaller(new FakeMarshaller()) - .setResponseMarshaller(new FakeMarshaller()) - .build(); - } - - private static class FakeMarshaller implements MethodDescriptor.Marshaller { - @Override - public T parse(InputStream stream) { - throw new UnsupportedOperationException("FakeMarshaller doesn't actually do anything"); - } - - @Override - public InputStream stream(T value) { - throw new UnsupportedOperationException("FakeMarshaller doesn't actually do anything"); - } - } -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/testing/FakeServiceGrpc.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/testing/FakeServiceGrpc.java deleted file mode 100644 index 20b8564d8..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/testing/FakeServiceGrpc.java +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc.testing; - -import static io.grpc.MethodDescriptor.generateFullMethodName; -import static io.grpc.stub.ServerCalls.asyncBidiStreamingCall; -import static io.grpc.stub.ServerCalls.asyncClientStreamingCall; -import static io.grpc.stub.ServerCalls.asyncServerStreamingCall; -import static io.grpc.stub.ServerCalls.asyncUnaryCall; -import static io.grpc.stub.ServerCalls.asyncUnimplementedStreamingCall; -import static io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall; - -import com.google.api.core.BetaApi; -import com.google.longrunning.Operation; -import com.google.protobuf.Descriptors.FileDescriptor; -import com.google.type.Color; -import com.google.type.Money; -import io.grpc.BindableService; -import io.grpc.MethodDescriptor; -import io.grpc.ServerServiceDefinition; -import io.grpc.ServiceDescriptor; -import io.grpc.protobuf.ProtoFileDescriptorSupplier; -import io.grpc.protobuf.ProtoUtils; -import io.grpc.stub.ServerCalls.BidiStreamingMethod; -import io.grpc.stub.ServerCalls.ClientStreamingMethod; -import io.grpc.stub.ServerCalls.ServerStreamingMethod; -import io.grpc.stub.ServerCalls.UnaryMethod; -import io.grpc.stub.StreamObserver; - -/** - * This is a manually-written grpc stub class that mirrors the same structure generated by grpc from - * proto declarations. - */ -@BetaApi -public final class FakeServiceGrpc { - - private FakeServiceGrpc() {} - - public static final String SERVICE_NAME = "google.gax.FakeService"; - - public static final MethodDescriptor METHOD_RECOGNIZE = - MethodDescriptor.newBuilder() - .setType(MethodDescriptor.MethodType.UNARY) - .setFullMethodName(generateFullMethodName("google.gax.FakeService", "Recognize")) - .setRequestMarshaller(ProtoUtils.marshaller(Color.getDefaultInstance())) - .setResponseMarshaller(ProtoUtils.marshaller(Money.getDefaultInstance())) - .build(); - - public static final MethodDescriptor METHOD_LONG_RUNNING_RECOGNIZE = - MethodDescriptor.newBuilder() - .setType(MethodDescriptor.MethodType.UNARY) - .setFullMethodName( - generateFullMethodName("google.gax.FakeService", "LongRunningRecognize")) - .setRequestMarshaller(ProtoUtils.marshaller(Color.getDefaultInstance())) - .setResponseMarshaller(ProtoUtils.marshaller(Operation.getDefaultInstance())) - .build(); - - public static final MethodDescriptor METHOD_STREAMING_RECOGNIZE = - MethodDescriptor.newBuilder() - .setType(MethodDescriptor.MethodType.BIDI_STREAMING) - .setFullMethodName(generateFullMethodName("google.gax.FakeService", "StreamingRecognize")) - .setRequestMarshaller(ProtoUtils.marshaller(Color.getDefaultInstance())) - .setResponseMarshaller(ProtoUtils.marshaller(Money.getDefaultInstance())) - .build(); - - public static final MethodDescriptor METHOD_STREAMING_RECOGNIZE_ERROR = - MethodDescriptor.newBuilder() - .setType(MethodDescriptor.MethodType.BIDI_STREAMING) - .setFullMethodName( - generateFullMethodName("google.gax.FakeService", "StreamingRecognizeError")) - .setRequestMarshaller(ProtoUtils.marshaller(Color.getDefaultInstance())) - .setResponseMarshaller(ProtoUtils.marshaller(Money.getDefaultInstance())) - .build(); - - public static final MethodDescriptor METHOD_SERVER_STREAMING_RECOGNIZE = - MethodDescriptor.newBuilder() - .setType(MethodDescriptor.MethodType.SERVER_STREAMING) - .setFullMethodName( - generateFullMethodName("google.gax.FakeService", "ServerStreamingRecognize")) - .setRequestMarshaller(ProtoUtils.marshaller(Color.getDefaultInstance())) - .setResponseMarshaller(ProtoUtils.marshaller(Money.getDefaultInstance())) - .build(); - - public static final MethodDescriptor METHOD_CLIENT_STREAMING_RECOGNIZE = - MethodDescriptor.newBuilder() - .setType(MethodDescriptor.MethodType.CLIENT_STREAMING) - .setFullMethodName( - generateFullMethodName("google.gax.FakeService", "ClientStreamingRecognize")) - .setRequestMarshaller(ProtoUtils.marshaller(Color.getDefaultInstance())) - .setResponseMarshaller(ProtoUtils.marshaller(Money.getDefaultInstance())) - .build(); - - public abstract static class FakeServiceImplBase implements BindableService { - - public void recognize(Color request, StreamObserver responseObserver) { - asyncUnimplementedUnaryCall(METHOD_RECOGNIZE, responseObserver); - } - - public void longRunningRecognize(Color request, StreamObserver responseObserver) { - asyncUnimplementedUnaryCall(METHOD_LONG_RUNNING_RECOGNIZE, responseObserver); - } - - public StreamObserver streamingRecognize(StreamObserver responseObserver) { - return asyncUnimplementedStreamingCall(METHOD_STREAMING_RECOGNIZE, responseObserver); - } - - public StreamObserver streamingRecognizeError(StreamObserver responseObserver) { - return asyncUnimplementedStreamingCall(METHOD_STREAMING_RECOGNIZE_ERROR, responseObserver); - } - - public void serverStreamingRecognize(Color request, StreamObserver responseObserver) { - asyncUnimplementedUnaryCall(METHOD_SERVER_STREAMING_RECOGNIZE, responseObserver); - } - - public StreamObserver clientStreamingRecognize(StreamObserver responseObserver) { - return asyncUnimplementedStreamingCall(METHOD_CLIENT_STREAMING_RECOGNIZE, responseObserver); - } - - @Override - public final ServerServiceDefinition bindService() { - return ServerServiceDefinition.builder(getServiceDescriptor()) - .addMethod( - METHOD_RECOGNIZE, - asyncUnaryCall(new MethodHandlers(this, METHODID_RECOGNIZE))) - .addMethod( - METHOD_LONG_RUNNING_RECOGNIZE, - asyncUnaryCall( - new MethodHandlers(this, METHODID_LONG_RUNNING_RECOGNIZE))) - .addMethod( - METHOD_STREAMING_RECOGNIZE, - asyncBidiStreamingCall( - new MethodHandlers(this, METHODID_STREAMING_RECOGNIZE))) - .addMethod( - METHOD_STREAMING_RECOGNIZE_ERROR, - asyncBidiStreamingCall( - new MethodHandlers(this, METHODID_STREAMING_RECOGNIZE_ERROR))) - .addMethod( - METHOD_SERVER_STREAMING_RECOGNIZE, - asyncServerStreamingCall( - new MethodHandlers(this, METHODID_SERVER_STREAMING_RECOGNIZE))) - .addMethod( - METHOD_CLIENT_STREAMING_RECOGNIZE, - asyncClientStreamingCall( - new MethodHandlers(this, METHODID_CLIENT_STREAMING_RECOGNIZE))) - .build(); - } - } - - private static final int METHODID_RECOGNIZE = 0; - private static final int METHODID_LONG_RUNNING_RECOGNIZE = 1; - private static final int METHODID_STREAMING_RECOGNIZE = 2; - private static final int METHODID_STREAMING_RECOGNIZE_ERROR = 3; - private static final int METHODID_SERVER_STREAMING_RECOGNIZE = 4; - private static final int METHODID_CLIENT_STREAMING_RECOGNIZE = 5; - - private static final class MethodHandlers - implements UnaryMethod, - ServerStreamingMethod, - ClientStreamingMethod, - BidiStreamingMethod { - - private final FakeServiceImplBase serviceImpl; - private final int methodId; - - MethodHandlers(FakeServiceImplBase serviceImpl, int methodId) { - this.serviceImpl = serviceImpl; - this.methodId = methodId; - } - - @Override - @SuppressWarnings("unchecked") - public void invoke(Req request, StreamObserver responseObserver) { - switch (methodId) { - case METHODID_RECOGNIZE: - serviceImpl.recognize((Color) request, (StreamObserver) responseObserver); - break; - case METHODID_LONG_RUNNING_RECOGNIZE: - serviceImpl.longRunningRecognize( - (Color) request, (StreamObserver) responseObserver); - break; - case METHODID_SERVER_STREAMING_RECOGNIZE: - serviceImpl.serverStreamingRecognize( - (Color) request, (StreamObserver) responseObserver); - break; - default: - throw new AssertionError(); - } - } - - @Override - @SuppressWarnings("unchecked") - public StreamObserver invoke(StreamObserver responseObserver) { - switch (methodId) { - case METHODID_STREAMING_RECOGNIZE: - return (StreamObserver) - serviceImpl.streamingRecognize((StreamObserver) responseObserver); - case METHODID_STREAMING_RECOGNIZE_ERROR: - return (StreamObserver) - serviceImpl.streamingRecognizeError((StreamObserver) responseObserver); - case METHODID_CLIENT_STREAMING_RECOGNIZE: - return (StreamObserver) - serviceImpl.clientStreamingRecognize((StreamObserver) responseObserver); - default: - throw new AssertionError(); - } - } - } - - private static final class FakeServiceDescriptorSupplier implements ProtoFileDescriptorSupplier { - - @Override - public FileDescriptor getFileDescriptor() { - return null; - } - } - - private static volatile ServiceDescriptor serviceDescriptor; - - public static ServiceDescriptor getServiceDescriptor() { - ServiceDescriptor result = serviceDescriptor; - if (result == null) { - synchronized (FakeServiceGrpc.class) { - result = serviceDescriptor; - if (result == null) { - serviceDescriptor = - result = - ServiceDescriptor.newBuilder(SERVICE_NAME) - .setSchemaDescriptor(new FakeServiceDescriptorSupplier()) - .addMethod(METHOD_RECOGNIZE) - .addMethod(METHOD_LONG_RUNNING_RECOGNIZE) - .addMethod(METHOD_STREAMING_RECOGNIZE) - .addMethod(METHOD_STREAMING_RECOGNIZE_ERROR) - .addMethod(METHOD_SERVER_STREAMING_RECOGNIZE) - .addMethod(METHOD_CLIENT_STREAMING_RECOGNIZE) - .build(); - } - } - } - return result; - } -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/testing/FakeServiceImpl.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/testing/FakeServiceImpl.java deleted file mode 100644 index 298e84783..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/testing/FakeServiceImpl.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc.testing; - -import com.google.api.core.BetaApi; -import com.google.api.gax.grpc.testing.FakeServiceGrpc.FakeServiceImplBase; -import com.google.type.Color; -import com.google.type.Money; -import io.grpc.Status; -import io.grpc.StatusRuntimeException; -import io.grpc.stub.StreamObserver; - -@BetaApi -public class FakeServiceImpl extends FakeServiceImplBase { - private Throwable receivedError; - - public Throwable getLastRecievedError() { - return receivedError; - } - - @Override - public StreamObserver streamingRecognize(StreamObserver responseObserver) { - return new RequestStreamObserver(responseObserver); - } - - public StreamObserver streamingRecognizeError( - final StreamObserver responseObserver) { - return new StreamObserver() { - @Override - public void onNext(Color color) { - responseObserver.onError(new StatusRuntimeException(Status.INVALID_ARGUMENT)); - } - - @Override - public void onError(Throwable throwable) { - receivedError = throwable; - } - - @Override - public void onCompleted() {} - }; - } - - @Override - public void serverStreamingRecognize( - final Color color, final StreamObserver responseObserver) { - if (color.getRed() < 0) { - responseObserver.onError( - Status.INVALID_ARGUMENT.withDescription("red must be positive").asRuntimeException()); - return; - } - - // Defer the execution using the green channel. This is necessary when testing cancellation, - // because the InProcessServer uses a direct executor and will buffer the results ignoring - // cancellation - Runnable runnable = - new Runnable() { - @Override - public void run() { - try { - Thread.sleep((long) color.getGreen()); - } catch (InterruptedException e) { - Thread.interrupted(); - return; - } - responseObserver.onNext(convert(color)); - responseObserver.onCompleted(); - } - }; - - if (color.getGreen() > 0) { - new Thread(runnable).start(); - } else { - runnable.run(); - } - } - - public StreamObserver clientStreamingRecognize(StreamObserver responseObserver) { - return new RequestStreamObserver(responseObserver); - } - - private static Money convert(Color color) { - Money result = - Money.newBuilder().setCurrencyCode("USD").setUnits((long) (color.getRed() * 255)).build(); - return result; - } - - private static class RequestStreamObserver implements StreamObserver { - private StreamObserver responseObserver; - - public RequestStreamObserver(StreamObserver responseObserver) { - this.responseObserver = responseObserver; - } - - @Override - public void onNext(Color color) { - responseObserver.onNext(convert(color)); - } - - @Override - public void onError(Throwable throwable) { - throwable.printStackTrace(System.err); - } - - @Override - public void onCompleted() { - responseObserver.onCompleted(); - } - }; -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/testing/InProcessServer.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/testing/InProcessServer.java deleted file mode 100644 index d93495aa8..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/testing/InProcessServer.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc.testing; - -import com.google.api.core.BetaApi; -import io.grpc.BindableService; -import io.grpc.Metadata; -import io.grpc.Server; -import io.grpc.ServerCall; -import io.grpc.ServerCall.Listener; -import io.grpc.ServerCallHandler; -import io.grpc.ServerInterceptor; -import io.grpc.inprocess.InProcessServerBuilder; -import java.io.IOException; - -@BetaApi -public class InProcessServer { - private T serverImpl; - private String name; - private ServerInterceptor interceptor; - - private Server server; - - public InProcessServer(T serverImpl, String name) { - this( - serverImpl, - name, - new ServerInterceptor() { - @Override - public Listener interceptCall( - ServerCall call, Metadata headers, ServerCallHandler next) { - return next.startCall(call, headers); - } - }); - } - - public InProcessServer(T serverImpl, String name, ServerInterceptor interceptor) { - this.serverImpl = serverImpl; - this.name = name; - this.interceptor = interceptor; - } - - public void start() throws IOException, InstantiationException, IllegalAccessException { - server = - InProcessServerBuilder.forName(name) - .directExecutor() - .addService(serverImpl) - .intercept(interceptor) - .build() - .start(); - Runtime.getRuntime() - .addShutdownHook( - new Thread() { - @Override - public void run() { - InProcessServer.this.stop(); - } - }); - } - - public void stop() { - if (server != null) { - server.shutdown(); - } - } - - public void blockUntilShutdown() throws InterruptedException { - if (server != null) { - server.awaitTermination(); - } - } -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/testing/LocalChannelProvider.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/testing/LocalChannelProvider.java deleted file mode 100644 index 5e538a06c..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/testing/LocalChannelProvider.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc.testing; - -import com.google.api.core.BetaApi; -import com.google.api.gax.grpc.GrpcHeaderInterceptor; -import com.google.api.gax.grpc.GrpcTransportChannel; -import com.google.api.gax.rpc.FixedHeaderProvider; -import com.google.api.gax.rpc.HeaderProvider; -import com.google.api.gax.rpc.TransportChannel; -import com.google.api.gax.rpc.TransportChannelProvider; -import com.google.auth.Credentials; -import io.grpc.CallOptions; -import io.grpc.Channel; -import io.grpc.ClientCall; -import io.grpc.ClientInterceptor; -import io.grpc.ForwardingClientCall.SimpleForwardingClientCall; -import io.grpc.ManagedChannelBuilder; -import io.grpc.Metadata; -import io.grpc.MethodDescriptor; -import io.grpc.inprocess.InProcessChannelBuilder; -import java.io.IOException; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.Executor; -import java.util.concurrent.ScheduledExecutorService; -import java.util.regex.Pattern; - -/** LocalChannelProvider creates channels for in-memory gRPC services. */ -@BetaApi -public class LocalChannelProvider implements TransportChannelProvider { - - private final List interceptors; - private final String address; - - private volatile HeaderProvider headerProvider; - - private LocalChannelProvider(String address, HeaderProvider headerProvider) { - this.interceptors = new CopyOnWriteArrayList<>(); - this.address = address; - this.headerProvider = headerProvider; - } - - @Override - public boolean shouldAutoClose() { - return true; - } - - @Deprecated - @Override - public boolean needsExecutor() { - return false; - } - - @Deprecated - @Override - public TransportChannelProvider withExecutor(ScheduledExecutorService executor) { - return withExecutor((Executor) executor); - } - - @Override - public TransportChannelProvider withExecutor(Executor executor) { - throw new UnsupportedOperationException("LocalChannelProvider doesn't need an executor"); - } - - @Override - public boolean needsHeaders() { - return headerProvider == null; - } - - @Override - public boolean needsEndpoint() { - return false; - } - - @Override - public TransportChannelProvider withEndpoint(String endpoint) { - throw new UnsupportedOperationException("LocalChannelProvider doesn't need an endpoint"); - } - - @Override - @BetaApi("The surface for customizing pool size is not stable yet and may change in the future.") - public boolean acceptsPoolSize() { - return false; - } - - @Override - @BetaApi("The surface for customizing pool size is not stable yet and may change in the future.") - public TransportChannelProvider withPoolSize(int size) { - throw new UnsupportedOperationException( - "LocalChannelProvider doesn't allow pool size customization"); - } - - @Override - public TransportChannelProvider withHeaders(Map headers) { - this.headerProvider = FixedHeaderProvider.create(headers); - return this; - } - - @Override - public TransportChannel getTransportChannel() throws IOException { - ManagedChannelBuilder channelBuilder = InProcessChannelBuilder.forName(address).usePlaintext(); - if (headerProvider != null) { - GrpcHeaderInterceptor interceptor = new GrpcHeaderInterceptor(headerProvider.getHeaders()); - LocalHeaderInterceptor localHeaderInterceptor = new LocalHeaderInterceptor(interceptor); - interceptors.add(localHeaderInterceptor); - channelBuilder.intercept(localHeaderInterceptor).userAgent(interceptor.getUserAgentHeader()); - } - return GrpcTransportChannel.newBuilder().setManagedChannel(channelBuilder.build()).build(); - } - - @Override - public String getTransportName() { - return GrpcTransportChannel.getGrpcTransportName(); - } - - @Override - public boolean needsCredentials() { - return false; - } - - @Override - public TransportChannelProvider withCredentials(Credentials credentials) { - throw new UnsupportedOperationException("LocalChannelProvider doesn't need credentials"); - } - - /** Creates a LocalChannelProvider. */ - public static LocalChannelProvider create(String addressString) { - return new LocalChannelProvider(addressString, null); - } - - public boolean isHeaderSent(String headerKey, Pattern headerPattern) { - Metadata.Key key = Metadata.Key.of(headerKey, Metadata.ASCII_STRING_MARSHALLER); - - if (interceptors.isEmpty()) { - return false; - } - for (LocalHeaderInterceptor interceptor : interceptors) { - if (interceptor.getSubmittedHeaders().isEmpty()) { - return false; - } - for (Metadata submittedHeaders : interceptor.getSubmittedHeaders()) { - String headerValue = submittedHeaders.get(key); - if (headerValue == null || !headerPattern.matcher(headerValue).matches()) { - return false; - } - } - } - return true; - } - - private static class LocalHeaderInterceptor implements ClientInterceptor { - private final ClientInterceptor innerInterceptor; - private final List submittedHeaders; - - private LocalHeaderInterceptor(ClientInterceptor innerInterceptor) { - this.innerInterceptor = innerInterceptor; - this.submittedHeaders = new CopyOnWriteArrayList<>(); - } - - @Override - public ClientCall interceptCall( - MethodDescriptor method, CallOptions callOptions, Channel next) { - ClientCall call = innerInterceptor.interceptCall(method, callOptions, next); - return new SimpleForwardingClientCall(call) { - @Override - public void start(Listener responseListener, Metadata headers) { - super.start(responseListener, headers); - submittedHeaders.add(headers); - } - }; - } - - List getSubmittedHeaders() { - return submittedHeaders; - } - } -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/testing/MockGrpcService.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/testing/MockGrpcService.java deleted file mode 100644 index 237760913..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/testing/MockGrpcService.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc.testing; - -import com.google.api.core.BetaApi; -import com.google.protobuf.AbstractMessage; -import io.grpc.ServerServiceDefinition; -import java.util.List; - -/** An interface of mock gRPC service. */ -@BetaApi -public interface MockGrpcService { - /** Returns all the requests received. */ - List getRequests(); - - /** Adds the response to the response queue. */ - void addResponse(AbstractMessage response); - - /** Adds the exception to the response queue. */ - void addException(Exception exception); - - /** Returns gRPC service definition used for binding. */ - ServerServiceDefinition getServiceDefinition(); - - /** Resets the state. */ - void reset(); -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/testing/MockServiceHelper.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/testing/MockServiceHelper.java deleted file mode 100644 index 9f763b0f5..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/testing/MockServiceHelper.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc.testing; - -import com.google.api.core.BetaApi; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.Lists; -import io.grpc.Server; -import io.grpc.inprocess.InProcessServerBuilder; -import java.io.IOException; -import java.util.Arrays; -import java.util.List; - -/** A utility class to control a local service which is used by testing. */ -@BetaApi -public class MockServiceHelper { - private static final int FLOW_CONTROL_WINDOW = 65 * 1024; - - private final String addressString; - private final Server server; - private final List mockServices; - - /** Constructs a new MockServiceHelper. The method start() must be called before it is used. */ - public MockServiceHelper(String addressString, MockGrpcService mockService) { - this(addressString, Arrays.asList(mockService)); - } - - public MockServiceHelper(String addressString, List mockServices) { - this.addressString = addressString; - this.mockServices = Lists.newArrayList(mockServices); - InProcessServerBuilder builder = InProcessServerBuilder.forName(addressString); - for (MockGrpcService mockService : mockServices) { - builder.addService(mockService.getServiceDefinition()); - } - this.server = builder.build(); - } - - @VisibleForTesting - MockServiceHelper(Server server, String address, MockGrpcService mockService) { - this(server, address, Arrays.asList(mockService)); - } - - @VisibleForTesting - MockServiceHelper(Server server, String addressString, List mockServices) { - this.server = server; - this.addressString = addressString; - this.mockServices = mockServices; - } - - /** Starts the local server. */ - public void start() { - try { - server.start(); - } catch (IOException ex) { - throw new RuntimeException(ex); - } - } - - /** Resets the state of the mock service. */ - public void reset() { - for (MockGrpcService mockService : mockServices) { - mockService.reset(); - } - } - - /** Stops the local server. */ - public void stop() { - server.shutdownNow(); - } - - /** Returns the mock grpc service. */ - public MockGrpcService getService() { - if (mockServices.size() != 1) { - throw new IllegalStateException( - "MockServiceHelper.getService() can only be called if " - + "there is one service, but there are " - + mockServices.size()); - } - return mockServices.get(0); - } - - /** Returns all of the mocked grpc services. */ - public List getServices() { - return mockServices; - } - - /** Creates a channel for making requests to the mock service. */ - public LocalChannelProvider createChannelProvider() { - return LocalChannelProvider.create(addressString); - } -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/testing/MockServiceHelperTest.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/testing/MockServiceHelperTest.java deleted file mode 100644 index 585f8ec65..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/testing/MockServiceHelperTest.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc.testing; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.api.gax.rpc.TransportChannel; -import com.google.common.truth.Truth; -import io.grpc.Server; -import io.grpc.ServerServiceDefinition; -import java.io.IOException; -import java.util.Arrays; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** Tests for {@link MockServiceHelper}. */ -@RunWith(JUnit4.class) -public class MockServiceHelperTest { - @Mock private MockGrpcService grpcService; - @Mock private MockGrpcService grpcService2; - - @Mock private Server server; - - /** Sets up mocks. */ - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - when(grpcService.getServiceDefinition()) - .thenReturn(ServerServiceDefinition.builder("fake-service").build()); - when(grpcService2.getServiceDefinition()) - .thenReturn(ServerServiceDefinition.builder("fake-service2").build()); - } - - @Test - public void testGetService() { - MockServiceHelper serviceHelper = new MockServiceHelper(server, "fake-address", grpcService); - Truth.assertThat(serviceHelper.getService()).isSameInstanceAs(grpcService); - Truth.assertThat(serviceHelper.getServices().size()).isEqualTo(1); - } - - @Test(expected = IllegalStateException.class) - public void testGetServiceInvalid() { - MockServiceHelper serviceHelper = - new MockServiceHelper(server, "fake-address2", Arrays.asList(grpcService, grpcService2)); - serviceHelper.getService(); - } - - @Test - public void testStart() throws IOException { - MockServiceHelper serviceHelper = new MockServiceHelper(server, "fake-address", grpcService); - serviceHelper.start(); - verify(server, times(1)).start(); - } - - @Test - public void testReset() { - MockServiceHelper serviceHelper = new MockServiceHelper("fake-address", grpcService); - serviceHelper.reset(); - verify(grpcService, times(1)).getServiceDefinition(); - verify(grpcService, times(1)).reset(); - } - - @Test - public void testCreateChannelProvider() throws Exception { - MockServiceHelper serviceHelper = new MockServiceHelper("fake-address", grpcService); - TransportChannel channel = serviceHelper.createChannelProvider().getTransportChannel(); - assertNotNull(channel); - assertFalse(channel.isTerminated()); - channel.shutdownNow(); - } -} diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/testing/MockStreamObserver.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/testing/MockStreamObserver.java deleted file mode 100644 index ce86cff5a..000000000 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/testing/MockStreamObserver.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.grpc.testing; - -import com.google.api.core.BetaApi; -import com.google.api.core.SettableApiFuture; -import com.google.api.gax.rpc.ApiStreamObserver; -import java.util.ArrayList; -import java.util.List; - -/** An implementation of ApiStreamObserver used by testing. */ -@BetaApi -public class MockStreamObserver implements ApiStreamObserver { - - private final SettableApiFuture> future = SettableApiFuture.create(); - private final List actualMessages = new ArrayList<>(); - - @Override - public void onNext(T message) { - actualMessages.add(message); - } - - @Override - public void onError(Throwable t) { - future.setException(t); - } - - @Override - public void onCompleted() { - future.set(actualMessages); - } - // Returns the SettableFuture object which can be used to retrieve received messages. - public SettableApiFuture> future() { - return future; - } -} diff --git a/gax-grpc/src/test/java/com/google/longrunning/MockOperations.java b/gax-grpc/src/test/java/com/google/longrunning/MockOperations.java deleted file mode 100644 index 624eaa5c6..000000000 --- a/gax-grpc/src/test/java/com/google/longrunning/MockOperations.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.longrunning; - -import com.google.api.core.BetaApi; -import com.google.api.gax.grpc.testing.MockGrpcService; -import com.google.protobuf.AbstractMessage; -import io.grpc.ServerServiceDefinition; -import java.util.List; - -@BetaApi -public class MockOperations implements MockGrpcService { - private final MockOperationsImpl serviceImpl; - - public MockOperations() { - serviceImpl = new MockOperationsImpl(); - } - - @Override - public List getRequests() { - return serviceImpl.getRequests(); - } - - @Override - public void addResponse(AbstractMessage response) { - serviceImpl.addResponse(response); - } - - @Override - public void addException(Exception exception) { - serviceImpl.addException(exception); - } - - @Override - public ServerServiceDefinition getServiceDefinition() { - return serviceImpl.bindService(); - } - - @Override - public void reset() { - serviceImpl.reset(); - } -} diff --git a/gax-grpc/src/test/java/com/google/longrunning/MockOperationsImpl.java b/gax-grpc/src/test/java/com/google/longrunning/MockOperationsImpl.java deleted file mode 100644 index 594508d3d..000000000 --- a/gax-grpc/src/test/java/com/google/longrunning/MockOperationsImpl.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.longrunning; - -import com.google.api.core.BetaApi; -import com.google.longrunning.OperationsGrpc.OperationsImplBase; -import com.google.protobuf.AbstractMessage; -import com.google.protobuf.Empty; -import io.grpc.stub.StreamObserver; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.Queue; - -@BetaApi -public class MockOperationsImpl extends OperationsImplBase { - private List requests; - private Queue responses; - - public MockOperationsImpl() { - requests = new ArrayList<>(); - responses = new LinkedList<>(); - } - - public List getRequests() { - return requests; - } - - public void addResponse(AbstractMessage response) { - responses.add(response); - } - - public void setResponses(List responses) { - this.responses = new LinkedList(responses); - } - - public void addException(Exception exception) { - responses.add(exception); - } - - public void reset() { - requests = new ArrayList<>(); - responses = new LinkedList<>(); - } - - @Override - public void listOperations( - ListOperationsRequest request, StreamObserver responseObserver) { - Object response = responses.remove(); - if (response instanceof ListOperationsResponse) { - requests.add(request); - responseObserver.onNext((ListOperationsResponse) response); - responseObserver.onCompleted(); - } else if (response instanceof Exception) { - responseObserver.onError((Exception) response); - } else { - responseObserver.onError(new IllegalArgumentException("Unrecognized response type")); - } - } - - @Override - public void getOperation( - GetOperationRequest request, StreamObserver responseObserver) { - Object response = responses.remove(); - if (response instanceof Operation) { - requests.add(request); - responseObserver.onNext((Operation) response); - responseObserver.onCompleted(); - } else if (response instanceof Exception) { - responseObserver.onError((Exception) response); - } else { - responseObserver.onError(new IllegalArgumentException("Unrecognized response type")); - } - } - - @Override - public void deleteOperation( - DeleteOperationRequest request, StreamObserver responseObserver) { - Object response = responses.remove(); - if (response instanceof Empty) { - requests.add(request); - responseObserver.onNext((Empty) response); - responseObserver.onCompleted(); - } else if (response instanceof Exception) { - responseObserver.onError((Exception) response); - } else { - responseObserver.onError(new IllegalArgumentException("Unrecognized response type")); - } - } - - @Override - public void cancelOperation( - CancelOperationRequest request, StreamObserver responseObserver) { - Object response = responses.remove(); - if (response instanceof Empty) { - requests.add(request); - responseObserver.onNext((Empty) response); - responseObserver.onCompleted(); - } else if (response instanceof Exception) { - responseObserver.onError((Exception) response); - } else { - responseObserver.onError(new IllegalArgumentException("Unrecognized response type")); - } - } - - @Override - public void waitOperation( - WaitOperationRequest request, StreamObserver responseObserver) { - Object response = responses.remove(); - if (response instanceof Operation) { - requests.add(request); - responseObserver.onNext((Operation) response); - responseObserver.onCompleted(); - } else if (response instanceof Exception) { - responseObserver.onError((Exception) response); - } else { - responseObserver.onError( - new IllegalArgumentException( - String.format( - "Unrecognized response type %s, expected %s or %s", - response.getClass().getName(), - Operation.class.getName(), - Exception.class.getName()))); - } - } -} diff --git a/gax-grpc/src/test/java/com/google/longrunning/OperationsClientTest.java b/gax-grpc/src/test/java/com/google/longrunning/OperationsClientTest.java deleted file mode 100644 index 0c5eaa302..000000000 --- a/gax-grpc/src/test/java/com/google/longrunning/OperationsClientTest.java +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.longrunning; - -import com.google.api.gax.core.NoCredentialsProvider; -import com.google.api.gax.grpc.testing.LocalChannelProvider; -import com.google.api.gax.grpc.testing.MockGrpcService; -import com.google.api.gax.grpc.testing.MockServiceHelper; -import com.google.api.gax.rpc.InvalidArgumentException; -import com.google.common.collect.Lists; -import com.google.longrunning.OperationsClient.ListOperationsPagedResponse; -import com.google.protobuf.AbstractMessage; -import com.google.protobuf.Duration; -import com.google.protobuf.Empty; -import io.grpc.Status; -import io.grpc.StatusRuntimeException; -import java.io.IOException; -import java.util.Arrays; -import java.util.List; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - -public class OperationsClientTest { - private static MockOperations mockOperations; - private static MockServiceHelper serviceHelper; - private OperationsClient client; - private LocalChannelProvider channelProvider; - - @BeforeClass - public static void startStaticServer() { - mockOperations = new MockOperations(); - serviceHelper = - new MockServiceHelper("in-process-1", Arrays.asList(mockOperations)); - serviceHelper.start(); - } - - @AfterClass - public static void stopServer() { - serviceHelper.stop(); - } - - @Before - public void setUp() throws IOException { - serviceHelper.reset(); - channelProvider = serviceHelper.createChannelProvider(); - OperationsSettings settings = - OperationsSettings.newBuilder() - .setTransportChannelProvider(channelProvider) - .setCredentialsProvider(NoCredentialsProvider.create()) - .build(); - client = OperationsClient.create(settings); - } - - @After - public void tearDown() { - client.close(); - } - - @Test - @SuppressWarnings("all") - public void getOperationTest() { - String name2 = "name2-1052831874"; - boolean done = true; - Operation expectedResponse = Operation.newBuilder().setName(name2).setDone(done).build(); - mockOperations.addResponse(expectedResponse); - - String name = "name3373707"; - - Operation actualResponse = client.getOperation(name); - Assert.assertEquals(expectedResponse, actualResponse); - - List actualRequests = mockOperations.getRequests(); - Assert.assertEquals(1, actualRequests.size()); - GetOperationRequest actualRequest = (GetOperationRequest) actualRequests.get(0); - - Assert.assertEquals(name, actualRequest.getName()); - } - - @Test - @SuppressWarnings("all") - public void getOperationExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); - mockOperations.addException(exception); - - try { - String name = "name3373707"; - - client.getOperation(name); - Assert.fail("No exception raised"); - } catch (InvalidArgumentException e) { - // Expected exception - } - } - - @Test - @SuppressWarnings("all") - public void listOperationsTest() { - String nextPageToken = ""; - Operation operationsElement = Operation.newBuilder().build(); - List operations = Arrays.asList(operationsElement); - ListOperationsResponse expectedResponse = - ListOperationsResponse.newBuilder() - .setNextPageToken(nextPageToken) - .addAllOperations(operations) - .build(); - mockOperations.addResponse(expectedResponse); - - String name = "name3373707"; - String filter = "filter-1274492040"; - - ListOperationsPagedResponse pagedListResponse = client.listOperations(name, filter); - - List resources = Lists.newArrayList(pagedListResponse.iterateAll()); - Assert.assertEquals(1, resources.size()); - Assert.assertEquals(expectedResponse.getOperationsList().get(0), resources.get(0)); - - List actualRequests = mockOperations.getRequests(); - Assert.assertEquals(1, actualRequests.size()); - ListOperationsRequest actualRequest = (ListOperationsRequest) actualRequests.get(0); - - Assert.assertEquals(name, actualRequest.getName()); - Assert.assertEquals(filter, actualRequest.getFilter()); - } - - @Test - @SuppressWarnings("all") - public void listOperationsExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); - mockOperations.addException(exception); - - try { - String name = "name3373707"; - String filter = "filter-1274492040"; - - client.listOperations(name, filter); - Assert.fail("No exception raised"); - } catch (InvalidArgumentException e) { - // Expected exception - } - } - - @Test - @SuppressWarnings("all") - public void cancelOperationTest() { - Empty expectedResponse = Empty.newBuilder().build(); - mockOperations.addResponse(expectedResponse); - - String name = "name3373707"; - - client.cancelOperation(name); - - List actualRequests = mockOperations.getRequests(); - Assert.assertEquals(1, actualRequests.size()); - CancelOperationRequest actualRequest = (CancelOperationRequest) actualRequests.get(0); - - Assert.assertEquals(name, actualRequest.getName()); - } - - @Test - @SuppressWarnings("all") - public void cancelOperationExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); - mockOperations.addException(exception); - - try { - String name = "name3373707"; - - client.cancelOperation(name); - Assert.fail("No exception raised"); - } catch (InvalidArgumentException e) { - // Expected exception - } - } - - @Test - @SuppressWarnings("all") - public void deleteOperationTest() { - Empty expectedResponse = Empty.newBuilder().build(); - mockOperations.addResponse(expectedResponse); - - String name = "name3373707"; - - client.deleteOperation(name); - - List actualRequests = mockOperations.getRequests(); - Assert.assertEquals(1, actualRequests.size()); - DeleteOperationRequest actualRequest = (DeleteOperationRequest) actualRequests.get(0); - - Assert.assertEquals(name, actualRequest.getName()); - } - - @Test - @SuppressWarnings("all") - public void deleteOperationExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); - mockOperations.addException(exception); - - try { - String name = "name3373707"; - - client.deleteOperation(name); - Assert.fail("No exception raised"); - } catch (InvalidArgumentException e) { - // Expected exception - } - } - - @Test - @SuppressWarnings("all") - public void waitOperationTest() { - String name2 = "name2-1052831874"; - boolean done = true; - Operation expectedResponse = Operation.newBuilder().setName(name2).setDone(done).build(); - mockOperations.addResponse(expectedResponse); - - String name = "name3373707"; - Duration timeout = Duration.newBuilder().setSeconds(5).build(); - WaitOperationRequest request = - WaitOperationRequest.newBuilder().setName(name).setTimeout(timeout).build(); - - Operation actualResponse = client.waitOperation(request); - Assert.assertEquals(expectedResponse, actualResponse); - - List actualRequests = mockOperations.getRequests(); - Assert.assertEquals(1, actualRequests.size()); - WaitOperationRequest actualRequest = (WaitOperationRequest) actualRequests.get(0); - - Assert.assertEquals(name, actualRequest.getName()); - } - - @Test - @SuppressWarnings("all") - public void waitOperationExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(Status.INVALID_ARGUMENT); - mockOperations.addException(exception); - - try { - String name = "name3373707"; - Duration timeout = Duration.newBuilder().setSeconds(5).build(); - WaitOperationRequest request = - WaitOperationRequest.newBuilder().setName(name).setTimeout(timeout).build(); - - client.waitOperation(request); - Assert.fail("No exception raised"); - } catch (InvalidArgumentException e) { - // Expected exception - } - } -} diff --git a/gax-httpjson/BUILD.bazel b/gax-httpjson/BUILD.bazel deleted file mode 100644 index 0ddf20181..000000000 --- a/gax-httpjson/BUILD.bazel +++ /dev/null @@ -1,79 +0,0 @@ -load("//:gax_java.bzl", "google_java_format", "google_java_format_verification", "java_tests") - -_JAVA_COPTS = [ - "-source", - "1.8", - "-target", - "1.8", -] - -_COMPILE_DEPS = [ - "@com_google_code_gson_gson//jar", - "@com_google_guava_guava//jar", - "@com_google_code_findbugs_jsr305//jar", - "@org_threeten_threetenbp//jar", - "@com_google_http_client_google_http_client//jar", - "@com_google_auth_google_auth_library_oauth2_http//jar", - "@com_google_auth_google_auth_library_credentials//jar", - "@com_google_api_api_common//jar", - "@com_google_auto_value_auto_value//jar", - "@com_google_auto_value_auto_value_annotations//jar", - "@javax_annotation_javax_annotation_api//jar", - "@com_google_http_client_google_http_client_gson//jar", - "@com_google_api_grpc_proto_google_common_protos//jar", - "@com_google_protobuf//:protobuf_java", - "@com_google_protobuf_java_util//jar", - "//gax:gax", -] - -_TEST_COMPILE_DEPS = [ - "@junit_junit//jar", - "@org_mockito_mockito_core//jar", - "@com_google_truth_truth//jar", - "//gax:gax_testlib", - "@com_googlecode_java_diff_utils_diffutils//jar", -] - -java_library( - name = "gax_httpjson", - srcs = glob(["src/main/java/**/*.java"]), - javacopts = _JAVA_COPTS, - plugins = ["//:auto_value_plugin"], - resources = ["//:dependencies.properties"], - visibility = ["//visibility:public"], - deps = _COMPILE_DEPS, -) - -java_library( - name = "gax_httpjson_testlib", - srcs = glob(["src/test/java/**/*.java"]), - javacopts = _JAVA_COPTS, - plugins = ["//:auto_value_plugin"], - visibility = ["//visibility:public"], - deps = [":gax_httpjson"] + _COMPILE_DEPS + _TEST_COMPILE_DEPS, -) - -java_tests( - name = "gax_httpjson_tests", - size = "small", - srcs = glob( - include = ["src/test/java/**/*Test.java"], - exclude = [ - "src/test/java/**/Abstract*Test.java", - ], - ), - runtime_deps = [":gax_httpjson_testlib"], -) - -google_java_format( - name = "google_java_format", - srcs = glob(["src/**/*.java"]), - formatter = "//:google_java_format_binary", -) - -#Uncomment once java formatter is upgraded to 1.6+ -#google_java_format_verification( -# name = "google_java_format_verification", -# srcs = glob(["src/**/*.java"]), -# formatter = "//:google_java_format_binary", -#) diff --git a/gax-httpjson/build.gradle b/gax-httpjson/build.gradle deleted file mode 100644 index d16bf0fed..000000000 --- a/gax-httpjson/build.gradle +++ /dev/null @@ -1,43 +0,0 @@ -archivesBaseName = 'gax-httpjson' - -// TODO: Populate this from dependencies.properties version property (for proper Gradle-Bazel sync) -project.version = "0.105.1" // {x-version-update:gax-httpjson:current} - -dependencies { - api(project(':gax'), - libraries['maven.com_google_api_api_common'], - libraries['maven.com_google_api_grpc_proto_google_common_protos'], - libraries['maven.com_google_auth_google_auth_library_credentials'], - libraries['maven.com_google_code_gson_gson'], - libraries['maven.com_google_guava_guava'], - libraries['maven.com_google_http_client_google_http_client'], - libraries['maven.com_google_protobuf'], - libraries['maven.org_threeten_threetenbp']) - - implementation(libraries['maven.com_google_auth_google_auth_library_oauth2_http'], - libraries['maven.com_google_code_findbugs_jsr305'], - libraries['maven.com_google_http_client_google_http_client_gson'], - libraries['maven.com_google_protobuf_java_util']) - - compileOnly libraries['maven.com_google_auto_value_auto_value'] - - testImplementation(project(':gax').sourceSets.test.output, - libraries['maven.junit_junit'], - libraries['maven.org_mockito_mockito_core'], - libraries['maven.com_google_truth_truth']) - - annotationProcessor libraries['maven.com_google_auto_value_auto_value'] - - shadowNoGuava libraries['maven.com_google_guava_guava'] -} - -jar { - manifest { - attributes 'Specification-Title': project.name, - 'Specification-Version': project.version, - 'Specification-Vendor': libraryVendor, - 'Implementation-Title': project.name, - 'Implementation-Version': project.version, - 'Implementation-Vendor': libraryVendor - } -} diff --git a/gax-httpjson/pom.xml b/gax-httpjson/pom.xml deleted file mode 100644 index 32fcdc5f1..000000000 --- a/gax-httpjson/pom.xml +++ /dev/null @@ -1,114 +0,0 @@ - - - 4.0.0 - - gax-httpjson - 0.105.1 - jar - GAX (Google Api eXtensions) for Java (HTTP JSON) - Google Api eXtensions for Java (HTTP JSON) - - - com.google.api - gax-parent - 2.20.1 - - - - - true - - - - - com.google.api - gax - - - com.google.api - api-common - - - com.google.api.grpc - proto-google-common-protos - - - com.google.auth - google-auth-library-credentials - - - com.google.code.gson - gson - - - com.google.guava - guava - - - com.google.http-client - google-http-client - - - com.google.protobuf - protobuf-java - - - org.threeten - threetenbp - - - com.google.auth - google-auth-library-oauth2-http - - - com.google.http-client - google-http-client-gson - - - com.google.protobuf - protobuf-java-util - - - com.google.code.findbugs - jsr305 - provided - - - com.google.auto.value - auto-value-annotations - provided - - - - - com.google.api - gax - test-jar - test - testlib - - - - - - - org.apache.maven.plugins - maven-jar-plugin - - - - test-jar - - - false - testlib - - com/google/api/gax/httpjson/testing/** - - - - - - - - \ No newline at end of file diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ApiMethodDescriptor.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ApiMethodDescriptor.java deleted file mode 100644 index 6952f4885..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ApiMethodDescriptor.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.core.BetaApi; -import com.google.auto.value.AutoValue; -import javax.annotation.Nullable; - -@BetaApi -@AutoValue -/* Method descriptor for messages to be transmitted over HTTP. */ -public abstract class ApiMethodDescriptor { - public enum MethodType { - UNARY, - CLIENT_STREAMING, - SERVER_STREAMING, - BIDI_STREAMING, - UNKNOWN; - } - - public abstract String getFullMethodName(); - - public abstract HttpRequestFormatter getRequestFormatter(); - - public abstract HttpResponseParser getResponseParser(); - - /** Return the HTTP method for this request message type. */ - @Nullable - public abstract String getHttpMethod(); - - @Nullable - public abstract OperationSnapshotFactory getOperationSnapshotFactory(); - - @Nullable - public abstract PollingRequestFactory getPollingRequestFactory(); - - public abstract MethodType getType(); - - public static Builder newBuilder() { - return new AutoValue_ApiMethodDescriptor.Builder() - .setType(MethodType.UNARY); - } - - public abstract Builder toBuilder(); - - @AutoValue.Builder - public abstract static class Builder { - - public abstract Builder setFullMethodName(String fullMethodName); - - public abstract Builder setRequestFormatter( - HttpRequestFormatter requestFormatter); - - public abstract HttpRequestFormatter getRequestFormatter(); - - public abstract Builder setResponseParser( - HttpResponseParser responseParser); - - public abstract Builder setHttpMethod(String httpMethod); - - public abstract Builder setOperationSnapshotFactory( - OperationSnapshotFactory operationSnapshotFactory); - - public abstract Builder setPollingRequestFactory( - PollingRequestFactory pollingRequestFactory); - - public abstract Builder setType(MethodType type); - - public abstract ApiMethodDescriptor build(); - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/FieldsExtractor.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/FieldsExtractor.java deleted file mode 100644 index 024e8d3d1..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/FieldsExtractor.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -/** - * A functional interface to be implemented for each request message to extract specific fields from - * it. For advanced usage only. - */ -public interface FieldsExtractor { - ParamsT extract(RequestT request); -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ForwardingHttpJsonClientCall.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ForwardingHttpJsonClientCall.java deleted file mode 100644 index 8539b2b50..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ForwardingHttpJsonClientCall.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.core.BetaApi; -import javax.annotation.Nullable; - -/** - * A {@link HttpJsonClientCall} which forwards all of its methods to another {@link - * HttpJsonClientCall}. - */ -@BetaApi -public abstract class ForwardingHttpJsonClientCall - extends HttpJsonClientCall { - - protected abstract HttpJsonClientCall delegate(); - - @Override - public void start(Listener responseListener, HttpJsonMetadata requestHeaders) { - delegate().start(responseListener, requestHeaders); - } - - @Override - public void request(int numMessages) { - delegate().request(numMessages); - } - - @Override - public void cancel(@Nullable String message, @Nullable Throwable cause) { - delegate().cancel(message, cause); - } - - @Override - public void halfClose() { - delegate().halfClose(); - } - - @Override - public void sendMessage(RequestT message) { - delegate().sendMessage(message); - } - - /** - * A simplified version of {@link ForwardingHttpJsonClientCall} where subclasses can pass in a - * {@link HttpJsonClientCall} as the delegate. - */ - public abstract static class SimpleForwardingHttpJsonClientCall - extends ForwardingHttpJsonClientCall { - - private final HttpJsonClientCall delegate; - - protected SimpleForwardingHttpJsonClientCall(HttpJsonClientCall delegate) { - this.delegate = delegate; - } - - @Override - protected HttpJsonClientCall delegate() { - return delegate; - } - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ForwardingHttpJsonClientCallListener.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ForwardingHttpJsonClientCallListener.java deleted file mode 100644 index 8c64b957f..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ForwardingHttpJsonClientCallListener.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.gax.httpjson; - -import com.google.api.core.BetaApi; - -/** - * A {@link HttpJsonClientCall.Listener} which forwards all of its methods to another {@link - * HttpJsonClientCall.Listener}. - */ -@BetaApi -public abstract class ForwardingHttpJsonClientCallListener - extends HttpJsonClientCall.Listener { - - protected abstract HttpJsonClientCall.Listener delegate(); - - @Override - public void onHeaders(HttpJsonMetadata responseHeaders) { - delegate().onHeaders(responseHeaders); - } - - @Override - public void onMessage(ResponseT message) { - delegate().onMessage(message); - } - - @Override - public void onClose(int statusCode, HttpJsonMetadata trailers) { - delegate().onClose(statusCode, trailers); - } - - /** - * A simplified version of {@link ForwardingHttpJsonClientCallListener} where subclasses can pass - * in a {@link HttpJsonClientCall.Listener} as the delegate. - */ - public abstract static class SimpleForwardingHttpJsonClientCallListener - extends ForwardingHttpJsonClientCallListener { - - private final HttpJsonClientCall.Listener delegate; - - protected SimpleForwardingHttpJsonClientCallListener( - HttpJsonClientCall.Listener delegate) { - this.delegate = delegate; - } - - @Override - protected HttpJsonClientCall.Listener delegate() { - return delegate; - } - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/GaxHttpJsonProperties.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/GaxHttpJsonProperties.java deleted file mode 100644 index fab63c320..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/GaxHttpJsonProperties.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.core.InternalApi; -import java.util.regex.Pattern; - -/** Provides properties of the GAX-HTTPJSON library. */ -@InternalApi -public class GaxHttpJsonProperties { - private static final Pattern DEFAULT_API_CLIENT_HEADER_PATTERN = - Pattern.compile("gl-java/.+ gapic/.* gax/.+ rest/.*"); - - /** Returns default api client header pattern (to facilitate testing) */ - public static Pattern getDefaultApiClientHeaderPattern() { - return DEFAULT_API_CLIENT_HEADER_PATTERN; - } - - public static String getHttpJsonTokenName() { - return "rest"; - } - - public static String getHttpJsonVersion() { - return ""; - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpHeadersUtils.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpHeadersUtils.java deleted file mode 100644 index 8f1ce432e..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpHeadersUtils.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.client.http.HttpHeaders; -import com.google.api.client.util.ClassInfo; -import com.google.api.client.util.FieldInfo; -import com.google.api.core.InternalApi; -import com.google.common.collect.ImmutableList; -import java.util.List; -import java.util.Map; - -/** This class is for internal use only and is public for technical reasons. */ -@InternalApi -public class HttpHeadersUtils { - public static String getUserAgentValue(Map headersMap) { - for (Map.Entry entry : headersMap.entrySet()) { - if ("user-agent".equalsIgnoreCase(entry.getKey())) { - return entry.getValue(); - } - } - return null; - } - - public static HttpHeaders setHeaders(HttpHeaders headers, Map headersMap) { - for (Map.Entry entry : headersMap.entrySet()) { - setHeader(headers, entry.getKey(), entry.getValue()); - } - return headers; - } - - public static HttpHeaders setHeader(HttpHeaders headers, String key, String value) { - ClassInfo classInfo = headers.getClassInfo(); - FieldInfo fieldInfo = classInfo.getFieldInfo(key); - Object headerValue; - if (fieldInfo == null) { - headerValue = value; - } else { - Class elementyType = fieldInfo.getType(); - if (List.class.isAssignableFrom(fieldInfo.getType())) { - elementyType = - "Age".equalsIgnoreCase(key) || "Content-Length".equalsIgnoreCase(key) - ? Long.class - : String.class; - } - headerValue = ImmutableList.of(fromString(elementyType, value)); - } - headers.set(key, headerValue); - return headers; - } - - private static Object fromString(Class clazz, String stringValue) { - if (String.class == clazz) { - return stringValue; - } else if (Long.class == clazz) { - return Long.valueOf(stringValue); - } - - // It seems only String and Long have chances of being used. Not adding other - // classes to avoid having dead code, even though without them this looks incomplete. - throw new IllegalArgumentException( - "Instantiating " - + clazz - + " from string representation is not supported. Most likely an" - + " incompatible version of google-http-client was used."); - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonApiExceptionFactory.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonApiExceptionFactory.java deleted file mode 100644 index a48f0b5a2..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonApiExceptionFactory.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.client.http.HttpResponseException; -import com.google.api.gax.rpc.ApiException; -import com.google.api.gax.rpc.ApiExceptionFactory; -import com.google.api.gax.rpc.StatusCode; -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.common.collect.ImmutableSet; -import java.util.Set; -import java.util.concurrent.CancellationException; - -class HttpJsonApiExceptionFactory { - private final Set retryableCodes; - - HttpJsonApiExceptionFactory(Set retryableCodes) { - this.retryableCodes = ImmutableSet.copyOf(retryableCodes); - } - - ApiException create(Throwable throwable) { - if (throwable instanceof HttpResponseException) { - HttpResponseException e = (HttpResponseException) throwable; - StatusCode statusCode = HttpJsonStatusCode.of(e.getStatusCode()); - boolean canRetry = retryableCodes.contains(statusCode.getCode()); - String message = e.getStatusMessage(); - return createApiException(throwable, statusCode, message, canRetry); - } else if (throwable instanceof HttpJsonStatusRuntimeException) { - HttpJsonStatusRuntimeException e = (HttpJsonStatusRuntimeException) throwable; - StatusCode statusCode = HttpJsonStatusCode.of(e.getStatusCode()); - return createApiException( - throwable, statusCode, e.getMessage(), retryableCodes.contains(statusCode.getCode())); - } else if (throwable instanceof CancellationException) { - return ApiExceptionFactory.createException( - throwable, HttpJsonStatusCode.of(Code.CANCELLED), false); - } else if (throwable instanceof ApiException) { - return (ApiException) throwable; - } else { - // Do not retry on unknown throwable, even when UNKNOWN is in retryableCodes - return ApiExceptionFactory.createException( - throwable, HttpJsonStatusCode.of(StatusCode.Code.UNKNOWN), false); - } - } - - private ApiException createApiException( - Throwable throwable, StatusCode statusCode, String message, boolean canRetry) { - return message == null - ? ApiExceptionFactory.createException(throwable, statusCode, canRetry) - : ApiExceptionFactory.createException(message, throwable, statusCode, canRetry); - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonCallContext.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonCallContext.java deleted file mode 100644 index 469435d60..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonCallContext.java +++ /dev/null @@ -1,530 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.core.BetaApi; -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.StatusCode; -import com.google.api.gax.rpc.TransportChannel; -import com.google.api.gax.rpc.internal.ApiCallContextOptions; -import com.google.api.gax.rpc.internal.Headers; -import com.google.api.gax.tracing.ApiTracer; -import com.google.api.gax.tracing.BaseApiTracer; -import com.google.auth.Credentials; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import org.threeten.bp.Duration; -import org.threeten.bp.Instant; - -/** - * HttpJsonCallContext encapsulates context data used to make an http-json call. - * - *

HttpJsonCallContext is immutable in the sense that none of its methods modifies the - * HttpJsonCallContext itself or the underlying data. Methods of the form {@code withX} return - * copies of the object, but with one field changed. The immutability and thread safety of the - * arguments solely depends on the arguments themselves. - */ -@BetaApi("Reference ApiCallContext instead - this class is likely to experience breaking changes") -public final class HttpJsonCallContext implements ApiCallContext { - private final HttpJsonChannel channel; - private final HttpJsonCallOptions callOptions; - @Nullable private final Duration timeout; - @Nullable private final Duration streamWaitTimeout; - @Nullable private final Duration streamIdleTimeout; - private final ImmutableMap> extraHeaders; - private final ApiCallContextOptions options; - private final ApiTracer tracer; - @Nullable private final RetrySettings retrySettings; - @Nullable private final ImmutableSet retryableCodes; - - /** Returns an empty instance. */ - public static HttpJsonCallContext createDefault() { - return new HttpJsonCallContext( - null, - HttpJsonCallOptions.newBuilder().build(), - null, - null, - null, - ImmutableMap.of(), - ApiCallContextOptions.getDefaultOptions(), - null, - null, - null); - } - - public static HttpJsonCallContext of(HttpJsonChannel channel, HttpJsonCallOptions options) { - return new HttpJsonCallContext( - channel, - options, - null, - null, - null, - ImmutableMap.of(), - ApiCallContextOptions.getDefaultOptions(), - null, - null, - null); - } - - private HttpJsonCallContext( - HttpJsonChannel channel, - HttpJsonCallOptions callOptions, - Duration timeout, - Duration streamWaitTimeout, - Duration streamIdleTimeout, - ImmutableMap> extraHeaders, - ApiCallContextOptions options, - ApiTracer tracer, - RetrySettings defaultRetrySettings, - Set defaultRetryableCodes) { - this.channel = channel; - this.callOptions = callOptions; - this.timeout = timeout; - this.streamWaitTimeout = streamWaitTimeout; - this.streamIdleTimeout = streamIdleTimeout; - this.extraHeaders = extraHeaders; - this.options = options; - this.tracer = tracer; - this.retrySettings = defaultRetrySettings; - this.retryableCodes = - defaultRetryableCodes == null ? null : ImmutableSet.copyOf(defaultRetryableCodes); - } - - /** - * Returns inputContext cast to {@link HttpJsonCallContext}, or an empty {@link - * HttpJsonCallContext} if inputContext is null. - * - * @param inputContext the {@link ApiCallContext} to cast if it is not null - */ - @Override - public HttpJsonCallContext nullToSelf(ApiCallContext inputContext) { - HttpJsonCallContext httpJsonCallContext; - if (inputContext == null) { - httpJsonCallContext = this; - } else { - if (!(inputContext instanceof HttpJsonCallContext)) { - throw new IllegalArgumentException( - "context must be an instance of HttpJsonCallContext, but found " - + inputContext.getClass().getName()); - } - httpJsonCallContext = (HttpJsonCallContext) inputContext; - } - return httpJsonCallContext; - } - - @Override - public HttpJsonCallContext merge(ApiCallContext inputCallContext) { - if (inputCallContext == null) { - return this; - } - if (!(inputCallContext instanceof HttpJsonCallContext)) { - throw new IllegalArgumentException( - "context must be an instance of HttpJsonCallContext, but found " - + inputCallContext.getClass().getName()); - } - HttpJsonCallContext httpJsonCallContext = (HttpJsonCallContext) inputCallContext; - - HttpJsonChannel newChannel = httpJsonCallContext.channel; - if (newChannel == null) { - newChannel = this.channel; - } - - // Do deep merge of callOptions - HttpJsonCallOptions newCallOptions = callOptions.merge(httpJsonCallContext.callOptions); - - Duration newTimeout = httpJsonCallContext.timeout; - if (newTimeout == null) { - newTimeout = this.timeout; - } - - Duration newStreamWaitTimeout = httpJsonCallContext.streamWaitTimeout; - if (newStreamWaitTimeout == null) { - newStreamWaitTimeout = streamWaitTimeout; - } - - Duration newStreamIdleTimeout = httpJsonCallContext.streamIdleTimeout; - if (newStreamIdleTimeout == null) { - newStreamIdleTimeout = streamIdleTimeout; - } - - ImmutableMap> newExtraHeaders = - Headers.mergeHeaders(extraHeaders, httpJsonCallContext.extraHeaders); - - ApiCallContextOptions newOptions = options.merge(httpJsonCallContext.options); - - ApiTracer newTracer = httpJsonCallContext.tracer; - if (newTracer == null) { - newTracer = this.tracer; - } - - RetrySettings newRetrySettings = httpJsonCallContext.retrySettings; - if (newRetrySettings == null) { - newRetrySettings = this.retrySettings; - } - - Set newRetryableCodes = httpJsonCallContext.retryableCodes; - if (newRetryableCodes == null) { - newRetryableCodes = this.retryableCodes; - } - - return new HttpJsonCallContext( - newChannel, - newCallOptions, - newTimeout, - newStreamWaitTimeout, - newStreamIdleTimeout, - newExtraHeaders, - newOptions, - newTracer, - newRetrySettings, - newRetryableCodes); - } - - @Override - public HttpJsonCallContext withCredentials(Credentials newCredentials) { - HttpJsonCallOptions.Builder builder = - callOptions != null ? callOptions.toBuilder() : HttpJsonCallOptions.newBuilder(); - return withCallOptions(builder.setCredentials(newCredentials).build()); - } - - @Override - public HttpJsonCallContext withTransportChannel(TransportChannel inputChannel) { - Preconditions.checkNotNull(inputChannel); - if (!(inputChannel instanceof HttpJsonTransportChannel)) { - throw new IllegalArgumentException( - "Expected HttpJsonTransportChannel, got " + inputChannel.getClass().getName()); - } - HttpJsonTransportChannel transportChannel = (HttpJsonTransportChannel) inputChannel; - return withChannel(transportChannel.getChannel()); - } - - @Override - public HttpJsonCallContext withTimeout(Duration timeout) { - // Default RetrySettings use 0 for RPC timeout. Treat that as disabled timeouts. - if (timeout != null && (timeout.isZero() || timeout.isNegative())) { - timeout = null; - } - - // Prevent expanding deadlines - if (timeout != null && this.timeout != null && this.timeout.compareTo(timeout) <= 0) { - return this; - } - - return new HttpJsonCallContext( - this.channel, - this.callOptions, - timeout, - this.streamWaitTimeout, - this.streamIdleTimeout, - this.extraHeaders, - this.options, - this.tracer, - this.retrySettings, - this.retryableCodes); - } - - @Nullable - @Override - public Duration getTimeout() { - return timeout; - } - - @Override - public HttpJsonCallContext withStreamWaitTimeout(@Nullable Duration streamWaitTimeout) { - if (streamWaitTimeout != null) { - Preconditions.checkArgument( - streamWaitTimeout.compareTo(Duration.ZERO) >= 0, "Invalid timeout: < 0 s"); - } - - return new HttpJsonCallContext( - this.channel, - this.callOptions, - this.timeout, - streamWaitTimeout, - this.streamIdleTimeout, - this.extraHeaders, - this.options, - this.tracer, - this.retrySettings, - this.retryableCodes); - } - - /** - * The stream wait timeout set for this context. - * - * @see ApiCallContext#withStreamWaitTimeout(Duration) - */ - @Override - @Nullable - public Duration getStreamWaitTimeout() { - return streamWaitTimeout; - } - - @Override - public HttpJsonCallContext withStreamIdleTimeout(@Nullable Duration streamIdleTimeout) { - if (streamIdleTimeout != null) { - Preconditions.checkArgument( - streamIdleTimeout.compareTo(Duration.ZERO) >= 0, "Invalid timeout: < 0 s"); - } - - return new HttpJsonCallContext( - this.channel, - this.callOptions, - this.timeout, - this.streamWaitTimeout, - streamIdleTimeout, - this.extraHeaders, - this.options, - this.tracer, - this.retrySettings, - this.retryableCodes); - } - - /** - * The stream idle timeout set for this context. - * - * @see ApiCallContext#withStreamIdleTimeout(Duration) - */ - @Override - @Nullable - public Duration getStreamIdleTimeout() { - return streamIdleTimeout; - } - - @BetaApi("The surface for extra headers is not stable yet and may change in the future.") - @Override - public ApiCallContext withExtraHeaders(Map> extraHeaders) { - Preconditions.checkNotNull(extraHeaders); - ImmutableMap> newExtraHeaders = - Headers.mergeHeaders(this.extraHeaders, extraHeaders); - return new HttpJsonCallContext( - this.channel, - this.callOptions, - this.timeout, - this.streamWaitTimeout, - this.streamIdleTimeout, - newExtraHeaders, - this.options, - this.tracer, - this.retrySettings, - this.retryableCodes); - } - - @BetaApi("The surface for extra headers is not stable yet and may change in the future.") - @Override - public Map> getExtraHeaders() { - return extraHeaders; - } - - /** {@inheritDoc} */ - @Override - public ApiCallContext withOption(Key key, T value) { - ApiCallContextOptions newOptions = options.withOption(key, value); - return new HttpJsonCallContext( - this.channel, - this.callOptions, - this.timeout, - this.streamWaitTimeout, - this.streamIdleTimeout, - this.extraHeaders, - newOptions, - this.tracer, - this.retrySettings, - this.retryableCodes); - } - - /** {@inheritDoc} */ - @Override - public T getOption(Key key) { - return options.getOption(key); - } - - public HttpJsonChannel getChannel() { - return channel; - } - - public HttpJsonCallOptions getCallOptions() { - return callOptions; - } - - @Deprecated - @Nullable - public Instant getDeadline() { - return getCallOptions() != null ? getCallOptions().getDeadline() : null; - } - - @Deprecated - @Nullable - public Credentials getCredentials() { - return getCallOptions() != null ? getCallOptions().getCredentials() : null; - } - - @Override - public RetrySettings getRetrySettings() { - return retrySettings; - } - - @Override - public HttpJsonCallContext withRetrySettings(RetrySettings retrySettings) { - return new HttpJsonCallContext( - this.channel, - this.callOptions, - this.timeout, - this.streamWaitTimeout, - this.streamIdleTimeout, - this.extraHeaders, - this.options, - this.tracer, - retrySettings, - this.retryableCodes); - } - - @Override - public Set getRetryableCodes() { - return retryableCodes; - } - - @Override - public HttpJsonCallContext withRetryableCodes(Set retryableCodes) { - return new HttpJsonCallContext( - this.channel, - this.callOptions, - this.timeout, - this.streamWaitTimeout, - this.streamIdleTimeout, - this.extraHeaders, - this.options, - this.tracer, - this.retrySettings, - retryableCodes); - } - - public HttpJsonCallContext withChannel(HttpJsonChannel newChannel) { - return new HttpJsonCallContext( - newChannel, - this.callOptions, - this.timeout, - this.streamWaitTimeout, - this.streamIdleTimeout, - this.extraHeaders, - this.options, - this.tracer, - this.retrySettings, - this.retryableCodes); - } - - public HttpJsonCallContext withCallOptions(HttpJsonCallOptions newCallOptions) { - return new HttpJsonCallContext( - this.channel, - newCallOptions, - this.timeout, - this.streamWaitTimeout, - this.streamIdleTimeout, - this.extraHeaders, - this.options, - this.tracer, - this.retrySettings, - this.retryableCodes); - } - - @Deprecated - public HttpJsonCallContext withDeadline(Instant newDeadline) { - HttpJsonCallOptions.Builder builder = - callOptions != null ? callOptions.toBuilder() : HttpJsonCallOptions.newBuilder(); - return withCallOptions(builder.setDeadline(newDeadline).build()); - } - - @Nonnull - @Override - public ApiTracer getTracer() { - if (tracer == null) { - return BaseApiTracer.getInstance(); - } - return tracer; - } - - /** {@inheritDoc} */ - @Override - public HttpJsonCallContext withTracer(@Nonnull ApiTracer newTracer) { - Preconditions.checkNotNull(newTracer); - - return new HttpJsonCallContext( - this.channel, - this.callOptions, - this.timeout, - this.streamWaitTimeout, - this.streamIdleTimeout, - this.extraHeaders, - this.options, - newTracer, - this.retrySettings, - this.retryableCodes); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - HttpJsonCallContext that = (HttpJsonCallContext) o; - return Objects.equals(this.channel, that.channel) - && Objects.equals(this.callOptions, that.callOptions) - && Objects.equals(this.timeout, that.timeout) - && Objects.equals(this.extraHeaders, that.extraHeaders) - && Objects.equals(this.options, that.options) - && Objects.equals(this.tracer, that.tracer) - && Objects.equals(this.retrySettings, that.retrySettings) - && Objects.equals(this.retryableCodes, that.retryableCodes); - } - - @Override - public int hashCode() { - return Objects.hash( - channel, - callOptions, - timeout, - extraHeaders, - options, - tracer, - retrySettings, - retryableCodes); - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonCallOptions.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonCallOptions.java deleted file mode 100644 index dbb3cb625..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonCallOptions.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.core.BetaApi; -import com.google.auth.Credentials; -import com.google.auto.value.AutoValue; -import com.google.protobuf.TypeRegistry; -import javax.annotation.Nullable; -import org.threeten.bp.Instant; - -/** Options for an http-json call, including deadline and credentials. */ -@BetaApi -@AutoValue -public abstract class HttpJsonCallOptions { - public static final HttpJsonCallOptions DEFAULT = newBuilder().build(); - - @Nullable - public abstract Instant getDeadline(); - - @Nullable - public abstract Credentials getCredentials(); - - @Nullable - public abstract TypeRegistry getTypeRegistry(); - - public abstract Builder toBuilder(); - - public static Builder newBuilder() { - return new AutoValue_HttpJsonCallOptions.Builder(); - } - - public HttpJsonCallOptions merge(HttpJsonCallOptions inputOptions) { - if (inputOptions == null) { - return this; - } - - Builder builder = this.toBuilder(); - - Instant newDeadline = inputOptions.getDeadline(); - if (newDeadline != null) { - builder.setDeadline(newDeadline); - } - - Credentials newCredentials = inputOptions.getCredentials(); - if (newCredentials != null) { - builder.setCredentials(newCredentials); - } - - TypeRegistry newTypeRegistry = inputOptions.getTypeRegistry(); - if (newTypeRegistry != null) { - builder.setTypeRegistry(newTypeRegistry); - } - - return builder.build(); - } - - @AutoValue.Builder - public abstract static class Builder { - public abstract Builder setDeadline(Instant value); - - public abstract Builder setCredentials(Credentials value); - - public abstract Builder setTypeRegistry(TypeRegistry value); - - public abstract HttpJsonCallOptions build(); - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonCallSettings.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonCallSettings.java deleted file mode 100644 index ac013ed74..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonCallSettings.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.protobuf.TypeRegistry; - -/** HTTP-specific settings for creating callables. */ -public class HttpJsonCallSettings { - private final ApiMethodDescriptor methodDescriptor; - private final TypeRegistry typeRegistry; - - private HttpJsonCallSettings( - ApiMethodDescriptor methodDescriptor, TypeRegistry typeRegistry) { - this.methodDescriptor = methodDescriptor; - this.typeRegistry = typeRegistry; - } - - public ApiMethodDescriptor getMethodDescriptor() { - return methodDescriptor; - } - - public TypeRegistry getTypeRegistry() { - return typeRegistry; - } - - public static Builder newBuilder() { - return new Builder<>(); - } - - public static HttpJsonCallSettings create( - ApiMethodDescriptor methodDescriptor) { - return HttpJsonCallSettings.newBuilder() - .setMethodDescriptor(methodDescriptor) - .build(); - } - - public Builder toBuilder() { - return new Builder<>(this); - } - - public static class Builder { - private ApiMethodDescriptor methodDescriptor; - private TypeRegistry typeRegistry; - - private Builder() {} - - private Builder(HttpJsonCallSettings settings) { - this.methodDescriptor = settings.methodDescriptor; - } - - public Builder setMethodDescriptor( - ApiMethodDescriptor methodDescriptor) { - this.methodDescriptor = methodDescriptor; - return this; - } - - public Builder setTypeRegistry(TypeRegistry typeRegistry) { - this.typeRegistry = typeRegistry; - return this; - } - - public HttpJsonCallSettings build() { - return new HttpJsonCallSettings<>(methodDescriptor, typeRegistry); - } - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonCallableFactory.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonCallableFactory.java deleted file mode 100644 index 6131c911f..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonCallableFactory.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.core.InternalApi; -import com.google.api.gax.longrunning.OperationSnapshot; -import com.google.api.gax.rpc.BatchingCallSettings; -import com.google.api.gax.rpc.Callables; -import com.google.api.gax.rpc.ClientContext; -import com.google.api.gax.rpc.LongRunningClient; -import com.google.api.gax.rpc.OperationCallSettings; -import com.google.api.gax.rpc.OperationCallable; -import com.google.api.gax.rpc.PagedCallSettings; -import com.google.api.gax.rpc.ServerStreamingCallSettings; -import com.google.api.gax.rpc.ServerStreamingCallable; -import com.google.api.gax.rpc.UnaryCallSettings; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.api.gax.tracing.SpanName; -import com.google.api.gax.tracing.TracedUnaryCallable; -import com.google.common.base.Preconditions; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import javax.annotation.Nonnull; - -/** Class with utility methods to create http/json-based direct callables. */ -public class HttpJsonCallableFactory { - // Used to extract service and method name from a grpc MethodDescriptor. - // fullMethodName has the format: service.resource.action - // For example: compute.instances.addAccessConfig - private static final Pattern FULL_METHOD_NAME_REGEX = Pattern.compile("^(.+)\\.(.+)$"); - - private HttpJsonCallableFactory() {} - - private static UnaryCallable createDirectUnaryCallable( - HttpJsonCallSettings httpJsonCallSettings) { - return new HttpJsonDirectCallable( - httpJsonCallSettings.getMethodDescriptor(), httpJsonCallSettings.getTypeRegistry()); - } - - static UnaryCallable createUnaryCallable( - UnaryCallable innerCallable, - UnaryCallSettings callSettings, - ClientContext clientContext) { - UnaryCallable callable = - new HttpJsonExceptionCallable<>(innerCallable, callSettings.getRetryableCodes()); - callable = Callables.retrying(callable, callSettings, clientContext); - return callable.withDefaultCallContext(clientContext.getDefaultCallContext()); - } - - /** - * Create a Unary callable object with minimal http/json-specific functionality. Designed for use - * by generated code. - * - * @param httpJsonCallSettings the gRPC call settings - * @param callSettings the unary call settings - * @param clientContext {@link ClientContext} to use to connect to the service. - */ - public static UnaryCallable createBaseUnaryCallable( - HttpJsonCallSettings httpJsonCallSettings, - UnaryCallSettings callSettings, - ClientContext clientContext) { - UnaryCallable callable = createDirectUnaryCallable(httpJsonCallSettings); - callable = new HttpJsonExceptionCallable<>(callable, callSettings.getRetryableCodes()); - callable = Callables.retrying(callable, callSettings, clientContext); - - return callable; - } - - /** - * Create a callable object with http/json-specific functionality. Designed for use by generated - * code. - * - * @param httpJsonCallSettings the http/json call settings - * @param callSettings {@link UnaryCallSettings} to configure the method-level settings with. - * @param clientContext {@link ClientContext} to use to connect to the service. - * @return {@link UnaryCallable} callable object. - */ - public static UnaryCallable createUnaryCallable( - HttpJsonCallSettings httpJsonCallSettings, - UnaryCallSettings callSettings, - ClientContext clientContext) { - UnaryCallable innerCallable = - createDirectUnaryCallable(httpJsonCallSettings); - - innerCallable = - new TracedUnaryCallable<>( - innerCallable, - clientContext.getTracerFactory(), - getSpanName(httpJsonCallSettings.getMethodDescriptor())); - - return createUnaryCallable(innerCallable, callSettings, clientContext); - } - - /** - * Create a paged callable object that represents a paged API method. Designed for use by - * generated code. - * - * @param httpJsonCallSettings the http/json call settings - * @param pagedCallSettings {@link PagedCallSettings} to configure the paged settings with. - * @param clientContext {@link ClientContext} to use to connect to the service. - * @return {@link UnaryCallable} callable object. - */ - public static - UnaryCallable createPagedCallable( - HttpJsonCallSettings httpJsonCallSettings, - PagedCallSettings pagedCallSettings, - ClientContext clientContext) { - UnaryCallable callable = createDirectUnaryCallable(httpJsonCallSettings); - callable = createUnaryCallable(callable, pagedCallSettings, clientContext); - UnaryCallable pagedCallable = - Callables.paged(callable, pagedCallSettings); - return pagedCallable.withDefaultCallContext(clientContext.getDefaultCallContext()); - } - - /** - * Create a callable object that represents a batching API method. Designed for use by generated - * code. - * - * @param httpJsonCallSettings the http/json call settings - * @param batchingCallSettings {@link BatchingCallSettings} to configure the batching related - * settings with. - * @param clientContext {@link ClientContext} to use to connect to the service. - * @return {@link UnaryCallable} callable object. - */ - public static UnaryCallable createBatchingCallable( - HttpJsonCallSettings httpJsonCallSettings, - BatchingCallSettings batchingCallSettings, - ClientContext clientContext) { - UnaryCallable callable = createDirectUnaryCallable(httpJsonCallSettings); - callable = createUnaryCallable(callable, batchingCallSettings, clientContext); - callable = Callables.batching(callable, batchingCallSettings, clientContext); - return callable.withDefaultCallContext(clientContext.getDefaultCallContext()); - } - - public static - OperationCallable createOperationCallable( - OperationCallSettings operationCallSettings, - ClientContext clientContext, - LongRunningClient longRunningClient, - UnaryCallable operationSnapshotCallable) { - OperationCallable operationCallable = - Callables.longRunningOperation( - operationSnapshotCallable, operationCallSettings, clientContext, longRunningClient); - return operationCallable.withDefaultCallContext(clientContext.getDefaultCallContext()); - } - - public static - ServerStreamingCallable createServerStreamingCallable( - HttpJsonCallSettings httpJsoncallSettings, - ServerStreamingCallSettings streamingCallSettings, - ClientContext clientContext) { - - ServerStreamingCallable callable = - new HttpJsonDirectServerStreamingCallable<>(httpJsoncallSettings.getMethodDescriptor()); - - callable = - new HttpJsonExceptionServerStreamingCallable<>( - callable, streamingCallSettings.getRetryableCodes()); - - if (clientContext.getStreamWatchdog() != null) { - callable = Callables.watched(callable, streamingCallSettings, clientContext); - } - - callable = Callables.retrying(callable, streamingCallSettings, clientContext); - return callable.withDefaultCallContext(clientContext.getDefaultCallContext()); - } - - @InternalApi("Visible for testing") - static SpanName getSpanName(@Nonnull ApiMethodDescriptor methodDescriptor) { - Matcher matcher = FULL_METHOD_NAME_REGEX.matcher(methodDescriptor.getFullMethodName()); - - Preconditions.checkArgument(matcher.matches(), "Invalid fullMethodName"); - return SpanName.of(matcher.group(1), matcher.group(2)); - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonChannel.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonChannel.java deleted file mode 100644 index 96db96b46..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonChannel.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.core.BetaApi; - -/** HttpJsonChannel contains the functionality to issue http-json calls. */ -@BetaApi -public interface HttpJsonChannel { - HttpJsonClientCall newCall( - ApiMethodDescriptor methodDescriptor, HttpJsonCallOptions callOptions); -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonClientCall.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonClientCall.java deleted file mode 100644 index 16ecd6795..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonClientCall.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.core.BetaApi; -import javax.annotation.Nullable; - -// This class mimics the structure and behavior of the corresponding ClientCall from gRPC package as -// closely as possible. -/** - * An instance of a call to a remote method. A call will send zero or more request messages to the - * server and receive zero or more response messages back. - * - *

Instances are created by a {@link HttpJsonChannel} and used by stubs to invoke their remote - * behavior. - * - *

{@link #start} must be called prior to calling any other methods, with the exception of {@link - * #cancel}. Whereas {@link #cancel} must not be followed by any other methods, but can be called - * more than once, while only the first one has effect. - * - *

Methods are potentially blocking but are designed to execute quickly. The implementations of - * this class are expected to be thread-safe. - * - *

There is a race between {@link #cancel} and the completion/failure of the RPC in other ways. - * If {@link #cancel} won the race, {@link HttpJsonClientCall.Listener#onClose Listener.onClose()} - * is called with {@code statusCode} corresponding to {@link - * com.google.api.gax.rpc.StatusCode.Code#CANCELLED CANCELLED}. Otherwise, {@link - * HttpJsonClientCall.Listener#onClose Listener.onClose()} is called with whatever status the RPC - * was finished. We ensure that at most one is called. - * - * @param type of message sent to the server - * @param type of message received one or more times from the server - */ -@BetaApi -public abstract class HttpJsonClientCall { - /** - * Callbacks for receiving metadata, response messages and completion status from the server. - * - *

Implementations are discouraged to block for extended periods of time. Implementations are - * not required to be thread-safe, but they must not be thread-hostile. The caller is free to call - * an instance from multiple threads, but only one call simultaneously. - */ - @BetaApi - public abstract static class Listener { - /** - * The response headers have been received. Headers always precede messages. - * - * @param responseHeaders containing metadata sent by the server at the start of the response - */ - public void onHeaders(HttpJsonMetadata responseHeaders) {} - - /** - * A response message has been received. May be called zero or more times depending on whether - * the call response is empty, a single message or a stream of messages. - * - * @param message returned by the server - */ - public void onMessage(T message) {} - - /** - * The ClientCall has been closed. Any additional calls to the {@code ClientCall} will not be - * processed by the server. No further receiving will occur and no further notifications will be - * made. - * - *

This method should not throw. If this method throws, there is no way to be notified of the - * exception. Implementations should therefore be careful of exceptions which can accidentally - * leak resources. - * - * @param statusCode the HTTP status code representing the result of the remote call - * @param trailers metadata provided at call completion - */ - public void onClose(int statusCode, HttpJsonMetadata trailers) {} - } - - /** - * Start a call, using {@code responseListener} for processing response messages. - * - *

It must be called prior to any other method on this class, except for {@link #cancel} which - * may be called at any time. - * - * @param responseListener receives response messages - * @param requestHeaders which can contain extra call metadata, e.g. authentication credentials. - */ - public abstract void start(Listener responseListener, HttpJsonMetadata requestHeaders); - - /** - * Requests up to the given number of messages from the call to be delivered to {@link - * HttpJsonClientCall.Listener#onMessage(Object)}. No additional messages will be delivered. - * - *

Message delivery is guaranteed to be sequential in the order received. In addition, the - * listener methods will not be accessed concurrently. While it is not guaranteed that the same - * thread will always be used, it is guaranteed that only a single thread will access the listener - * at a time. - * - *

If called multiple times, the number of messages able to delivered will be the sum of the - * calls. - * - *

This method is safe to call from multiple threads without external synchronization. - * - * @param numMessages the requested number of messages to be delivered to the listener. Must be - * non-negative. - */ - public abstract void request(int numMessages); - - /** - * Prevent any further processing for this {@code HttpJsonClientCall}. No further messages may be - * sent or will be received. The server is not informed of cancellations. Cancellation is - * permitted even if previously {@link #halfClose}d. Cancelling an already {@code cancel()}ed - * {@code ClientCall} has no effect. - * - *

No other methods on this class can be called after this method has been called. - * - * @param message if not {@code null}, will appear as the description of the CANCELLED status - * @param cause if not {@code null}, will appear as the cause of the CANCELLED status - */ - public abstract void cancel(@Nullable String message, @Nullable Throwable cause); - - /** - * Close the call for request message sending. Incoming response messages are unaffected. This - * should be called when no more messages will be sent from the client. - */ - public abstract void halfClose(); - - /** - * Send a request message to the server. May be called zero or more times but for unary and server - * streaming calls it must be called not more than once. - * - * @param message message to be sent to the server. - */ - public abstract void sendMessage(RequestT message); -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonClientCallImpl.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonClientCallImpl.java deleted file mode 100644 index 9f52712b2..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonClientCallImpl.java +++ /dev/null @@ -1,493 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.client.http.HttpTransport; -import com.google.api.gax.httpjson.ApiMethodDescriptor.MethodType; -import com.google.api.gax.httpjson.HttpRequestRunnable.ResultListener; -import com.google.api.gax.httpjson.HttpRequestRunnable.RunnableResult; -import com.google.common.base.Preconditions; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Reader; -import java.nio.charset.StandardCharsets; -import java.util.ArrayDeque; -import java.util.Queue; -import java.util.concurrent.CancellationException; -import java.util.concurrent.Executor; -import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; - -/** - * This class serves as main implementation of {@link HttpJsonClientCall} for REST transport and is - * expected to be used for every REST call. It currently supports unary and server-streaming - * workflows. The overall behavior and surface of the class mimics as close as possible behavior of - * the corresponding ClientCall implementation in gRPC transport. - * - *

This class is thread-safe. - * - * @param call request type - * @param call response type - */ -final class HttpJsonClientCallImpl - extends HttpJsonClientCall implements ResultListener { - // - // A lock to guard the state of this call (and the response stream). - // - private final Object lock = new Object(); - - // An active delivery loop marker. - @GuardedBy("lock") - private boolean inDelivery = false; - - // A queue to keep "scheduled" calls to HttpJsonClientCall.Listener in a form of tasks. - // It may seem like an overkill, but it exists to implement the following listeners contract: - // - onHeaders() must be called before any onMessage(); - // - onClose() must be the last call made, no onMessage() or onHeaders() are allowed after that; - // - while methods on the same listener may be called from different threads they must never be - // called simultaneously; - // - listeners should not be called under the internal lock of the client call to reduce risk of - // deadlocking and minimize time spent under lock; - // - a specialized notifications' dispatcher thread may be used in the future to send - // notifications (not the case right now). - @GuardedBy("lock") - private final Queue> pendingNotifications = new ArrayDeque<>(); - - // - // Immutable API method-specific data. - // - private final HttpJsonCallOptions callOptions; - private final String endpoint; - private final ApiMethodDescriptor methodDescriptor; - private final HttpTransport httpTransport; - private final Executor executor; - - // - // Request-specific data (provided by client code) before we get a response. - // - @GuardedBy("lock") - private HttpJsonMetadata requestHeaders; - - @GuardedBy("lock") - private Listener listener; - - @GuardedBy("lock") - private int pendingNumMessages; - - // - // Response-specific data (received from server). - // - @GuardedBy("lock") - private HttpRequestRunnable requestRunnable; - - @GuardedBy("lock") - private RunnableResult runnableResult; - - @GuardedBy("lock") - private ProtoMessageJsonStreamIterator responseStreamIterator; - - @GuardedBy("lock") - private boolean closed; - - HttpJsonClientCallImpl( - ApiMethodDescriptor methodDescriptor, - String endpoint, - HttpJsonCallOptions callOptions, - HttpTransport httpTransport, - Executor executor) { - this.methodDescriptor = methodDescriptor; - this.endpoint = endpoint; - this.callOptions = callOptions; - this.httpTransport = httpTransport; - this.executor = executor; - this.closed = false; - } - - @Override - public void setResult(RunnableResult runnableResult) { - Preconditions.checkNotNull(runnableResult); - synchronized (lock) { - if (closed) { - return; - } - Preconditions.checkState(this.runnableResult == null, "The call result is already set"); - this.runnableResult = runnableResult; - if (runnableResult.getResponseHeaders() != null) { - pendingNotifications.offer( - new OnHeadersNotificationTask<>(listener, runnableResult.getResponseHeaders())); - } - } - - // trigger delivery loop if not already running - deliver(); - } - - @Override - public void start(Listener responseListener, HttpJsonMetadata requestHeaders) { - Preconditions.checkNotNull(responseListener); - Preconditions.checkNotNull(requestHeaders); - synchronized (lock) { - if (closed) { - return; - } - Preconditions.checkState(this.listener == null, "The call is already started"); - this.listener = responseListener; - this.requestHeaders = requestHeaders; - } - } - - @Override - public void request(int numMessages) { - if (numMessages < 0) { - throw new IllegalArgumentException("numMessages must be non-negative"); - } - synchronized (lock) { - if (closed) { - return; - } - pendingNumMessages += numMessages; - } - - // trigger delivery loop if not already running - deliver(); - } - - @Override - public void cancel(@Nullable String message, @Nullable Throwable cause) { - Throwable actualCause = cause; - if (actualCause == null) { - actualCause = new CancellationException(message); - } - - synchronized (lock) { - close(499, message, actualCause, true); - } - - // trigger delivery loop if not already running - deliver(); - } - - @Override - public void sendMessage(RequestT message) { - Preconditions.checkNotNull(message); - HttpRequestRunnable localRunnable; - synchronized (lock) { - if (closed) { - return; - } - Preconditions.checkState(listener != null, "The call hasn't been started"); - Preconditions.checkState( - requestRunnable == null, - "The message has already been sent. Bidirectional streaming calls are not supported"); - - requestRunnable = - new HttpRequestRunnable<>( - message, - methodDescriptor, - endpoint, - callOptions, - httpTransport, - requestHeaders, - this); - localRunnable = requestRunnable; - } - executor.execute(localRunnable); - } - - @Override - public void halfClose() { - // no-op for now, as halfClose makes sense only for bidirectional streams. - } - - private void deliver() { - // A flag stored in method stack space to detect when we enter a delivery loop (regardless if - // it is a concurrent thread or a recursive call execution of delivery() method within the same - // thread). - boolean newActiveDeliveryLoop = true; - boolean allMessagesConsumed = false; - while (true) { - // The try block around listener notification logic. We need to keep this - // block inside the loop to make sure that in case onMessage() call throws, we close the - // request properly and call onClose() method on listener once eventually (because the - // listener can be called only inside this loop). - try { - // Check if there is only one delivery loop active. Exit if a competing delivery loop - // detected (either in a concurrent thread or in a previous recursive call to this method in - // the same thread). The last-standing delivery loop will do all the job. Even if something - // in this loop throws, the code will first go through this block before exiting the loop to - // make sure that the activeDeliveryLoops counter stays correct. - // - // Note, we must enter the loop before doing the check. - synchronized (lock) { - if (inDelivery && newActiveDeliveryLoop) { - // EXIT delivery loop because another active delivery loop has been detected. - break; - } - newActiveDeliveryLoop = false; - inDelivery = true; - } - - if (Thread.interrupted()) { - // The catch block below will properly cancel the call. Note Thread.interrupted() clears - // the interruption flag on this thread, so we don't throw forever. - throw new InterruptedException("Message delivery has been interrupted"); - } - - // All listeners must be called under delivery loop (but outside the lock) to ensure that no - // two notifications come simultaneously from two different threads and that we do not go - // indefinitely deep in the stack if delivery logic is called recursively via listeners. - notifyListeners(); - - // The synchronized block around message reading and cancellation notification processing - // logic - synchronized (lock) { - if (allMessagesConsumed) { - // allMessagesProcessed was set to true on previous loop iteration. We do it this - // way to make sure that notifyListeners() is called in between consuming the last - // message in a stream and closing the call. - // This is to make sure that onMessage() for the last message in a stream is called - // before closing this call, because that last onMessage() listener execution may change - // how the call has to be closed (normally or cancelled). - - // Close the call normally. - // once close() is called we will never ever enter this again, because `close` flag - // will be set to true by the close() method. If the call is already closed, close() - // will have no effect. - allMessagesConsumed = false; - close( - runnableResult.getStatusCode(), - runnableResult.getTrailers().getStatusMessage(), - runnableResult.getTrailers().getException(), - false); - } - - // Attempt to terminate the delivery loop if: - // `runnableResult == null` => there is no response from the server yet; - // `pendingNumMessages <= 0` => we have already delivered as much as has been asked; - // `closed` => this call has been closed already; - if (runnableResult == null || pendingNumMessages <= 0 || closed) { - // The loop terminates only when there are no pending notifications left. The check - // happens under the lock, so no other thread may add a listener notification task in - // the middle of this logic. - if (pendingNotifications.isEmpty()) { - // EXIT delivery loop because there is no more work left to do. This is expected to be - // the only active delivery loop. - inDelivery = false; - break; - } else { - // We still have some stuff in notiticationTasksQueue so continue the loop, most - // likely we will finally terminate on the next cycle. - continue; - } - } - pendingNumMessages--; - allMessagesConsumed = consumeMessageFromStream(); - } - } catch (Throwable e) { - // Exceptions in message delivery result into cancellation of the call to stay consistent - // with other transport implementations. - HttpJsonStatusRuntimeException ex = - new HttpJsonStatusRuntimeException(499, "Exception in message delivery", e); - // If we are already closed the exception will be swallowed, which is the best thing we - // can do in such an unlikely situation (otherwise we would stay forever in the delivery - // loop). - synchronized (lock) { - // Close the call immediately marking it cancelled. If already closed close() will have no - // effect. - close(ex.getStatusCode(), ex.getMessage(), ex, true); - } - } - } - } - - private void notifyListeners() { - while (true) { - NotificationTask notification; - synchronized (lock) { - if (pendingNotifications.isEmpty()) { - return; - } - notification = pendingNotifications.poll(); - } - notification.call(); - } - } - - @GuardedBy("lock") - private boolean consumeMessageFromStream() throws IOException { - if (runnableResult.getTrailers().getException() != null - || runnableResult.getResponseContent() == null) { - // Server returned an error, no messages to process. This will result into closing a call with - // an error. - return true; - } - - boolean allMessagesConsumed; - Reader responseReader; - if (methodDescriptor.getType() == MethodType.SERVER_STREAMING) { - // Lazily initialize responseStreamIterator in case if it is a server steraming response - if (responseStreamIterator == null) { - responseStreamIterator = - new ProtoMessageJsonStreamIterator( - new InputStreamReader(runnableResult.getResponseContent(), StandardCharsets.UTF_8)); - } - if (responseStreamIterator.hasNext()) { - responseReader = responseStreamIterator.next(); - } else { - return true; - } - // To make sure that the call will be closed immediately once we read the last - // message from the response (otherwise we would need to wait for another request(1) - // from the client to check if there is anything else left in the stream). - allMessagesConsumed = !responseStreamIterator.hasNext(); - } else { - responseReader = - new InputStreamReader(runnableResult.getResponseContent(), StandardCharsets.UTF_8); - // Unary calls have only one message in their response, so we should be ready to close - // immediately after delivering a single response message. - allMessagesConsumed = true; - } - - ResponseT message = - methodDescriptor.getResponseParser().parse(responseReader, callOptions.getTypeRegistry()); - pendingNotifications.offer(new OnMessageNotificationTask<>(listener, message)); - - return allMessagesConsumed; - } - - @GuardedBy("lock") - private void close( - int statusCode, String message, Throwable cause, boolean terminateImmediatelly) { - try { - if (closed) { - return; - } - closed = true; - // Best effort task cancellation (to not be confused with task's thread interruption). - // If the task is in blocking I/O waiting for the server response, it will keep waiting for - // the response from the server, but once response is received the task will exit silently. - // If the task has already completed, this call has no effect. - if (requestRunnable != null) { - requestRunnable.cancel(); - requestRunnable = null; - } - - HttpJsonMetadata.Builder meatadaBuilder = HttpJsonMetadata.newBuilder(); - if (runnableResult != null && runnableResult.getTrailers() != null) { - meatadaBuilder = runnableResult.getTrailers().toBuilder(); - } - meatadaBuilder.setException(cause); - meatadaBuilder.setStatusMessage(message); - if (responseStreamIterator != null) { - responseStreamIterator.close(); - } - if (runnableResult != null && runnableResult.getResponseContent() != null) { - runnableResult.getResponseContent().close(); - } - - // onClose() suppresses all other pending notifications. - // there should be no place in the code which inserts something in this queue before checking - // the `closed` flag under the lock and refusing to insert anything if `closed == true`. - if (terminateImmediatelly) { - // This usually means we are cancelling the call before processing the response in full. - // It may happen if a user explicitly cancels the call or in response to an unexpected - // exception either from server or a call listener execution. - pendingNotifications.clear(); - } - - pendingNotifications.offer( - new OnCloseNotificationTask<>(listener, statusCode, meatadaBuilder.build())); - - } catch (Throwable e) { - // suppress stream closing exceptions in favor of the actual call closing cause. This method - // should not throw, otherwise we may stuck in an infinite loop of exception processing. - } - } - - // - // Listener notification tasks. Each class simply calls only one specific method on the Listener - // interface, and to do so it also stores tha parameters needed to make the all. - // - private abstract static class NotificationTask { - private final Listener listener; - - NotificationTask(Listener listener) { - this.listener = listener; - } - - protected Listener getListener() { - return listener; - } - - abstract void call(); - } - - private static class OnHeadersNotificationTask extends NotificationTask { - private final HttpJsonMetadata responseHeaders; - - OnHeadersNotificationTask(Listener listener, HttpJsonMetadata responseHeaders) { - super(listener); - this.responseHeaders = responseHeaders; - } - - public void call() { - getListener().onHeaders(responseHeaders); - } - } - - private static class OnMessageNotificationTask extends NotificationTask { - private final ResponseT message; - - OnMessageNotificationTask(Listener listener, ResponseT message) { - super(listener); - this.message = message; - } - - public void call() { - getListener().onMessage(message); - } - } - - private static class OnCloseNotificationTask extends NotificationTask { - private final int statusCode; - private final HttpJsonMetadata trailers; - - OnCloseNotificationTask( - Listener listener, int statusCode, HttpJsonMetadata trailers) { - super(listener); - this.statusCode = statusCode; - this.trailers = trailers; - } - - public void call() { - getListener().onClose(statusCode, trailers); - } - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonClientCalls.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonClientCalls.java deleted file mode 100644 index 9512537cd..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonClientCalls.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.core.AbstractApiFuture; -import com.google.api.core.ApiFuture; -import com.google.api.gax.rpc.ApiCallContext; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.annotation.Nonnull; -import org.threeten.bp.Instant; - -/** - * {@code HttpJsonClientCalls} creates a new {@code HttpJsonClientCAll} from the given call context. - * - *

Package-private for internal use. - */ -class HttpJsonClientCalls { - private static final Logger LOGGER = Logger.getLogger(HttpJsonClientCalls.class.getName()); - - public static HttpJsonClientCall newCall( - ApiMethodDescriptor methodDescriptor, ApiCallContext context) { - - HttpJsonCallContext httpJsonContext = HttpJsonCallContext.createDefault().nullToSelf(context); - - // Try to convert the timeout into a deadline and use it if it occurs before the actual deadline - if (httpJsonContext.getTimeout() != null) { - @Nonnull Instant newDeadline = Instant.now().plus(httpJsonContext.getTimeout()); - HttpJsonCallOptions callOptions = httpJsonContext.getCallOptions(); - if (callOptions.getDeadline() == null || newDeadline.isBefore(callOptions.getDeadline())) { - callOptions = callOptions.toBuilder().setDeadline(newDeadline).build(); - httpJsonContext = httpJsonContext.withCallOptions(callOptions); - } - } - - // TODO: add headers interceptor logic - return httpJsonContext.getChannel().newCall(methodDescriptor, httpJsonContext.getCallOptions()); - } - - static ApiFuture eagerFutureUnaryCall( - HttpJsonClientCall clientCall, RequestT request) { - // Start the call - HttpJsonFuture future = new HttpJsonFuture<>(clientCall); - clientCall.start(new FutureListener<>(future), HttpJsonMetadata.newBuilder().build()); - - // Send the request - try { - clientCall.sendMessage(request); - clientCall.halfClose(); - // Request an extra message to detect misconfigured servers - clientCall.request(2); - } catch (Throwable sendError) { - // Cancel if anything goes wrong - try { - clientCall.cancel(null, sendError); - } catch (Throwable cancelError) { - LOGGER.log(Level.SEVERE, "Error encountered while closing it", sendError); - } - - throw sendError; - } - - return future; - } - - private static class HttpJsonFuture extends AbstractApiFuture { - private final HttpJsonClientCall call; - - private HttpJsonFuture(HttpJsonClientCall call) { - this.call = call; - } - - @Override - protected void interruptTask() { - call.cancel("HttpJsonFuture was cancelled", null); - } - - @Override - public boolean set(T value) { - return super.set(value); - } - - @Override - public boolean setException(Throwable throwable) { - return super.setException(throwable); - } - } - - private static class FutureListener extends HttpJsonClientCall.Listener { - private final HttpJsonFuture future; - - private FutureListener(HttpJsonFuture future) { - this.future = future; - } - - @Override - public void onMessage(T message) { - if (!future.set(message)) { - throw new IllegalStateException("More than one value received for unary call"); - } - } - - @Override - public void onClose(int statusCode, HttpJsonMetadata trailers) { - if (!future.isDone()) { - if (trailers == null || trailers.getException() == null) { - future.setException( - new HttpJsonStatusRuntimeException( - statusCode, - "Exception during a client call closure", - new NullPointerException( - "Both response message and response exception were null"))); - } else { - future.setException(trailers.getException()); - } - } else if (statusCode < 200 || statusCode >= 400) { - LOGGER.log( - Level.WARNING, "Received error for unary call after receiving a successful response"); - } - } - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonClientInterceptor.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonClientInterceptor.java deleted file mode 100644 index 446fe09f2..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonClientInterceptor.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.core.BetaApi; - -/** - * Interface for intercepting outgoing calls before they are dispatched by a {@link - * HttpJsonChannel}. - * - *

The interceptor may be called for multiple {@link HttpJsonClientCall calls} by one or more - * threads without completing the previous ones first. The implementations must be thread-safe. - */ -@BetaApi -public interface HttpJsonClientInterceptor { - /** - * Intercept {@link HttpJsonClientCall} creation by the {@code next} {@link HttpJsonChannel}. - * - * @param method the remote method to be called - * @param callOptions the runtime options to be applied to this call - * @param next the channel which is being intercepted - * @return the call object for the remote operation, never {@code null} - */ - HttpJsonClientCall interceptCall( - ApiMethodDescriptor method, - HttpJsonCallOptions callOptions, - HttpJsonChannel next); -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonDirectCallable.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonDirectCallable.java deleted file mode 100644 index dd0826dd6..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonDirectCallable.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.core.ApiFuture; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.common.base.Preconditions; -import com.google.protobuf.TypeRegistry; - -/** - * {@code HttpJsonDirectCallable} creates HTTP calls. - * - *

Package-private for internal use. - */ -class HttpJsonDirectCallable extends UnaryCallable { - private final ApiMethodDescriptor descriptor; - private final TypeRegistry typeRegistry; - - HttpJsonDirectCallable(ApiMethodDescriptor descriptor) { - this(descriptor, null); - } - - HttpJsonDirectCallable( - ApiMethodDescriptor descriptor, TypeRegistry typeRegistry) { - this.descriptor = descriptor; - this.typeRegistry = typeRegistry; - } - - @Override - public ApiFuture futureCall(RequestT request, ApiCallContext inputContext) { - Preconditions.checkNotNull(request); - HttpJsonCallContext context = HttpJsonCallContext.createDefault().nullToSelf(inputContext); - - context = - context.withCallOptions( - context.getCallOptions().toBuilder().setTypeRegistry(typeRegistry).build()); - - HttpJsonClientCall clientCall = - HttpJsonClientCalls.newCall(descriptor, context); - return HttpJsonClientCalls.eagerFutureUnaryCall(clientCall, request); - } - - @Override - public String toString() { - return String.format("direct(%s)", descriptor); - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonDirectServerStreamingCallable.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonDirectServerStreamingCallable.java deleted file mode 100644 index ed3bebde3..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonDirectServerStreamingCallable.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.ResponseObserver; -import com.google.api.gax.rpc.ServerStreamingCallable; -import com.google.api.gax.rpc.StreamController; -import com.google.common.base.Preconditions; - -/** - * {@code HttpJsonDirectServerStreamingCallable} creates server-streaming REST calls. - * - *

In a chain of {@link ServerStreamingCallable}s this is the innermost callable. It wraps a - * {@link HttpJsonClientCall} in a {@link StreamController} and the downstream {@link - * ResponseObserver} in a {@link HttpJsonClientCall.Listener}. This class is implemented to look and - * behave as similarly as possible to gRPC variant of it. - * - *

Package-private for internal use. - */ -class HttpJsonDirectServerStreamingCallable - extends ServerStreamingCallable { - - private final ApiMethodDescriptor descriptor; - - HttpJsonDirectServerStreamingCallable(ApiMethodDescriptor descriptor) { - this.descriptor = descriptor; - } - - @Override - public void call( - RequestT request, ResponseObserver responseObserver, ApiCallContext context) { - - Preconditions.checkNotNull(request); - Preconditions.checkNotNull(responseObserver); - - HttpJsonClientCall call = HttpJsonClientCalls.newCall(descriptor, context); - HttpJsonDirectStreamController controller = - new HttpJsonDirectStreamController<>(call, responseObserver); - controller.start(request); - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonDirectStreamController.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonDirectStreamController.java deleted file mode 100644 index 5f56390f0..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonDirectStreamController.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.gax.rpc.ResponseObserver; -import com.google.api.gax.rpc.StreamController; -import com.google.common.base.Preconditions; -import java.util.concurrent.CancellationException; - -/** - * Wraps a HttpJsonClientCall in a {@link StreamController}. It feeds events to a {@link - * ResponseObserver} and allows for back pressure. - * - *

Package-private for internal use. - */ -class HttpJsonDirectStreamController implements StreamController { - private final HttpJsonClientCall clientCall; - private final ResponseObserver responseObserver; - private volatile boolean hasStarted; - private volatile boolean autoflowControl = true; - private volatile int numRequested; - private volatile CancellationException cancellationException; - - HttpJsonDirectStreamController( - HttpJsonClientCall clientCall, - ResponseObserver responseObserver) { - this.clientCall = clientCall; - this.responseObserver = responseObserver; - } - - @Override - public void cancel() { - cancellationException = new CancellationException("User cancelled stream"); - clientCall.cancel(null, cancellationException); - } - - @Override - public void disableAutoInboundFlowControl() { - Preconditions.checkState( - !hasStarted, "Can't disable automatic flow control after the stream has started."); - autoflowControl = false; - } - - @Override - public void request(int count) { - Preconditions.checkState(!autoflowControl, "Autoflow control is enabled."); - - // Buffer the requested count in case the consumer requested responses in the onStart() - if (!hasStarted) { - numRequested += count; - } else { - clientCall.request(count); - } - } - - void start(RequestT request) { - responseObserver.onStart(this); - this.hasStarted = true; - clientCall.start(new ResponseObserverAdapter(), HttpJsonMetadata.newBuilder().build()); - - if (autoflowControl) { - clientCall.request(1); - } else if (numRequested > 0) { - clientCall.request(numRequested); - } - - clientCall.sendMessage(request); - } - - private class ResponseObserverAdapter extends HttpJsonClientCall.Listener { - /** - * Notifies the outerObserver of the new message and if automatic flow control is enabled, - * requests the next message. Any errors raised by the outerObserver will be bubbled up to GRPC, - * which cancel the ClientCall and close this listener. - * - * @param message The new message. - */ - @Override - public void onMessage(ResponseT message) { - responseObserver.onResponse(message); - - if (autoflowControl) { - clientCall.request(1); - } - } - - @Override - public void onClose(int statusCode, HttpJsonMetadata trailers) { - if (statusCode >= 200 && statusCode < 300) { - responseObserver.onComplete(); - } else if (cancellationException != null) { - // Intercept cancellations and replace with the top level cause - responseObserver.onError(cancellationException); - } else { - responseObserver.onError(trailers.getException()); - } - } - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonExceptionCallable.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonExceptionCallable.java deleted file mode 100644 index ede9ce343..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonExceptionCallable.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import static com.google.common.util.concurrent.MoreExecutors.directExecutor; - -import com.google.api.core.AbstractApiFuture; -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutureCallback; -import com.google.api.core.ApiFutures; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.ApiException; -import com.google.api.gax.rpc.StatusCode; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.common.base.Preconditions; -import java.util.Set; -import java.util.concurrent.CancellationException; - -/** - * Transforms all {@code Throwable}s thrown during a call into an instance of {@link ApiException}. - * - *

Package-private for internal use. - */ -class HttpJsonExceptionCallable extends UnaryCallable { - private final UnaryCallable callable; - private final HttpJsonApiExceptionFactory exceptionFactory; - - HttpJsonExceptionCallable( - UnaryCallable callable, Set retryableCodes) { - this.callable = Preconditions.checkNotNull(callable); - this.exceptionFactory = new HttpJsonApiExceptionFactory(retryableCodes); - } - - @Override - public ApiFuture futureCall(RequestT request, ApiCallContext inputContext) { - HttpJsonCallContext context = HttpJsonCallContext.createDefault().nullToSelf(inputContext); - ApiFuture innerCallFuture = callable.futureCall(request, context); - ExceptionTransformingFuture transformingFuture = - new ExceptionTransformingFuture(innerCallFuture); - ApiFutures.addCallback(innerCallFuture, transformingFuture, directExecutor()); - return transformingFuture; - } - - private class ExceptionTransformingFuture extends AbstractApiFuture - implements ApiFutureCallback { - private final ApiFuture innerCallFuture; - private volatile boolean cancelled = false; - - public ExceptionTransformingFuture(ApiFuture innerCallFuture) { - this.innerCallFuture = innerCallFuture; - } - - @Override - protected void interruptTask() { - cancelled = true; - innerCallFuture.cancel(true); - } - - @Override - public void onSuccess(ResponseT r) { - super.set(r); - } - - @Override - public void onFailure(Throwable throwable) { - if (throwable instanceof CancellationException && cancelled) { - // this just circled around, so ignore. - return; - } - setException(exceptionFactory.create(throwable)); - } - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonExceptionResponseObserver.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonExceptionResponseObserver.java deleted file mode 100644 index 0264a33f0..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonExceptionResponseObserver.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.gax.rpc.ResponseObserver; -import com.google.api.gax.rpc.StateCheckingResponseObserver; -import com.google.api.gax.rpc.StreamController; -import java.util.concurrent.CancellationException; - -/** Package-private for internal use. */ -class HttpJsonExceptionResponseObserver - extends StateCheckingResponseObserver { - private final ResponseObserver innerObserver; - private volatile CancellationException cancellationException; - private final HttpJsonApiExceptionFactory exceptionFactory; - - public HttpJsonExceptionResponseObserver( - ResponseObserver innerObserver, HttpJsonApiExceptionFactory exceptionFactory) { - this.innerObserver = innerObserver; - this.exceptionFactory = exceptionFactory; - } - - @Override - protected void onStartImpl(final StreamController controller) { - innerObserver.onStart( - new StreamController() { - @Override - public void cancel() { - cancellationException = new CancellationException("User cancelled stream"); - controller.cancel(); - } - - @Override - public void disableAutoInboundFlowControl() { - controller.disableAutoInboundFlowControl(); - } - - @Override - public void request(int count) { - controller.request(count); - } - }); - } - - @Override - protected void onResponseImpl(ResponseT response) { - innerObserver.onResponse(response); - } - - @Override - protected void onErrorImpl(Throwable t) { - if (cancellationException != null) { - t = cancellationException; - } else { - t = exceptionFactory.create(t); - } - innerObserver.onError(t); - } - - @Override - protected void onCompleteImpl() { - innerObserver.onComplete(); - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonExceptionServerStreamingCallable.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonExceptionServerStreamingCallable.java deleted file mode 100644 index 7c82b2fb1..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonExceptionServerStreamingCallable.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.gax.httpjson; - -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.ApiException; -import com.google.api.gax.rpc.ResponseObserver; -import com.google.api.gax.rpc.ServerStreamingCallable; -import com.google.api.gax.rpc.StatusCode.Code; -import java.util.Set; - -/** - * Transforms all {@code Throwable}s thrown during a rest call into an instance of {@link - * ApiException}. - * - *

Package-private for internal use. - */ -class HttpJsonExceptionServerStreamingCallable - extends ServerStreamingCallable { - private final ServerStreamingCallable inner; - private final HttpJsonApiExceptionFactory exceptionFactory; - - public HttpJsonExceptionServerStreamingCallable( - ServerStreamingCallable inner, Set retryableCodes) { - this.inner = inner; - this.exceptionFactory = new HttpJsonApiExceptionFactory(retryableCodes); - } - - @Override - public void call( - RequestT request, ResponseObserver responseObserver, ApiCallContext context) { - inner.call( - request, - new HttpJsonExceptionResponseObserver<>(responseObserver, exceptionFactory), - context); - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonHeaderEnhancer.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonHeaderEnhancer.java deleted file mode 100644 index 897fecf8f..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonHeaderEnhancer.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.client.http.HttpHeaders; -import com.google.api.core.BetaApi; - -/** Interface for functionality to enhance headers for an http-json call. */ -@BetaApi -public interface HttpJsonHeaderEnhancer { - void enhance(HttpHeaders headers); -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonHeaderEnhancers.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonHeaderEnhancers.java deleted file mode 100644 index 3d3deda30..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonHeaderEnhancers.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.client.http.HttpHeaders; -import com.google.api.core.BetaApi; - -/** Utility class that creates instances of {@link HttpJsonHeaderEnhancer}. */ -@BetaApi -public class HttpJsonHeaderEnhancers { - - private HttpJsonHeaderEnhancers() {} - - public static HttpJsonHeaderEnhancer create(final String key, final String value) { - return new HttpJsonHeaderEnhancer() { - @Override - public void enhance(HttpHeaders headers) { - HttpHeadersUtils.setHeader(headers, key, value); - } - }; - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonHeaderInterceptor.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonHeaderInterceptor.java deleted file mode 100644 index 0f58181cb..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonHeaderInterceptor.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.gax.httpjson.ForwardingHttpJsonClientCall.SimpleForwardingHttpJsonClientCall; -import com.google.common.collect.ImmutableMap; -import java.util.Map; - -/** - * An interceptor to handle custom headers. - * - *

Package-private for internal usage. - */ -class HttpJsonHeaderInterceptor implements HttpJsonClientInterceptor { - - private final Map staticHeaders; - - public HttpJsonHeaderInterceptor(Map staticHeaders) { - this.staticHeaders = staticHeaders; - } - - @Override - public HttpJsonClientCall interceptCall( - ApiMethodDescriptor method, - final HttpJsonCallOptions callOptions, - HttpJsonChannel next) { - HttpJsonClientCall call = next.newCall(method, callOptions); - return new SimpleForwardingHttpJsonClientCall(call) { - @Override - public void start( - HttpJsonClientCall.Listener responseListener, HttpJsonMetadata headers) { - Map mergedHeaders = - ImmutableMap.builder() - .putAll(headers.getHeaders()) - .putAll(staticHeaders) - .build(); - - super.start(responseListener, headers.toBuilder().setHeaders(mergedHeaders).build()); - } - }; - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonInterceptorProvider.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonInterceptorProvider.java deleted file mode 100644 index 4c5ddb475..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonInterceptorProvider.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.core.BetaApi; -import java.util.List; - -/** Provider of custom REST ClientInterceptors. */ -@BetaApi( - "The surface for adding custom interceptors is not stable yet and may change in the future.") -public interface HttpJsonInterceptorProvider { - - /** - * Get the list of client interceptors. - * - * @return interceptors - */ - List getInterceptors(); -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonLongRunningClient.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonLongRunningClient.java deleted file mode 100644 index 55bb5733c..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonLongRunningClient.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.core.ApiFunction; -import com.google.api.core.InternalApi; -import com.google.api.gax.longrunning.OperationSnapshot; -import com.google.api.gax.rpc.LongRunningClient; -import com.google.api.gax.rpc.TranslatingUnaryCallable; -import com.google.api.gax.rpc.UnaryCallable; - -/** - * Implementation of LongRunningClient based on REST transport. - * - *

Public for technical reasons. For internal use only. - */ -@InternalApi -public class HttpJsonLongRunningClient implements LongRunningClient { - - private final UnaryCallable operationCallable; - private final OperationSnapshotFactory operationSnapshotFactory; - private final PollingRequestFactory pollingRequestFactory; - - public HttpJsonLongRunningClient( - UnaryCallable operationCallable, - OperationSnapshotFactory operationSnapshotFactory, - PollingRequestFactory pollingRequestFactory) { - this.operationCallable = operationCallable; - this.operationSnapshotFactory = operationSnapshotFactory; - this.pollingRequestFactory = pollingRequestFactory; - } - - /** {@inheritDoc} */ - @Override - public UnaryCallable getOperationCallable() { - return TranslatingUnaryCallable.create( - operationCallable, - new ApiFunction() { - @Override - public RequestT apply(String id) { - return pollingRequestFactory.create(id); - } - }, - new ApiFunction() { - @Override - public OperationSnapshot apply(OperationT operation) { - return operationSnapshotFactory.create(null, operation); - } - }); - } - - /** {@inheritDoc} */ - @Override - public UnaryCallable cancelOperationCallable() { - return null; - } - - /** {@inheritDoc} */ - @Override - public UnaryCallable deleteOperationCallable() { - return null; - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonMetadata.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonMetadata.java deleted file mode 100644 index 9fef6db5c..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonMetadata.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.core.BetaApi; -import com.google.api.core.InternalExtensionOnly; -import com.google.auto.value.AutoValue; -import java.util.Collections; -import java.util.Map; -import javax.annotation.Nullable; - -@AutoValue -@BetaApi -@InternalExtensionOnly -public abstract class HttpJsonMetadata { - public abstract Map getHeaders(); - - @Nullable - public abstract String getStatusMessage(); - - @Nullable - public abstract Throwable getException(); - - public abstract Builder toBuilder(); - - public static HttpJsonMetadata.Builder newBuilder() { - return new AutoValue_HttpJsonMetadata.Builder().setHeaders(Collections.emptyMap()); - } - - @AutoValue.Builder - abstract static class Builder { - abstract Builder setHeaders(Map headers); - - public abstract Builder setStatusMessage(String value); - - public abstract Builder setException(Throwable value); - - abstract HttpJsonMetadata build(); - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonOperationSnapshot.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonOperationSnapshot.java deleted file mode 100644 index 1e616a31a..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonOperationSnapshot.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.core.BetaApi; -import com.google.api.core.InternalApi; -import com.google.api.gax.longrunning.OperationSnapshot; -import com.google.api.gax.rpc.StatusCode; -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.longrunning.Operation; - -/** - * Implementation of OperationSnapshot based on REST transport. - * - *

Public for technical reasons. For internal use only. - */ -@BetaApi -@InternalApi -public class HttpJsonOperationSnapshot implements OperationSnapshot { - private final String name; - private final Object metadata; - private final boolean done; - private final Object response; - private final StatusCode errorCode; - private final String errorMessage; - - private HttpJsonOperationSnapshot( - String name, - Object metadata, - boolean done, - Object response, - StatusCode errorCode, - String errorMessage) { - this.name = name; - this.metadata = metadata; - this.done = done; - this.response = response; - this.errorCode = errorCode; - this.errorMessage = errorMessage; - } - - /** {@inheritDoc} */ - @Override - public String getName() { - return this.name; - } - - /** {@inheritDoc} */ - @Override - public Object getMetadata() { - return this.metadata; - } - - /** {@inheritDoc} */ - @Override - public boolean isDone() { - return done; - } - - /** {@inheritDoc} */ - @Override - public Object getResponse() { - return this.response; - } - - /** {@inheritDoc} */ - @Override - public StatusCode getErrorCode() { - return this.errorCode; - } - - /** {@inheritDoc} */ - @Override - public String getErrorMessage() { - return this.errorMessage; - } - - public static HttpJsonOperationSnapshot create(Operation operation) { - return newBuilder().setOperation(operation).build(); - } - - public static Builder newBuilder() { - return new HttpJsonOperationSnapshot.Builder(); - } - - public static class Builder { - private String name; - private Object metadata; - private boolean done; - private Object response; - private StatusCode errorCode; - private String errorMessage; - - public Builder setName(String name) { - this.name = name; - return this; - } - - public Builder setMetadata(Object metadata) { - this.metadata = metadata; - return this; - } - - public Builder setDone(boolean done) { - this.done = done; - return this; - } - - public Builder setResponse(Object response) { - this.response = response; - return this; - } - - public Builder setError(int httpStatus, String errorMessage) { - this.errorCode = - httpStatus == 0 ? HttpJsonStatusCode.of(Code.OK) : HttpJsonStatusCode.of(httpStatus); - this.errorMessage = errorMessage; - return this; - } - - private Builder setOperation(Operation operation) { - this.name = operation.getName(); - this.done = operation.getDone(); - this.response = operation.getResponse(); - this.metadata = operation.getMetadata(); - this.errorCode = - HttpJsonStatusCode.of(com.google.rpc.Code.forNumber(operation.getError().getCode())); - this.errorMessage = operation.getError().getMessage(); - return this; - } - - public HttpJsonOperationSnapshot build() { - return new HttpJsonOperationSnapshot(name, metadata, done, response, errorCode, errorMessage); - } - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonOperationSnapshotCallable.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonOperationSnapshotCallable.java deleted file mode 100644 index 58f99064a..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonOperationSnapshotCallable.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import static com.google.common.util.concurrent.MoreExecutors.directExecutor; - -import com.google.api.core.ApiFunction; -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.api.core.BetaApi; -import com.google.api.core.InternalApi; -import com.google.api.gax.longrunning.OperationSnapshot; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.UnaryCallable; - -/** - * A {@code UnaryCallable} that wraps a UnaryCallable returning an Operation and returns an - * OperationSnapshot instead. - * - *

Public for technical reasons. For internal use only. - */ -@BetaApi -@InternalApi -public class HttpJsonOperationSnapshotCallable - extends UnaryCallable { - - private final UnaryCallable innerCallable; - private final OperationSnapshotFactory operationSnapshotFactory; - - public HttpJsonOperationSnapshotCallable( - UnaryCallable innerCallable, - OperationSnapshotFactory operationSnapshotFactory) { - this.innerCallable = innerCallable; - this.operationSnapshotFactory = operationSnapshotFactory; - } - - /** {@inheritDoc} */ - @Override - public ApiFuture futureCall(final RequestT request, ApiCallContext context) { - return ApiFutures.transform( - innerCallable.futureCall(request, context), - new ApiFunction() { - @Override - public OperationSnapshot apply(OperationT operation) { - return operationSnapshotFactory.create(request, operation); - } - }, - directExecutor()); - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonStatusCode.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonStatusCode.java deleted file mode 100644 index 617496eb5..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonStatusCode.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.core.BetaApi; -import com.google.api.core.InternalExtensionOnly; -import com.google.api.gax.rpc.StatusCode; -import java.util.Objects; - -/** A failure code specific to an HTTP call. */ -@BetaApi -@InternalExtensionOnly -public class HttpJsonStatusCode implements StatusCode { - private final int httpStatus; - private final Code statusCode; - - /** Creates a new instance with the given status code. */ - public static HttpJsonStatusCode of(int httpStatus) { - return new HttpJsonStatusCode(httpStatus, httpStatusToStatusCode(httpStatus)); - } - - public static HttpJsonStatusCode of(Code statusCode) { - return new HttpJsonStatusCode(statusCode.getHttpStatusCode(), statusCode); - } - - public static HttpJsonStatusCode of(com.google.rpc.Code rpcCode) { - return HttpJsonStatusCode.of(rpcCodeToStatusCode(rpcCode)); - } - - static Code rpcCodeToStatusCode(com.google.rpc.Code rpcCode) { - switch (rpcCode) { - case OK: - return Code.OK; - case CANCELLED: - return Code.CANCELLED; - case UNKNOWN: - return Code.UNKNOWN; - case INVALID_ARGUMENT: - return Code.INVALID_ARGUMENT; - case DEADLINE_EXCEEDED: - return Code.DEADLINE_EXCEEDED; - case NOT_FOUND: - return Code.NOT_FOUND; - case ALREADY_EXISTS: - return Code.ALREADY_EXISTS; - case PERMISSION_DENIED: - return Code.PERMISSION_DENIED; - case RESOURCE_EXHAUSTED: - return Code.RESOURCE_EXHAUSTED; - case FAILED_PRECONDITION: - return Code.FAILED_PRECONDITION; - case ABORTED: - return Code.ABORTED; - case OUT_OF_RANGE: - return Code.OUT_OF_RANGE; - case UNIMPLEMENTED: - return Code.UNIMPLEMENTED; - case INTERNAL: - return Code.INTERNAL; - case UNAVAILABLE: - return Code.UNAVAILABLE; - case DATA_LOSS: - return Code.DATA_LOSS; - case UNAUTHENTICATED: - return Code.UNAUTHENTICATED; - default: - throw new IllegalArgumentException("Unrecognized rpc code: " + rpcCode); - } - } - - static Code httpStatusToStatusCode(int httpStatus) { - if (200 <= httpStatus && httpStatus < 300) { - return Code.OK; - } else if (400 <= httpStatus && httpStatus < 500) { - switch (httpStatus) { - case 400: - return Code.INVALID_ARGUMENT; - case 401: - return Code.UNAUTHENTICATED; - case 403: - return Code.PERMISSION_DENIED; - case 404: - return Code.NOT_FOUND; - case 409: - return Code.ABORTED; - case 416: - return Code.OUT_OF_RANGE; - case 429: - return Code.RESOURCE_EXHAUSTED; - case 499: - return Code.CANCELLED; - default: - return Code.FAILED_PRECONDITION; - } - } else if (500 <= httpStatus && httpStatus < 600) { - switch (httpStatus) { - case 501: - return Code.UNIMPLEMENTED; - case 503: - return Code.UNAVAILABLE; - case 504: - return Code.DEADLINE_EXCEEDED; - default: - return Code.INTERNAL; - } - } - return Code.UNKNOWN; - } - - @Override - public Code getCode() { - return statusCode; - } - - /** Returns the status code from the http call. */ - @Override - public Integer getTransportCode() { - return httpStatus; - } - - private HttpJsonStatusCode(int httpStatus, Code statusCode) { - this.httpStatus = httpStatus; - this.statusCode = statusCode; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - HttpJsonStatusCode that = (HttpJsonStatusCode) o; - - return Objects.equals(statusCode, that.statusCode); - } - - @Override - public int hashCode() { - return Objects.hash(statusCode); - } - - @Override - public String toString() { - return "HttpJsonStatusCode{" + "statusCode=" + statusCode + "}"; - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonStatusRuntimeException.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonStatusRuntimeException.java deleted file mode 100644 index a1b9b1c1b..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonStatusRuntimeException.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.gax.httpjson; - -/** - * HTTP status code in RuntimeException form, for propagating status code information via - * exceptions. - */ -public class HttpJsonStatusRuntimeException extends RuntimeException { - private static final long serialVersionUID = -5390915748330242256L; - - private final int statusCode; - - public HttpJsonStatusRuntimeException(int statusCode, String message, Throwable cause) { - super(message, cause); - this.statusCode = statusCode; - } - - public int getStatusCode() { - return statusCode; - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonStubCallableFactory.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonStubCallableFactory.java deleted file mode 100644 index a12ca89eb..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonStubCallableFactory.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.gax.core.BackgroundResource; -import com.google.api.gax.rpc.BatchingCallSettings; -import com.google.api.gax.rpc.ClientContext; -import com.google.api.gax.rpc.OperationCallSettings; -import com.google.api.gax.rpc.OperationCallable; -import com.google.api.gax.rpc.PagedCallSettings; -import com.google.api.gax.rpc.ServerStreamingCallSettings; -import com.google.api.gax.rpc.ServerStreamingCallable; -import com.google.api.gax.rpc.StreamingCallSettings; -import com.google.api.gax.rpc.UnaryCallSettings; -import com.google.api.gax.rpc.UnaryCallable; - -public interface HttpJsonStubCallableFactory< - OperationT, OperationsStub extends BackgroundResource> { - - /** - * Create a callable object with http/json-specific functionality. Designed for use by generated - * code. - * - * @param httpJsonCallSettings the http/json call settings - * @param callSettings {@link UnaryCallSettings} to configure the method-level settings with - * @param clientContext {@link ClientContext} to use to connect to the service - * @return {@link UnaryCallable} callable object - */ - UnaryCallable createUnaryCallable( - HttpJsonCallSettings httpJsonCallSettings, - UnaryCallSettings callSettings, - ClientContext clientContext); - - /** - * Create a paged callable object that represents a paged API method. Designed for use by - * generated code. - * - * @param httpJsonCallSettings the http/json call settings - * @param pagedCallSettings {@link PagedCallSettings} to configure the paged settings with - * @param clientContext {@link ClientContext} to use to connect to the service - * @return {@link UnaryCallable} callable object - */ - - UnaryCallable createPagedCallable( - HttpJsonCallSettings httpJsonCallSettings, - PagedCallSettings pagedCallSettings, - ClientContext clientContext); - - /** - * Create a callable object that represents a batching API method. Designed for use by generated - * code. - * - * @param httpJsonCallSettings the http/json call settings - * @param batchingCallSettings {@link BatchingCallSettings} to configure the batching related - * settings with - * @param clientContext {@link ClientContext} to use to connect to the service - * @return {@link UnaryCallable} callable object - */ - UnaryCallable createBatchingCallable( - HttpJsonCallSettings httpJsonCallSettings, - BatchingCallSettings batchingCallSettings, - ClientContext clientContext); - - /** - * Creates a callable object that represents a long-running operation. Designed for use by - * generated code. - * - * @param httpJsonCallSettings the http/json call settings - * @param operationCallSettings {@link OperationCallSettings} to configure the method-level - * settings with - * @param clientContext {@link ClientContext} to use to connect to the service - * @param operationsStub opertation stub to use to poll for updates on the Operation - * @return {@link OperationCallable} callable object - */ - - OperationCallable createOperationCallable( - HttpJsonCallSettings httpJsonCallSettings, - OperationCallSettings operationCallSettings, - ClientContext clientContext, - OperationsStub operationsStub); - - /** - * Create a server-streaming callable with. Designed for use by generated code. - * - * @param httpJsonCallSettings the gRPC call settings - * @param callSettings {@link StreamingCallSettings} to configure the method-level settings with. - * @param clientContext {@link ClientContext} to use to connect to the service. - */ - default - ServerStreamingCallable createServerStreamingCallable( - HttpJsonCallSettings httpJsonCallSettings, - ServerStreamingCallSettings callSettings, - ClientContext clientContext) { - return HttpJsonCallableFactory.createServerStreamingCallable( - httpJsonCallSettings, callSettings, clientContext); - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonTransportChannel.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonTransportChannel.java deleted file mode 100644 index 355193964..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonTransportChannel.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.core.InternalExtensionOnly; -import com.google.api.gax.rpc.TransportChannel; -import com.google.auto.value.AutoValue; -import java.util.concurrent.TimeUnit; - -/** Implementation of TransportChannel based on http/json. */ -@AutoValue -@InternalExtensionOnly -public abstract class HttpJsonTransportChannel implements TransportChannel { - - /** The name of the Http-JSON transport. */ - public static String getHttpJsonTransportName() { - return "httpjson"; - } - - @Override - public String getTransportName() { - return getHttpJsonTransportName(); - } - - @Override - public HttpJsonCallContext getEmptyCallContext() { - return HttpJsonCallContext.createDefault(); - } - - /** The channel in use. */ - public abstract ManagedHttpJsonChannel getManagedChannel(); - - /** The channel in use. */ - public HttpJsonChannel getChannel() { - return getManagedChannel(); - } - - @Override - public void shutdown() { - getManagedChannel().shutdown(); - } - - @Override - public boolean isShutdown() { - return getManagedChannel().isShutdown(); - } - - @Override - public boolean isTerminated() { - return getManagedChannel().isTerminated(); - } - - @Override - public void shutdownNow() { - getManagedChannel().shutdownNow(); - } - - @Override - public boolean awaitTermination(long duration, TimeUnit unit) throws InterruptedException { - return getManagedChannel().awaitTermination(duration, unit); - } - - @Override - public void close() { - getManagedChannel().shutdown(); - } - - public static Builder newBuilder() { - return new AutoValue_HttpJsonTransportChannel.Builder(); - } - - public static HttpJsonTransportChannel create(ManagedHttpJsonChannel channel) { - return newBuilder().setManagedChannel(channel).build(); - } - - @AutoValue.Builder - public abstract static class Builder { - public abstract Builder setManagedChannel(ManagedHttpJsonChannel value); - - public abstract HttpJsonTransportChannel build(); - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpRequestFormatter.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpRequestFormatter.java deleted file mode 100644 index a60bf08e9..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpRequestFormatter.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.core.BetaApi; -import com.google.api.pathtemplate.PathTemplate; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -/** Interface for classes that create parts of HTTP requests from a parameterized message. */ -public interface HttpRequestFormatter { - /** - * Return a map where each entry is the name of a query param mapped to the values of the param. - */ - Map> getQueryParamNames(MessageFormatT apiMessage); - - /** Return the serialized inner request body of the given message. */ - String getRequestBody(MessageFormatT apiMessage); - - /* Return the relative URL path created from the path parameters from the given message. */ - String getPath(MessageFormatT apiMessage); - - /** Path template for endpoint URL path. */ - PathTemplate getPathTemplate(); - - /** Additional (alternative) path templates for endpoint URL path. */ - @BetaApi - default List getAdditionalPathTemplates() { - return Collections.emptyList(); - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpRequestRunnable.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpRequestRunnable.java deleted file mode 100644 index 2edb4ceb2..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpRequestRunnable.java +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.client.http.EmptyContent; -import com.google.api.client.http.GenericUrl; -import com.google.api.client.http.HttpContent; -import com.google.api.client.http.HttpMediaType; -import com.google.api.client.http.HttpMethods; -import com.google.api.client.http.HttpRequest; -import com.google.api.client.http.HttpRequestFactory; -import com.google.api.client.http.HttpResponse; -import com.google.api.client.http.HttpResponseException; -import com.google.api.client.http.HttpTransport; -import com.google.api.client.http.json.JsonHttpContent; -import com.google.api.client.json.JsonFactory; -import com.google.api.client.json.JsonObjectParser; -import com.google.api.client.json.gson.GsonFactory; -import com.google.api.client.util.GenericData; -import com.google.auth.Credentials; -import com.google.auth.http.HttpCredentialsAdapter; -import com.google.auto.value.AutoValue; -import com.google.common.base.Strings; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import javax.annotation.Nullable; -import org.threeten.bp.Duration; -import org.threeten.bp.Instant; - -/** A runnable object that creates and executes an HTTP request. */ -class HttpRequestRunnable implements Runnable { - private final RequestT request; - private final ApiMethodDescriptor methodDescriptor; - private final String endpoint; - private final HttpJsonCallOptions httpJsonCallOptions; - private final HttpTransport httpTransport; - private final HttpJsonMetadata headers; - private final ResultListener resultListener; - - private volatile boolean cancelled = false; - - HttpRequestRunnable( - RequestT request, - ApiMethodDescriptor methodDescriptor, - String endpoint, - HttpJsonCallOptions httpJsonCallOptions, - HttpTransport httpTransport, - HttpJsonMetadata headers, - ResultListener resultListener) { - this.request = request; - this.methodDescriptor = methodDescriptor; - this.endpoint = endpoint; - this.httpJsonCallOptions = httpJsonCallOptions; - this.httpTransport = httpTransport; - this.headers = headers; - this.resultListener = resultListener; - } - - // Best effort cancellation without guarantees. - // It will check if the task cancelled before each three sequential potentially time-consuming - // operations: - // - request construction; - // - request execution (the most time consuming, taking); - // - response construction. - void cancel() { - cancelled = true; - } - - @Override - public void run() { - HttpResponse httpResponse = null; - RunnableResult.Builder result = RunnableResult.builder(); - HttpJsonMetadata.Builder trailers = HttpJsonMetadata.newBuilder(); - HttpRequest httpRequest = null; - try { - // Check if already cancelled before even creating a request - if (cancelled) { - return; - } - httpRequest = createHttpRequest(); - // Check if already cancelled before sending the request; - if (cancelled) { - return; - } - - httpResponse = httpRequest.execute(); - - // Check if already cancelled before sending the request; - if (cancelled) { - httpResponse.disconnect(); - return; - } - result.setResponseHeaders( - HttpJsonMetadata.newBuilder().setHeaders(httpResponse.getHeaders()).build()); - result.setStatusCode(httpResponse.getStatusCode()); - result.setResponseContent(httpResponse.getContent()); - trailers.setStatusMessage(httpResponse.getStatusMessage()); - } catch (HttpResponseException e) { - result.setStatusCode(e.getStatusCode()); - result.setResponseHeaders(HttpJsonMetadata.newBuilder().setHeaders(e.getHeaders()).build()); - result.setResponseContent( - e.getContent() != null - ? new ByteArrayInputStream(e.getContent().getBytes(StandardCharsets.UTF_8)) - : null); - trailers.setStatusMessage(e.getStatusMessage()); - trailers.setException(e); - } catch (Throwable e) { - if (httpResponse != null) { - trailers.setStatusMessage(httpResponse.getStatusMessage()); - result.setStatusCode(httpResponse.getStatusCode()); - } else { - result.setStatusCode(400); - } - trailers.setException(e); - } finally { - if (!cancelled) { - resultListener.setResult(result.setTrailers(trailers.build()).build()); - } - } - } - - HttpRequest createHttpRequest() throws IOException { - GenericData tokenRequest = new GenericData(); - - HttpRequestFormatter requestFormatter = methodDescriptor.getRequestFormatter(); - - HttpRequestFactory requestFactory; - Credentials credentials = httpJsonCallOptions.getCredentials(); - if (credentials != null) { - requestFactory = httpTransport.createRequestFactory(new HttpCredentialsAdapter(credentials)); - } else { - requestFactory = httpTransport.createRequestFactory(); - } - - JsonFactory jsonFactory = GsonFactory.getDefaultInstance(); - // Create HTTP request body. - String requestBody = requestFormatter.getRequestBody(request); - HttpContent jsonHttpContent; - if (!Strings.isNullOrEmpty(requestBody)) { - jsonFactory.createJsonParser(requestBody).parse(tokenRequest); - jsonHttpContent = - new JsonHttpContent(jsonFactory, tokenRequest) - .setMediaType((new HttpMediaType("application/json"))); - } else { - // Force underlying HTTP lib to set Content-Length header to avoid 411s. - // See EmptyContent.java. - jsonHttpContent = new EmptyContent(); - } - - // Populate URL path and query parameters. - String normalizedEndpoint = normalizeEndpoint(endpoint); - GenericUrl url = new GenericUrl(normalizedEndpoint + requestFormatter.getPath(request)); - Map> queryParams = requestFormatter.getQueryParamNames(request); - for (Entry> queryParam : queryParams.entrySet()) { - if (queryParam.getValue() != null) { - url.set(queryParam.getKey(), queryParam.getValue()); - } - } - - HttpRequest httpRequest = buildRequest(requestFactory, url, jsonHttpContent); - - Instant deadline = httpJsonCallOptions.getDeadline(); - if (deadline != null) { - long readTimeout = Duration.between(Instant.now(), deadline).toMillis(); - if (httpRequest.getReadTimeout() > 0 - && httpRequest.getReadTimeout() < readTimeout - && readTimeout < Integer.MAX_VALUE) { - httpRequest.setReadTimeout((int) readTimeout); - } - } - - for (Map.Entry entry : headers.getHeaders().entrySet()) { - HttpHeadersUtils.setHeader( - httpRequest.getHeaders(), entry.getKey(), (String) entry.getValue()); - } - - httpRequest.setParser(new JsonObjectParser(jsonFactory)); - - return httpRequest; - } - - private HttpRequest buildRequest( - HttpRequestFactory requestFactory, GenericUrl url, HttpContent jsonHttpContent) - throws IOException { - // A workaround to support PATCH request. This assumes support of "X-HTTP-Method-Override" - // header on the server side, which GCP services usually do. - // - // Long story short, the problems is as follows: gax-httpjson depends on NetHttpTransport class - // from google-http-client, which depends on JDK standard java.net.HttpUrlConnection, which does - // not support PATCH http method. - // - // It is a won't fix for JDK8: https://bugs.openjdk.java.net/browse/JDK-8207840. - // A corresponding google-http-client issue: - // https://github.com/googleapis/google-http-java-client/issues/167 - // - // In JDK11 there is java.net.http.HttpRequest with PATCH method support but, gax-httpjson must - // remain compatible with Java 8. - // - // Using "X-HTTP-Method-Override" header is probably the cleanest way to fix it. Other options - // would be: hideous reflection hacks (not a safe option in a generic library, which - // gax-httpjson is), writing own implementation of HttpUrlConnection (fragile and a lot of - // work), depending on v2.ApacheHttpTransport (it has many extra dependencies, does not support - // mtls etc). - String actualHttpMethod = methodDescriptor.getHttpMethod(); - String originalHttpMethod = actualHttpMethod; - if (HttpMethods.PATCH.equals(actualHttpMethod)) { - actualHttpMethod = HttpMethods.POST; - } - HttpRequest httpRequest = requestFactory.buildRequest(actualHttpMethod, url, jsonHttpContent); - if (originalHttpMethod != null && !originalHttpMethod.equals(actualHttpMethod)) { - HttpHeadersUtils.setHeader( - httpRequest.getHeaders(), "X-HTTP-Method-Override", originalHttpMethod); - } - return httpRequest; - } - - // This will be frequently executed, so avoiding using regexps if not necessary. - private String normalizeEndpoint(String rawEndpoint) { - String normalized = rawEndpoint; - // Set protocol as https by default if not set explicitly - if (!normalized.contains("://")) { - normalized = "https://" + normalized; - } - - if (normalized.charAt(normalized.length() - 1) != '/') { - normalized += '/'; - } - - return normalized; - } - - @FunctionalInterface - interface ResultListener { - void setResult(RunnableResult result); - } - - @AutoValue - abstract static class RunnableResult { - @Nullable - abstract HttpJsonMetadata getResponseHeaders(); - - abstract int getStatusCode(); - - @Nullable - abstract InputStream getResponseContent(); - - abstract HttpJsonMetadata getTrailers(); - - public static Builder builder() { - return new AutoValue_HttpRequestRunnable_RunnableResult.Builder(); - } - - @AutoValue.Builder - public abstract static class Builder { - - public abstract Builder setResponseHeaders(HttpJsonMetadata newResponseHeaders); - - public abstract Builder setStatusCode(int newStatusCode); - - public abstract Builder setResponseContent(InputStream newResponseContent); - - public abstract Builder setTrailers(HttpJsonMetadata newTrailers); - - public abstract RunnableResult build(); - } - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpResponseParser.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpResponseParser.java deleted file mode 100644 index b2c3d5fc8..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpResponseParser.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.core.InternalApi; -import com.google.api.core.InternalExtensionOnly; -import com.google.protobuf.TypeRegistry; -import java.io.InputStream; -import java.io.Reader; - -/** Interface for classes that parse parts of HTTP responses into the parameterized message type. */ -@InternalExtensionOnly -public interface HttpResponseParser { - - /** - * Parse the http body content JSON stream into the MessageFormatT. - * - * @param httpContent the body of an HTTP response - * @throws RestSerializationException if failed to parse the {@code httpContent} to a valid {@code - * MessageFormatT} - */ - MessageFormatT parse(InputStream httpContent); - - /** - * Parse the http body content JSON stream into the MessageFormatT. - * - * @param httpContent the body of an HTTP response, represented as an {@link InputStream} - * @param registry type registry with Any fields descriptors - * @throws RestSerializationException if failed to parse the {@code httpContent} to a valid {@code - * MessageFormatT} - */ - MessageFormatT parse(InputStream httpContent, TypeRegistry registry); - - /** - * Parse the http body content JSON reader into the MessageFormatT. - * - * @param httpContent the body of an HTTP response, represented as a {@link Reader} - * @param registry type registry with Any fields descriptors - * @throws RestSerializationException if failed to parse the {@code httpContent} to a valid {@code - * MessageFormatT} - */ - MessageFormatT parse(Reader httpContent, TypeRegistry registry); - - /** - * Serialize an object into an HTTP body, which is written out to output. - * - * @param response the object to serialize - * @throws RestSerializationException if failed to serialize {@code response} to a valid {@code - * String} representation - */ - @InternalApi - String serialize(MessageFormatT response); -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/InstantiatingHttpJsonChannelProvider.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/InstantiatingHttpJsonChannelProvider.java deleted file mode 100644 index 57b0ff128..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/InstantiatingHttpJsonChannelProvider.java +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.client.http.HttpTransport; -import com.google.api.client.http.javanet.NetHttpTransport; -import com.google.api.core.BetaApi; -import com.google.api.core.InternalExtensionOnly; -import com.google.api.gax.core.ExecutorProvider; -import com.google.api.gax.rpc.FixedHeaderProvider; -import com.google.api.gax.rpc.HeaderProvider; -import com.google.api.gax.rpc.TransportChannelProvider; -import com.google.api.gax.rpc.mtls.MtlsProvider; -import com.google.auth.Credentials; -import com.google.common.annotations.VisibleForTesting; -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.security.KeyStore; -import java.util.Map; -import java.util.concurrent.Executor; -import java.util.concurrent.ScheduledExecutorService; - -/** - * InstantiatingHttpJsonChannelProvider is a TransportChannelProvider which constructs a {@link - * ManagedHttpJsonChannel} with a number of configured inputs every time getChannel(...) is called. - * These inputs include a port, a service address, and credentials. - * - *

The credentials can either be supplied directly (by providing a FixedCredentialsProvider to - * Builder.setCredentialsProvider()) or acquired implicitly from Application Default Credentials (by - * providing a GoogleCredentialsProvider to Builder.setCredentialsProvider()). - * - *

The client lib header and generator header values are used to form a value that goes into the - * http header of requests to the service. - */ -@BetaApi -@InternalExtensionOnly -public final class InstantiatingHttpJsonChannelProvider implements TransportChannelProvider { - - private final Executor executor; - private final HeaderProvider headerProvider; - private final HttpJsonInterceptorProvider interceptorProvider; - private final String endpoint; - private final HttpTransport httpTransport; - private final MtlsProvider mtlsProvider; - - private InstantiatingHttpJsonChannelProvider( - Executor executor, - HeaderProvider headerProvider, - HttpJsonInterceptorProvider interceptorProvider, - String endpoint, - HttpTransport httpTransport, - MtlsProvider mtlsProvider) { - this.executor = executor; - this.headerProvider = headerProvider; - this.interceptorProvider = interceptorProvider; - this.endpoint = endpoint; - this.httpTransport = httpTransport; - this.mtlsProvider = mtlsProvider; - } - - /** - * @deprecated If executor is not set, this channel provider will create channels with default - * executor defined in {@link ManagedHttpJsonChannel}. - */ - @Deprecated - @Override - public boolean needsExecutor() { - return executor == null; - } - - @Deprecated - @Override - public TransportChannelProvider withExecutor(ScheduledExecutorService executor) { - return withExecutor((Executor) executor); - } - - @Override - public TransportChannelProvider withExecutor(Executor executor) { - return toBuilder().setExecutor(executor).build(); - } - - @Override - public boolean needsHeaders() { - return headerProvider == null; - } - - @Override - public TransportChannelProvider withHeaders(Map headers) { - return toBuilder().setHeaderProvider(FixedHeaderProvider.create(headers)).build(); - } - - @Override - public boolean needsEndpoint() { - return endpoint == null; - } - - @Override - public TransportChannelProvider withEndpoint(String endpoint) { - return toBuilder().setEndpoint(endpoint).build(); - } - - /** @deprecated REST transport channel doesn't support channel pooling */ - @Deprecated - @Override - public boolean acceptsPoolSize() { - return false; - } - - /** @deprecated REST transport channel doesn't support channel pooling */ - @Deprecated - @Override - public TransportChannelProvider withPoolSize(int size) { - throw new UnsupportedOperationException( - "InstantiatingHttpJsonChannelProvider doesn't allow pool size customization"); - } - - @Override - public String getTransportName() { - return HttpJsonTransportChannel.getHttpJsonTransportName(); - } - - @Override - public HttpJsonTransportChannel getTransportChannel() throws IOException { - if (needsHeaders()) { - throw new IllegalStateException("getTransportChannel() called when needsHeaders() is true"); - } else { - try { - return createChannel(); - } catch (GeneralSecurityException e) { - throw new IOException(e); - } - } - } - - @Override - public boolean needsCredentials() { - return false; - } - - @Override - public TransportChannelProvider withCredentials(Credentials credentials) { - throw new UnsupportedOperationException( - "InstantiatingHttpJsonChannelProvider doesn't need credentials"); - } - - HttpTransport createHttpTransport() throws IOException, GeneralSecurityException { - if (mtlsProvider.useMtlsClientCertificate()) { - KeyStore mtlsKeyStore = mtlsProvider.getKeyStore(); - if (mtlsKeyStore != null) { - return new NetHttpTransport.Builder().trustCertificates(null, mtlsKeyStore, "").build(); - } - } - return null; - } - - private HttpJsonTransportChannel createChannel() throws IOException, GeneralSecurityException { - HttpTransport httpTransportToUse = httpTransport; - if (httpTransportToUse == null) { - httpTransportToUse = createHttpTransport(); - } - - ManagedHttpJsonChannel channel = - ManagedHttpJsonChannel.newBuilder() - .setEndpoint(endpoint) - .setExecutor(executor) - .setHttpTransport(httpTransportToUse) - .build(); - - HttpJsonClientInterceptor headerInterceptor = - new HttpJsonHeaderInterceptor(headerProvider.getHeaders()); - - channel = new ManagedHttpJsonInterceptorChannel(channel, headerInterceptor); - if (interceptorProvider != null && interceptorProvider.getInterceptors() != null) { - for (HttpJsonClientInterceptor interceptor : interceptorProvider.getInterceptors()) { - channel = new ManagedHttpJsonInterceptorChannel(channel, interceptor); - } - } - - return HttpJsonTransportChannel.newBuilder().setManagedChannel(channel).build(); - } - - /** The endpoint to be used for the channel. */ - public String getEndpoint() { - return endpoint; - } - - @Override - public boolean shouldAutoClose() { - return true; - } - - public Builder toBuilder() { - return new Builder(this); - } - - public static Builder newBuilder() { - return new Builder(); - } - - public static final class Builder { - - private Executor executor; - private HeaderProvider headerProvider; - private HttpJsonInterceptorProvider interceptorProvider; - private String endpoint; - private HttpTransport httpTransport; - private MtlsProvider mtlsProvider = new MtlsProvider(); - - private Builder() {} - - private Builder(InstantiatingHttpJsonChannelProvider provider) { - this.executor = provider.executor; - this.headerProvider = provider.headerProvider; - this.endpoint = provider.endpoint; - this.httpTransport = provider.httpTransport; - this.mtlsProvider = provider.mtlsProvider; - this.interceptorProvider = provider.interceptorProvider; - } - - /** - * Sets the Executor for this TransportChannelProvider. - * - *

This is optional; if it is not provided, needsExecutor() will return true, meaning that an - * Executor must be provided when getChannel is called on the constructed - * TransportChannelProvider instance. Note: InstantiatingHttpJsonChannelProvider will - * automatically provide its own Executor in this circumstance when it calls getChannel. - */ - public Builder setExecutor(Executor executor) { - this.executor = executor; - return this; - } - - /** @deprecated Please use {@link #setExecutor(Executor)}. */ - @Deprecated - public Builder setExecutorProvider(ExecutorProvider executorProvider) { - return setExecutor((Executor) executorProvider.getExecutor()); - } - - /** - * Sets the HeaderProvider for this TransportChannelProvider. - * - *

This is optional; if it is not provided, needsHeaders() will return true, meaning that - * headers must be provided when getChannel is called on the constructed - * TransportChannelProvider instance. - */ - public Builder setHeaderProvider(HeaderProvider headerProvider) { - this.headerProvider = headerProvider; - return this; - } - - /** - * Sets the GrpcInterceptorProvider for this TransportChannelProvider. - * - *

The provider will be called once for each underlying gRPC ManagedChannel that is created. - * It is recommended to return a new list of new interceptors on each call so that interceptors - * are not shared among channels, but this is not required. - */ - public Builder setInterceptorProvider(HttpJsonInterceptorProvider interceptorProvider) { - this.interceptorProvider = interceptorProvider; - return this; - } - - /** Sets the endpoint used to reach the service, eg "localhost:8080". */ - public Builder setEndpoint(String endpoint) { - this.endpoint = endpoint; - return this; - } - - /** Sets the HTTP transport to be used. */ - public Builder setHttpTransport(HttpTransport httpTransport) { - this.httpTransport = httpTransport; - return this; - } - - public String getEndpoint() { - return endpoint; - } - - @VisibleForTesting - Builder setMtlsProvider(MtlsProvider mtlsProvider) { - this.mtlsProvider = mtlsProvider; - return this; - } - - public InstantiatingHttpJsonChannelProvider build() { - return new InstantiatingHttpJsonChannelProvider( - executor, headerProvider, interceptorProvider, endpoint, httpTransport, mtlsProvider); - } - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ManagedHttpJsonChannel.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ManagedHttpJsonChannel.java deleted file mode 100644 index 6fb4200d3..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ManagedHttpJsonChannel.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.client.http.HttpTransport; -import com.google.api.client.http.javanet.NetHttpTransport; -import com.google.api.core.BetaApi; -import com.google.api.gax.core.BackgroundResource; -import com.google.api.gax.core.InstantiatingExecutorProvider; -import com.google.common.base.Preconditions; -import java.io.IOException; -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.TimeUnit; -import javax.annotation.Nullable; - -/** Implementation of HttpJsonChannel which can issue http-json calls. */ -@BetaApi -public class ManagedHttpJsonChannel implements HttpJsonChannel, BackgroundResource { - - private static final ExecutorService DEFAULT_EXECUTOR = - InstantiatingExecutorProvider.newBuilder().build().getExecutor(); - - private final Executor executor; - private final String endpoint; - private final HttpTransport httpTransport; - - private boolean isTransportShutdown; - - protected ManagedHttpJsonChannel() { - this(null, null, null); - } - - private ManagedHttpJsonChannel( - Executor executor, String endpoint, @Nullable HttpTransport httpTransport) { - this.executor = executor; - this.endpoint = endpoint; - this.httpTransport = httpTransport == null ? new NetHttpTransport() : httpTransport; - } - - @Override - public HttpJsonClientCall newCall( - ApiMethodDescriptor methodDescriptor, HttpJsonCallOptions callOptions) { - - return new HttpJsonClientCallImpl<>( - methodDescriptor, endpoint, callOptions, httpTransport, executor); - } - - @Override - public synchronized void shutdown() { - if (isTransportShutdown) { - return; - } - try { - httpTransport.shutdown(); - isTransportShutdown = true; - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public boolean isShutdown() { - return isTransportShutdown; - } - - @Override - public boolean isTerminated() { - return isTransportShutdown; - } - - @Override - public void shutdownNow() { - shutdown(); - } - - @Override - public boolean awaitTermination(long duration, TimeUnit unit) throws InterruptedException { - // TODO - return false; - } - - @Override - public void close() {} - - public static Builder newBuilder() { - return new Builder().setExecutor(DEFAULT_EXECUTOR); - } - - public static class Builder { - - private Executor executor; - private String endpoint; - private HttpTransport httpTransport; - - private Builder() {} - - public Builder setExecutor(Executor executor) { - this.executor = executor == null ? DEFAULT_EXECUTOR : executor; - return this; - } - - public Builder setEndpoint(String endpoint) { - this.endpoint = endpoint; - return this; - } - - public Builder setHttpTransport(HttpTransport httpTransport) { - this.httpTransport = httpTransport; - return this; - } - - public ManagedHttpJsonChannel build() { - Preconditions.checkNotNull(endpoint); - - return new ManagedHttpJsonChannel( - executor, endpoint, httpTransport == null ? new NetHttpTransport() : httpTransport); - } - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ManagedHttpJsonInterceptorChannel.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ManagedHttpJsonInterceptorChannel.java deleted file mode 100644 index 05321e2fd..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ManagedHttpJsonInterceptorChannel.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.core.BetaApi; -import java.util.concurrent.TimeUnit; - -@BetaApi -class ManagedHttpJsonInterceptorChannel extends ManagedHttpJsonChannel { - - private final ManagedHttpJsonChannel channel; - private final HttpJsonClientInterceptor interceptor; - - ManagedHttpJsonInterceptorChannel( - ManagedHttpJsonChannel channel, HttpJsonClientInterceptor interceptor) { - super(); - this.channel = channel; - this.interceptor = interceptor; - } - - @Override - public HttpJsonClientCall newCall( - ApiMethodDescriptor methodDescriptor, HttpJsonCallOptions callOptions) { - return interceptor.interceptCall(methodDescriptor, callOptions, channel); - } - - @Override - public synchronized void shutdown() { - channel.shutdown(); - } - - @Override - public boolean isShutdown() { - return channel.isShutdown(); - } - - @Override - public boolean isTerminated() { - return channel.isTerminated(); - } - - @Override - public void shutdownNow() { - channel.shutdownNow(); - } - - @Override - public boolean awaitTermination(long duration, TimeUnit unit) throws InterruptedException { - return channel.awaitTermination(duration, unit); - } - - @Override - public void close() { - channel.close(); - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/OperationSnapshotFactory.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/OperationSnapshotFactory.java deleted file mode 100644 index 21a746c51..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/OperationSnapshotFactory.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.gax.longrunning.OperationSnapshot; - -/** - * A factory which creates an {@link OperationSnapshot} from an initial request message (the one - * which started a long running operation) and an operation response (which may be either initial - * request response or the polling request response). - * - *

Public for technical reasons. For internal use only. - * - * @param initial request message type - * @param initial or polling response type - */ -public interface OperationSnapshotFactory { - OperationSnapshot create(RequestT request, OperationT response); -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/PollingRequestFactory.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/PollingRequestFactory.java deleted file mode 100644 index f5a6e9c8d..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/PollingRequestFactory.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -/** - * A factory which creates a subsequent polling request from a compund operation id. - * - * @param polling request type - */ -public interface PollingRequestFactory { - /** - * Creates a polling request message from a {@code compoundOperationId}. - * - * @param compoundOperationId the compound operation ID, consisting of an operation name and - * potentially any other relevant information delimited by a ':' * character - */ - RequestT create(String compoundOperationId); -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ProtoMessageJsonStreamIterator.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ProtoMessageJsonStreamIterator.java deleted file mode 100644 index 84167de5e..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ProtoMessageJsonStreamIterator.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonToken; -import com.google.gson.stream.JsonWriter; -import java.io.Closeable; -import java.io.IOException; -import java.io.PipedReader; -import java.io.PipedWriter; -import java.io.Reader; -import java.util.Iterator; - -/** This class is not thread-safe and is expected to be used under external synchronization. */ -class ProtoMessageJsonStreamIterator implements Closeable, Iterator { - private volatile boolean arrayStarted; - private final JsonReader jsonReader; - private final PipedReader reader; - private final PipedWriter writer; - - ProtoMessageJsonStreamIterator(Reader rawReader) throws IOException { - this.arrayStarted = false; - this.jsonReader = new JsonReader(rawReader); - this.reader = new PipedReader(0x40000); // 256K - this.writer = new PipedWriter(); - writer.connect(reader); - } - - @Override - public void close() throws IOException { - reader.close(); - writer.close(); - jsonReader.close(); - } - - public boolean hasNext() { - try { - if (!arrayStarted) { - jsonReader.beginArray(); - arrayStarted = true; - } - return jsonReader.hasNext(); - } catch (IOException e) { - throw new RestSerializationException(e); - } - } - - @Override - public Reader next() { - try { - int nestedObjectCount = 0; - JsonWriter jsonWriter = new JsonWriter(writer); - do { - JsonToken token = jsonReader.peek(); - switch (token) { - case BEGIN_ARRAY: - jsonReader.beginArray(); - jsonWriter.beginArray(); - break; - case END_ARRAY: - jsonReader.endArray(); - jsonWriter.endArray(); - break; - case BEGIN_OBJECT: - nestedObjectCount++; - jsonReader.beginObject(); - jsonWriter.beginObject(); - break; - case END_OBJECT: - jsonReader.endObject(); - jsonWriter.endObject(); - nestedObjectCount--; - break; - case NAME: - String name = jsonReader.nextName(); - jsonWriter.name(name); - break; - case STRING: - String s = jsonReader.nextString(); - jsonWriter.value(s); - break; - case NUMBER: - String n = jsonReader.nextString(); - jsonWriter.value(n); - break; - case BOOLEAN: - boolean b = jsonReader.nextBoolean(); - jsonWriter.value(b); - break; - case NULL: - jsonReader.nextNull(); - jsonWriter.nullValue(); - break; - case END_DOCUMENT: - nestedObjectCount--; - } - } while (nestedObjectCount > 0); - - jsonWriter.flush(); - - return reader; - } catch (IOException e) { - throw new RestSerializationException(e); - } - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ProtoMessageRequestFormatter.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ProtoMessageRequestFormatter.java deleted file mode 100644 index f04a16edb..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ProtoMessageRequestFormatter.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.core.BetaApi; -import com.google.api.core.InternalApi; -import com.google.api.pathtemplate.PathTemplate; -import com.google.protobuf.Message; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** Creates parts of a HTTP request from a protobuf message. */ -public class ProtoMessageRequestFormatter - implements HttpRequestFormatter { - - private final FieldsExtractor requestBodyExtractor; - // Using of triple nested generics (which is not pretty) is predetermined by the - // Map> returned value type of the getQueryParamNames interface method - // implemented by this class. - private final FieldsExtractor>> queryParamsExtractor; - private final String rawPath; - private final PathTemplate pathTemplate; - private final FieldsExtractor> pathVarsExtractor; - private final List additionalRawPaths; - private final List additionalPathTemplates; - - private ProtoMessageRequestFormatter( - FieldsExtractor requestBodyExtractor, - FieldsExtractor>> queryParamsExtractor, - String rawPath, - PathTemplate pathTemplate, - FieldsExtractor> pathVarsExtractor, - List additionalRawPaths, - List additionalPathTemplates) { - this.requestBodyExtractor = requestBodyExtractor; - this.queryParamsExtractor = queryParamsExtractor; - this.rawPath = rawPath; - this.pathTemplate = pathTemplate; - this.pathVarsExtractor = pathVarsExtractor; - this.additionalRawPaths = additionalRawPaths; - this.additionalPathTemplates = additionalPathTemplates; - } - - public static - ProtoMessageRequestFormatter.Builder newBuilder() { - return new Builder().setAdditionalPaths(); - } - - public Builder toBuilder() { - return new Builder() - .setPath(rawPath, pathVarsExtractor) - .setAdditionalPaths(additionalRawPaths.toArray(new String[] {})) - .setQueryParamsExtractor(queryParamsExtractor) - .setRequestBodyExtractor(requestBodyExtractor); - } - - /* {@inheritDoc} */ - @Override - public Map> getQueryParamNames(RequestT apiMessage) { - return queryParamsExtractor.extract(apiMessage); - } - - /* {@inheritDoc} */ - @Override - public String getRequestBody(RequestT apiMessage) { - return requestBodyExtractor.extract(apiMessage); - } - - /* {@inheritDoc} */ - @Override - public String getPath(RequestT apiMessage) { - return pathTemplate.instantiate(pathVarsExtractor.extract(apiMessage)); - } - - @BetaApi - @Override - public List getAdditionalPathTemplates() { - return additionalPathTemplates; - } - - /* {@inheritDoc} */ - @Override - public PathTemplate getPathTemplate() { - return pathTemplate; - } - - // This has class has compound setter methods (multiple arguments in setters), that is why not - // using @AutoValue. - public static class Builder { - private FieldsExtractor requestBodyExtractor; - private FieldsExtractor>> queryParamsExtractor; - private String rawPath; - private FieldsExtractor> pathVarsExtractor; - private List rawAdditionalPaths; - - public Builder setRequestBodyExtractor( - FieldsExtractor requestBodyExtractor) { - this.requestBodyExtractor = requestBodyExtractor; - return this; - } - - public Builder setQueryParamsExtractor( - FieldsExtractor>> queryParamsExtractor) { - this.queryParamsExtractor = queryParamsExtractor; - return this; - } - - public Builder setPath( - String rawPath, FieldsExtractor> pathVarsExtractor) { - this.rawPath = rawPath; - this.pathVarsExtractor = pathVarsExtractor; - return this; - } - - @BetaApi - public Builder setAdditionalPaths(String... rawAdditionalPaths) { - this.rawAdditionalPaths = Arrays.asList(rawAdditionalPaths); - return this; - } - - @InternalApi - public Builder updateRawPath(String target, String replacement) { - this.rawPath = this.rawPath.replace(target, replacement); - return this; - } - - public ProtoMessageRequestFormatter build() { - return new ProtoMessageRequestFormatter<>( - requestBodyExtractor, - queryParamsExtractor, - rawPath, - PathTemplate.create(rawPath), - pathVarsExtractor, - rawAdditionalPaths, - rawAdditionalPaths.stream().map(PathTemplate::create).collect(Collectors.toList())); - } - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ProtoMessageResponseParser.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ProtoMessageResponseParser.java deleted file mode 100644 index 815d19c7a..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ProtoMessageResponseParser.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.protobuf.Message; -import com.google.protobuf.TypeRegistry; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.nio.charset.StandardCharsets; - -/** The implementation of {@link HttpResponseParser} which works with protobuf messages. */ -public class ProtoMessageResponseParser - implements HttpResponseParser { - - private final ResponseT defaultInstance; - private final TypeRegistry defaultRegistry; - - private ProtoMessageResponseParser(ResponseT defaultInstance, TypeRegistry defaultRegistry) { - this.defaultInstance = defaultInstance; - this.defaultRegistry = defaultRegistry; - } - - public static - ProtoMessageResponseParser.Builder newBuilder() { - return new ProtoMessageResponseParser.Builder() - .setDefaultTypeRegistry(TypeRegistry.getEmptyTypeRegistry()); - } - - /* {@inheritDoc} */ - @Override - public ResponseT parse(InputStream httpContent) { - return parse(httpContent, defaultRegistry); - } - - @Override - public ResponseT parse(InputStream httpContent, TypeRegistry registry) { - try (Reader json = new InputStreamReader(httpContent, StandardCharsets.UTF_8)) { - return parse(json, registry); - } catch (IOException e) { - throw new RestSerializationException("Failed to parse response message", e); - } - } - - @Override - public ResponseT parse(Reader httpContent, TypeRegistry registry) { - return ProtoRestSerializer.create(registry) - .fromJson(httpContent, defaultInstance.newBuilderForType()); - } - - /* {@inheritDoc} */ - @Override - public String serialize(ResponseT response) { - return ProtoRestSerializer.create(defaultRegistry).toJson(response, false); - } - - // Convert to @AutoValue if this class gets more complicated - public static class Builder { - private ResponseT defaultInstance; - private TypeRegistry defaultRegistry; - - public Builder setDefaultInstance(ResponseT defaultInstance) { - this.defaultInstance = defaultInstance; - return this; - } - - public Builder setDefaultTypeRegistry(TypeRegistry defaultRegistry) { - this.defaultRegistry = defaultRegistry; - return this; - } - - public ProtoMessageResponseParser build() { - return new ProtoMessageResponseParser<>(defaultInstance, defaultRegistry); - } - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ProtoOperationTransformers.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ProtoOperationTransformers.java deleted file mode 100644 index a5a3e436c..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ProtoOperationTransformers.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.core.ApiFunction; -import com.google.api.gax.longrunning.OperationSnapshot; -import com.google.api.gax.rpc.ApiExceptionFactory; -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.protobuf.Any; -import com.google.protobuf.InvalidProtocolBufferException; -import com.google.protobuf.Message; - -/** Public for technical reasons; intended for use by generated code. */ -public class ProtoOperationTransformers { - private ProtoOperationTransformers() {} - - public static class ResponseTransformer - implements ApiFunction { - private final AnyTransformer transformer; - - private ResponseTransformer(Class packedClass) { - this.transformer = new AnyTransformer<>(packedClass); - } - - @Override - public ResponseT apply(OperationSnapshot operationSnapshot) { - if (!operationSnapshot.getErrorCode().getCode().equals(Code.OK)) { - throw ApiExceptionFactory.createException( - "Operation with name \"" - + operationSnapshot.getName() - + "\" failed with status = " - + operationSnapshot.getErrorCode() - + " and message = " - + operationSnapshot.getErrorMessage(), - null, - operationSnapshot.getErrorCode(), - false); - } - - if (!(operationSnapshot.getResponse() instanceof Any)) { - return (ResponseT) operationSnapshot.getResponse(); - } - - try { - return transformer.apply((Any) operationSnapshot.getResponse()); - } catch (RuntimeException e) { - throw ApiExceptionFactory.createException( - "Operation with name \"" - + operationSnapshot.getName() - + "\" succeeded, but encountered a problem unpacking it.", - e, - operationSnapshot.getErrorCode(), - false); - } - } - - public static ResponseTransformer create( - Class packedClass) { - return new ResponseTransformer<>(packedClass); - } - } - - public static class MetadataTransformer - implements ApiFunction { - private final AnyTransformer transformer; - - private MetadataTransformer(Class packedClass) { - this.transformer = new AnyTransformer<>(packedClass); - } - - @Override - public MetadataT apply(OperationSnapshot operationSnapshot) { - if (!(operationSnapshot.getMetadata() instanceof Any)) { - return (MetadataT) operationSnapshot.getMetadata(); - } - try { - return transformer.apply((Any) operationSnapshot.getMetadata()); - } catch (RuntimeException e) { - throw ApiExceptionFactory.createException( - "Polling operation with name \"" - + operationSnapshot.getName() - + "\" succeeded, but encountered a problem unpacking it.", - e, - operationSnapshot.getErrorCode(), - false); - } - } - - public static MetadataTransformer create( - Class packedClass) { - return new MetadataTransformer<>(packedClass); - } - } - - static class AnyTransformer implements ApiFunction { - private final Class packedClass; - - public AnyTransformer(Class packedClass) { - this.packedClass = packedClass; - } - - @Override - public PackedT apply(Any input) { - try { - return input == null || packedClass == null ? null : input.unpack(packedClass); - } catch (InvalidProtocolBufferException | ClassCastException e) { - throw new IllegalStateException( - "Failed to unpack object from 'any' field. Expected " - + packedClass.getName() - + ", found " - + input.getTypeUrl()); - } - } - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ProtoRestSerializer.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ProtoRestSerializer.java deleted file mode 100644 index 0c5158f76..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ProtoRestSerializer.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.core.BetaApi; -import com.google.common.collect.ImmutableList; -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import com.google.protobuf.InvalidProtocolBufferException; -import com.google.protobuf.Message; -import com.google.protobuf.TypeRegistry; -import com.google.protobuf.util.JsonFormat; -import com.google.protobuf.util.JsonFormat.Printer; -import java.io.IOException; -import java.io.Reader; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * This class serializes/deserializes protobuf {@link Message} for REST interactions. It serializes - * requests protobuf messages into REST messages, splitting the message into the JSON request body, - * URL path parameters, and query parameters. It deserializes JSON responses into response protobuf - * message. - */ -@BetaApi -public class ProtoRestSerializer { - - private final TypeRegistry registry; - - private ProtoRestSerializer(TypeRegistry registry) { - this.registry = registry; - } - - /** Creates a new instance of ProtoRestSerializer. */ - public static ProtoRestSerializer create() { - return create(TypeRegistry.getEmptyTypeRegistry()); - } - - /** Creates a new instance of ProtoRestSerializer. */ - static ProtoRestSerializer create(TypeRegistry registry) { - return new ProtoRestSerializer<>(registry); - } - - /** - * Serializes the data from {@code message} to a JSON string. The implementation relies on - * protobuf native JSON formatter. - * - * @param message a message to serialize - * @param numericEnum a boolean flag that determine if enum values should be serialized to number - * or not - * @throws InvalidProtocolBufferException if failed to serialize the protobuf message to JSON - * format - */ - String toJson(Message message, boolean numericEnum) { - try { - Printer printer = JsonFormat.printer().usingTypeRegistry(registry); - if (numericEnum) { - return printer.printingEnumsAsInts().print(message); - } else { - return printer.print(message); - } - } catch (InvalidProtocolBufferException e) { - throw new RestSerializationException("Failed to serialize message to JSON", e); - } - } - - /** - * Deserializes a {@code message} from an input stream to a protobuf message. - * - * @param json the input reader with a JSON-encoded message in it - * @param builder an empty builder for the specific {@code RequestT} message to serialize - * @throws RestSerializationException if failed to deserialize a protobuf message from the JSON - * stream - */ - @SuppressWarnings("unchecked") - RequestT fromJson(Reader json, Message.Builder builder) { - try { - JsonFormat.parser().usingTypeRegistry(registry).ignoringUnknownFields().merge(json, builder); - return (RequestT) builder.build(); - } catch (IOException e) { - throw new RestSerializationException("Failed to parse response message", e); - } - } - - /** - * Puts a message field in {@code fields} map which will be used to populate URL path of a - * request. - * - * @param fields a map with serialized fields - * @param fieldName a field name - * @param fieldValue a field value - */ - public void putPathParam(Map fields, String fieldName, Object fieldValue) { - fields.put(fieldName, String.valueOf(fieldValue)); - } - - private void putDecomposedMessageQueryParam( - Map> fields, String fieldName, JsonElement parsed) { - if (parsed.isJsonPrimitive() || parsed.isJsonNull()) { - putQueryParam(fields, fieldName, parsed.getAsString()); - } else if (parsed.isJsonArray()) { - for (JsonElement element : parsed.getAsJsonArray()) { - putDecomposedMessageQueryParam(fields, fieldName, element); - } - } else { - // it is a json object - for (String key : parsed.getAsJsonObject().keySet()) { - putDecomposedMessageQueryParam( - fields, String.format("%s.%s", fieldName, key), parsed.getAsJsonObject().get(key)); - } - } - } - - /** - * Puts a message field in {@code fields} map which will be used to populate query parameters of a - * request. - * - * @param fields a map with serialized fields - * @param fieldName a field name - * @param fieldValue a field value - */ - public void putQueryParam(Map> fields, String fieldName, Object fieldValue) { - List currentParamValueList = new ArrayList<>(); - List toProcess = - fieldValue instanceof List ? (List) fieldValue : ImmutableList.of(fieldValue); - for (Object fieldValueItem : toProcess) { - if (fieldValueItem instanceof Message) { - String json = toJson(((Message) fieldValueItem), true); - JsonElement parsed = JsonParser.parseString(json); - putDecomposedMessageQueryParam(fields, fieldName, parsed); - } else { - currentParamValueList.add(String.valueOf(fieldValueItem)); - } - } - if (currentParamValueList.isEmpty()) { - // We try to avoid putting non-leaf level fields to the query params - return; - } - List accumulativeParamValueList = fields.getOrDefault(fieldName, new ArrayList<>()); - accumulativeParamValueList.addAll(currentParamValueList); - fields.put(fieldName, accumulativeParamValueList); - } - - /** - * Serializes a message to a request body in a form of JSON-encoded string. - * - * @param fieldName a name of a request message field this message belongs to - * @param fieldValue a field value to serialize - */ - public String toBody(String fieldName, RequestT fieldValue) { - return toJson(fieldValue, false); - } - - /** - * Serializes a message to a request body in a form of JSON-encoded string. - * - * @param fieldName a name of a request message field this message belongs to - * @param fieldValue a field value to serialize - * @param numericEnum a boolean flag that determine if enum values should be serialized to number - */ - public String toBody(String fieldName, RequestT fieldValue, boolean numericEnum) { - return toJson(fieldValue, numericEnum); - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/RestSerializationException.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/RestSerializationException.java deleted file mode 100644 index 7f5252595..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/RestSerializationException.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.core.BetaApi; - -/** - * An exception thrown when a protobuf message cannot be serialized/deserialized for REST - * interactions. - */ -@BetaApi -public class RestSerializationException extends RuntimeException { - - private static final long serialVersionUID = -6485633460933364916L; - - public RestSerializationException(Throwable cause) { - super(cause); - } - - public RestSerializationException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/longrunning/OperationsClient.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/longrunning/OperationsClient.java deleted file mode 100644 index fe5093c19..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/longrunning/OperationsClient.java +++ /dev/null @@ -1,655 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson.longrunning; - -import com.google.api.core.ApiFunction; -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.api.core.BetaApi; -import com.google.api.gax.core.BackgroundResource; -import com.google.api.gax.httpjson.longrunning.stub.OperationsStub; -import com.google.api.gax.httpjson.longrunning.stub.OperationsStubSettings; -import com.google.api.gax.paging.AbstractFixedSizeCollection; -import com.google.api.gax.paging.AbstractPage; -import com.google.api.gax.paging.AbstractPagedListResponse; -import com.google.api.gax.rpc.PageContext; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.common.util.concurrent.MoreExecutors; -import com.google.longrunning.CancelOperationRequest; -import com.google.longrunning.DeleteOperationRequest; -import com.google.longrunning.GetOperationRequest; -import com.google.longrunning.ListOperationsRequest; -import com.google.longrunning.ListOperationsResponse; -import com.google.longrunning.Operation; -import com.google.protobuf.Empty; -import java.io.IOException; -import java.util.List; -import java.util.concurrent.TimeUnit; - -// AUTO-GENERATED DOCUMENTATION AND CLASS. -/** - * Service Description: Manages long-running operations with an API service. - * - *

When an API method normally takes long time to complete, it can be designed to return - * [Operation][google.longrunning.Operation] to the client, and the client can use this interface to - * receive the real response asynchronously by polling the operation resource, or pass the operation - * resource to another API (such as Google Cloud Pub/Sub API) to receive the response. Any API - * service that returns long-running operations should implement the `Operations` interface so - * developers can have a consistent client experience. - * - *

This class provides the ability to make remote calls to the backing service through method - * calls that map to API methods. Sample code to get started: - * - *

{@code
- * try (OperationsClient operationsClient = OperationsClient.create()) {
- *   String name = "name3373707";
- *   Operation response = operationsClient.getOperation(name);
- * }
- * }
- * - *

Note: close() needs to be called on the OperationsClient object to clean up resources such as - * threads. In the example above, try-with-resources is used, which automatically calls close(). - * - *

The surface of this class includes several types of Java methods for each of the API's - * methods: - * - *

    - *
  1. A "flattened" method. With this type of method, the fields of the request type have been - * converted into function parameters. It may be the case that not all fields are available as - * parameters, and not every API method will have a flattened method entry point. - *
  2. A "request object" method. This type of method only takes one parameter, a request object, - * which must be constructed before the call. Not every API method will have a request object - * method. - *
  3. A "callable" method. This type of method takes no parameters and returns an immutable API - * callable object, which can be used to initiate calls to the service. - *
- * - *

See the individual methods for example code. - * - *

Many parameters require resource names to be formatted in a particular way. To assist with - * these names, this class includes a format method for each type of name, and additionally a parse - * method to extract the individual identifiers contained within names that are returned. - * - *

This class can be customized by passing in a custom instance of OperationsSettings to - * create(). For example: - * - *

To customize credentials: - * - *

{@code
- * OperationsSettings operationsSettings =
- *     OperationsSettings.newBuilder()
- *         .setCredentialsProvider(FixedCredentialsProvider.create(myCredentials))
- *         .build();
- * OperationsClient operationsClient = OperationsClient.create(operationsSettings);
- * }
- * - *

To customize the endpoint: - * - *

{@code
- * OperationsSettings operationsSettings =
- *     OperationsSettings.newBuilder().setEndpoint(myEndpoint).build();
- * OperationsClient operationsClient = OperationsClient.create(operationsSettings);
- * }
- * - *

Please refer to the GitHub repository's samples for more quickstart code snippets. - */ -@BetaApi -public class OperationsClient implements BackgroundResource { - private final OperationsSettings settings; - private final OperationsStub stub; - - /** Constructs an instance of OperationsClient with default settings. */ - public static final OperationsClient create() throws IOException { - return create(OperationsSettings.newBuilder().build()); - } - - /** - * Constructs an instance of OperationsClient, using the given settings. The channels are created - * based on the settings passed in, or defaults for any settings that are not set. - */ - public static final OperationsClient create(OperationsSettings settings) throws IOException { - return new OperationsClient(settings); - } - - /** - * Constructs an instance of OperationsClient, using the given stub for making calls. This is for - * advanced usage - prefer using create(OperationsSettings). - */ - public static final OperationsClient create(OperationsStub stub) { - return new OperationsClient(stub); - } - - /** - * Constructs an instance of OperationsClient, using the given stub for making calls. This is for - * advanced usage - prefer using create(OperationsSettings). - */ - public static final OperationsClient create(BackgroundResource stub) { - return new OperationsClient((OperationsStub) stub); - } - - /** - * Constructs an instance of OperationsClient, using the given settings. This is protected so that - * it is easy to make a subclass, but otherwise, the static factory methods should be preferred. - */ - protected OperationsClient(OperationsSettings settings) throws IOException { - this.settings = settings; - this.stub = ((OperationsStubSettings) settings.getStubSettings()).createStub(); - } - - @BetaApi("A restructuring of stub classes is planned, so this may break in the future") - protected OperationsClient(OperationsStub stub) { - this.settings = null; - this.stub = stub; - } - - public final OperationsSettings getSettings() { - return settings; - } - - @BetaApi("A restructuring of stub classes is planned, so this may break in the future") - public OperationsStub getStub() { - return stub; - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD. - /** - * Lists operations that match the specified filter in the request. If the server doesn't support - * this method, it returns `UNIMPLEMENTED`. - * - *

NOTE: the `name` binding allows API services to override the binding to use different - * resource name schemes, such as `users/*/operations`. To override the binding, API services - * can add a binding such as `"/v1/{name=users/*}/operations"` to their service configuration. - * For backwards compatibility, the default name includes the operations collection id, however - * overriding users must ensure the name binding is the parent resource, without the operations - * collection id. - * - *

Sample code: - * - *

{@code
-   * try (OperationsClient operationsClient = OperationsClient.create()) {
-   *   String name = "name3373707";
-   *   String filter = "filter-1274492040";
-   *   for (Operation element : operationsClient.listOperations(name, filter).iterateAll()) {
-   *     // doThingsWith(element);
-   *   }
-   * }
-   * }
- * - * @param name The name of the operation's parent resource. - * @param filter The standard list filter. - * @throws com.google.api.gax.rpc.ApiException if the remote call fails - */ - public final ListOperationsPagedResponse listOperations(String name, String filter) { - ListOperationsRequest request = - ListOperationsRequest.newBuilder().setName(name).setFilter(filter).build(); - return listOperations(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD. - /** - * Lists operations that match the specified filter in the request. If the server doesn't support - * this method, it returns `UNIMPLEMENTED`. - * - *

NOTE: the `name` binding allows API services to override the binding to use different - * resource name schemes, such as `users/*/operations`. To override the binding, API services - * can add a binding such as `"/v1/{name=users/*}/operations"` to their service configuration. - * For backwards compatibility, the default name includes the operations collection id, however - * overriding users must ensure the name binding is the parent resource, without the operations - * collection id. - * - *

Sample code: - * - *

{@code
-   * try (OperationsClient operationsClient = OperationsClient.create()) {
-   *   ListOperationsRequest request =
-   *       ListOperationsRequest.newBuilder()
-   *           .setName("name3373707")
-   *           .setFilter("filter-1274492040")
-   *           .setPageSize(883849137)
-   *           .setPageToken("pageToken873572522")
-   *           .build();
-   *   for (Operation element : operationsClient.listOperations(request).iterateAll()) {
-   *     // doThingsWith(element);
-   *   }
-   * }
-   * }
- * - * @param request The request object containing all of the parameters for the API call. - * @throws com.google.api.gax.rpc.ApiException if the remote call fails - */ - public final ListOperationsPagedResponse listOperations(ListOperationsRequest request) { - return listOperationsPagedCallable().call(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD. - /** - * Lists operations that match the specified filter in the request. If the server doesn't support - * this method, it returns `UNIMPLEMENTED`. - * - *

NOTE: the `name` binding allows API services to override the binding to use different - * resource name schemes, such as `users/*/operations`. To override the binding, API services - * can add a binding such as `"/v1/{name=users/*}/operations"` to their service configuration. - * For backwards compatibility, the default name includes the operations collection id, however - * overriding users must ensure the name binding is the parent resource, without the operations - * collection id. - * - *

Sample code: - * - *

{@code
-   * try (OperationsClient operationsClient = OperationsClient.create()) {
-   *   ListOperationsRequest request =
-   *       ListOperationsRequest.newBuilder()
-   *           .setName("name3373707")
-   *           .setFilter("filter-1274492040")
-   *           .setPageSize(883849137)
-   *           .setPageToken("pageToken873572522")
-   *           .build();
-   *   ApiFuture future =
-   *       operationsClient.listOperationsPagedCallable().futureCall(request);
-   *   // Do something.
-   *   for (Operation element : future.get().iterateAll()) {
-   *     // doThingsWith(element);
-   *   }
-   * }
-   * }
- */ - public final UnaryCallable - listOperationsPagedCallable() { - return stub.listOperationsPagedCallable(); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD. - /** - * Lists operations that match the specified filter in the request. If the server doesn't support - * this method, it returns `UNIMPLEMENTED`. - * - *

NOTE: the `name` binding allows API services to override the binding to use different - * resource name schemes, such as `users/*/operations`. To override the binding, API services - * can add a binding such as `"/v1/{name=users/*}/operations"` to their service configuration. - * For backwards compatibility, the default name includes the operations collection id, however - * overriding users must ensure the name binding is the parent resource, without the operations - * collection id. - * - *

Sample code: - * - *

{@code
-   * try (OperationsClient operationsClient = OperationsClient.create()) {
-   *   ListOperationsRequest request =
-   *       ListOperationsRequest.newBuilder()
-   *           .setName("name3373707")
-   *           .setFilter("filter-1274492040")
-   *           .setPageSize(883849137)
-   *           .setPageToken("pageToken873572522")
-   *           .build();
-   *   while (true) {
-   *     ListOperationsResponse response = operationsClient.listOperationsCallable().call(request);
-   *     for (Operation element : response.getResponsesList()) {
-   *       // doThingsWith(element);
-   *     }
-   *     String nextPageToken = response.getNextPageToken();
-   *     if (!Strings.isNullOrEmpty(nextPageToken)) {
-   *       request = request.toBuilder().setPageToken(nextPageToken).build();
-   *     } else {
-   *       break;
-   *     }
-   *   }
-   * }
-   * }
- */ - public final UnaryCallable - listOperationsCallable() { - return stub.listOperationsCallable(); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD. - /** - * Gets the latest state of a long-running operation. Clients can use this method to poll the - * operation result at intervals as recommended by the API service. - * - *

Sample code: - * - *

{@code
-   * try (OperationsClient operationsClient = OperationsClient.create()) {
-   *   String name = "name3373707";
-   *   Operation response = operationsClient.getOperation(name);
-   * }
-   * }
- * - * @param name The name of the operation resource. - * @throws com.google.api.gax.rpc.ApiException if the remote call fails - */ - public final Operation getOperation(String name) { - GetOperationRequest request = GetOperationRequest.newBuilder().setName(name).build(); - return getOperation(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD. - /** - * Gets the latest state of a long-running operation. Clients can use this method to poll the - * operation result at intervals as recommended by the API service. - * - *

Sample code: - * - *

{@code
-   * try (OperationsClient operationsClient = OperationsClient.create()) {
-   *   GetOperationRequest request = GetOperationRequest.newBuilder().setName("name3373707").build();
-   *   Operation response = operationsClient.getOperation(request);
-   * }
-   * }
- * - * @param request The request object containing all of the parameters for the API call. - * @throws com.google.api.gax.rpc.ApiException if the remote call fails - */ - public final Operation getOperation(GetOperationRequest request) { - return getOperationCallable().call(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD. - /** - * Gets the latest state of a long-running operation. Clients can use this method to poll the - * operation result at intervals as recommended by the API service. - * - *

Sample code: - * - *

{@code
-   * try (OperationsClient operationsClient = OperationsClient.create()) {
-   *   GetOperationRequest request = GetOperationRequest.newBuilder().setName("name3373707").build();
-   *   ApiFuture future = operationsClient.getOperationCallable().futureCall(request);
-   *   // Do something.
-   *   Operation response = future.get();
-   * }
-   * }
- */ - public final UnaryCallable getOperationCallable() { - return stub.getOperationCallable(); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD. - /** - * Deletes a long-running operation. This method indicates that the client is no longer interested - * in the operation result. It does not cancel the operation. If the server doesn't support this - * method, it returns `google.rpc.Code.UNIMPLEMENTED`. - * - *

Sample code: - * - *

{@code
-   * try (OperationsClient operationsClient = OperationsClient.create()) {
-   *   String name = "name3373707";
-   *   operationsClient.deleteOperation(name);
-   * }
-   * }
- * - * @param name The name of the operation resource to be deleted. - * @throws com.google.api.gax.rpc.ApiException if the remote call fails - */ - public final void deleteOperation(String name) { - DeleteOperationRequest request = DeleteOperationRequest.newBuilder().setName(name).build(); - deleteOperation(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD. - /** - * Deletes a long-running operation. This method indicates that the client is no longer interested - * in the operation result. It does not cancel the operation. If the server doesn't support this - * method, it returns `google.rpc.Code.UNIMPLEMENTED`. - * - *

Sample code: - * - *

{@code
-   * try (OperationsClient operationsClient = OperationsClient.create()) {
-   *   DeleteOperationRequest request =
-   *       DeleteOperationRequest.newBuilder().setName("name3373707").build();
-   *   operationsClient.deleteOperation(request);
-   * }
-   * }
- * - * @param request The request object containing all of the parameters for the API call. - * @throws com.google.api.gax.rpc.ApiException if the remote call fails - */ - public final void deleteOperation(DeleteOperationRequest request) { - deleteOperationCallable().call(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD. - /** - * Deletes a long-running operation. This method indicates that the client is no longer interested - * in the operation result. It does not cancel the operation. If the server doesn't support this - * method, it returns `google.rpc.Code.UNIMPLEMENTED`. - * - *

Sample code: - * - *

{@code
-   * try (OperationsClient operationsClient = OperationsClient.create()) {
-   *   DeleteOperationRequest request =
-   *       DeleteOperationRequest.newBuilder().setName("name3373707").build();
-   *   ApiFuture future = operationsClient.deleteOperationCallable().futureCall(request);
-   *   // Do something.
-   *   future.get();
-   * }
-   * }
- */ - public final UnaryCallable deleteOperationCallable() { - return stub.deleteOperationCallable(); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD. - /** - * Starts asynchronous cancellation on a long-running operation. The server makes a best effort to - * cancel the operation, but success is not guaranteed. If the server doesn't support this method, - * it returns `google.rpc.Code.UNIMPLEMENTED`. Clients can use - * [Operations.GetOperation][google.longrunning.Operations.GetOperation] or other methods to check - * whether the cancellation succeeded or whether the operation completed despite cancellation. On - * successful cancellation, the operation is not deleted; instead, it becomes an operation with an - * [Operation.error][google.longrunning.Operation.error] value with a - * [google.rpc.Status.code][google.rpc.Status.code] of 1, corresponding to `Code.CANCELLED`. - * - *

Sample code: - * - *

{@code
-   * try (OperationsClient operationsClient = OperationsClient.create()) {
-   *   String name = "name3373707";
-   *   operationsClient.cancelOperation(name);
-   * }
-   * }
- * - * @param name The name of the operation resource to be cancelled. - * @throws com.google.api.gax.rpc.ApiException if the remote call fails - */ - public final void cancelOperation(String name) { - CancelOperationRequest request = CancelOperationRequest.newBuilder().setName(name).build(); - cancelOperation(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD. - /** - * Starts asynchronous cancellation on a long-running operation. The server makes a best effort to - * cancel the operation, but success is not guaranteed. If the server doesn't support this method, - * it returns `google.rpc.Code.UNIMPLEMENTED`. Clients can use - * [Operations.GetOperation][google.longrunning.Operations.GetOperation] or other methods to check - * whether the cancellation succeeded or whether the operation completed despite cancellation. On - * successful cancellation, the operation is not deleted; instead, it becomes an operation with an - * [Operation.error][google.longrunning.Operation.error] value with a - * [google.rpc.Status.code][google.rpc.Status.code] of 1, corresponding to `Code.CANCELLED`. - * - *

Sample code: - * - *

{@code
-   * try (OperationsClient operationsClient = OperationsClient.create()) {
-   *   CancelOperationRequest request =
-   *       CancelOperationRequest.newBuilder().setName("name3373707").build();
-   *   operationsClient.cancelOperation(request);
-   * }
-   * }
- * - * @param request The request object containing all of the parameters for the API call. - * @throws com.google.api.gax.rpc.ApiException if the remote call fails - */ - public final void cancelOperation(CancelOperationRequest request) { - cancelOperationCallable().call(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD. - /** - * Starts asynchronous cancellation on a long-running operation. The server makes a best effort to - * cancel the operation, but success is not guaranteed. If the server doesn't support this method, - * it returns `google.rpc.Code.UNIMPLEMENTED`. Clients can use - * [Operations.GetOperation][google.longrunning.Operations.GetOperation] or other methods to check - * whether the cancellation succeeded or whether the operation completed despite cancellation. On - * successful cancellation, the operation is not deleted; instead, it becomes an operation with an - * [Operation.error][google.longrunning.Operation.error] value with a - * [google.rpc.Status.code][google.rpc.Status.code] of 1, corresponding to `Code.CANCELLED`. - * - *

Sample code: - * - *

{@code
-   * try (OperationsClient operationsClient = OperationsClient.create()) {
-   *   CancelOperationRequest request =
-   *       CancelOperationRequest.newBuilder().setName("name3373707").build();
-   *   ApiFuture future = operationsClient.cancelOperationCallable().futureCall(request);
-   *   // Do something.
-   *   future.get();
-   * }
-   * }
- */ - public final UnaryCallable cancelOperationCallable() { - return stub.cancelOperationCallable(); - } - - @Override - public final void close() { - stub.close(); - } - - @Override - public void shutdown() { - stub.shutdown(); - } - - @Override - public boolean isShutdown() { - return stub.isShutdown(); - } - - @Override - public boolean isTerminated() { - return stub.isTerminated(); - } - - @Override - public void shutdownNow() { - stub.shutdownNow(); - } - - @Override - public boolean awaitTermination(long duration, TimeUnit unit) throws InterruptedException { - return stub.awaitTermination(duration, unit); - } - - public static class ListOperationsPagedResponse - extends AbstractPagedListResponse< - ListOperationsRequest, - ListOperationsResponse, - Operation, - ListOperationsPage, - ListOperationsFixedSizeCollection> { - - public static ApiFuture createAsync( - PageContext context, - ApiFuture futureResponse) { - ApiFuture futurePage = - ListOperationsPage.createEmptyPage().createPageAsync(context, futureResponse); - return ApiFutures.transform( - futurePage, - new ApiFunction() { - @Override - public ListOperationsPagedResponse apply(ListOperationsPage input) { - return new ListOperationsPagedResponse(input); - } - }, - MoreExecutors.directExecutor()); - } - - private ListOperationsPagedResponse(ListOperationsPage page) { - super(page, ListOperationsFixedSizeCollection.createEmptyCollection()); - } - } - - public static class ListOperationsPage - extends AbstractPage< - ListOperationsRequest, ListOperationsResponse, Operation, ListOperationsPage> { - - private ListOperationsPage( - PageContext context, - ListOperationsResponse response) { - super(context, response); - } - - private static ListOperationsPage createEmptyPage() { - return new ListOperationsPage(null, null); - } - - @Override - protected ListOperationsPage createPage( - PageContext context, - ListOperationsResponse response) { - return new ListOperationsPage(context, response); - } - - @Override - public ApiFuture createPageAsync( - PageContext context, - ApiFuture futureResponse) { - return super.createPageAsync(context, futureResponse); - } - } - - public static class ListOperationsFixedSizeCollection - extends AbstractFixedSizeCollection< - ListOperationsRequest, - ListOperationsResponse, - Operation, - ListOperationsPage, - ListOperationsFixedSizeCollection> { - - private ListOperationsFixedSizeCollection(List pages, int collectionSize) { - super(pages, collectionSize); - } - - private static ListOperationsFixedSizeCollection createEmptyCollection() { - return new ListOperationsFixedSizeCollection(null, 0); - } - - @Override - protected ListOperationsFixedSizeCollection createCollection( - List pages, int collectionSize) { - return new ListOperationsFixedSizeCollection(pages, collectionSize); - } - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/longrunning/OperationsSettings.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/longrunning/OperationsSettings.java deleted file mode 100644 index 58aff3d7c..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/longrunning/OperationsSettings.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson.longrunning; - -import static com.google.api.gax.httpjson.longrunning.OperationsClient.ListOperationsPagedResponse; - -import com.google.api.core.ApiFunction; -import com.google.api.core.BetaApi; -import com.google.api.gax.core.GoogleCredentialsProvider; -import com.google.api.gax.core.InstantiatingExecutorProvider; -import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider; -import com.google.api.gax.httpjson.longrunning.stub.OperationsStubSettings; -import com.google.api.gax.rpc.ApiClientHeaderProvider; -import com.google.api.gax.rpc.ClientContext; -import com.google.api.gax.rpc.ClientSettings; -import com.google.api.gax.rpc.PagedCallSettings; -import com.google.api.gax.rpc.TransportChannelProvider; -import com.google.api.gax.rpc.UnaryCallSettings; -import com.google.longrunning.CancelOperationRequest; -import com.google.longrunning.DeleteOperationRequest; -import com.google.longrunning.GetOperationRequest; -import com.google.longrunning.ListOperationsRequest; -import com.google.longrunning.ListOperationsResponse; -import com.google.longrunning.Operation; -import com.google.protobuf.Empty; -import java.io.IOException; -import java.util.List; - -// AUTO-GENERATED DOCUMENTATION AND CLASS. -/** - * Settings class to configure an instance of {@link OperationsClient}. - * - *

The default instance has everything set to sensible defaults: - * - *

    - *
  • The default service address (longrunning.googleapis.com) and default port (443) are used. - *
  • Credentials are acquired automatically through Application Default Credentials. - *
  • Retries are configured for idempotent methods but not for non-idempotent methods. - *
- * - *

The builder of this class is recursive, so contained classes are themselves builders. When - * build() is called, the tree of builders is called to create the complete settings object. - * - *

For example, to set the total timeout of getOperation to 30 seconds: - * - *

{@code
- * OperationsSettings.Builder operationsSettingsBuilder = OperationsSettings.newBuilder();
- * operationsSettingsBuilder
- *     .getOperationSettings()
- *     .setRetrySettings(
- *         operationsSettingsBuilder
- *             .getOperationSettings()
- *             .getRetrySettings()
- *             .toBuilder()
- *             .setTotalTimeout(Duration.ofSeconds(30))
- *             .build());
- * OperationsSettings operationsSettings = operationsSettingsBuilder.build();
- * }
- */ -@BetaApi -public class OperationsSettings extends ClientSettings { - - /** Returns the object with the settings used for calls to listOperations. */ - public PagedCallSettings< - ListOperationsRequest, ListOperationsResponse, ListOperationsPagedResponse> - listOperationsSettings() { - return ((OperationsStubSettings) getStubSettings()).listOperationsSettings(); - } - - /** Returns the object with the settings used for calls to get. */ - public UnaryCallSettings getOperationSettings() { - return ((OperationsStubSettings) getStubSettings()).getOperationSettings(); - } - - /** Returns the object with the settings used for calls to delete. */ - public UnaryCallSettings deleteOperationSettings() { - return ((OperationsStubSettings) getStubSettings()).deleteOperationSettings(); - } - - /** Returns the object with the settings used for calls to cancel. */ - public UnaryCallSettings cancelOperationSettings() { - return ((OperationsStubSettings) getStubSettings()).cancelOperationSettings(); - } - - public static final OperationsSettings create(OperationsStubSettings stub) throws IOException { - return new OperationsSettings.Builder(stub.toBuilder()).build(); - } - - /** Returns a builder for the default ExecutorProvider for this service. */ - public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuilder() { - return OperationsStubSettings.defaultExecutorProviderBuilder(); - } - - /** Returns the default service endpoint. */ - public static String getDefaultEndpoint() { - return OperationsStubSettings.getDefaultEndpoint(); - } - - /** Returns the default service scopes. */ - public static List getDefaultServiceScopes() { - return OperationsStubSettings.getDefaultServiceScopes(); - } - - /** Returns a builder for the default credentials for this service. */ - public static GoogleCredentialsProvider.Builder defaultCredentialsProviderBuilder() { - return OperationsStubSettings.defaultCredentialsProviderBuilder(); - } - - /** Returns a builder for the default ChannelProvider for this service. */ - public static InstantiatingHttpJsonChannelProvider.Builder - defaultHttpJsonTransportProviderBuilder() { - return OperationsStubSettings.defaultHttpJsonTransportProviderBuilder(); - } - - public static TransportChannelProvider defaultTransportChannelProvider() { - return OperationsStubSettings.defaultTransportChannelProvider(); - } - - public static ApiClientHeaderProvider.Builder defaultApiClientHeaderProviderBuilder() { - return OperationsStubSettings.defaultApiClientHeaderProviderBuilder(); - } - - /** Returns a new builder for this class. */ - public static Builder newBuilder() { - return Builder.createDefault(); - } - - /** Returns a new builder for this class. */ - public static Builder newBuilder(ClientContext clientContext) { - return new Builder(clientContext); - } - - /** Returns a builder containing all the values of this settings class. */ - public Builder toBuilder() { - return new Builder(this); - } - - protected OperationsSettings(Builder settingsBuilder) throws IOException { - super(settingsBuilder); - } - - /** Builder for OperationsSettings. */ - public static class Builder extends ClientSettings.Builder { - - protected Builder() throws IOException { - this(((ClientContext) null)); - } - - protected Builder(ClientContext clientContext) { - super(OperationsStubSettings.newBuilder(clientContext)); - } - - protected Builder(OperationsSettings settings) { - super(settings.getStubSettings().toBuilder()); - } - - protected Builder(OperationsStubSettings.Builder stubSettings) { - super(stubSettings); - } - - private static Builder createDefault() { - return new Builder(OperationsStubSettings.newBuilder()); - } - - public OperationsStubSettings.Builder getStubSettingsBuilder() { - return ((OperationsStubSettings.Builder) getStubSettings()); - } - - // NEXT_MAJOR_VER: remove 'throws Exception'. - /** - * Applies the given settings updater function to all of the unary API methods in this service. - * - *

Note: This method does not support applying settings to streaming methods. - */ - public Builder applyToAllUnaryMethods( - ApiFunction, Void> settingsUpdater) throws Exception { - super.applyToAllUnaryMethods( - getStubSettingsBuilder().unaryMethodSettingsBuilders(), settingsUpdater); - return this; - } - - /** Returns the builder for the settings used for calls to listOperations. */ - public PagedCallSettings.Builder< - ListOperationsRequest, ListOperationsResponse, ListOperationsPagedResponse> - listOperationsSettings() { - return getStubSettingsBuilder().listOperationsSettings(); - } - - /** Returns the builder for the settings used for calls to get. */ - public UnaryCallSettings.Builder getOperationSettings() { - return getStubSettingsBuilder().getOperationSettings(); - } - - /** Returns the builder for the settings used for calls to delete. */ - public UnaryCallSettings.Builder deleteOperationSettings() { - return getStubSettingsBuilder().deleteOperationSettings(); - } - - /** Returns the builder for the settings used for calls to cancel. */ - public UnaryCallSettings.Builder cancelOperationSettings() { - return getStubSettingsBuilder().cancelOperationSettings(); - } - - @Override - public OperationsSettings build() throws IOException { - return new OperationsSettings(this); - } - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/longrunning/stub/HttpJsonOperationsCallableFactory.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/longrunning/stub/HttpJsonOperationsCallableFactory.java deleted file mode 100644 index 9d8a435d8..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/longrunning/stub/HttpJsonOperationsCallableFactory.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson.longrunning.stub; - -import com.google.api.core.BetaApi; -import com.google.api.gax.core.BackgroundResource; -import com.google.api.gax.httpjson.HttpJsonCallSettings; -import com.google.api.gax.httpjson.HttpJsonCallableFactory; -import com.google.api.gax.httpjson.HttpJsonStubCallableFactory; -import com.google.api.gax.rpc.BatchingCallSettings; -import com.google.api.gax.rpc.ClientContext; -import com.google.api.gax.rpc.OperationCallSettings; -import com.google.api.gax.rpc.OperationCallable; -import com.google.api.gax.rpc.PagedCallSettings; -import com.google.api.gax.rpc.UnaryCallSettings; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.longrunning.Operation; - -// AUTO-GENERATED DOCUMENTATION AND CLASS. -/** - * REST callable factory implementation for the Operations service API. - * - *

This class is for advanced usage. - */ -@BetaApi -public class HttpJsonOperationsCallableFactory - implements HttpJsonStubCallableFactory { - - @Override - public UnaryCallable createUnaryCallable( - HttpJsonCallSettings httpJsonCallSettings, - UnaryCallSettings callSettings, - ClientContext clientContext) { - return HttpJsonCallableFactory.createUnaryCallable( - httpJsonCallSettings, callSettings, clientContext); - } - - @Override - public - UnaryCallable createPagedCallable( - HttpJsonCallSettings httpJsonCallSettings, - PagedCallSettings callSettings, - ClientContext clientContext) { - return HttpJsonCallableFactory.createPagedCallable( - httpJsonCallSettings, callSettings, clientContext); - } - - @Override - public UnaryCallable createBatchingCallable( - HttpJsonCallSettings httpJsonCallSettings, - BatchingCallSettings callSettings, - ClientContext clientContext) { - return HttpJsonCallableFactory.createBatchingCallable( - httpJsonCallSettings, callSettings, clientContext); - } - - @Override - public - OperationCallable createOperationCallable( - HttpJsonCallSettings httpJsonCallSettings, - OperationCallSettings callSettings, - ClientContext clientContext, - BackgroundResource operationsStub) { - return null; - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/longrunning/stub/HttpJsonOperationsStub.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/longrunning/stub/HttpJsonOperationsStub.java deleted file mode 100644 index 5759c4172..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/longrunning/stub/HttpJsonOperationsStub.java +++ /dev/null @@ -1,400 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson.longrunning.stub; - -import com.google.api.client.http.HttpMethods; -import com.google.api.core.InternalApi; -import com.google.api.gax.core.BackgroundResource; -import com.google.api.gax.core.BackgroundResourceAggregation; -import com.google.api.gax.httpjson.ApiMethodDescriptor; -import com.google.api.gax.httpjson.HttpJsonCallSettings; -import com.google.api.gax.httpjson.HttpJsonLongRunningClient; -import com.google.api.gax.httpjson.HttpJsonOperationSnapshot; -import com.google.api.gax.httpjson.HttpJsonStubCallableFactory; -import com.google.api.gax.httpjson.ProtoMessageRequestFormatter; -import com.google.api.gax.httpjson.ProtoMessageResponseParser; -import com.google.api.gax.httpjson.ProtoRestSerializer; -import com.google.api.gax.httpjson.longrunning.OperationsClient.ListOperationsPagedResponse; -import com.google.api.gax.rpc.ClientContext; -import com.google.api.gax.rpc.LongRunningClient; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.longrunning.CancelOperationRequest; -import com.google.longrunning.DeleteOperationRequest; -import com.google.longrunning.GetOperationRequest; -import com.google.longrunning.ListOperationsRequest; -import com.google.longrunning.ListOperationsResponse; -import com.google.longrunning.Operation; -import com.google.protobuf.Empty; -import com.google.protobuf.Message; -import com.google.protobuf.TypeRegistry; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -// AUTO-GENERATED DOCUMENTATION AND CLASS. -/** - * REST stub implementation for the Operations service API. - * - *

This class is for advanced usage and reflects the underlying API directly. - */ -public class HttpJsonOperationsStub extends OperationsStub { - private static final Pattern CLIENT_PACKAGE_VERSION_PATTERN = - Pattern.compile("\\.(?v\\d+[a-zA-Z]*\\d*[a-zA-Z]*\\d*)\\.[\\w.]*stub"); - - private static final ApiMethodDescriptor - listOperationsMethodDescriptor = - ApiMethodDescriptor.newBuilder() - .setFullMethodName("google.longrunning.Operations/ListOperations") - .setHttpMethod(HttpMethods.GET) - .setRequestFormatter( - ProtoMessageRequestFormatter.newBuilder() - .setPath( - "/v1/{name=**}/operations", - request -> { - Map fields = new HashMap<>(); - ProtoRestSerializer serializer = - ProtoRestSerializer.create(); - serializer.putPathParam(fields, "name", request.getName()); - return fields; - }) - .setQueryParamsExtractor( - request -> { - Map> fields = new HashMap<>(); - ProtoRestSerializer serializer = - ProtoRestSerializer.create(); - serializer.putQueryParam(fields, "filter", request.getFilter()); - serializer.putQueryParam(fields, "pageSize", request.getPageSize()); - serializer.putQueryParam(fields, "pageToken", request.getPageToken()); - return fields; - }) - .setRequestBodyExtractor(request -> null) - .build()) - .setResponseParser( - ProtoMessageResponseParser.newBuilder() - .setDefaultInstance(ListOperationsResponse.getDefaultInstance()) - .build()) - .build(); - - private static final ApiMethodDescriptor - getOperationMethodDescriptor = - ApiMethodDescriptor.newBuilder() - .setFullMethodName("google.longrunning.Operations/GetOperation") - .setHttpMethod(HttpMethods.GET) - .setRequestFormatter( - ProtoMessageRequestFormatter.newBuilder() - .setPath( - "/v1/{name=**/operations/*}", - request -> { - Map fields = new HashMap<>(); - ProtoRestSerializer serializer = - ProtoRestSerializer.create(); - serializer.putPathParam(fields, "name", request.getName()); - return fields; - }) - .setQueryParamsExtractor(request -> new HashMap<>()) - .setRequestBodyExtractor(request -> null) - .build()) - .setResponseParser( - ProtoMessageResponseParser.newBuilder() - .setDefaultInstance(Operation.getDefaultInstance()) - .build()) - .setOperationSnapshotFactory( - (request, response) -> HttpJsonOperationSnapshot.create(response)) - .setPollingRequestFactory( - compoundOperationId -> - GetOperationRequest.newBuilder().setName(compoundOperationId).build()) - .build(); - - private static final ApiMethodDescriptor - deleteOperationMethodDescriptor = - ApiMethodDescriptor.newBuilder() - .setFullMethodName("google.longrunning.Operations/DeleteOperation") - .setHttpMethod(HttpMethods.DELETE) - .setRequestFormatter( - ProtoMessageRequestFormatter.newBuilder() - .setPath( - "/v1/{name=**/operations/*}", - request -> { - Map fields = new HashMap<>(); - ProtoRestSerializer serializer = - ProtoRestSerializer.create(); - serializer.putPathParam(fields, "name", request.getName()); - return fields; - }) - .setQueryParamsExtractor(request -> new HashMap<>()) - .setRequestBodyExtractor(request -> null) - .build()) - .setResponseParser( - ProtoMessageResponseParser.newBuilder() - .setDefaultInstance(Empty.getDefaultInstance()) - .build()) - .build(); - - private static final ApiMethodDescriptor - cancelOperationMethodDescriptor = - ApiMethodDescriptor.newBuilder() - .setFullMethodName("google.longrunning.Operations/CancelOperation") - .setHttpMethod(HttpMethods.POST) - .setRequestFormatter( - ProtoMessageRequestFormatter.newBuilder() - .setPath( - "/v1/{name=**/operations/*}:cancel", - request -> { - Map fields = new HashMap<>(); - ProtoRestSerializer serializer = - ProtoRestSerializer.create(); - serializer.putPathParam(fields, "name", request.getName()); - return fields; - }) - .setQueryParamsExtractor(request -> new HashMap<>()) - .setRequestBodyExtractor(request -> null) - .build()) - .setResponseParser( - ProtoMessageResponseParser.newBuilder() - .setDefaultInstance(Empty.getDefaultInstance()) - .build()) - .build(); - - private final UnaryCallable listOperationsCallable; - private final UnaryCallable - listOperationsPagedCallable; - private final UnaryCallable getOperationCallable; - private final UnaryCallable deleteOperationCallable; - private final UnaryCallable cancelOperationCallable; - - private final LongRunningClient longRunningClient; - private final BackgroundResource backgroundResources; - private final HttpJsonStubCallableFactory callableFactory; - - public static final HttpJsonOperationsStub create(OperationsStubSettings settings) - throws IOException { - return new HttpJsonOperationsStub(settings, ClientContext.create(settings)); - } - - public static final HttpJsonOperationsStub create(ClientContext clientContext) - throws IOException { - return new HttpJsonOperationsStub(OperationsStubSettings.newBuilder().build(), clientContext); - } - - public static final HttpJsonOperationsStub create( - ClientContext clientContext, HttpJsonStubCallableFactory callableFactory) throws IOException { - return new HttpJsonOperationsStub( - OperationsStubSettings.newBuilder().build(), - clientContext, - callableFactory, - TypeRegistry.getEmptyTypeRegistry()); - } - - public static final HttpJsonOperationsStub create( - ClientContext clientContext, - HttpJsonStubCallableFactory callableFactory, - TypeRegistry typeRegistry) - throws IOException { - return new HttpJsonOperationsStub( - OperationsStubSettings.newBuilder().build(), clientContext, callableFactory, typeRegistry); - } - - /** - * Constructs an instance of HttpJsonOperationsStub, using the given settings. This is protected - * so that it is easy to make a subclass, but otherwise, the static factory methods should be - * preferred. - */ - protected HttpJsonOperationsStub(OperationsStubSettings settings, ClientContext clientContext) - throws IOException { - this( - settings, - clientContext, - new HttpJsonOperationsCallableFactory(), - TypeRegistry.getEmptyTypeRegistry()); - } - - /** - * Constructs an instance of HttpJsonOperationsStub, using the given settings. This is protected - * so that it is easy to make a subclass, but otherwise, the static factory methods should be - * preferred. - */ - protected HttpJsonOperationsStub( - OperationsStubSettings settings, - ClientContext clientContext, - HttpJsonStubCallableFactory callableFactory, - TypeRegistry typeRegistry) - throws IOException { - this.callableFactory = callableFactory; - - Matcher packageMatcher = - CLIENT_PACKAGE_VERSION_PATTERN.matcher(callableFactory.getClass().getPackage().getName()); - - String apiVersion = packageMatcher.find() ? packageMatcher.group("version") : null; - - HttpJsonCallSettings - listOperationsTransportSettings = - HttpJsonCallSettings.newBuilder() - .setMethodDescriptor( - getApiVersionedMethodDescriptor(listOperationsMethodDescriptor, apiVersion)) - .setTypeRegistry(typeRegistry) - .build(); - HttpJsonCallSettings getOperationTransportSettings = - HttpJsonCallSettings.newBuilder() - .setMethodDescriptor( - getApiVersionedMethodDescriptor(getOperationMethodDescriptor, apiVersion)) - .setTypeRegistry(typeRegistry) - .build(); - HttpJsonCallSettings deleteOperationTransportSettings = - HttpJsonCallSettings.newBuilder() - .setMethodDescriptor( - getApiVersionedMethodDescriptor(deleteOperationMethodDescriptor, apiVersion)) - .setTypeRegistry(typeRegistry) - .build(); - HttpJsonCallSettings cancelOperationTransportSettings = - HttpJsonCallSettings.newBuilder() - .setMethodDescriptor( - getApiVersionedMethodDescriptor(cancelOperationMethodDescriptor, apiVersion)) - .setTypeRegistry(typeRegistry) - .build(); - - listOperationsCallable = - callableFactory.createUnaryCallable( - listOperationsTransportSettings, settings.listOperationsSettings(), clientContext); - listOperationsPagedCallable = - callableFactory.createPagedCallable( - listOperationsTransportSettings, settings.listOperationsSettings(), clientContext); - getOperationCallable = - callableFactory.createUnaryCallable( - getOperationTransportSettings, settings.getOperationSettings(), clientContext); - deleteOperationCallable = - callableFactory.createUnaryCallable( - deleteOperationTransportSettings, settings.deleteOperationSettings(), clientContext); - cancelOperationCallable = - callableFactory.createUnaryCallable( - cancelOperationTransportSettings, settings.cancelOperationSettings(), clientContext); - - longRunningClient = - new HttpJsonLongRunningClient<>( - getOperationCallable, - getOperationMethodDescriptor.getOperationSnapshotFactory(), - getOperationMethodDescriptor.getPollingRequestFactory()); - - backgroundResources = new BackgroundResourceAggregation(clientContext.getBackgroundResources()); - } - - private static - ApiMethodDescriptor getApiVersionedMethodDescriptor( - ApiMethodDescriptor methodDescriptor, String apiVersion) { - if (apiVersion == null) { - return methodDescriptor; - } - - ApiMethodDescriptor.Builder descriptorBuilder = - methodDescriptor.toBuilder(); - ProtoMessageRequestFormatter requestFormatter = - (ProtoMessageRequestFormatter) descriptorBuilder.getRequestFormatter(); - - return descriptorBuilder - .setRequestFormatter( - requestFormatter.toBuilder().updateRawPath("/v1/", '/' + apiVersion + '/').build()) - .build(); - } - - @InternalApi - public static List getMethodDescriptors() { - List methodDescriptors = new ArrayList<>(); - methodDescriptors.add(listOperationsMethodDescriptor); - methodDescriptors.add(getOperationMethodDescriptor); - methodDescriptors.add(deleteOperationMethodDescriptor); - methodDescriptors.add(cancelOperationMethodDescriptor); - return methodDescriptors; - } - - @Override - public UnaryCallable listOperationsCallable() { - return listOperationsCallable; - } - - @Override - public UnaryCallable - listOperationsPagedCallable() { - return listOperationsPagedCallable; - } - - @Override - public UnaryCallable getOperationCallable() { - return getOperationCallable; - } - - @Override - public UnaryCallable deleteOperationCallable() { - return deleteOperationCallable; - } - - @Override - public UnaryCallable cancelOperationCallable() { - return cancelOperationCallable; - } - - @Override - public LongRunningClient longRunningClient() { - return longRunningClient; - } - - @Override - public final void close() { - shutdown(); - } - - @Override - public void shutdown() { - backgroundResources.shutdown(); - } - - @Override - public boolean isShutdown() { - return backgroundResources.isShutdown(); - } - - @Override - public boolean isTerminated() { - return backgroundResources.isTerminated(); - } - - @Override - public void shutdownNow() { - backgroundResources.shutdownNow(); - } - - @Override - public boolean awaitTermination(long duration, TimeUnit unit) throws InterruptedException { - return backgroundResources.awaitTermination(duration, unit); - } -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/longrunning/stub/OperationsStub.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/longrunning/stub/OperationsStub.java deleted file mode 100644 index bbfec5bde..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/longrunning/stub/OperationsStub.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson.longrunning.stub; - -import com.google.api.gax.core.BackgroundResource; -import com.google.api.gax.httpjson.longrunning.OperationsClient.ListOperationsPagedResponse; -import com.google.api.gax.rpc.LongRunningClient; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.longrunning.CancelOperationRequest; -import com.google.longrunning.DeleteOperationRequest; -import com.google.longrunning.GetOperationRequest; -import com.google.longrunning.ListOperationsRequest; -import com.google.longrunning.ListOperationsResponse; -import com.google.longrunning.Operation; -import com.google.protobuf.Empty; - -// AUTO-GENERATED DOCUMENTATION AND CLASS. -/** - * Base stub class for the Operations service API. - * - *

This class is for advanced usage and reflects the underlying API directly. - */ -public abstract class OperationsStub implements BackgroundResource { - - public UnaryCallable - listOperationsPagedCallable() { - throw new UnsupportedOperationException("Not implemented: listOperationsPagedCallable()"); - } - - public UnaryCallable listOperationsCallable() { - throw new UnsupportedOperationException("Not implemented: listOperationsCallable()"); - } - - public UnaryCallable getOperationCallable() { - throw new UnsupportedOperationException("Not implemented: getOperationCallable()"); - } - - public UnaryCallable deleteOperationCallable() { - throw new UnsupportedOperationException("Not implemented: deleteOperationCallable()"); - } - - public UnaryCallable cancelOperationCallable() { - throw new UnsupportedOperationException("Not implemented: cancelOperationCallable()"); - } - - public LongRunningClient longRunningClient() { - throw new UnsupportedOperationException("Not implemented: longRunningClient()"); - } - - @Override - public abstract void close(); -} diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/longrunning/stub/OperationsStubSettings.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/longrunning/stub/OperationsStubSettings.java deleted file mode 100644 index 5f327a109..000000000 --- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/longrunning/stub/OperationsStubSettings.java +++ /dev/null @@ -1,425 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson.longrunning.stub; - -import static com.google.api.gax.httpjson.longrunning.OperationsClient.ListOperationsPagedResponse; - -import com.google.api.core.ApiFunction; -import com.google.api.core.ApiFuture; -import com.google.api.gax.core.GaxProperties; -import com.google.api.gax.core.GoogleCredentialsProvider; -import com.google.api.gax.core.InstantiatingExecutorProvider; -import com.google.api.gax.httpjson.GaxHttpJsonProperties; -import com.google.api.gax.httpjson.HttpJsonTransportChannel; -import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider; -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.ApiClientHeaderProvider; -import com.google.api.gax.rpc.ClientContext; -import com.google.api.gax.rpc.PageContext; -import com.google.api.gax.rpc.PagedCallSettings; -import com.google.api.gax.rpc.PagedListDescriptor; -import com.google.api.gax.rpc.PagedListResponseFactory; -import com.google.api.gax.rpc.StatusCode; -import com.google.api.gax.rpc.StubSettings; -import com.google.api.gax.rpc.TransportChannelProvider; -import com.google.api.gax.rpc.UnaryCallSettings; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Lists; -import com.google.longrunning.CancelOperationRequest; -import com.google.longrunning.DeleteOperationRequest; -import com.google.longrunning.GetOperationRequest; -import com.google.longrunning.ListOperationsRequest; -import com.google.longrunning.ListOperationsResponse; -import com.google.longrunning.Operation; -import com.google.protobuf.Empty; -import java.io.IOException; -import java.util.List; -import org.threeten.bp.Duration; - -// AUTO-GENERATED DOCUMENTATION AND CLASS. -/** - * Settings class to configure an instance of {@link OperationsStub}. - * - *

The default instance has everything set to sensible defaults: - * - *

    - *
  • The default service address (longrunning.googleapis.com) and default port (443) are used. - *
  • Credentials are acquired automatically through Application Default Credentials. - *
  • Retries are configured for idempotent methods but not for non-idempotent methods. - *
- * - *

The builder of this class is recursive, so contained classes are themselves builders. When - * build() is called, the tree of builders is called to create the complete settings object. - * - *

For example, to set the total timeout of getOperation to 30 seconds: - * - *

{@code
- * OperationsStubSettings.Builder operationsSettingsBuilder = OperationsStubSettings.newBuilder();
- * operationsSettingsBuilder
- *     .getOperationSettings()
- *     .setRetrySettings(
- *         operationsSettingsBuilder
- *             .getOperationSettings()
- *             .getRetrySettings()
- *             .toBuilder()
- *             .setTotalTimeout(Duration.ofSeconds(30))
- *             .build());
- * OperationsStubSettings operationsSettings = operationsSettingsBuilder.build();
- * }
- */ -public class OperationsStubSettings extends StubSettings { - /** The default scopes of the service. */ - private static final ImmutableList DEFAULT_SERVICE_SCOPES = - ImmutableList.builder().build(); - - private final PagedCallSettings< - ListOperationsRequest, ListOperationsResponse, ListOperationsPagedResponse> - listOperationsSettings; - private final UnaryCallSettings getOperationSettings; - private final UnaryCallSettings deleteOperationSettings; - private final UnaryCallSettings cancelOperationSettings; - - private static final PagedListDescriptor - LIST_OPERATIONS_PAGE_STR_DESC = - new PagedListDescriptor() { - @Override - public String emptyToken() { - return ""; - } - - @Override - public ListOperationsRequest injectToken(ListOperationsRequest payload, String token) { - return ListOperationsRequest.newBuilder(payload).setPageToken(token).build(); - } - - @Override - public ListOperationsRequest injectPageSize( - ListOperationsRequest payload, int pageSize) { - return ListOperationsRequest.newBuilder(payload).setPageSize(pageSize).build(); - } - - @Override - public Integer extractPageSize(ListOperationsRequest payload) { - return payload.getPageSize(); - } - - @Override - public String extractNextToken(ListOperationsResponse payload) { - return payload.getNextPageToken(); - } - - @Override - public Iterable extractResources(ListOperationsResponse payload) { - return payload.getOperationsList() == null - ? ImmutableList.of() - : payload.getOperationsList(); - } - }; - - private static final PagedListResponseFactory< - ListOperationsRequest, ListOperationsResponse, ListOperationsPagedResponse> - LIST_OPERATIONS_PAGE_STR_FACT = - new PagedListResponseFactory< - ListOperationsRequest, ListOperationsResponse, ListOperationsPagedResponse>() { - @Override - public ApiFuture getFuturePagedResponse( - UnaryCallable callable, - ListOperationsRequest request, - ApiCallContext context, - ApiFuture futureResponse) { - PageContext pageContext = - PageContext.create(callable, LIST_OPERATIONS_PAGE_STR_DESC, request, context); - return ListOperationsPagedResponse.createAsync(pageContext, futureResponse); - } - }; - - /** Returns the object with the settings used for calls to listOperations. */ - public PagedCallSettings< - ListOperationsRequest, ListOperationsResponse, ListOperationsPagedResponse> - listOperationsSettings() { - return listOperationsSettings; - } - - /** Returns the object with the settings used for calls to get. */ - public UnaryCallSettings getOperationSettings() { - return getOperationSettings; - } - - /** Returns the object with the settings used for calls to delete. */ - public UnaryCallSettings deleteOperationSettings() { - return deleteOperationSettings; - } - - /** Returns the object with the settings used for calls to cancel. */ - public UnaryCallSettings cancelOperationSettings() { - return cancelOperationSettings; - } - - public OperationsStub createStub() throws IOException { - if (getTransportChannelProvider() - .getTransportName() - .equals(HttpJsonTransportChannel.getHttpJsonTransportName())) { - return HttpJsonOperationsStub.create(this); - } - throw new UnsupportedOperationException( - String.format( - "Transport not supported: %s", getTransportChannelProvider().getTransportName())); - } - - /** Returns a builder for the default ExecutorProvider for this service. */ - public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuilder() { - return InstantiatingExecutorProvider.newBuilder(); - } - - /** Returns the default service endpoint. */ - public static String getDefaultEndpoint() { - return "longrunning.googleapis.com:443"; - } - - /** Returns the default mTLS service endpoint. */ - public static String getDefaultMtlsEndpoint() { - return "longrunning.mtls.googleapis.com:443"; - } - - /** Returns the default service scopes. */ - public static List getDefaultServiceScopes() { - return DEFAULT_SERVICE_SCOPES; - } - - /** Returns a builder for the default credentials for this service. */ - public static GoogleCredentialsProvider.Builder defaultCredentialsProviderBuilder() { - return GoogleCredentialsProvider.newBuilder().setScopesToApply(DEFAULT_SERVICE_SCOPES); - } - - /** Returns a builder for the default ChannelProvider for this service. */ - public static InstantiatingHttpJsonChannelProvider.Builder - defaultHttpJsonTransportProviderBuilder() { - return InstantiatingHttpJsonChannelProvider.newBuilder(); - } - - public static TransportChannelProvider defaultTransportChannelProvider() { - return defaultHttpJsonTransportProviderBuilder().build(); - } - - public static ApiClientHeaderProvider.Builder defaultApiClientHeaderProviderBuilder() { - return ApiClientHeaderProvider.newBuilder() - .setGeneratedLibToken( - "gapic", GaxProperties.getLibraryVersion(OperationsStubSettings.class)) - .setTransportToken( - GaxHttpJsonProperties.getHttpJsonTokenName(), - GaxHttpJsonProperties.getHttpJsonVersion()); - } - - /** Returns a new builder for this class. */ - public static Builder newBuilder() { - return Builder.createDefault(); - } - - /** Returns a new builder for this class. */ - public static Builder newBuilder(ClientContext clientContext) { - return new Builder(clientContext); - } - - /** Returns a builder containing all the values of this settings class. */ - public Builder toBuilder() { - return new Builder(this); - } - - protected OperationsStubSettings(Builder settingsBuilder) throws IOException { - super(settingsBuilder); - - listOperationsSettings = settingsBuilder.listOperationsSettings().build(); - getOperationSettings = settingsBuilder.getOperationSettings().build(); - deleteOperationSettings = settingsBuilder.deleteOperationSettings().build(); - cancelOperationSettings = settingsBuilder.cancelOperationSettings().build(); - } - - /** Builder for OperationsStubSettings. */ - public static class Builder extends StubSettings.Builder { - private final ImmutableList> unaryMethodSettingsBuilders; - private final PagedCallSettings.Builder< - ListOperationsRequest, ListOperationsResponse, ListOperationsPagedResponse> - listOperationsSettings; - private final UnaryCallSettings.Builder getOperationSettings; - private final UnaryCallSettings.Builder deleteOperationSettings; - private final UnaryCallSettings.Builder cancelOperationSettings; - private static final ImmutableMap> - RETRYABLE_CODE_DEFINITIONS; - - static { - ImmutableMap.Builder> definitions = - ImmutableMap.builder(); - definitions.put( - "retry_policy_0_codes", - ImmutableSet.copyOf(Lists.newArrayList(StatusCode.Code.UNAVAILABLE))); - RETRYABLE_CODE_DEFINITIONS = definitions.build(); - } - - private static final ImmutableMap RETRY_PARAM_DEFINITIONS; - - static { - ImmutableMap.Builder definitions = ImmutableMap.builder(); - RetrySettings settings = null; - settings = - RetrySettings.newBuilder() - .setInitialRetryDelay(Duration.ofMillis(500L)) - .setRetryDelayMultiplier(2.0) - .setMaxRetryDelay(Duration.ofMillis(10000L)) - .setInitialRpcTimeout(Duration.ofMillis(10000L)) - .setRpcTimeoutMultiplier(1.0) - .setMaxRpcTimeout(Duration.ofMillis(10000L)) - .setTotalTimeout(Duration.ofMillis(10000L)) - .build(); - definitions.put("retry_policy_0_params", settings); - RETRY_PARAM_DEFINITIONS = definitions.build(); - } - - protected Builder() { - this(((ClientContext) null)); - } - - protected Builder(ClientContext clientContext) { - super(clientContext); - - listOperationsSettings = PagedCallSettings.newBuilder(LIST_OPERATIONS_PAGE_STR_FACT); - getOperationSettings = UnaryCallSettings.newUnaryCallSettingsBuilder(); - deleteOperationSettings = UnaryCallSettings.newUnaryCallSettingsBuilder(); - cancelOperationSettings = UnaryCallSettings.newUnaryCallSettingsBuilder(); - - unaryMethodSettingsBuilders = - ImmutableList.>of( - listOperationsSettings, - getOperationSettings, - deleteOperationSettings, - cancelOperationSettings); - initDefaults(this); - } - - protected Builder(OperationsStubSettings settings) { - super(settings); - - listOperationsSettings = settings.listOperationsSettings.toBuilder(); - getOperationSettings = settings.getOperationSettings.toBuilder(); - deleteOperationSettings = settings.deleteOperationSettings.toBuilder(); - cancelOperationSettings = settings.cancelOperationSettings.toBuilder(); - - unaryMethodSettingsBuilders = - ImmutableList.>of( - listOperationsSettings, - getOperationSettings, - deleteOperationSettings, - cancelOperationSettings); - } - - private static Builder createDefault() { - Builder builder = new Builder(((ClientContext) null)); - - builder.setTransportChannelProvider(defaultTransportChannelProvider()); - builder.setCredentialsProvider(defaultCredentialsProviderBuilder().build()); - builder.setInternalHeaderProvider(defaultApiClientHeaderProviderBuilder().build()); - builder.setEndpoint(getDefaultEndpoint()); - builder.setMtlsEndpoint(getDefaultMtlsEndpoint()); - builder.setSwitchToMtlsEndpointAllowed(true); - - return initDefaults(builder); - } - - private static Builder initDefaults(Builder builder) { - builder - .listOperationsSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("retry_policy_0_codes")) - .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("retry_policy_0_params")); - - builder - .getOperationSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("retry_policy_0_codes")) - .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("retry_policy_0_params")); - - builder - .deleteOperationSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("retry_policy_0_codes")) - .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("retry_policy_0_params")); - - builder - .cancelOperationSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("retry_policy_0_codes")) - .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("retry_policy_0_params")); - - return builder; - } - - // NEXT_MAJOR_VER: remove 'throws Exception'. - /** - * Applies the given settings updater function to all of the unary API methods in this service. - * - *

Note: This method does not support applying settings to streaming methods. - */ - public Builder applyToAllUnaryMethods( - ApiFunction, Void> settingsUpdater) throws Exception { - super.applyToAllUnaryMethods(unaryMethodSettingsBuilders, settingsUpdater); - return this; - } - - public ImmutableList> unaryMethodSettingsBuilders() { - return unaryMethodSettingsBuilders; - } - - /** Returns the builder for the settings used for calls to listOperations. */ - public PagedCallSettings.Builder< - ListOperationsRequest, ListOperationsResponse, ListOperationsPagedResponse> - listOperationsSettings() { - return listOperationsSettings; - } - - /** Returns the builder for the settings used for calls to get. */ - public UnaryCallSettings.Builder getOperationSettings() { - return getOperationSettings; - } - - /** Returns the builder for the settings used for calls to delete. */ - public UnaryCallSettings.Builder deleteOperationSettings() { - return deleteOperationSettings; - } - - /** Returns the builder for the settings used for calls to cancel. */ - public UnaryCallSettings.Builder cancelOperationSettings() { - return cancelOperationSettings; - } - - @Override - public OperationsStubSettings build() throws IOException { - return new OperationsStubSettings(this); - } - } -} diff --git a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/GaxHttpJsonPropertiesTest.java b/gax-httpjson/src/test/java/com/google/api/gax/httpjson/GaxHttpJsonPropertiesTest.java deleted file mode 100644 index 487605a62..000000000 --- a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/GaxHttpJsonPropertiesTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.gax.httpjson; - -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -public class GaxHttpJsonPropertiesTest { - private static final String X_GOOG_API_CLIENT = "x-goog-api-client"; - - @Test - public void testDefaultHeaderPattern() { - assertTrue( - GaxHttpJsonProperties.getDefaultApiClientHeaderPattern() - .matcher("gl-java/1.8_00 gapic/1.2.3-alpha gax/1.5.0 rest/1.7.0") - .matches()); - } -} diff --git a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpHeadersUtilsTest.java b/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpHeadersUtilsTest.java deleted file mode 100644 index 9c305977d..000000000 --- a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpHeadersUtilsTest.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -import com.google.api.client.http.HttpHeaders; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import java.util.Map; -import org.junit.Test; - -public class HttpHeadersUtilsTest { - - @Test - public void testSetHeader() { - HttpHeaders headers = new HttpHeaders(); - - assertEquals(headers, HttpHeadersUtils.setHeader(headers, "Custom-Header", "CustomHeader")); - HttpHeadersUtils.setHeader(headers, "accept", "Accept"); - HttpHeadersUtils.setHeader(headers, "accept-encoding", "AcceptEncoding"); - HttpHeadersUtils.setHeader(headers, "Authorization", "Authorization"); - HttpHeadersUtils.setHeader(headers, "cache-Control", "CacheControl"); - HttpHeadersUtils.setHeader(headers, "Content-Encoding", "ContentEncoding"); - HttpHeadersUtils.setHeader(headers, "Content-Length", "123"); - HttpHeadersUtils.setHeader(headers, "Content-MD5", "ContentMD5"); - HttpHeadersUtils.setHeader(headers, "Content-Range", "ContentRange"); - HttpHeadersUtils.setHeader(headers, "Content-Type", "ContentType"); - HttpHeadersUtils.setHeader(headers, "Cookie", "Cookie"); - HttpHeadersUtils.setHeader(headers, "Date", "Date"); - HttpHeadersUtils.setHeader(headers, "ETag", "ETag"); - HttpHeadersUtils.setHeader(headers, "Expires", "Expires"); - HttpHeadersUtils.setHeader(headers, "If-Modified-Since", "IfModifiedSince"); - HttpHeadersUtils.setHeader(headers, "If-Match", "IfMatch"); - HttpHeadersUtils.setHeader(headers, "If-None-Match", "IfNoneMatch"); - HttpHeadersUtils.setHeader(headers, "If-Unmodified-Since", "IfUnmodifiedSince"); - HttpHeadersUtils.setHeader(headers, "If-Range", "IfRange"); - HttpHeadersUtils.setHeader(headers, "Last-Modified", "LastModified"); - HttpHeadersUtils.setHeader(headers, "Location", "Location"); - HttpHeadersUtils.setHeader(headers, "Mime-Version", "MimeVersion"); - HttpHeadersUtils.setHeader(headers, "Range", "Range"); - HttpHeadersUtils.setHeader(headers, "Retry-After", "RetryAfter"); - HttpHeadersUtils.setHeader(headers, "User-Agent", "UserAgent"); - HttpHeadersUtils.setHeader(headers, "WWW-Authenticate", "Authenticate"); - HttpHeadersUtils.setHeader(headers, "Age", "456"); - - assertEquals("CustomHeader", headers.get("Custom-Header")); - assertEquals("CustomHeader", headers.get("custom-header")); - assertEquals("Accept", headers.getAccept()); - assertEquals("AcceptEncoding", headers.getAcceptEncoding()); - assertEquals("Authorization", headers.getAuthorization()); - assertEquals("CacheControl", headers.getCacheControl()); - assertEquals("ContentEncoding", headers.getContentEncoding()); - assertEquals(Long.valueOf(123L), headers.getContentLength()); - assertEquals("ContentMD5", headers.getContentMD5()); - assertEquals("ContentRange", headers.getContentRange()); - assertEquals("ContentType", headers.getContentType()); - assertEquals("Cookie", headers.getCookie()); - assertEquals("Date", headers.getDate()); - assertEquals("ETag", headers.getETag()); - assertEquals("Expires", headers.getExpires()); - assertEquals("IfModifiedSince", headers.getIfModifiedSince()); - assertEquals("IfMatch", headers.getIfMatch()); - assertEquals("IfNoneMatch", headers.getIfNoneMatch()); - assertEquals("IfUnmodifiedSince", headers.getIfUnmodifiedSince()); - assertEquals("IfRange", headers.getIfRange()); - assertEquals("LastModified", headers.getLastModified()); - assertEquals("Location", headers.getLocation()); - assertEquals("MimeVersion", headers.getMimeVersion()); - assertEquals("Range", headers.getRange()); - assertEquals("RetryAfter", headers.getRetryAfter()); - assertEquals("UserAgent", headers.getUserAgent()); - assertEquals(ImmutableList.of("UserAgent"), headers.get("User-Agent")); - assertEquals(ImmutableList.of("UserAgent"), headers.get("user-agent")); - assertEquals("Authenticate", headers.getAuthenticate()); - assertEquals(Long.valueOf(456L), headers.getAge()); - } - - @Test - public void testSetHeaders() { - HttpHeaders headers = new HttpHeaders(); - - Map headersMap = - ImmutableMap.of( - "Custom-Header", "CustomHeader", "accept", "Accept", "Content-Length", "123"); - - assertEquals(headers, HttpHeadersUtils.setHeaders(headers, headersMap)); - - assertEquals("CustomHeader", headers.get("Custom-Header")); - assertEquals("Accept", headers.getAccept()); - assertEquals(Long.valueOf(123L), headers.getContentLength()); - } - - @Test - public void testGetUserAgentValue() { - Map headersMap = - ImmutableMap.of( - "Custom-Header", "CustomHeader", "User-Agent", "this is me", "accept", "Accept"); - - assertEquals("this is me", HttpHeadersUtils.getUserAgentValue(headersMap)); - - headersMap = ImmutableMap.of("Custom-Header", "CustomHeader", "accept", "Accept"); - assertNull(HttpHeadersUtils.getUserAgentValue(headersMap)); - } -} diff --git a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonCallContextTest.java b/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonCallContextTest.java deleted file mode 100644 index fc872d352..000000000 --- a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonCallContextTest.java +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.StatusCode; -import com.google.api.gax.rpc.testing.FakeCallContext; -import com.google.api.gax.rpc.testing.FakeChannel; -import com.google.api.gax.rpc.testing.FakeTransportChannel; -import com.google.api.gax.tracing.ApiTracer; -import com.google.auth.Credentials; -import com.google.common.collect.ImmutableMap; -import com.google.common.truth.Truth; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class HttpJsonCallContextTest { - - @Test - public void testNullToSelfWrongType() { - try { - HttpJsonCallContext.createDefault().nullToSelf(FakeCallContext.createDefault()); - Assert.fail("HttpJsonCallContext should have thrown an exception"); - } catch (IllegalArgumentException expected) { - Truth.assertThat(expected) - .hasMessageThat() - .contains("context must be an instance of HttpJsonCallContext"); - } - } - - @Test - public void testWithCredentials() { - Credentials credentials = Mockito.mock(Credentials.class); - HttpJsonCallContext emptyContext = HttpJsonCallContext.createDefault(); - assertNull(emptyContext.getCredentials()); - HttpJsonCallContext context = emptyContext.withCredentials(credentials); - assertNotNull(context.getCredentials()); - } - - @Test - public void testWithTransportChannel() { - ManagedHttpJsonChannel channel = Mockito.mock(ManagedHttpJsonChannel.class); - - HttpJsonCallContext context = - HttpJsonCallContext.createDefault() - .withTransportChannel( - HttpJsonTransportChannel.newBuilder().setManagedChannel(channel).build()); - Truth.assertThat(context.getChannel()).isSameInstanceAs(channel); - } - - @Test - public void testWithTransportChannelWrongType() { - try { - FakeChannel channel = new FakeChannel(); - HttpJsonCallContext.createDefault() - .withTransportChannel(FakeTransportChannel.create(channel)); - Assert.fail("HttpJsonCallContext should have thrown an exception"); - } catch (IllegalArgumentException expected) { - Truth.assertThat(expected).hasMessageThat().contains("Expected HttpJsonTransportChannel"); - } - } - - @Test - public void testMergeWrongType() { - try { - HttpJsonCallContext.createDefault().merge(FakeCallContext.createDefault()); - Assert.fail("HttpJsonCallContext should have thrown an exception"); - } catch (IllegalArgumentException expected) { - Truth.assertThat(expected) - .hasMessageThat() - .contains("context must be an instance of HttpJsonCallContext"); - } - } - - @Test - public void testWithTimeout() { - assertNull(HttpJsonCallContext.createDefault().withTimeout(null).getTimeout()); - } - - @Test - public void testWithNegativeTimeout() { - assertNull( - HttpJsonCallContext.createDefault().withTimeout(Duration.ofSeconds(-1L)).getTimeout()); - } - - @Test - public void testWithZeroTimeout() { - assertNull( - HttpJsonCallContext.createDefault().withTimeout(Duration.ofSeconds(0L)).getTimeout()); - } - - @Test - public void testWithShorterTimeout() { - HttpJsonCallContext ctxWithLongTimeout = - HttpJsonCallContext.createDefault().withTimeout(Duration.ofSeconds(10)); - - // Sanity check - Truth.assertThat(ctxWithLongTimeout.getTimeout()).isEqualTo(Duration.ofSeconds(10)); - - // Shorten the timeout and make sure it changed - HttpJsonCallContext ctxWithShorterTimeout = - ctxWithLongTimeout.withTimeout(Duration.ofSeconds(5)); - Truth.assertThat(ctxWithShorterTimeout.getTimeout()).isEqualTo(Duration.ofSeconds(5)); - } - - @Test - public void testWithLongerTimeout() { - HttpJsonCallContext ctxWithShortTimeout = - HttpJsonCallContext.createDefault().withTimeout(Duration.ofSeconds(5)); - - // Sanity check - Truth.assertThat(ctxWithShortTimeout.getTimeout()).isEqualTo(Duration.ofSeconds(5)); - - // Try to extend the timeout and verify that it was ignored - HttpJsonCallContext ctxWithUnchangedTimeout = - ctxWithShortTimeout.withTimeout(Duration.ofSeconds(10)); - Truth.assertThat(ctxWithUnchangedTimeout.getTimeout()).isEqualTo(Duration.ofSeconds(5)); - } - - @Test - public void testMergeWithNullTimeout() { - Duration timeout = Duration.ofSeconds(10); - HttpJsonCallContext baseContext = HttpJsonCallContext.createDefault().withTimeout(timeout); - - HttpJsonCallContext defaultOverlay = HttpJsonCallContext.createDefault(); - Truth.assertThat(baseContext.merge(defaultOverlay).getTimeout()).isEqualTo(timeout); - - HttpJsonCallContext explicitNullOverlay = HttpJsonCallContext.createDefault().withTimeout(null); - Truth.assertThat(baseContext.merge(explicitNullOverlay).getTimeout()).isEqualTo(timeout); - } - - @Test - public void testMergeWithTimeout() { - Duration timeout = Duration.ofSeconds(19); - HttpJsonCallContext ctx1 = HttpJsonCallContext.createDefault(); - HttpJsonCallContext ctx2 = HttpJsonCallContext.createDefault().withTimeout(timeout); - - Truth.assertThat(ctx1.merge(ctx2).getTimeout()).isEqualTo(timeout); - } - - @Test - public void testMergeWithTracer() { - ApiTracer explicitTracer = Mockito.mock(ApiTracer.class); - HttpJsonCallContext ctxWithExplicitTracer = - HttpJsonCallContext.createDefault().withTracer(explicitTracer); - - HttpJsonCallContext ctxWithDefaultTracer = HttpJsonCallContext.createDefault(); - ApiTracer defaultTracer = ctxWithDefaultTracer.getTracer(); - - // Explicit tracer overrides the default tracer. - Truth.assertThat(ctxWithDefaultTracer.merge(ctxWithExplicitTracer).getTracer()) - .isSameInstanceAs(explicitTracer); - - // Default tracer does not override an explicit tracer. - Truth.assertThat(ctxWithExplicitTracer.merge(ctxWithDefaultTracer).getTracer()) - .isSameInstanceAs(explicitTracer); - - // Default tracer does not override another default tracer. - Truth.assertThat(ctxWithDefaultTracer.merge(HttpJsonCallContext.createDefault()).getTracer()) - .isSameInstanceAs(defaultTracer); - } - - @Test - public void testWithRetrySettings() { - RetrySettings retrySettings = Mockito.mock(RetrySettings.class); - HttpJsonCallContext emptyContext = HttpJsonCallContext.createDefault(); - assertNull(emptyContext.getRetrySettings()); - HttpJsonCallContext context = emptyContext.withRetrySettings(retrySettings); - assertNotNull(context.getRetrySettings()); - } - - @Test - public void testWithRetryableCodes() { - Set codes = Collections.singleton(StatusCode.Code.UNAVAILABLE); - HttpJsonCallContext emptyContext = HttpJsonCallContext.createDefault(); - assertNull(emptyContext.getRetryableCodes()); - HttpJsonCallContext context = emptyContext.withRetryableCodes(codes); - assertNotNull(context.getRetryableCodes()); - } - - @Test - public void testWithExtraHeaders() { - Map> headers = ImmutableMap.of("k", Arrays.asList("v")); - ApiCallContext emptyContext = HttpJsonCallContext.createDefault(); - assertTrue(emptyContext.getExtraHeaders().isEmpty()); - ApiCallContext context = emptyContext.withExtraHeaders(headers); - assertEquals(headers, context.getExtraHeaders()); - } - - @Test - public void testWithOptions() { - ApiCallContext emptyCallContext = HttpJsonCallContext.createDefault(); - ApiCallContext.Key contextKey1 = ApiCallContext.Key.create("testKey1"); - ApiCallContext.Key contextKey2 = ApiCallContext.Key.create("testKey2"); - String testContext1 = "test1"; - String testContext2 = "test2"; - String testContextOverwrite = "test1Overwrite"; - ApiCallContext context = - emptyCallContext - .withOption(contextKey1, testContext1) - .withOption(contextKey2, testContext2); - assertEquals(testContext1, context.getOption(contextKey1)); - assertEquals(testContext2, context.getOption(contextKey2)); - ApiCallContext newContext = context.withOption(contextKey1, testContextOverwrite); - assertEquals(testContextOverwrite, newContext.getOption(contextKey1)); - } - - @Test - public void testMergeOptions() { - ApiCallContext emptyCallContext = HttpJsonCallContext.createDefault(); - ApiCallContext.Key contextKey1 = ApiCallContext.Key.create("testKey1"); - ApiCallContext.Key contextKey2 = ApiCallContext.Key.create("testKey2"); - ApiCallContext.Key contextKey3 = ApiCallContext.Key.create("testKey3"); - String testContext1 = "test1"; - String testContext2 = "test2"; - String testContext3 = "test3"; - String testContextOverwrite = "test1Overwrite"; - ApiCallContext context1 = - emptyCallContext - .withOption(contextKey1, testContext1) - .withOption(contextKey2, testContext2); - ApiCallContext context2 = - emptyCallContext - .withOption(contextKey1, testContextOverwrite) - .withOption(contextKey3, testContext3); - ApiCallContext mergedContext = context1.merge(context2); - assertEquals(testContextOverwrite, mergedContext.getOption(contextKey1)); - assertEquals(testContext2, mergedContext.getOption(contextKey2)); - assertEquals(testContext3, mergedContext.getOption(contextKey3)); - } -} diff --git a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonCallableFactoryTest.java b/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonCallableFactoryTest.java deleted file mode 100644 index 4d0785f24..000000000 --- a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonCallableFactoryTest.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import static com.google.common.truth.Truth.assertThat; -import static com.google.common.truth.Truth.assertWithMessage; - -import com.google.api.client.http.HttpMethods; -import com.google.api.gax.tracing.SpanName; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; - -@RunWith(JUnit4.class) -public class HttpJsonCallableFactoryTest { - @Test - public void testGetSpanName() { - Map validNames = - ImmutableMap.of( - "compute.projects.disableXpnHost", SpanName.of("compute.projects", "disableXpnHost"), - "client.method", SpanName.of("client", "method")); - - for (Entry entry : validNames.entrySet()) { - @SuppressWarnings("unchecked") - ApiMethodDescriptor descriptor = - ApiMethodDescriptor.newBuilder() - .setFullMethodName(entry.getKey()) - .setHttpMethod(HttpMethods.POST) - .setRequestFormatter(Mockito.mock(HttpRequestFormatter.class)) - .setResponseParser(Mockito.mock(HttpResponseParser.class)) - .build(); - - SpanName actualSpanName = HttpJsonCallableFactory.getSpanName(descriptor); - assertThat(actualSpanName).isEqualTo(entry.getValue()); - } - } - - @Test - public void testGetSpanNameInvalid() { - List invalidNames = ImmutableList.of("no_split", ".no_client"); - - for (String invalidName : invalidNames) { - @SuppressWarnings("unchecked") - ApiMethodDescriptor descriptor = - ApiMethodDescriptor.newBuilder() - .setFullMethodName(invalidName) - .setHttpMethod(HttpMethods.POST) - .setRequestFormatter(Mockito.mock(HttpRequestFormatter.class)) - .setResponseParser(Mockito.mock(HttpResponseParser.class)) - .build(); - - IllegalArgumentException actualError = null; - try { - SpanName spanName = HttpJsonCallableFactory.getSpanName(descriptor); - assertWithMessage( - "Invalid method descriptor should not have a valid span name: %s should not generate the spanName: %s", - invalidName, spanName) - .fail(); - } catch (IllegalArgumentException e) { - actualError = e; - } - assertThat(actualError).isNotNull(); - } - } -} diff --git a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonClientInterceptorTest.java b/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonClientInterceptorTest.java deleted file mode 100644 index 9a27be86f..000000000 --- a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonClientInterceptorTest.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.api.gax.httpjson.ForwardingHttpJsonClientCall.SimpleForwardingHttpJsonClientCall; -import com.google.api.gax.httpjson.ForwardingHttpJsonClientCallListener.SimpleForwardingHttpJsonClientCallListener; -import com.google.api.gax.httpjson.testing.MockHttpService; -import com.google.protobuf.Field; -import com.google.protobuf.Field.Cardinality; -import java.io.IOException; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class HttpJsonClientInterceptorTest { - - private static final int NUM_RETRIES = 10; - private static final int BUSY_WAIT_TIME_IN_MS = 1000; - - private static class CapturingClientInterceptor implements HttpJsonClientInterceptor { - // Manually capturing arguments instead of using Mockito. This is intentional, as this - // specific test interceptor class represents a typical interceptor implementation. Doing the - // same with mocks will simply make this whole test less readable. - private volatile HttpJsonMetadata capturedResponseHeaders; - private volatile Object capturedMessage; - private volatile int capturedStatusCode; - - @Override - public HttpJsonClientCall interceptCall( - ApiMethodDescriptor method, - HttpJsonCallOptions callOptions, - HttpJsonChannel next) { - HttpJsonClientCall call = next.newCall(method, callOptions); - return new SimpleForwardingHttpJsonClientCall(call) { - @Override - public void start(Listener responseListener, HttpJsonMetadata requestHeaders) { - Listener forwardingResponseListener = - new SimpleForwardingHttpJsonClientCallListener(responseListener) { - @Override - public void onHeaders(HttpJsonMetadata responseHeaders) { - capturedResponseHeaders = responseHeaders; - super.onHeaders(responseHeaders); - } - - @Override - public void onMessage(ResponseT message) { - capturedMessage = message; - super.onMessage(message); - } - - @Override - public void onClose(int statusCode, HttpJsonMetadata trailers) { - capturedStatusCode = statusCode; - super.onClose(statusCode, trailers); - } - }; - - super.start(forwardingResponseListener, requestHeaders); - } - }; - } - } - - private static final ApiMethodDescriptor FAKE_METHOD_DESCRIPTOR = - ApiMethodDescriptor.newBuilder() - .setFullMethodName("google.cloud.v1.Fake/FakeMethod") - .setHttpMethod("POST") - .setRequestFormatter( - ProtoMessageRequestFormatter.newBuilder() - .setPath( - "/fake/v1/name/{name}", - request -> { - Map fields = new HashMap<>(); - ProtoRestSerializer serializer = ProtoRestSerializer.create(); - serializer.putPathParam(fields, "name", request.getName()); - return fields; - }) - .setQueryParamsExtractor( - request -> { - Map> fields = new HashMap<>(); - ProtoRestSerializer serializer = ProtoRestSerializer.create(); - serializer.putQueryParam(fields, "number", request.getNumber()); - return fields; - }) - .setRequestBodyExtractor( - request -> - ProtoRestSerializer.create() - .toBody("*", request.toBuilder().clearName().build(), false)) - .build()) - .setResponseParser( - ProtoMessageResponseParser.newBuilder() - .setDefaultInstance(Field.getDefaultInstance()) - .build()) - .build(); - - private static final MockHttpService MOCK_SERVICE = - new MockHttpService(Collections.singletonList(FAKE_METHOD_DESCRIPTOR), "google.com:443"); - - private static ExecutorService executorService; - - private CapturingClientInterceptor interceptor; - private ManagedHttpJsonChannel channel; - - @BeforeClass - public static void initialize() { - executorService = - Executors.newFixedThreadPool( - 2, - r -> { - Thread t = Executors.defaultThreadFactory().newThread(r); - t.setDaemon(true); - return t; - }); - } - - @AfterClass - public static void destroy() { - executorService.shutdownNow(); - } - - @Before - public void setUp() throws IOException { - interceptor = new CapturingClientInterceptor(); - channel = - InstantiatingHttpJsonChannelProvider.newBuilder() - .setEndpoint("google.com:443") - .setExecutor(executorService) - .setHttpTransport(MOCK_SERVICE) - .setHeaderProvider(() -> Collections.singletonMap("header-key", "headerValue")) - .setInterceptorProvider(() -> Collections.singletonList(interceptor)) - .build() - .getTransportChannel() - .getManagedChannel(); - } - - @After - public void tearDown() { - MOCK_SERVICE.reset(); - } - - @Test - public void testCustomInterceptor() throws ExecutionException, InterruptedException { - HttpJsonDirectCallable callable = - new HttpJsonDirectCallable<>(FAKE_METHOD_DESCRIPTOR); - - HttpJsonCallContext callContext = - HttpJsonCallContext.createDefault() - .withChannel(channel) - .withTimeout(Duration.ofSeconds(30)); - - Field request; - Field expectedResponse; - request = - expectedResponse = - Field.newBuilder() // "echo" service - .setName("imTheBestField") - .setNumber(2) - .setCardinality(Cardinality.CARDINALITY_OPTIONAL) - .setDefaultValue("blah") - .build(); - - MOCK_SERVICE.addResponse(expectedResponse); - - Field actualResponse = callable.futureCall(request, callContext).get(); - - // Test that the interceptors did not affect normal execution - assertThat(actualResponse).isEqualTo(expectedResponse); - assertThat(MOCK_SERVICE.getRequestPaths().size()).isEqualTo(1); - String headerValue = MOCK_SERVICE.getRequestHeaders().get("header-key").iterator().next(); - - // Test that internal interceptor worked (the one which inserts headers) - assertThat(headerValue).isEqualTo("headerValue"); - - // Test that the custom interceptor was called - // These two tests cases are guaranteed to respond back by the time `get()` is unblocked - assertThat(interceptor.capturedResponseHeaders).isNotNull(); - assertThat(interceptor.capturedMessage).isEqualTo(request); - - // Attempt to busy wait {NUM_RETRIES} times until the interceptor's `onClose()` is called - int attempts = 0; - while (interceptor.capturedStatusCode == 0) { - Thread.sleep(BUSY_WAIT_TIME_IN_MS); - attempts++; - if (attempts == NUM_RETRIES) { - break; - } - } - - assertThat(interceptor.capturedStatusCode).isEqualTo(200); - } -} diff --git a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonDirectCallableTest.java b/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonDirectCallableTest.java deleted file mode 100644 index e47719c5c..000000000 --- a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonDirectCallableTest.java +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.api.client.http.HttpResponseException; -import com.google.api.gax.httpjson.testing.MockHttpService; -import com.google.api.gax.rpc.ApiException; -import com.google.api.gax.rpc.ApiExceptionFactory; -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.api.gax.rpc.testing.FakeStatusCode; -import com.google.protobuf.Field; -import com.google.protobuf.Field.Cardinality; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class HttpJsonDirectCallableTest { - - private static final ApiMethodDescriptor FAKE_METHOD_DESCRIPTOR = - ApiMethodDescriptor.newBuilder() - .setFullMethodName("google.cloud.v1.Fake/FakeMethod") - .setHttpMethod("POST") - .setRequestFormatter( - ProtoMessageRequestFormatter.newBuilder() - .setPath( - "/fake/v1/name/{name=bob/*}", - request -> { - Map fields = new HashMap<>(); - ProtoRestSerializer serializer = ProtoRestSerializer.create(); - serializer.putPathParam(fields, "name", request.getName()); - return fields; - }) - .setAdditionalPaths("/fake/v1/name/{name=john/*}") - .setQueryParamsExtractor( - request -> { - Map> fields = new HashMap<>(); - ProtoRestSerializer serializer = ProtoRestSerializer.create(); - serializer.putQueryParam(fields, "number", request.getNumber()); - return fields; - }) - .setRequestBodyExtractor( - request -> - ProtoRestSerializer.create() - .toBody("*", request.toBuilder().clearName().build(), false)) - .build()) - .setResponseParser( - ProtoMessageResponseParser.newBuilder() - .setDefaultInstance(Field.getDefaultInstance()) - .build()) - .build(); - - private static final MockHttpService MOCK_SERVICE = - new MockHttpService(Collections.singletonList(FAKE_METHOD_DESCRIPTOR), "google.com:443"); - - private final ManagedHttpJsonChannel channel = - new ManagedHttpJsonInterceptorChannel( - ManagedHttpJsonChannel.newBuilder() - .setEndpoint("google.com:443") - .setExecutor(executorService) - .setHttpTransport(MOCK_SERVICE) - .build(), - new HttpJsonHeaderInterceptor(Collections.singletonMap("header-key", "headerValue"))); - - private static ExecutorService executorService; - - @BeforeClass - public static void initialize() { - executorService = - Executors.newFixedThreadPool( - 2, - r -> { - Thread t = Executors.defaultThreadFactory().newThread(r); - t.setDaemon(true); - return t; - }); - } - - @AfterClass - public static void destroy() { - executorService.shutdownNow(); - } - - @After - public void tearDown() { - MOCK_SERVICE.reset(); - } - - @Test - public void testSuccessfulUnaryResponse() throws ExecutionException, InterruptedException { - HttpJsonDirectCallable callable = - new HttpJsonDirectCallable<>(FAKE_METHOD_DESCRIPTOR); - - HttpJsonCallContext callContext = - HttpJsonCallContext.createDefault() - .withChannel(channel) - .withTimeout(Duration.ofSeconds(30)); - - Field request; - Field expectedResponse; - request = expectedResponse = createTestMessage(); - - MOCK_SERVICE.addResponse(expectedResponse); - - Field actualResponse = callable.futureCall(request, callContext).get(); - - assertThat(actualResponse).isEqualTo(expectedResponse); - assertThat(MOCK_SERVICE.getRequestPaths().size()).isEqualTo(1); - String headerValue = MOCK_SERVICE.getRequestHeaders().get("header-key").iterator().next(); - assertThat(headerValue).isEqualTo("headerValue"); - } - - @Test - public void testErrorUnaryResponse() throws InterruptedException { - HttpJsonDirectCallable callable = - new HttpJsonDirectCallable<>(FAKE_METHOD_DESCRIPTOR); - - HttpJsonCallContext callContext = HttpJsonCallContext.createDefault().withChannel(channel); - - ApiException exception = - ApiExceptionFactory.createException( - new Exception(), FakeStatusCode.of(Code.NOT_FOUND), false); - MOCK_SERVICE.addException(exception); - - try { - callable.futureCall(createTestMessage(), callContext).get(); - Assert.fail("No exception raised"); - } catch (ExecutionException e) { - HttpResponseException respExp = (HttpResponseException) e.getCause(); - assertThat(respExp.getStatusCode()).isEqualTo(400); - assertThat(respExp.getContent()).isEqualTo(exception.toString()); - } - } - - @Test - public void testErrorNullContentSuccessfulResponse() throws InterruptedException { - HttpJsonDirectCallable callable = - new HttpJsonDirectCallable<>(FAKE_METHOD_DESCRIPTOR); - - HttpJsonCallContext callContext = HttpJsonCallContext.createDefault().withChannel(channel); - - MOCK_SERVICE.addNullResponse(); - - try { - callable.futureCall(createTestMessage(), callContext).get(); - Assert.fail("No exception raised"); - } catch (ExecutionException e) { - HttpJsonStatusRuntimeException respExp = (HttpJsonStatusRuntimeException) e.getCause(); - assertThat(respExp.getStatusCode()).isEqualTo(200); - assertThat(respExp.getCause().getMessage()) - .isEqualTo("Both response message and response exception were null"); - } - } - - @Test - public void testErrorNullContentFailedResponse() throws InterruptedException { - HttpJsonDirectCallable callable = - new HttpJsonDirectCallable<>(FAKE_METHOD_DESCRIPTOR); - - HttpJsonCallContext callContext = HttpJsonCallContext.createDefault().withChannel(channel); - MOCK_SERVICE.addNullResponse(400); - - try { - callable.futureCall(createTestMessage(), callContext).get(); - Assert.fail("No exception raised"); - } catch (ExecutionException e) { - HttpResponseException respExp = (HttpResponseException) e.getCause(); - assertThat(respExp.getStatusCode()).isEqualTo(400); - assertThat(respExp.getContent()).isNull(); - } - } - - private Field createTestMessage() { - return Field.newBuilder() // "echo" service - .setName("john/imTheBestField") - .setNumber(2) - .setCardinality(Cardinality.CARDINALITY_OPTIONAL) - .setDefaultValue("blah") - .build(); - } -} diff --git a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonDirectServerStreamingCallableTest.java b/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonDirectServerStreamingCallableTest.java deleted file mode 100644 index fe0240602..000000000 --- a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonDirectServerStreamingCallableTest.java +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import com.google.api.core.SettableApiFuture; -import com.google.api.gax.httpjson.ApiMethodDescriptor.MethodType; -import com.google.api.gax.httpjson.testing.MockHttpService; -import com.google.api.gax.rpc.ApiException; -import com.google.api.gax.rpc.ClientContext; -import com.google.api.gax.rpc.ResponseObserver; -import com.google.api.gax.rpc.ServerStream; -import com.google.api.gax.rpc.ServerStreamingCallSettings; -import com.google.api.gax.rpc.ServerStreamingCallable; -import com.google.api.gax.rpc.StateCheckingResponseObserver; -import com.google.api.gax.rpc.StatusCode; -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.api.gax.rpc.StreamController; -import com.google.api.gax.rpc.testing.FakeCallContext; -import com.google.common.collect.Lists; -import com.google.common.truth.Truth; -import com.google.protobuf.Field; -import com.google.type.Color; -import com.google.type.Money; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CancellationException; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class HttpJsonDirectServerStreamingCallableTest { - private static final ApiMethodDescriptor METHOD_SERVER_STREAMING_RECOGNIZE = - ApiMethodDescriptor.newBuilder() - .setFullMethodName("google.cloud.v1.Fake/ServerStreamingRecognize") - .setHttpMethod("POST") - .setRequestFormatter( - ProtoMessageRequestFormatter.newBuilder() - .setPath( - "/fake/v1/recognize/{blue}", - request -> { - Map fields = new HashMap<>(); - ProtoRestSerializer serializer = ProtoRestSerializer.create(); - serializer.putPathParam(fields, "blue", request.getBlue()); - return fields; - }) - .setQueryParamsExtractor( - request -> { - Map> fields = new HashMap<>(); - ProtoRestSerializer serializer = ProtoRestSerializer.create(); - serializer.putQueryParam(fields, "red", request.getRed()); - return fields; - }) - .setRequestBodyExtractor( - request -> - ProtoRestSerializer.create() - .toBody( - "*", request.toBuilder().clearBlue().clearRed().build(), false)) - .build()) - .setResponseParser( - ProtoMessageResponseParser.newBuilder() - .setDefaultInstance(Money.getDefaultInstance()) - .build()) - .setType(MethodType.SERVER_STREAMING) - .build(); - - private static final MockHttpService MOCK_SERVICE = - new MockHttpService( - Collections.singletonList(METHOD_SERVER_STREAMING_RECOGNIZE), "google.com:443"); - - private static final Color DEFAULT_REQUEST = Color.newBuilder().setRed(0.5f).build(); - private static final Color ASYNC_REQUEST = DEFAULT_REQUEST.toBuilder().setGreen(1000).build(); - private static final Color ERROR_REQUEST = Color.newBuilder().setRed(-1).build(); - private static final Money DEFAULT_RESPONSE = - Money.newBuilder().setCurrencyCode("USD").setUnits(127).build(); - private static final Money DEFAULTER_RESPONSE = - Money.newBuilder().setCurrencyCode("UAH").setUnits(255).build(); - - private ClientContext clientContext; - private ServerStreamingCallSettings streamingCallSettings; - private ServerStreamingCallable streamingCallable; - - private static ExecutorService executorService; - - @BeforeClass - public static void initialize() { - executorService = Executors.newFixedThreadPool(2); - } - - @AfterClass - public static void destroy() { - executorService.shutdownNow(); - } - - @Before - public void setUp() { - ManagedHttpJsonChannel channel = - new ManagedHttpJsonInterceptorChannel( - ManagedHttpJsonChannel.newBuilder() - .setEndpoint("google.com:443") - .setExecutor(executorService) - .setHttpTransport(MOCK_SERVICE) - .build(), - new HttpJsonHeaderInterceptor(Collections.singletonMap("header-key", "headerValue"))); - - clientContext = - ClientContext.newBuilder() - .setTransportChannel(HttpJsonTransportChannel.create(channel)) - .setDefaultCallContext(HttpJsonCallContext.of(channel, HttpJsonCallOptions.DEFAULT)) - .build(); - streamingCallSettings = ServerStreamingCallSettings.newBuilder().build(); - streamingCallable = - HttpJsonCallableFactory.createServerStreamingCallable( - HttpJsonCallSettings.create(METHOD_SERVER_STREAMING_RECOGNIZE), - streamingCallSettings, - clientContext); - } - - @After - public void tearDown() { - MOCK_SERVICE.reset(); - } - - @Test - public void testBadContext() { - MOCK_SERVICE.addResponse(new Money[] {DEFAULT_RESPONSE}); - streamingCallable = - HttpJsonCallableFactory.createServerStreamingCallable( - HttpJsonCallSettings.create(METHOD_SERVER_STREAMING_RECOGNIZE), - streamingCallSettings, - clientContext - .toBuilder() - .setDefaultCallContext(FakeCallContext.createDefault()) - .build()); - - CountDownLatch latch = new CountDownLatch(1); - - MoneyObserver observer = new MoneyObserver(true, latch); - try { - streamingCallable.call(DEFAULT_REQUEST, observer); - Assert.fail("Callable should have thrown an exception"); - } catch (IllegalArgumentException expected) { - Truth.assertThat(expected) - .hasMessageThat() - .contains("context must be an instance of HttpJsonCallContext"); - } - } - - @Test - public void testServerStreamingStart() throws InterruptedException { - MOCK_SERVICE.addResponse(new Money[] {DEFAULT_RESPONSE}); - CountDownLatch latch = new CountDownLatch(1); - MoneyObserver moneyObserver = new MoneyObserver(true, latch); - - streamingCallable.call(DEFAULT_REQUEST, moneyObserver); - - Truth.assertThat(moneyObserver.controller).isNotNull(); - // wait for the task to complete, otherwise it may interfere with other tests, since they share - // the same MockService and unfinished request in this tes may start readind messages designated - // for other tests. - Truth.assertThat(latch.await(2, TimeUnit.SECONDS)).isTrue(); - } - - @Test - public void testServerStreaming() throws InterruptedException { - - MOCK_SERVICE.addResponse(new Money[] {DEFAULT_RESPONSE, DEFAULTER_RESPONSE}); - CountDownLatch latch = new CountDownLatch(3); - MoneyObserver moneyObserver = new MoneyObserver(true, latch); - - streamingCallable.call(DEFAULT_REQUEST, moneyObserver); - - Truth.assertThat(latch.await(10, TimeUnit.SECONDS)).isTrue(); - Truth.assertThat(latch.getCount()).isEqualTo(0); - Truth.assertThat(moneyObserver.error).isNull(); - Truth.assertThat(moneyObserver.response).isEqualTo(DEFAULTER_RESPONSE); - } - - @Test - public void testManualFlowControl() throws Exception { - MOCK_SERVICE.addResponse(new Money[] {DEFAULT_RESPONSE}); - CountDownLatch latch = new CountDownLatch(2); - MoneyObserver moneyObserver = new MoneyObserver(false, latch); - - streamingCallable.call(DEFAULT_REQUEST, moneyObserver); - - Truth.assertThat(latch.await(1000, TimeUnit.MILLISECONDS)).isFalse(); - Truth.assertWithMessage("Received response before requesting it") - .that(moneyObserver.response) - .isNull(); - - moneyObserver.controller.request(1); - Truth.assertThat(latch.await(1000, TimeUnit.MILLISECONDS)).isTrue(); - - Truth.assertThat(moneyObserver.response).isEqualTo(DEFAULT_RESPONSE); - Truth.assertThat(moneyObserver.completed).isTrue(); - } - - @Test - public void testCancelClientCall() throws Exception { - MOCK_SERVICE.addResponse(new Money[] {DEFAULT_RESPONSE}); - CountDownLatch latch = new CountDownLatch(1); - MoneyObserver moneyObserver = new MoneyObserver(false, latch); - - streamingCallable.call(ASYNC_REQUEST, moneyObserver); - - moneyObserver.controller.cancel(); - moneyObserver.controller.request(1); - Truth.assertThat(latch.await(500, TimeUnit.MILLISECONDS)).isTrue(); - - Truth.assertThat(moneyObserver.error).isInstanceOf(CancellationException.class); - Truth.assertThat(moneyObserver.error).hasMessageThat().isEqualTo("User cancelled stream"); - } - - @Test - public void testOnResponseError() throws Throwable { - MOCK_SERVICE.addException(404, new RuntimeException("some error")); - - CountDownLatch latch = new CountDownLatch(1); - MoneyObserver moneyObserver = new MoneyObserver(true, latch); - - streamingCallable.call(ERROR_REQUEST, moneyObserver); - Truth.assertThat(latch.await(1000, TimeUnit.MILLISECONDS)).isTrue(); - - Truth.assertThat(moneyObserver.error).isInstanceOf(ApiException.class); - Truth.assertThat(((ApiException) moneyObserver.error).getStatusCode().getCode()) - .isEqualTo(Code.NOT_FOUND); - Truth.assertThat(moneyObserver.error) - .hasMessageThat() - .isEqualTo( - "com.google.api.client.http.HttpResponseException: 404\n" - + "POST https://google.com:443/fake/v1/recognize/0.0?red=-1.0\n" - + "java.lang.RuntimeException: some error"); - } - - @Test - public void testObserverErrorCancelsCall() throws Throwable { - MOCK_SERVICE.addResponse(new Money[] {DEFAULT_RESPONSE}); - final RuntimeException expectedCause = new RuntimeException("some error"); - final SettableApiFuture actualErrorF = SettableApiFuture.create(); - - ResponseObserver moneyObserver = - new StateCheckingResponseObserver() { - @Override - protected void onStartImpl(StreamController controller) {} - - @Override - protected void onResponseImpl(Money response) { - throw expectedCause; - } - - @Override - protected void onErrorImpl(Throwable t) { - actualErrorF.set(t); - } - - @Override - protected void onCompleteImpl() { - actualErrorF.set(null); - } - }; - - streamingCallable.call(DEFAULT_REQUEST, moneyObserver); - Throwable actualError = actualErrorF.get(11500, TimeUnit.MILLISECONDS); - - Truth.assertThat(actualError).isInstanceOf(ApiException.class); - Truth.assertThat(((ApiException) actualError).getStatusCode().getCode()) - .isEqualTo(StatusCode.Code.CANCELLED); - - // gax httpjson transport layer is responsible for the immediate cancellation - Truth.assertThat(actualError.getCause()).isInstanceOf(HttpJsonStatusRuntimeException.class); - // and the client error is cause for httpjson transport layer to cancel it - Truth.assertThat(actualError.getCause().getCause()).isSameInstanceAs(expectedCause); - } - - @Test - public void testBlockingServerStreaming() { - MOCK_SERVICE.addResponse(new Money[] {DEFAULT_RESPONSE}); - Color request = Color.newBuilder().setRed(0.5f).build(); - ServerStream response = streamingCallable.call(request); - List responseData = Lists.newArrayList(response); - - Money expected = Money.newBuilder().setCurrencyCode("USD").setUnits(127).build(); - Truth.assertThat(responseData).containsExactly(expected); - } - - static class MoneyObserver extends StateCheckingResponseObserver { - private final boolean autoFlowControl; - private final CountDownLatch latch; - - volatile StreamController controller; - volatile Money response; - volatile Throwable error; - volatile boolean completed; - - MoneyObserver(boolean autoFlowControl, CountDownLatch latch) { - this.autoFlowControl = autoFlowControl; - this.latch = latch; - } - - @Override - protected void onStartImpl(StreamController controller) { - this.controller = controller; - if (!autoFlowControl) { - controller.disableAutoInboundFlowControl(); - } - } - - @Override - protected void onResponseImpl(Money value) { - response = value; - latch.countDown(); - } - - @Override - protected void onErrorImpl(Throwable t) { - error = t; - latch.countDown(); - } - - @Override - protected void onCompleteImpl() { - completed = true; - latch.countDown(); - } - } -} diff --git a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonLongRunningClientTest.java b/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonLongRunningClientTest.java deleted file mode 100644 index 702f327a6..000000000 --- a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonLongRunningClientTest.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.httpjson; - -import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.assertNull; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.api.gax.longrunning.OperationSnapshot; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.common.truth.Truth; -import com.google.protobuf.Field; -import com.google.protobuf.Option; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -public class HttpJsonLongRunningClientTest { - - private OperationSnapshotFactory operationSnapFact; - private PollingRequestFactory

As required by {@link MockHttpTransport} this implementation is thread-safe, but it is not - * idempotent (as a typical service would be) and must be used with extra caution. Mocked responses - * are returned in FIFO order and if multiple threads read from the same MockHttpService - * simultaneously, they may be getting responses intended for other consumers. - */ -public final class MockHttpService extends MockHttpTransport { - private final Multimap requestHeaders = LinkedListMultimap.create(); - private final List requestPaths = new LinkedList<>(); - private final Queue responseHandlers = new LinkedList<>(); - private final List serviceMethodDescriptors; - private final String endpoint; - - /** - * Create a MockHttpService. - * - * @param serviceMethodDescriptors - list of method descriptors for the methods that this mock - * server supports - * @param pathPrefix - the fixed portion of the endpoint URL that prefixes the methods' path - * template substring. - */ - public MockHttpService(List serviceMethodDescriptors, String pathPrefix) { - this.serviceMethodDescriptors = ImmutableList.copyOf(serviceMethodDescriptors); - this.endpoint = pathPrefix; - } - - @Override - public synchronized LowLevelHttpRequest buildRequest(String method, String url) { - requestPaths.add(url); - return new MockHttpRequest(this, method, url); - } - - /** Add an ApiMessage to the response queue. */ - public synchronized void addResponse(Object response) { - responseHandlers.add(new MessageResponseFactory(endpoint, serviceMethodDescriptors, response)); - } - - /** Add an expected null response (empty HTTP response body) with a custom status code. */ - public synchronized void addNullResponse(int statusCode) { - responseHandlers.add( - (httpMethod, targetUrl) -> new MockLowLevelHttpResponse().setStatusCode(statusCode)); - } - - /** Add an expected null response (empty HTTP response body). */ - public synchronized void addNullResponse() { - addNullResponse(200); - } - - /** Add an Exception to the response queue. */ - public synchronized void addException(Exception exception) { - addException(400, exception); - } - - public synchronized void addException(int statusCode, Exception exception) { - responseHandlers.add(new ExceptionResponseFactory(statusCode, exception)); - } - - /** Get the FIFO list of URL paths to which requests were sent. */ - public synchronized List getRequestPaths() { - return requestPaths; - } - - /** Get the FIFO list of request headers sent. */ - public synchronized Multimap getRequestHeaders() { - return ImmutableListMultimap.copyOf(requestHeaders); - } - - private synchronized void putRequestHeader(String name, String value) { - requestHeaders.put(name, value); - } - - private synchronized MockLowLevelHttpResponse getHttpResponse(String method, String url) { - Preconditions.checkArgument(!responseHandlers.isEmpty()); - return responseHandlers.poll().getHttpResponse(method, url); - } - - /* Reset the expected response queue, the method descriptor, and the logged request paths list. */ - public synchronized void reset() { - responseHandlers.clear(); - requestPaths.clear(); - requestHeaders.clear(); - } - - private interface HttpResponseFactory { - MockLowLevelHttpResponse getHttpResponse(String httpMethod, String targetUrl); - } - - private static class MockHttpRequest extends MockLowLevelHttpRequest { - private final MockHttpService service; - private final String method; - private final String url; - - public MockHttpRequest(MockHttpService service, String method, String url) { - this.service = service; - this.method = method; - this.url = url; - } - - @Override - public void addHeader(String name, String value) { - service.putRequestHeader(name, value); - } - - @Override - public LowLevelHttpResponse execute() { - return service.getHttpResponse(method, url); - } - } - - private static class ExceptionResponseFactory implements HttpResponseFactory { - private final int statusCode; - private final Exception exception; - - public ExceptionResponseFactory(int statusCode, Exception exception) { - this.statusCode = statusCode; - this.exception = exception; - } - - @Override - public MockLowLevelHttpResponse getHttpResponse(String httpMethod, String targetUrl) { - MockLowLevelHttpResponse httpResponse = new MockLowLevelHttpResponse(); - httpResponse.setStatusCode(statusCode); - httpResponse.setContent(exception.toString().getBytes()); - httpResponse.setContentEncoding("text/plain"); - return httpResponse; - } - } - - private static class MessageResponseFactory implements HttpResponseFactory { - private final List serviceMethodDescriptors; - private final Object response; - private final String endpoint; - - public MessageResponseFactory( - String endpoint, List serviceMethodDescriptors, Object response) { - this.endpoint = endpoint; - this.serviceMethodDescriptors = ImmutableList.copyOf(serviceMethodDescriptors); - this.response = response; - } - - @Override - public MockLowLevelHttpResponse getHttpResponse(String httpMethod, String fullTargetUrl) { - MockLowLevelHttpResponse httpResponse = new MockLowLevelHttpResponse(); - - String relativePath = getRelativePath(fullTargetUrl); - - for (ApiMethodDescriptor methodDescriptor : serviceMethodDescriptors) { - // Check the comment in com.google.api.gax.httpjson.HttpRequestRunnable.buildRequest() - // method for details why it is needed. - String descriptorHttpMethod = methodDescriptor.getHttpMethod(); - if (!httpMethod.equals(descriptorHttpMethod)) { - if (!(HttpMethods.PATCH.equals(descriptorHttpMethod) - && HttpMethods.POST.equals(httpMethod))) { - continue; - } - } - - PathTemplate pathTemplate = methodDescriptor.getRequestFormatter().getPathTemplate(); - List additionalPathTemplates = - methodDescriptor.getRequestFormatter().getAdditionalPathTemplates(); - // Server figures out which RPC method is called based on the endpoint path pattern(s). - if (!pathTemplate.matches(relativePath) - && additionalPathTemplates.stream().noneMatch(pt -> pt.matches(relativePath))) { - continue; - } - - // Emulate the server's creation of an HttpResponse from the response message - // instance. - String httpContent; - if (methodDescriptor.getType() == MethodType.SERVER_STREAMING) { - // Quick and dirty json array construction. Good enough for - Object[] responseArray = (Object[]) response; - StringBuilder sb = new StringBuilder(); - sb.append('['); - for (Object responseElement : responseArray) { - if (sb.length() > 1) { - sb.append(','); - } - sb.append(methodDescriptor.getResponseParser().serialize(responseElement)); - } - sb.append(']'); - httpContent = sb.toString(); - } else { - httpContent = methodDescriptor.getResponseParser().serialize(response); - } - - httpResponse.setContent(httpContent.getBytes()); - httpResponse.setStatusCode(200); - return httpResponse; - } - - // Return 404 when none of this server's endpoint templates match the given URL. - httpResponse.setContent( - String.format("Method not found for path '%s'", relativePath).getBytes()); - httpResponse.setStatusCode(404); - return httpResponse; - } - - private String getRelativePath(String fullTargetUrl) { - // relativePath will be repeatedly truncated until it contains only - // the path template substring of the endpoint URL. - String relativePath = fullTargetUrl.replaceFirst(endpoint, ""); - int queryParamIndex = relativePath.indexOf("?"); - queryParamIndex = queryParamIndex < 0 ? relativePath.length() : queryParamIndex; - relativePath = relativePath.substring(0, queryParamIndex); - - return relativePath; - } - } -} diff --git a/gax/BUILD.bazel b/gax/BUILD.bazel deleted file mode 100644 index 0152f2503..000000000 --- a/gax/BUILD.bazel +++ /dev/null @@ -1,86 +0,0 @@ -load("//:gax_java.bzl", "google_java_format", "google_java_format_verification", "java_tests") - -_JAVA_COPTS = [ - "-source", - "1.8", - "-target", - "1.8", -] - -_COMPILE_DEPS = [ - "@com_google_api_api_common//jar", - "@com_google_api_grpc_proto_google_common_protos//jar", - "@com_google_protobuf_java//jar", - "@com_google_auth_google_auth_library_credentials//jar", - "@com_google_auth_google_auth_library_oauth2_http//jar", - "@com_google_auto_value_auto_value//jar", - "@com_google_auto_value_auto_value_annotations//jar", - "@com_google_code_findbugs_jsr305//jar", - "@com_google_guava_guava//jar", - "@io_opencensus_opencensus_api//jar", - "@io_opencensus_opencensus_contrib_http_util//jar", - "@io_grpc_grpc_java//context:context", - "@org_threeten_threetenbp//jar", - "@com_google_http_client_google_http_client//jar", - "@com_google_http_client_google_http_client_gson//jar", - "@com_google_code_gson_gson//jar", - "@com_google_guava_failureaccess//jar", - "@javax_annotation_javax_annotation_api//jar", - "@org_graalvm_sdk//jar" -] - -_TEST_COMPILE_DEPS = [ - "@junit_junit//jar", - "@org_mockito_mockito_core//jar", - "@com_google_truth_truth//jar", - "@org_hamcrest_hamcrest_core//jar", - "@net_bytebuddy_byte_buddy//jar", - "@org_objenesis_objenesis//jar", - "@com_googlecode_java_diff_utils_diffutils//jar", -] - -java_library( - name = "gax", - srcs = glob(["src/main/java/**/*.java"]), - javacopts = _JAVA_COPTS, - plugins = ["//:auto_value_plugin"], - resources = ["//:dependencies.properties"], - visibility = ["//visibility:public"], - deps = _COMPILE_DEPS, -) - -java_library( - name = "gax_testlib", - srcs = glob(["src/test/java/**/*.java"]), - javacopts = _JAVA_COPTS, - plugins = ["//:auto_value_plugin"], - resources = glob([ - "src/test/resources/com/google/api/gax/rpc/mtls/mtls_context_aware_metadata.json", - "src/test/resources/com/google/api/gax/rpc/mtls/mtlsCertAndKey.pem", - ]), - visibility = ["//visibility:public"], - deps = [":gax"] + _COMPILE_DEPS + _TEST_COMPILE_DEPS, -) - -java_tests( - name = "gax_tests", - size = "small", - srcs = glob( - include = ["src/test/java/**/*Test.java"], - exclude = ["src/test/java/**/Abstract*Test.java"], - ), - runtime_deps = [":gax_testlib"], -) - -google_java_format( - name = "google_java_format", - srcs = glob(["src/**/*.java"]), - formatter = "//:google_java_format_binary", -) - -#Uncomment once java formatter is upgraded to 1.6+ -#google_java_format_verification( -# name = "google_java_format_verification", -# srcs = glob(["src/**/*.java"]), -# formatter = "//:google_java_format_binary", -#) diff --git a/gax/build.gradle b/gax/build.gradle deleted file mode 100644 index f92a8cf9f..000000000 --- a/gax/build.gradle +++ /dev/null @@ -1,47 +0,0 @@ -archivesBaseName = "gax" - -// TODO: Populate this from dependencies.properties version property (for proper Gradle-Bazel sync) -project.version = "2.20.1" // {x-version-update:gax:current} - -dependencies { - api(libraries['maven.com_google_api_api_common'], - libraries['maven.com_google_api_grpc_proto_google_common_protos'], - libraries['maven.com_google_auth_google_auth_library_credentials'], - libraries['maven.org_threeten_threetenbp']) - - implementation(libraries['maven.com_google_auth_google_auth_library_oauth2_http'], - libraries['maven.com_google_code_findbugs_jsr305'], - libraries['maven.com_google_guava_guava'], - libraries['maven.io_opencensus_opencensus_api']) - - compileOnly(libraries['maven.com_google_auto_value_auto_value'], - libraries['maven.org_graalvm_sdk']) - - testImplementation(libraries['maven.junit_junit'], - libraries['maven.org_mockito_mockito_core'], - libraries['maven.com_google_truth_truth'], - libraries['maven.com_google_auto_value_auto_value'], - libraries['maven.org_graalvm_sdk']) - - annotationProcessor libraries['maven.com_google_auto_value_auto_value'] - testAnnotationProcessor libraries['maven.com_google_auto_value_auto_value'] - - shadowNoGuava libraries['maven.com_google_guava_guava'] -} - -processResources { - filesMatching('dependencies.properties') { - expand('project': project) - } -} - -jar { - manifest { - attributes 'Specification-Title': project.name, - 'Specification-Version': project.version, - 'Specification-Vendor': libraryVendor, - 'Implementation-Title': project.name, - 'Implementation-Version': project.version, - 'Implementation-Vendor': libraryVendor - } -} diff --git a/gax/pom.xml b/gax/pom.xml deleted file mode 100644 index 09f587cb3..000000000 --- a/gax/pom.xml +++ /dev/null @@ -1,86 +0,0 @@ - - - 4.0.0 - - gax - 2.20.1 - jar - GAX (Google Api eXtensions) for Java (Core) - Google Api eXtensions for Java (Core) - - - com.google.api - gax-parent - 2.20.1 - - - - - com.google.api - api-common - - - com.google.auth - google-auth-library-credentials - - - com.google.api.grpc - proto-google-common-protos - - - com.google.protobuf - protobuf-java - - - org.threeten - threetenbp - - - io.opencensus - opencensus-api - - - com.google.guava - guava - - - com.google.auth - google-auth-library-oauth2-http - - - com.google.code.findbugs - jsr305 - provided - - - org.graalvm.sdk - graal-sdk - provided - - - - - - - org.apache.maven.plugins - maven-jar-plugin - - - - test-jar - - - false - testlib - - com/google/api/gax/core/** - com/google/api/gax/rpc/testing/** - com/google/api/gax/rpc/mtls/** - - - - - - - - \ No newline at end of file diff --git a/gax/src/main/java/com/google/api/gax/batching/AccumulatingBatchReceiver.java b/gax/src/main/java/com/google/api/gax/batching/AccumulatingBatchReceiver.java deleted file mode 100644 index 3e6e47013..000000000 --- a/gax/src/main/java/com/google/api/gax/batching/AccumulatingBatchReceiver.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -import com.google.api.core.ApiFuture; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ConcurrentLinkedQueue; - -/** A simple ThresholdBatchReceiver that just accumulates batches. */ -public final class AccumulatingBatchReceiver implements ThresholdBatchReceiver { - private final ConcurrentLinkedQueue batches = new ConcurrentLinkedQueue<>(); - private final ApiFuture retFuture; - - public AccumulatingBatchReceiver(ApiFuture retFuture) { - this.retFuture = retFuture; - } - - @Override - public void validateBatch(T message) { - // no-op - } - - @Override - public ApiFuture processBatch(T batch) { - batches.add(batch); - return retFuture; - } - - /** - * Returns the accumulated batches. If called concurrently with {@code processBatch}, the new - * batch may or may not be returned. - */ - public List getBatches() { - return new ArrayList<>(batches); - } -} diff --git a/gax/src/main/java/com/google/api/gax/batching/BatchEntry.java b/gax/src/main/java/com/google/api/gax/batching/BatchEntry.java deleted file mode 100644 index 163eae9fd..000000000 --- a/gax/src/main/java/com/google/api/gax/batching/BatchEntry.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -import com.google.api.core.InternalApi; -import com.google.api.core.SettableApiFuture; -import com.google.auto.value.AutoValue; -import javax.annotation.Nullable; - -/** - * This class contains the element and its corresponding unresolved future, which would be resolved - * when batch is {@link BatchingDescriptor#splitResponse successful} or {@link - * BatchingDescriptor#splitException failed}. - * - * @param The type of each individual element to be batched. - * @param The type of the result for each individual element. - */ -@InternalApi("For google-cloud-java client use only.") -@AutoValue -public abstract class BatchEntry { - - /** Returns a new BatchEntry */ - public static BatchEntry create( - @Nullable ElementT element, SettableApiFuture resultFuture) { - return new AutoValue_BatchEntry<>(element, resultFuture); - } - - @Nullable - public abstract ElementT getElement(); - - public abstract SettableApiFuture getResultFuture(); -} diff --git a/gax/src/main/java/com/google/api/gax/batching/BatchMerger.java b/gax/src/main/java/com/google/api/gax/batching/BatchMerger.java deleted file mode 100644 index 2d8005307..000000000 --- a/gax/src/main/java/com/google/api/gax/batching/BatchMerger.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -public interface BatchMerger { - void merge(B batch, B newBatch); -} diff --git a/gax/src/main/java/com/google/api/gax/batching/Batcher.java b/gax/src/main/java/com/google/api/gax/batching/Batcher.java deleted file mode 100644 index 1e069d53e..000000000 --- a/gax/src/main/java/com/google/api/gax/batching/Batcher.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -import com.google.api.core.ApiFuture; -import com.google.api.core.InternalExtensionOnly; -import com.google.api.gax.rpc.ApiCallContext; - -/** - * Represents a batching context where individual elements will be accumulated and flushed in a - * large batch request at some point in the future. The buffered elements can be flushed manually or - * when triggered by an internal threshold. This is intended to be used for high throughput - * scenarios at the cost of latency. - * - *

Batcher instances are not thread safe. To use across different threads, create a new Batcher - * instance per thread. - * - * @param The type of each individual element to be batched. - * @param The type of the result for each individual element. - */ -@InternalExtensionOnly -public interface Batcher extends AutoCloseable { - - /** {@link ApiCallContext.Key} for tracking batch total throttled time */ - ApiCallContext.Key THROTTLED_TIME_KEY = ApiCallContext.Key.create("total_throttled_time"); - - /** - * Queues the passed in element to be sent at some point in the future. - * - *

The element will be sent as part of a larger batch request at some point in the future. The - * returned {@link ApiFuture} will be resolved once the result for the element has been extracted - * from the batch response. - * - *

Note: Cancelling returned result simply marks the future cancelled, It would not stop the - * batch request. - */ - ApiFuture add(ElementT entry); - - /** - * Synchronously sends any pending elements as a batch and waits for all outstanding batches to be - * complete. - */ - void flush() throws InterruptedException; - - /** - * Sends accumulated elements asynchronously for batching. - * - *

Note: This method can be invoked concurrently unlike {@link #add} and {@link #close}, which - * can only be called from a single user thread. Please take caution to avoid race condition. - */ - void sendOutstanding(); - - /** - * Closes this Batcher by preventing new elements from being added, and then flushing the existing - * elements. - */ - @Override - void close() throws InterruptedException; - - /** - * Closes this Batcher by preventing new elements from being added, and then sending outstanding - * elements. The returned future will be resolved when the last element completes - */ - ApiFuture closeAsync(); -} diff --git a/gax/src/main/java/com/google/api/gax/batching/BatcherImpl.java b/gax/src/main/java/com/google/api/gax/batching/BatcherImpl.java deleted file mode 100644 index 2118ae24b..000000000 --- a/gax/src/main/java/com/google/api/gax/batching/BatcherImpl.java +++ /dev/null @@ -1,600 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -import static com.google.common.util.concurrent.MoreExecutors.directExecutor; - -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutureCallback; -import com.google.api.core.ApiFutures; -import com.google.api.core.InternalApi; -import com.google.api.core.SettableApiFuture; -import com.google.api.gax.batching.FlowController.FlowControlException; -import com.google.api.gax.batching.FlowController.FlowControlRuntimeException; -import com.google.api.gax.batching.FlowController.LimitExceededBehavior; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import com.google.common.base.Stopwatch; -import com.google.common.util.concurrent.Futures; -import java.lang.ref.Reference; -import java.lang.ref.ReferenceQueue; -import java.lang.ref.SoftReference; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.annotation.Nullable; - -/** - * Queues up the elements until {@link #flush()} is called; once batching is over, returned future - * resolves. - * - *

This class is not thread-safe, and expects to be used from a single thread. - * - * @param The type of each individual element to be batched. - * @param The type of the result for each individual element. - * @param The type of the request that will contain the accumulated elements. - * @param The type of the response that will unpack into individual element results. - */ -@InternalApi("For google-cloud-java client use only") -public class BatcherImpl - implements Batcher { - - private static final Logger LOG = Logger.getLogger(BatcherImpl.class.getName()); - private final BatchingDescriptor - batchingDescriptor; - private final UnaryCallable unaryCallable; - private final RequestT prototype; - private final BatchingSettings batchingSettings; - private final BatcherReference currentBatcherReference; - - private Batch currentOpenBatch; - private final AtomicInteger numOfOutstandingBatches = new AtomicInteger(0); - private final Object flushLock = new Object(); - private final Object elementLock = new Object(); - private final Future scheduledFuture; - private SettableApiFuture closeFuture; - private final BatcherStats batcherStats = new BatcherStats(); - private final FlowController flowController; - private final ApiCallContext callContext; - - /** - * @param batchingDescriptor a {@link BatchingDescriptor} for transforming individual elements - * into wrappers request and response - * @param unaryCallable a {@link UnaryCallable} object - * @param prototype a {@link RequestT} object - * @param batchingSettings a {@link BatchingSettings} with configuration of thresholds - * @deprecated Please instantiate the Batcher with {@link FlowController} and {@link - * ApiCallContext} - */ - @Deprecated - public BatcherImpl( - BatchingDescriptor batchingDescriptor, - UnaryCallable unaryCallable, - RequestT prototype, - BatchingSettings batchingSettings, - ScheduledExecutorService executor) { - - this(batchingDescriptor, unaryCallable, prototype, batchingSettings, executor, null, null); - } - - /** - * @param batchingDescriptor a {@link BatchingDescriptor} for transforming individual elements - * into wrappers request and response - * @param unaryCallable a {@link UnaryCallable} object - * @param prototype a {@link RequestT} object - * @param batchingSettings a {@link BatchingSettings} with configuration of thresholds - * @param flowController a {@link FlowController} for throttling requests. If it's null, create a - * {@link FlowController} object from {@link BatchingSettings#getFlowControlSettings()}. - * @deprecated Please instantiate the Batcher with {@link ApiCallContext} - */ - @Deprecated - public BatcherImpl( - BatchingDescriptor batchingDescriptor, - UnaryCallable unaryCallable, - RequestT prototype, - BatchingSettings batchingSettings, - ScheduledExecutorService executor, - @Nullable FlowController flowController) { - - this( - batchingDescriptor, - unaryCallable, - prototype, - batchingSettings, - executor, - flowController, - null); - } - - /** - * @param batchingDescriptor a {@link BatchingDescriptor} for transforming individual elements - * into wrappers request and response - * @param unaryCallable a {@link UnaryCallable} object - * @param prototype a {@link RequestT} object - * @param batchingSettings a {@link BatchingSettings} with configuration of thresholds - * @param flowController a {@link FlowController} for throttling requests. If it's null, create a - * {@link FlowController} object from {@link BatchingSettings#getFlowControlSettings()}. - * @param callContext a {@link ApiCallContext} object that'll be merged in unaryCallable - */ - public BatcherImpl( - BatchingDescriptor batchingDescriptor, - UnaryCallable unaryCallable, - RequestT prototype, - BatchingSettings batchingSettings, - ScheduledExecutorService executor, - @Nullable FlowController flowController, - @Nullable ApiCallContext callContext) { - - this.batchingDescriptor = - Preconditions.checkNotNull(batchingDescriptor, "batching descriptor cannot be null"); - this.unaryCallable = Preconditions.checkNotNull(unaryCallable, "callable cannot be null"); - this.prototype = Preconditions.checkNotNull(prototype, "request prototype cannot be null"); - this.batchingSettings = - Preconditions.checkNotNull(batchingSettings, "batching setting cannot be null"); - Preconditions.checkNotNull(executor, "executor cannot be null"); - if (flowController == null) { - flowController = new FlowController(batchingSettings.getFlowControlSettings()); - } - // If throttling is enabled, make sure flow control limits are greater or equal to batch sizes - // to avoid deadlocking - if (flowController.getLimitExceededBehavior() != LimitExceededBehavior.Ignore) { - Preconditions.checkArgument( - flowController.getMaxElementCountLimit() == null - || batchingSettings.getElementCountThreshold() == null - || flowController.getMaxElementCountLimit() - >= batchingSettings.getElementCountThreshold(), - "If throttling and batching on element count are enabled, FlowController" - + "#maxOutstandingElementCount must be greater or equal to elementCountThreshold"); - Preconditions.checkArgument( - flowController.getMaxRequestBytesLimit() == null - || batchingSettings.getRequestByteThreshold() == null - || flowController.getMaxRequestBytesLimit() - >= batchingSettings.getRequestByteThreshold(), - "If throttling and batching on request bytes are enabled, FlowController" - + "#maxOutstandingRequestBytes must be greater or equal to requestByteThreshold"); - } - this.flowController = flowController; - currentOpenBatch = new Batch<>(prototype, batchingDescriptor, batchingSettings, batcherStats); - if (batchingSettings.getDelayThreshold() != null) { - long delay = batchingSettings.getDelayThreshold().toMillis(); - PushCurrentBatchRunnable runnable = - new PushCurrentBatchRunnable<>(this); - scheduledFuture = - executor.scheduleWithFixedDelay(runnable, delay, delay, TimeUnit.MILLISECONDS); - } else { - scheduledFuture = Futures.immediateCancelledFuture(); - } - currentBatcherReference = new BatcherReference(this); - this.callContext = callContext; - } - - /** {@inheritDoc} */ - @Override - public ApiFuture add(ElementT element) { - // Note: there is no need to synchronize over closeFuture. The write & read of the variable - // will only be done from a single calling thread. - Preconditions.checkState(closeFuture == null, "Cannot add elements on a closed batcher"); - - long bytesSize = batchingDescriptor.countBytes(element); - - // This is not the optimal way of throttling. It does not send out partial batches, which - // means that the Batcher might not use up all the resources allowed by FlowController. - // The more efficient implementation should look like: - // if (!flowController.tryReserve(1, bytes)) { - // sendOutstanding(); - // reserve(1, bytes); - // } - // where tryReserve() will return false if there isn't enough resources, or reserve and return - // true. - // However, with the current FlowController implementation, adding a tryReserve() could be - // confusing. FlowController will end up having 3 different reserve behaviors: blocking, - // non blocking and try reserve. And we'll also need to add a tryAcquire() to the Semaphore64 - // class, which made it seem unnecessary to have blocking and non-blocking semaphore - // implementations. Some refactoring may be needed for the optimized implementation. So we'll - // defer it till we decide on if refactoring FlowController is necessary. - Stopwatch stopwatch = Stopwatch.createStarted(); - try { - flowController.reserve(1, bytesSize); - } catch (FlowControlException e) { - // This exception will only be thrown if the FlowController is set to ThrowException behavior - throw FlowControlRuntimeException.fromFlowControlException(e); - } - long throttledTimeMs = stopwatch.elapsed(TimeUnit.MILLISECONDS); - - SettableApiFuture result = SettableApiFuture.create(); - synchronized (elementLock) { - currentOpenBatch.add(element, result, throttledTimeMs); - } - - if (currentOpenBatch.hasAnyThresholdReached()) { - sendOutstanding(); - } - return result; - } - - /** {@inheritDoc} */ - @Override - public void flush() throws InterruptedException { - sendOutstanding(); - awaitAllOutstandingBatches(); - } - - /** {@inheritDoc} */ - @Override - public void sendOutstanding() { - final Batch accumulatedBatch; - - synchronized (elementLock) { - if (currentOpenBatch.isEmpty()) { - return; - } - accumulatedBatch = currentOpenBatch; - currentOpenBatch = new Batch<>(prototype, batchingDescriptor, batchingSettings, batcherStats); - } - - // This check is for old clients that instantiated the batcher without ApiCallContext - ApiCallContext callContextWithOption = null; - if (callContext != null) { - callContextWithOption = - callContext.withOption(THROTTLED_TIME_KEY, accumulatedBatch.totalThrottledTimeMs); - } - final ApiFuture batchResponse = - unaryCallable.futureCall(accumulatedBatch.builder.build(), callContextWithOption); - - numOfOutstandingBatches.incrementAndGet(); - ApiFutures.addCallback( - batchResponse, - new ApiFutureCallback() { - @Override - public void onSuccess(ResponseT response) { - try { - flowController.release(accumulatedBatch.elementCounter, accumulatedBatch.byteCounter); - accumulatedBatch.onBatchSuccess(response); - } finally { - onBatchCompletion(); - } - } - - @Override - public void onFailure(Throwable throwable) { - try { - flowController.release(accumulatedBatch.elementCounter, accumulatedBatch.byteCounter); - accumulatedBatch.onBatchFailure(throwable); - } finally { - onBatchCompletion(); - } - } - }, - directExecutor()); - } - - private void onBatchCompletion() { - boolean shouldClose = false; - - synchronized (flushLock) { - if (numOfOutstandingBatches.decrementAndGet() == 0) { - flushLock.notifyAll(); - shouldClose = closeFuture != null; - } - } - if (shouldClose) { - BatchingException overallError = batcherStats.asException(); - if (overallError != null) { - closeFuture.setException(overallError); - } else { - closeFuture.set(null); - } - } - } - - private void awaitAllOutstandingBatches() throws InterruptedException { - while (numOfOutstandingBatches.get() > 0) { - synchronized (flushLock) { - // Check again under lock to avoid racing with onBatchCompletion - if (numOfOutstandingBatches.get() == 0) { - break; - } - flushLock.wait(); - } - } - } - - /** {@inheritDoc} */ - @Override - public void close() throws InterruptedException { - try { - closeAsync().get(); - } catch (ExecutionException e) { - // Original stacktrace of a batching exception is not useful, so rethrow the error with - // the caller stacktrace - if (e.getCause() instanceof BatchingException) { - BatchingException cause = (BatchingException) e.getCause(); - throw new BatchingException(cause.getMessage()); - } else { - throw new IllegalStateException("unexpected error closing the batcher", e.getCause()); - } - } - } - - @Override - public ApiFuture closeAsync() { - if (closeFuture != null) { - return closeFuture; - } - - // Send any buffered elements - // Must come before numOfOutstandingBatches check below - sendOutstanding(); - - boolean closeImmediately; - - synchronized (flushLock) { - // prevent admission of new elements - closeFuture = SettableApiFuture.create(); - // check if we can close immediately - closeImmediately = numOfOutstandingBatches.get() == 0; - } - - // Clean up accounting - scheduledFuture.cancel(false); - currentBatcherReference.closed = true; - currentBatcherReference.clear(); - - // notify futures - if (closeImmediately) { - finishClose(); - } - return closeFuture; - } - - private void finishClose() { - BatchingException batchingException = batcherStats.asException(); - if (batchingException != null) { - closeFuture.setException(batchingException); - } else { - closeFuture.set(null); - } - } - - @InternalApi("For google-cloud-java client use only") - public FlowController getFlowController() { - return flowController; - } - - /** - * This class represent one logical Batch. It accumulates all the elements and their corresponding - * future results for one batch. - */ - private static class Batch { - private final BatchingRequestBuilder builder; - private final List> entries; - private final BatchingDescriptor descriptor; - private final BatcherStats batcherStats; - private final long elementThreshold; - private final long bytesThreshold; - - private long elementCounter = 0; - private long byteCounter = 0; - private long totalThrottledTimeMs = 0; - - private Batch( - RequestT prototype, - BatchingDescriptor descriptor, - BatchingSettings batchingSettings, - BatcherStats batcherStats) { - this.descriptor = descriptor; - this.builder = descriptor.newRequestBuilder(prototype); - this.entries = new ArrayList<>(); - Long elementCountThreshold = batchingSettings.getElementCountThreshold(); - this.elementThreshold = elementCountThreshold == null ? 0 : elementCountThreshold; - Long requestByteThreshold = batchingSettings.getRequestByteThreshold(); - this.bytesThreshold = requestByteThreshold == null ? 0 : requestByteThreshold; - this.batcherStats = batcherStats; - } - - void add(ElementT element, SettableApiFuture result, long throttledTimeMs) { - builder.add(element); - entries.add(BatchEntry.create(element, result)); - elementCounter++; - byteCounter += descriptor.countBytes(element); - totalThrottledTimeMs += throttledTimeMs; - } - - void onBatchSuccess(ResponseT response) { - try { - descriptor.splitResponse(response, entries); - batcherStats.recordBatchElementsCompletion(entries); - } catch (Exception ex) { - onBatchFailure(ex); - } - } - - void onBatchFailure(Throwable throwable) { - try { - descriptor.splitException(throwable, entries); - } catch (Exception ex) { - for (BatchEntry batchEntry : entries) { - batchEntry.getResultFuture().setException(ex); - } - } - batcherStats.recordBatchFailure(throwable); - } - - boolean isEmpty() { - return elementCounter == 0; - } - - boolean hasAnyThresholdReached() { - return elementCounter >= elementThreshold || byteCounter >= bytesThreshold; - } - } - - /** - * Executes {@link #sendOutstanding()} on a periodic interval. - * - *

This class holds a weak reference to the Batcher instance and cancels polling if the target - * Batcher has been garbage collected. - */ - @VisibleForTesting - static class PushCurrentBatchRunnable - implements Runnable { - - private Future scheduledFuture; - private final WeakReference> - batcherReferent; - - PushCurrentBatchRunnable(BatcherImpl batcher) { - this.batcherReferent = new WeakReference<>(batcher); - } - - @Override - public void run() { - BatcherImpl batcher = batcherReferent.get(); - if (batcher == null) { - scheduledFuture.cancel(true); - } else { - batcher.sendOutstanding(); - } - } - - void setScheduledFuture(Future scheduledFuture) { - this.scheduledFuture = scheduledFuture; - } - - boolean isCancelled() { - return scheduledFuture.isCancelled(); - } - } - - /** - * On every Batcher allocation this class will check for garbage collected batchers that were - * never closed and emit warning logs. - */ - @VisibleForTesting - static final class BatcherReference extends WeakReference { - - private static final ReferenceQueue refQueue = new ReferenceQueue<>(); - - // Retain the References so they don't get GC'd - private static final ConcurrentMap refs = - new ConcurrentHashMap<>(); - - private static final String ALLOCATION_SITE_PROPERTY_NAME = - "com.google.api.gax.batching.Batcher.enableAllocationTracking"; - - private static final boolean ENABLE_ALLOCATION_TRACKING = - Boolean.parseBoolean(System.getProperty(ALLOCATION_SITE_PROPERTY_NAME, "true")); - private static final RuntimeException missingCallSite = missingCallSite(); - - private final Reference allocationSite; - private volatile boolean closed; - - BatcherReference(BatcherImpl referent) { - super(referent, refQueue); - // allocationSite is softReference to make it garbage collectible, but delay it as long as - // possible as BatcherReference can only be weakly referred. - allocationSite = - new SoftReference<>( - ENABLE_ALLOCATION_TRACKING - ? new RuntimeException("Batcher allocation site") - : missingCallSite); - refs.put(this, this); - cleanQueue(); - } - - /** - * This clear() is *not* called automatically by the JVM. As this is a weak ref, the reference - * will be cleared automatically by the JVM, but will not be removed from {@link #refs}. We do - * it here to avoid this ending up on the reference queue. - */ - @Override - public void clear() { - clearInternal(); - // We run this here to periodically clean up the queue if any Batcher is being - // closed properly. - cleanQueue(); - } - - private void clearInternal() { - super.clear(); - refs.remove(this); - allocationSite.clear(); - } - - /** - * It performs below tasks: - * - *

    - *
  • Check each batcher registered on refQueue while initialization. - *
  • Unregister them from refQueue. - *
  • If close() is not called on the batcher, then emits log with possible allocationSite. - *
  • Keeps track of number of batcher on which close() is not called. - *
- */ - @VisibleForTesting - static int cleanQueue() { - BatcherReference ref; - int orphanedBatchers = 0; - while ((ref = (BatcherReference) refQueue.poll()) != null) { - RuntimeException maybeAllocationSite = ref.allocationSite.get(); - ref.clearInternal(); // technically the reference is gone already. - if (!ref.closed) { - orphanedBatchers++; - if (LOG.isLoggable(Level.SEVERE)) { - String message = "Batcher was not closed properly!!! Make sure to call close()."; - LOG.log(Level.SEVERE, message, maybeAllocationSite); - } - } - } - return orphanedBatchers; - } - - private static RuntimeException missingCallSite() { - RuntimeException e = - new RuntimeException( - "Batcher allocation site not recorded. Set -D" - + ALLOCATION_SITE_PROPERTY_NAME - + "=true to enable it"); - e.setStackTrace(new StackTraceElement[0]); - return e; - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/batching/BatcherStats.java b/gax/src/main/java/com/google/api/gax/batching/BatcherStats.java deleted file mode 100644 index 784af6f59..000000000 --- a/gax/src/main/java/com/google/api/gax/batching/BatcherStats.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -import com.google.api.gax.rpc.ApiException; -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.common.base.MoreObjects; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import javax.annotation.Nullable; - -/** - * Keeps the statistics about failed operations(both at RPC and ElementT) in {@link Batcher}. This - * provides the count of individual exception failure and count of each failed {@link Code} occurred - * in the batching process. - */ -class BatcherStats { - - private final Map requestExceptionCounts = new HashMap<>(); - private final Map requestStatusCounts = new HashMap<>(); - private int requestPartialFailureCount; - - private final Map entryExceptionCounts = new HashMap<>(); - private final Map entryStatusCounts = new HashMap<>(); - - /** - * Records the count of the exception and it's type when a complete batch failed to apply. - * - *

Note: This method aggregates all the subclasses of {@link ApiException} under ApiException - * using the {@link Code status codes} and its number of occurrences. - */ - synchronized void recordBatchFailure(Throwable throwable) { - Class exceptionClass = throwable.getClass(); - - if (throwable instanceof ApiException) { - Code code = ((ApiException) throwable).getStatusCode().getCode(); - exceptionClass = ApiException.class; - - int oldStatusCount = MoreObjects.firstNonNull(requestStatusCounts.get(code), 0); - requestStatusCounts.put(code, oldStatusCount + 1); - } - - int oldExceptionCount = MoreObjects.firstNonNull(requestExceptionCounts.get(exceptionClass), 0); - requestExceptionCounts.put(exceptionClass, oldExceptionCount + 1); - } - - /** - * Records partial failures within each batch. partialBatchFailures counts the number of batches - * that have at least one failed entry while entryStatusCounts and entryExceptionCounts track the - * count of the entries themselves. - * - *

Note: This method aggregates all the subclasses of {@link ApiException} under ApiException - * using the {@link Code status codes} and its number of occurrences. - */ - synchronized void recordBatchElementsCompletion( - List batchElementResultFutures) { - boolean isRequestPartiallyFailed = false; - for (final BatchEntry elementResult : batchElementResultFutures) { - try { - elementResult.getResultFuture().get(); - } catch (Throwable throwable) { - - if (!isRequestPartiallyFailed) { - isRequestPartiallyFailed = true; - requestPartialFailureCount++; - } - Throwable actualCause = throwable.getCause(); - Class exceptionClass = actualCause.getClass(); - - if (actualCause instanceof ApiException) { - Code code = ((ApiException) actualCause).getStatusCode().getCode(); - exceptionClass = ApiException.class; - - int oldStatusCount = MoreObjects.firstNonNull(entryStatusCounts.get(code), 0); - entryStatusCounts.put(code, oldStatusCount + 1); - } - - int oldExceptionCount = - MoreObjects.firstNonNull(entryExceptionCounts.get(exceptionClass), 0); - entryExceptionCounts.put(exceptionClass, oldExceptionCount + 1); - } - } - } - - /** Calculates and formats the message with request and entry failure count. */ - @Nullable - synchronized BatchingException asException() { - if (requestExceptionCounts.isEmpty() && requestPartialFailureCount == 0) { - return null; - } - - StringBuilder messageBuilder = new StringBuilder(); - messageBuilder.append("Batching finished with "); - - if (!requestExceptionCounts.isEmpty()) { - messageBuilder - .append( - String.format("%d batches failed to apply due to: ", requestExceptionCounts.size())) - .append(buildExceptionList(requestExceptionCounts, requestStatusCounts)) - .append(" and "); - } - - messageBuilder.append(String.format("%d partial failures.", requestPartialFailureCount)); - if (requestPartialFailureCount > 0) { - int totalEntriesCount = 0; - for (Integer count : entryExceptionCounts.values()) { - totalEntriesCount += count; - } - - messageBuilder - .append( - String.format( - " The %d partial failures contained %d entries that failed with: ", - requestPartialFailureCount, totalEntriesCount)) - .append(buildExceptionList(entryExceptionCounts, entryStatusCounts)) - .append("."); - } - return new BatchingException(messageBuilder.toString()); - } - - /** - * Prints the class name and it's count along with {@link Code status code} and it's counts. - * - *

Example: "1 IllegalStateException, 1 ApiException(1 UNAVAILABLE, 1 ALREADY_EXISTS)". - */ - private String buildExceptionList( - Map exceptionCounts, Map statusCounts) { - StringBuilder messageBuilder = new StringBuilder(); - Iterator> exceptionIterator = exceptionCounts.entrySet().iterator(); - - while (exceptionIterator.hasNext()) { - Map.Entry request = exceptionIterator.next(); - messageBuilder.append( - String.format("%d %s", request.getValue(), request.getKey().getSimpleName())); - - if (ApiException.class.equals(request.getKey())) { - messageBuilder.append("("); - Iterator> statusIterator = statusCounts.entrySet().iterator(); - while (statusIterator.hasNext()) { - Map.Entry statusCode = statusIterator.next(); - messageBuilder.append(String.format("%d %s", statusCode.getValue(), statusCode.getKey())); - if (statusIterator.hasNext()) { - messageBuilder.append(", "); - } - } - messageBuilder.append(")"); - } - if (exceptionIterator.hasNext()) { - messageBuilder.append(", "); - } - } - - return messageBuilder.toString(); - } -} diff --git a/gax/src/main/java/com/google/api/gax/batching/BatchingCallSettings.java b/gax/src/main/java/com/google/api/gax/batching/BatchingCallSettings.java deleted file mode 100644 index f7a25ae77..000000000 --- a/gax/src/main/java/com/google/api/gax/batching/BatchingCallSettings.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -import com.google.api.core.InternalApi; -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.rpc.StatusCode; -import com.google.api.gax.rpc.UnaryCallSettings; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.common.base.MoreObjects; -import com.google.common.base.Preconditions; -import java.util.Set; - -/** - * This is an extension of {@link UnaryCallSettings} class to configure a {@link UnaryCallable} for - * calls to an API method that supports batching. The batching settings are provided using the - * instance of {@link BatchingSettings}. - * - *

Retry configuration will be applied on each batching RPC request. - * - *

Sample settings configuration: - * - *

{@code
- * BatchingCallSettings batchingCallSettings = // Default BatchingCallSettings from the client
- * BatchingCallSettings customBatchingCallSettings =
- *     batchingCallSettings
- *         .toBuilder()
- *         .setRetryableCodes(StatusCode.Code.UNAVAILABLE, ...)
- *         .setRetrySettings(RetrySettings.newBuilder()...build())
- *         .setBatchingSettings(BatchingSettings.newBuilder()...build())
- *         .build();
- * }
- * - * @param The type of each individual element to be batched. - * @param The type of the result for each individual element. - * @param The type of the request that will contain the accumulated elements. - * @param The type of the response that will unpack into individual element results. - */ -public final class BatchingCallSettings - extends UnaryCallSettings { - private final BatchingDescriptor - batchingDescriptor; - private final BatchingSettings batchingSettings; - - @InternalApi("For google-cloud-java client use only") - public BatchingDescriptor getBatchingDescriptor() { - return batchingDescriptor; - } - - /** Returns batching settings which contains multiple batch threshold levels. */ - public BatchingSettings getBatchingSettings() { - return batchingSettings; - } - - private BatchingCallSettings(Builder builder) { - super(builder); - Preconditions.checkState(builder.batchingSettings != null, "batching settings cannot be null"); - this.batchingDescriptor = builder.batchingDescriptor; - this.batchingSettings = builder.batchingSettings; - } - - /** Please use {@link #toBuilder()} to override settings values. */ - @InternalApi("For google-cloud-java client use only") - public static - Builder newBuilder( - BatchingDescriptor batchingDescriptor) { - return new Builder<>(batchingDescriptor); - } - - /** - * Get a builder with the same values as this object. See the class documentation of {@link - * BatchingCallSettings} for a sample settings configuration. - */ - @Override - public final Builder toBuilder() { - return new Builder<>(this); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("retryableCodes", getRetryableCodes()) - .add("retrySettings", getRetrySettings()) - .add("batchingSettings", batchingSettings) - .toString(); - } - - /** - * A base builder class for {@link BatchingCallSettings}. See the class documentation of {@link - * BatchingCallSettings} for a description of the different values that can be set. - */ - public static class Builder - extends UnaryCallSettings.Builder { - - private BatchingDescriptor batchingDescriptor; - private BatchingSettings batchingSettings; - - private Builder( - BatchingDescriptor batchingDescriptor) { - this.batchingDescriptor = - Preconditions.checkNotNull(batchingDescriptor, "batching descriptor cannot be null"); - } - - private Builder(BatchingCallSettings settings) { - super(settings); - this.batchingDescriptor = settings.batchingDescriptor; - this.batchingSettings = settings.batchingSettings; - } - - /** Sets the batching settings with various thresholds. */ - public Builder setBatchingSettings( - BatchingSettings batchingSettings) { - this.batchingSettings = batchingSettings; - return this; - } - - /** Returns the {@link BatchingSettings}. */ - public BatchingSettings getBatchingSettings() { - return batchingSettings; - } - - /** Sets the rpc failure {@link StatusCode.Code code}, for which retries should be performed. */ - @Override - public Builder setRetryableCodes( - StatusCode.Code... codes) { - super.setRetryableCodes(codes); - return this; - } - - /** Sets the rpc failure {@link StatusCode.Code code}, for which retries should be performed. */ - @Override - public Builder setRetryableCodes( - Set retryableCodes) { - super.setRetryableCodes(retryableCodes); - return this; - } - - /** Sets the {@link RetrySettings} values for each retry attempts. */ - @Override - public Builder setRetrySettings( - RetrySettings retrySettings) { - super.setRetrySettings(retrySettings); - return this; - } - - /** Builds the {@link BatchingCallSettings} object with provided configuration. */ - @Override - public BatchingCallSettings build() { - return new BatchingCallSettings<>(this); - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/batching/BatchingDescriptor.java b/gax/src/main/java/com/google/api/gax/batching/BatchingDescriptor.java deleted file mode 100644 index d81068a98..000000000 --- a/gax/src/main/java/com/google/api/gax/batching/BatchingDescriptor.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -import com.google.api.core.InternalApi; -import java.util.List; - -/** - * An adapter that packs and unpacks the elements in and out of batch requests and responses. - * - *

This interface should be implemented by either a service specific client or autogenerated by - * gapic-generator. - * - *

Example implementation: - * - *

{@code
- * class ListDescriptor implements BatchingDescriptor, List> {
- *
- *   RequestBuilder> newRequestBuilder(List prototype) {
- *     return new RequestBuilder>() {
- *
- *       void add(String element) {
- *         list.add(element);
- *       }
- *
- *       List build() {
- *         return list.clone();
- *       }
- *     };
- *   }
- *
- *   void splitResponse(List callableResponse, List> batch) {
- *     for (int i = 0; i < batchResponse.size(); i++) {
- *       batch.get(i).set(batchResponse.get(i);
- *     }
- *   }
- *
- *   void splitException(Throwable throwable, List> batch) {
- *     for (SettableApiFuture result : batch) {
- *       result.setException(throwable);
- *     }
- *   }
- *
- *   long countBytes(String element) {
- *     return element.length();
- *   }
- * }
- * }
- * - * @param The type of each individual element to be batched - * @param The type of the result for each individual element - * @param The type of the request that will contain the accumulated elements - * @param The type of the response that will be unpacked into individual element results - */ -@InternalApi("For google-cloud-java client use only.") -public interface BatchingDescriptor { - - /** - * Creates a new wrapper for the underlying request builder. It's used to pack the current batch - * request with elements. - */ - BatchingRequestBuilder newRequestBuilder(RequestT prototype); - - /** Unpacks the batch response into individual elements results. */ - void splitResponse(ResponseT batchResponse, List> batch); - - /** Unpacks the batch response error into individual element errors. */ - void splitException(Throwable throwable, List> batch); - - /** Returns the size of the passed element object in bytes. */ - long countBytes(ElementT element); -} diff --git a/gax/src/main/java/com/google/api/gax/batching/BatchingException.java b/gax/src/main/java/com/google/api/gax/batching/BatchingException.java deleted file mode 100644 index 470c659d0..000000000 --- a/gax/src/main/java/com/google/api/gax/batching/BatchingException.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -/** Represents exception occurred during batching. */ -public final class BatchingException extends RuntimeException { - - BatchingException(String message) { - super(message); - } -} diff --git a/gax/src/main/java/com/google/api/gax/batching/BatchingFlowController.java b/gax/src/main/java/com/google/api/gax/batching/BatchingFlowController.java deleted file mode 100644 index 4252f7594..000000000 --- a/gax/src/main/java/com/google/api/gax/batching/BatchingFlowController.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -import com.google.api.gax.batching.FlowController.FlowControlException; -import com.google.common.base.Preconditions; -import com.google.common.primitives.Ints; - -/** Wraps a {@link FlowController} for use by batching. */ -public class BatchingFlowController { - - private final FlowController flowController; - private final ElementCounter elementCounter; - private final ElementCounter byteCounter; - - public BatchingFlowController( - FlowController flowController, - ElementCounter elementCounter, - ElementCounter byteCounter) { - this.flowController = flowController; - this.elementCounter = elementCounter; - this.byteCounter = byteCounter; - } - - public void reserve(T batch) throws FlowControlException { - Preconditions.checkNotNull(batch); - int elements = Ints.checkedCast(elementCounter.count(batch)); - int bytes = Ints.checkedCast(byteCounter.count(batch)); - flowController.reserve(elements, bytes); - } - - public void release(T batch) { - Preconditions.checkNotNull(batch); - int elements = Ints.checkedCast(elementCounter.count(batch)); - int bytes = Ints.checkedCast(byteCounter.count(batch)); - flowController.release(elements, bytes); - } -} diff --git a/gax/src/main/java/com/google/api/gax/batching/BatchingRequestBuilder.java b/gax/src/main/java/com/google/api/gax/batching/BatchingRequestBuilder.java deleted file mode 100644 index 448e15c5b..000000000 --- a/gax/src/main/java/com/google/api/gax/batching/BatchingRequestBuilder.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -import com.google.api.core.InternalApi; - -/** - * Adapter to pack individual elements into a larger batch request. - * - *

The implementation for this interface will be implemented by service specific client or auto - * generated by the gapic-generator. - * - * @param The type of each individual element to be batched. - * @param The type of the request that will contain the accumulated elements. - */ -@InternalApi("For google-cloud-java client use only.") -public interface BatchingRequestBuilder { - - /** Adds element object into client specific batch request. */ - void add(ElementT element); - - /** Returns the collected elements as a single client specific batch request. */ - RequestT build(); -} diff --git a/gax/src/main/java/com/google/api/gax/batching/BatchingSettings.java b/gax/src/main/java/com/google/api/gax/batching/BatchingSettings.java deleted file mode 100644 index 8982c46ff..000000000 --- a/gax/src/main/java/com/google/api/gax/batching/BatchingSettings.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -import com.google.api.gax.batching.FlowController.LimitExceededBehavior; -import com.google.auto.value.AutoValue; -import com.google.common.base.Preconditions; -import javax.annotation.Nullable; -import org.threeten.bp.Duration; - -/** - * Represents the batching settings to use for an API method that is capable of batching. - * - *

By default the settings are configured to not use batching (i.e. the batch size - * threshold is 1). This is the safest default behavior, which has meaning in all possible - * scenarios. Users are expected to configure actual batching thresholds explicitly: the element - * count, the request bytes count and the delay. - * - *

Warning: With the wrong settings, it is possible to cause long periods of dead waiting time. - * - *

When batching is turned on for an API method, a call to that method will result in the request - * being queued up with other requests. When any of the set thresholds are reached, the queued up - * requests are packaged together in a batch and set to the service as a single RPC. When the - * response comes back, it is split apart into individual responses according to the individual - * input requests. - * - *

There are several supported thresholds: - * - *

    - *
  • Delay Threshold: Counting from the time that the first message is queued, once this - * delay has passed, then send the batch. The default value is 1 millisecond. - *
  • Message Count Threshold: Once this many messages are queued, send all of the - * messages in a single call, even if the delay threshold hasn't elapsed yet. The default - * value is 1 message. - *
  • Request Byte Threshold: Once the number of bytes in the batched request reaches this - * threshold, send all of the messages in a single call, even if neither the delay or message - * count thresholds have been exceeded yet. The default value is 1 byte. - *
- * - *

These thresholds are treated as triggers, not as limits. Thus, if a request is made with 2x - * the message count threshold, it will not be split apart (unless one of the limits listed further - * down is crossed); only one batch will be sent. Each threshold is an independent trigger and - * doesn't have any knowledge of the other thresholds. - * - *

Two of the values above also have limits: - * - *

    - *
  • Message Count Limit: The limit of the number of messages that the server will accept - * in a single request. - *
  • Request Byte Limit: The limit of the byte size of a request that the server will - * accept. - *
- * - *

For these values, individual requests that surpass the limit are rejected, and the batching - * logic will not batch together requests if the resulting batch will surpass the limit. Thus, a - * batch can be sent that is actually under the threshold if the next request would put the combined - * request over the limit. - * - *

Batching also supports FlowControl. This can be used to prevent the batching implementation - * from accumulating messages without limit, resulting eventually in an OutOfMemory exception. This - * can occur if messages are created and added to batching faster than they can be processed. The - * flow control behavior is controlled using FlowControlSettings. - */ -@AutoValue -public abstract class BatchingSettings { - /** Get the element count threshold to use for batching. */ - @Nullable - public abstract Long getElementCountThreshold(); - - /** Get the request byte threshold to use for batching. */ - @Nullable - public abstract Long getRequestByteThreshold(); - - /** Get the delay threshold to use for batching. */ - @Nullable - public abstract Duration getDelayThreshold(); - - /** Returns the Boolean object to indicate if the batching is enabled. Default to true */ - public abstract Boolean getIsEnabled(); - - /** Get the flow control settings to use. */ - public abstract FlowControlSettings getFlowControlSettings(); - - /** Get a new builder. */ - public static Builder newBuilder() { - return new AutoValue_BatchingSettings.Builder() - .setIsEnabled(true) - .setElementCountThreshold(1L) - .setRequestByteThreshold(1L) - .setDelayThreshold(Duration.ofMillis(1)) - .setFlowControlSettings( - FlowControlSettings.newBuilder() - .setLimitExceededBehavior(LimitExceededBehavior.Ignore) - .build()); - } - - /** Get a builder with the same values as this object. */ - public abstract Builder toBuilder(); - - /** - * See the class documentation of {@link BatchingSettings} for a description of the different - * values that can be set. - */ - @AutoValue.Builder - public abstract static class Builder { - /** - * Set the element count threshold to use for batching. After this many elements are - * accumulated, they will be wrapped up in a batch and sent. - */ - public abstract Builder setElementCountThreshold(Long elementCountThreshold); - - /** - * Set the request byte threshold to use for batching. After this many bytes are accumulated, - * the elements will be wrapped up in a batch and sent. - */ - public abstract Builder setRequestByteThreshold(Long requestByteThreshold); - - /** - * Set the delay threshold to use for batching. After this amount of time has elapsed (counting - * from the first element added), the elements will be wrapped up in a batch and sent. This - * value should not be set too high, usually on the order of milliseconds. Otherwise, calls - * might appear to never complete. - */ - public abstract Builder setDelayThreshold(Duration delayThreshold); - - /** - * Set if the batch should be enabled. If set to false, the batch logic will be disabled and the - * simple API call will be used. Default to true. - */ - public abstract Builder setIsEnabled(Boolean enabled); - - /** Set the flow control settings to be used. */ - public abstract Builder setFlowControlSettings(FlowControlSettings flowControlSettings); - - abstract BatchingSettings autoBuild(); - - /** Build the BatchingSettings object. */ - public BatchingSettings build() { - BatchingSettings settings = autoBuild(); - Preconditions.checkArgument( - settings.getElementCountThreshold() == null || settings.getElementCountThreshold() > 0, - "elementCountThreshold must be either unset or positive"); - Preconditions.checkArgument( - settings.getRequestByteThreshold() == null || settings.getRequestByteThreshold() > 0, - "requestByteThreshold must be either unset or positive"); - Preconditions.checkArgument( - settings.getDelayThreshold() == null - || settings.getDelayThreshold().compareTo(Duration.ZERO) > 0, - "delayThreshold must be either unset or positive"); - return settings; - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/batching/BatchingThreshold.java b/gax/src/main/java/com/google/api/gax/batching/BatchingThreshold.java deleted file mode 100644 index 02ceabdb1..000000000 --- a/gax/src/main/java/com/google/api/gax/batching/BatchingThreshold.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -/** - * The interface representing a threshold to be used in ThresholdBatcher. Thresholds do not need to - * be thread-safe if they are only used inside ThresholdBatcher. - */ -public interface BatchingThreshold { - - /** - * Presents the element to the threshold for the attribute of interest to be accumulated. - * - *

Any calls into this function from ThresholdBatcher will be under a lock. - */ - void accumulate(E e); - - /** - * Any calls into this function from ThresholdBatcher will be under a lock. - * - * @return whether the threshold has been reached. - */ - boolean isThresholdReached(); - - /** - * Make a copy of this threshold but with the accumulated value zeroed. - * - *

Any calls into this function from ThresholdBatcher will be under a lock. - */ - BatchingThreshold copyWithZeroedValue(); -} diff --git a/gax/src/main/java/com/google/api/gax/batching/BatchingThresholds.java b/gax/src/main/java/com/google/api/gax/batching/BatchingThresholds.java deleted file mode 100644 index 28409b00b..000000000 --- a/gax/src/main/java/com/google/api/gax/batching/BatchingThresholds.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -import com.google.common.collect.ImmutableList; -import java.util.List; - -/** Factory methods for general-purpose batching thresholds. */ -public final class BatchingThresholds { - - /** - * Creates an ImmutableList containing only a single threshold which counts the number of - * elements. This is helpful for when using ThresholdBatcher for the simple case, when the element - * count is the only threshold. - */ - public static List> create(long elementThreshold) { - BatchingThreshold batchingThreshold = - new NumericThreshold<>( - elementThreshold, - new ElementCounter() { - @Override - public long count(E e) { - return 1; - } - }); - return ImmutableList.of(batchingThreshold); - } -} diff --git a/gax/src/main/java/com/google/api/gax/batching/BlockingSemaphore.java b/gax/src/main/java/com/google/api/gax/batching/BlockingSemaphore.java deleted file mode 100644 index 0271f7e8a..000000000 --- a/gax/src/main/java/com/google/api/gax/batching/BlockingSemaphore.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.gax.batching; - -import com.google.common.base.Preconditions; - -/** A {@link Semaphore64} that blocks until permits become available. */ -class BlockingSemaphore implements Semaphore64 { - private long availablePermits; - private long limit; - - private static void checkNotNegative(long l) { - Preconditions.checkArgument(l >= 0, "negative permits not allowed: %s", l); - } - - BlockingSemaphore(long permits) { - checkNotNegative(permits); - this.availablePermits = permits; - this.limit = permits; - } - - @Override - public synchronized void release(long permits) { - checkNotNegative(permits); - // TODO: throw exceptions when the permits overflow - availablePermits = Math.min(availablePermits + permits, limit); - notifyAll(); - } - - @Override - public synchronized boolean acquire(long permits) { - checkNotNegative(permits); - - boolean interrupted = false; - while (availablePermits < permits) { - try { - wait(); - } catch (InterruptedException e) { - interrupted = true; - } - } - // TODO: if thread is interrupted, we should not grant the permits - availablePermits -= permits; - - if (interrupted) { - Thread.currentThread().interrupt(); - } - return true; - } - - @Override - public synchronized boolean acquirePartial(long permits) { - checkNotNegative(permits); - - boolean interrupted = false; - // To allow individual oversized requests to be sent, clamp the requested permits to the maximum - // limit. This will allow individual large requests to be sent. Please note that this behavior - // will result in availablePermits going negative. - while (availablePermits < Math.min(limit, permits)) { - try { - wait(); - } catch (InterruptedException e) { - interrupted = true; - } - } - - if (interrupted) { - Thread.currentThread().interrupt(); - } - - availablePermits -= permits; - return true; - } - - @Override - public synchronized void increasePermitLimit(long permits) { - checkNotNegative(permits); - availablePermits += permits; - limit += permits; - notifyAll(); - } - - @Override - public synchronized void reducePermitLimit(long reduction) { - checkNotNegative(reduction); - Preconditions.checkState(limit - reduction > 0, "permit limit underflow"); - availablePermits -= reduction; - limit -= reduction; - } - - @Override - public synchronized long getPermitLimit() { - return limit; - } -} diff --git a/gax/src/main/java/com/google/api/gax/batching/DynamicFlowControlSettings.java b/gax/src/main/java/com/google/api/gax/batching/DynamicFlowControlSettings.java deleted file mode 100644 index 95025183a..000000000 --- a/gax/src/main/java/com/google/api/gax/batching/DynamicFlowControlSettings.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -import com.google.api.core.InternalApi; -import com.google.api.gax.batching.FlowController.LimitExceededBehavior; -import com.google.auto.value.AutoValue; -import com.google.common.base.Preconditions; -import javax.annotation.Nullable; - -/** Settings for dynamic flow control */ -@AutoValue -@InternalApi("For google-cloud-java client use only") -public abstract class DynamicFlowControlSettings { - - /** Number of outstanding elements that {@link FlowController} allows when it's initiated. */ - @Nullable - public abstract Long getInitialOutstandingElementCount(); - - /** Number of outstanding bytes that {@link FlowController} allows when it's initiated. */ - @Nullable - public abstract Long getInitialOutstandingRequestBytes(); - - /** - * Maximum number of outstanding elements {@link FlowController} allows before enforcing flow - * control. - */ - @Nullable - public abstract Long getMaxOutstandingElementCount(); - - /** - * Maximum number of outstanding bytes {@link FlowController} allows before enforcing flow - * control. - */ - @Nullable - public abstract Long getMaxOutstandingRequestBytes(); - - /** - * Minimum number of outstanding elements {@link FlowController} allows before enforcing flow - * control. - */ - @Nullable - public abstract Long getMinOutstandingElementCount(); - - /** - * Minimum number of outstanding bytes {@link FlowController} allows before enforcing flow - * control. - */ - @Nullable - public abstract Long getMinOutstandingRequestBytes(); - - /** @see FlowControlSettings#getLimitExceededBehavior() */ - public abstract LimitExceededBehavior getLimitExceededBehavior(); - - public abstract Builder toBuilder(); - - public static Builder newBuilder() { - return new AutoValue_DynamicFlowControlSettings.Builder() - .setLimitExceededBehavior(LimitExceededBehavior.Block); - } - - @AutoValue.Builder - public abstract static class Builder { - - public abstract Builder setInitialOutstandingElementCount(Long value); - - public abstract Builder setInitialOutstandingRequestBytes(Long value); - - public abstract Builder setMaxOutstandingElementCount(Long value); - - public abstract Builder setMaxOutstandingRequestBytes(Long value); - - public abstract Builder setMinOutstandingElementCount(Long value); - - public abstract Builder setMinOutstandingRequestBytes(Long value); - - public abstract Builder setLimitExceededBehavior(LimitExceededBehavior value); - - abstract DynamicFlowControlSettings autoBuild(); - - public DynamicFlowControlSettings build() { - DynamicFlowControlSettings settings = autoBuild(); - - verifyElementCountSettings(settings); - verifyRequestBytesSettings(settings); - - return settings; - } - - private void verifyElementCountSettings(DynamicFlowControlSettings settings) { - // If LimitExceededBehavior is Ignore, dynamic flow control is disabled, there's no need to - // check element count limit settings - if (settings.getLimitExceededBehavior() == LimitExceededBehavior.Ignore) { - return; - } - if (settings.getInitialOutstandingElementCount() == null - && settings.getMinOutstandingElementCount() == null - && settings.getMaxOutstandingElementCount() == null) { - return; - } - Preconditions.checkState( - settings.getInitialOutstandingElementCount() != null - && settings.getMinOutstandingElementCount() != null - && settings.getMaxOutstandingElementCount() != null, - "Throttling on element count is disabled by default. To enable this setting," - + " minOutstandingElementCount, initialOutstandingElementCount, and " - + "maxOutstandingElementCount must all be set."); - Preconditions.checkState( - settings.getMinOutstandingElementCount() > 0 - && settings.getInitialOutstandingElementCount() - <= settings.getMaxOutstandingElementCount() - && settings.getInitialOutstandingElementCount() - >= settings.getMinOutstandingElementCount(), - "If throttling on element count is set, minOutstandingElementCount must be" - + " greater than 0, and minOutstandingElementCount <= " - + "initialOutstandingElementCount <= maxOutstandingElementCount"); - } - - private void verifyRequestBytesSettings(DynamicFlowControlSettings settings) { - // If LimitExceededBehavior is Ignore, dynamic flow control is disabled, there's no need to - // check request bytes limit settings - if (settings.getLimitExceededBehavior() == LimitExceededBehavior.Ignore) { - return; - } - if (settings.getInitialOutstandingRequestBytes() == null - && settings.getMinOutstandingRequestBytes() == null - && settings.getMaxOutstandingRequestBytes() == null) { - return; - } - Preconditions.checkState( - settings.getInitialOutstandingRequestBytes() != null - && settings.getMinOutstandingRequestBytes() != null - && settings.getMaxOutstandingRequestBytes() != null, - "Throttling on number of bytes is disabled by default. To enable this " - + "setting, minOutstandingRequestBytes, initialOutstandingRequestBytes, and " - + "maxOutstandingRequestBytes must all be set"); - Preconditions.checkState( - settings.getMinOutstandingRequestBytes() > 0 - && settings.getInitialOutstandingRequestBytes() - <= settings.getMaxOutstandingRequestBytes() - && settings.getInitialOutstandingRequestBytes() - >= settings.getMinOutstandingRequestBytes(), - "If throttling on number of bytes is set, minOutstandingRequestBytes must " - + "be greater than 0, and minOutstandingRequestBytes <= " - + "initialOutstandingRequestBytes <= maxOutstandingRequestBytes"); - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/batching/ElementCounter.java b/gax/src/main/java/com/google/api/gax/batching/ElementCounter.java deleted file mode 100644 index 40c271699..000000000 --- a/gax/src/main/java/com/google/api/gax/batching/ElementCounter.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -/** - * Interface representing an object that provides a numerical count given an object of the - * parameterized type. - */ -public interface ElementCounter { - /** Provides the numerical count associated with the given object. */ - long count(E element); -} diff --git a/gax/src/main/java/com/google/api/gax/batching/FlowControlEventStats.java b/gax/src/main/java/com/google/api/gax/batching/FlowControlEventStats.java deleted file mode 100644 index 005b2bced..000000000 --- a/gax/src/main/java/com/google/api/gax/batching/FlowControlEventStats.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -import static com.google.api.gax.batching.FlowController.LimitExceededBehavior; - -import com.google.api.core.InternalApi; -import com.google.api.gax.batching.FlowController.FlowControlException; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import java.util.concurrent.TimeUnit; -import javax.annotation.Nullable; - -/** - * Record the statistics of flow control events. - * - *

This class is populated by FlowController, which will record throttling events. Currently it - * only keeps the last flow control event, but it could be expanded to record more information in - * the future. The events can be used to dynamically adjust concurrency in the client. For example: - * - *

{@code
- * // Increase flow control limits if there was throttling in the past 5 minutes and throttled time
- * // was longer than 1 minute.
- * while(true) {
- *    FlowControlEvent event = flowControlEventStats.getLastFlowControlEvent();
- *    if (event != null
- *         && event.getTimestampMs() > System.currentMillis() - TimeUnit.MINUTES.toMillis(5)
- *         && event.getThrottledTimeInMs() > TimeUnit.MINUTES.toMillis(1)) {
- *      flowController.increaseThresholds(elementSteps, byteSteps);
- *    }
- *    Thread.sleep(TimeUnit.MINUTE.toMillis(10));
- * }
- * }
- */ -@InternalApi("For google-cloud-java client use only") -public class FlowControlEventStats { - - private volatile FlowControlEvent lastFlowControlEvent; - - // We only need the last event to check if there was throttling in the past X minutes so this - // doesn't need to be super accurate. - void recordFlowControlEvent(FlowControlEvent event) { - if (lastFlowControlEvent == null || event.compareTo(lastFlowControlEvent) > 0) { - lastFlowControlEvent = event; - } - } - - public FlowControlEvent getLastFlowControlEvent() { - return lastFlowControlEvent; - } - - /** - * A flow control event. Record throttled time if {@link LimitExceededBehavior} is {@link - * LimitExceededBehavior#Block}, or the exception if the behavior is {@link - * LimitExceededBehavior#ThrowException}. - */ - public static class FlowControlEvent implements Comparable { - static FlowControlEvent createReserveDelayed(long throttledTimeInMs) { - return createReserveDelayed(System.currentTimeMillis(), throttledTimeInMs); - } - - static FlowControlEvent createReserveDenied(FlowControlException exception) { - return createReserveDenied(System.currentTimeMillis(), exception); - } - - /** Package-private for use in testing. */ - @VisibleForTesting - static FlowControlEvent createReserveDelayed(long timestampMs, long throttledTimeInMs) { - Preconditions.checkArgument(timestampMs > 0, "timestamp must be greater than 0"); - Preconditions.checkArgument(throttledTimeInMs > 0, "throttled time must be greater than 0"); - return new FlowControlEvent(timestampMs, throttledTimeInMs, null); - } - - /** Package-private for use in testing. */ - @VisibleForTesting - static FlowControlEvent createReserveDenied(long timestampMs, FlowControlException exception) { - Preconditions.checkArgument(timestampMs > 0, "timestamp must be greater than 0"); - Preconditions.checkNotNull( - exception, "FlowControlException can't be null when reserve is denied"); - return new FlowControlEvent(timestampMs, null, exception); - } - - private long timestampMs; - private Long throttledTimeMs; - private FlowControlException exception; - - private FlowControlEvent( - long timestampMs, - @Nullable Long throttledTimeMs, - @Nullable FlowControlException exception) { - this.timestampMs = timestampMs; - this.throttledTimeMs = throttledTimeMs; - this.exception = exception; - } - - public long getTimestampMs() { - return timestampMs; - } - - @Nullable - public FlowControlException getException() { - return exception; - } - - @Nullable - public Long getThrottledTime(TimeUnit timeUnit) { - return throttledTimeMs == null - ? null - : timeUnit.convert(throttledTimeMs, TimeUnit.MILLISECONDS); - } - - @Override - public int compareTo(FlowControlEvent otherEvent) { - return Long.compare(this.getTimestampMs(), otherEvent.getTimestampMs()); - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/batching/FlowControlSettings.java b/gax/src/main/java/com/google/api/gax/batching/FlowControlSettings.java deleted file mode 100644 index b1634c2f6..000000000 --- a/gax/src/main/java/com/google/api/gax/batching/FlowControlSettings.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -import com.google.api.gax.batching.FlowController.FlowControlException; -import com.google.api.gax.batching.FlowController.LimitExceededBehavior; -import com.google.auto.value.AutoValue; -import com.google.common.base.Preconditions; -import javax.annotation.Nullable; - -/** Settings for {@link FlowController}. */ -@AutoValue -public abstract class FlowControlSettings { - public static FlowControlSettings getDefaultInstance() { - return FlowControlSettings.newBuilder().build(); - } - - /** Maximum number of outstanding elements to keep in memory before enforcing flow control. */ - @Nullable - public abstract Long getMaxOutstandingElementCount(); - - /** Maximum number of outstanding bytes to keep in memory before enforcing flow control. */ - @Nullable - public abstract Long getMaxOutstandingRequestBytes(); - - /** - * The behavior of {@link FlowController} when the specified limits are exceeded. Defaults to - * Block. - * - *

The expected behavior for each of these values is: - * - *

    - *
  • ThrowException: the FlowController will throw a {@link FlowControlException} if any of - * the limits are exceeded. - *
  • Block: the reserve() method of FlowController will block until the quote is available to - * be reserved. - *
  • Ignore: all flow control limits will be ignored; the FlowController is disabled. - *
- */ - public abstract LimitExceededBehavior getLimitExceededBehavior(); - - public abstract Builder toBuilder(); - - public static Builder newBuilder() { - return new AutoValue_FlowControlSettings.Builder() - .setLimitExceededBehavior(LimitExceededBehavior.Block); - } - - @AutoValue.Builder - public abstract static class Builder { - public abstract Builder setMaxOutstandingElementCount(Long value); - - public abstract Builder setMaxOutstandingRequestBytes(Long value); - - public abstract Builder setLimitExceededBehavior(LimitExceededBehavior value); - - abstract FlowControlSettings autoBuild(); - - public FlowControlSettings build() { - FlowControlSettings settings = autoBuild(); - Preconditions.checkArgument( - settings.getMaxOutstandingElementCount() == null - || settings.getMaxOutstandingElementCount() > 0, - "maxOutstandingElementCount limit is disabled by default, but if set it must be set to a value greater than 0."); - Preconditions.checkArgument( - settings.getMaxOutstandingRequestBytes() == null - || settings.getMaxOutstandingRequestBytes() > 0, - "maxOutstandingRequestBytes limit is disabled by default, but if set it must be set to a value greater than 0."); - return settings; - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/batching/FlowController.java b/gax/src/main/java/com/google/api/gax/batching/FlowController.java deleted file mode 100644 index 00bf6988d..000000000 --- a/gax/src/main/java/com/google/api/gax/batching/FlowController.java +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -import com.google.api.core.InternalApi; -import com.google.api.gax.batching.FlowControlEventStats.FlowControlEvent; -import com.google.common.base.Preconditions; -import com.google.common.base.Stopwatch; -import java.util.concurrent.TimeUnit; -import javax.annotation.Nullable; - -/** Provides flow control capability. */ -public class FlowController { - /** Base exception that signals a flow control state. */ - public abstract static class FlowControlException extends Exception { - private FlowControlException() {} - } - - /** - * Runtime exception that can be used in place of FlowControlException when an unchecked exception - * is required. - */ - public static class FlowControlRuntimeException extends RuntimeException { - private FlowControlRuntimeException(FlowControlException e) { - super(e); - } - - public static FlowControlRuntimeException fromFlowControlException(FlowControlException e) { - return new FlowControlRuntimeException(e); - } - } - - /** - * Exception thrown when client-side flow control is enforced based on the maximum number of - * outstanding in-memory elements. - */ - public static final class MaxOutstandingElementCountReachedException - extends FlowControlException { - private final long currentMaxElementCount; - - public MaxOutstandingElementCountReachedException(long currentMaxElementCount) { - this.currentMaxElementCount = currentMaxElementCount; - } - - public long getCurrentMaxBatchElementCount() { - return currentMaxElementCount; - } - - @Override - public String toString() { - return String.format( - "The maximum number of batch elements: %d have been reached.", currentMaxElementCount); - } - } - - /** - * Exception thrown when client-side flow control is enforced based on the maximum number of - * unacknowledged in-memory bytes. - */ - public static final class MaxOutstandingRequestBytesReachedException - extends FlowControlException { - private final long currentMaxBytes; - - public MaxOutstandingRequestBytesReachedException(long currentMaxBytes) { - this.currentMaxBytes = currentMaxBytes; - } - - public long getCurrentMaxBatchBytes() { - return currentMaxBytes; - } - - @Override - public String toString() { - return String.format( - "The maximum number of batch bytes: %d have been reached.", currentMaxBytes); - } - } - - /** - * Enumeration of behaviors that FlowController can use in case the flow control limits are - * exceeded. - */ - public enum LimitExceededBehavior { - /** - * Throws {@link MaxOutstandingElementCountReachedException} or {@link - * MaxOutstandingRequestBytesReachedException}. - * - *

This might be appropriate in interactive scenarios. For example, a web server might catch - * these exceptions and report to the user that the system is overloaded and that the user could - * try again later. It could also be useful in applications that implement custom rate-limiting - * logic. - */ - ThrowException, - - /** - * Waits until the request can be made without exceeding the limit. - * - *

This might be appropriate in batch-processing, where latencies of individual requests are - * not important. - */ - Block, - - /** - * Disables flow-control. - * - *

This is provided mainly for debugging and not recommended for production use. Having too - * many requests in-flight might cause RPCs to fail due to congested network or the computer to - * run out of memory due to excessive buffering, etc. - */ - Ignore, - } - - @Nullable private final Semaphore64 outstandingElementCount; - @Nullable private final Semaphore64 outstandingByteCount; - @Nullable private final Long maxElementCountLimit; - @Nullable private final Long maxRequestBytesLimit; - @Nullable private final Long minElementCountLimit; - @Nullable private final Long minRequestBytesLimit; - private final LimitExceededBehavior limitExceededBehavior; - private final Object updateLimitLock; - - // Threshold to record throttling events. If reserve() takes longer than this threshold, it will - // be recorded as a throttling event. - private static final long RESERVE_FLOW_CONTROL_THRESHOLD_MS = 1; - private final FlowControlEventStats flowControlEventStats; - - public FlowController(FlowControlSettings settings) { - // When the FlowController is initialized with FlowControlSettings, flow control limits can't be - // adjusted. min, current, max element count and request bytes are initialized with the max - // values in FlowControlSettings. - this(convertFlowControlSettings(settings)); - } - - @InternalApi("For google-cloud-java client use only") - public FlowController(DynamicFlowControlSettings settings) { - this.limitExceededBehavior = settings.getLimitExceededBehavior(); - this.updateLimitLock = new Object(); - this.flowControlEventStats = new FlowControlEventStats(); - switch (settings.getLimitExceededBehavior()) { - case ThrowException: - case Block: - break; - case Ignore: - this.maxElementCountLimit = null; - this.maxRequestBytesLimit = null; - this.minElementCountLimit = null; - this.minRequestBytesLimit = null; - - this.outstandingElementCount = null; - this.outstandingByteCount = null; - return; - default: - throw new IllegalArgumentException( - "Unknown LimitBehaviour: " + settings.getLimitExceededBehavior()); - } - this.maxElementCountLimit = settings.getMaxOutstandingElementCount(); - this.minElementCountLimit = settings.getMinOutstandingElementCount(); - Long initialElementCountLimit = settings.getInitialOutstandingElementCount(); - if (initialElementCountLimit == null) { - outstandingElementCount = null; - } else if (settings.getLimitExceededBehavior() == FlowController.LimitExceededBehavior.Block) { - outstandingElementCount = new BlockingSemaphore(initialElementCountLimit); - } else { - outstandingElementCount = new NonBlockingSemaphore(initialElementCountLimit); - } - - this.maxRequestBytesLimit = settings.getMaxOutstandingRequestBytes(); - this.minRequestBytesLimit = settings.getMinOutstandingRequestBytes(); - Long initialRequestBytesLimit = settings.getInitialOutstandingRequestBytes(); - if (initialRequestBytesLimit == null) { - outstandingByteCount = null; - } else if (settings.getLimitExceededBehavior() == FlowController.LimitExceededBehavior.Block) { - outstandingByteCount = new BlockingSemaphore(initialRequestBytesLimit); - } else { - outstandingByteCount = new NonBlockingSemaphore(initialRequestBytesLimit); - } - } - - public void reserve(long elements, long bytes) throws FlowControlException { - Preconditions.checkArgument(elements >= 0); - Preconditions.checkArgument(bytes >= 0); - - Stopwatch stopwatch = Stopwatch.createStarted(); - if (outstandingElementCount != null) { - if (!outstandingElementCount.acquire(elements)) { - MaxOutstandingElementCountReachedException exception = - new MaxOutstandingElementCountReachedException( - outstandingElementCount.getPermitLimit()); - flowControlEventStats.recordFlowControlEvent( - FlowControlEvent.createReserveDenied(exception)); - throw exception; - } - } - - // Always allows to send a request even if it is larger than the flow control limit, - // if it doesn't then it will deadlock the thread. - if (outstandingByteCount != null) { - if (!outstandingByteCount.acquirePartial(bytes)) { - if (outstandingElementCount != null) { - outstandingElementCount.release(elements); - } - MaxOutstandingRequestBytesReachedException exception = - new MaxOutstandingRequestBytesReachedException(outstandingByteCount.getPermitLimit()); - flowControlEventStats.recordFlowControlEvent( - FlowControlEvent.createReserveDenied(exception)); - throw exception; - } - } - long elapsed = stopwatch.elapsed(TimeUnit.MILLISECONDS); - if (elapsed >= RESERVE_FLOW_CONTROL_THRESHOLD_MS) { - flowControlEventStats.recordFlowControlEvent(FlowControlEvent.createReserveDelayed(elapsed)); - } - } - - public void release(long elements, long bytes) { - Preconditions.checkArgument(elements >= 0); - Preconditions.checkArgument(bytes >= 0); - - if (outstandingElementCount != null) { - outstandingElementCount.release(elements); - } - if (outstandingByteCount != null) { - outstandingByteCount.release(bytes); - } - } - - /** - * Increase flow control limits to allow extra elementSteps elements and byteSteps request bytes - * before enforcing flow control. - */ - @InternalApi("For google-cloud-java client use only") - public void increaseThresholds(long elementSteps, long byteSteps) { - Preconditions.checkArgument(elementSteps >= 0); - Preconditions.checkArgument(byteSteps >= 0); - synchronized (updateLimitLock) { - if (outstandingElementCount != null) { - long actualStep = - Math.min(elementSteps, maxElementCountLimit - outstandingElementCount.getPermitLimit()); - outstandingElementCount.increasePermitLimit(actualStep); - } - - if (outstandingByteCount != null) { - long actualStep = - Math.min(byteSteps, maxRequestBytesLimit - outstandingByteCount.getPermitLimit()); - outstandingByteCount.increasePermitLimit(actualStep); - } - } - } - - /** - * Decrease flow control limits to allow elementSteps fewer elements and byteSteps fewer request - * bytes before enforcing flow control. - */ - @InternalApi("For google-cloud-java client use only") - public void decreaseThresholds(long elementSteps, long byteSteps) { - Preconditions.checkArgument(elementSteps >= 0); - Preconditions.checkArgument(byteSteps >= 0); - synchronized (updateLimitLock) { - if (outstandingElementCount != null) { - long actualStep = - Math.min(elementSteps, outstandingElementCount.getPermitLimit() - minElementCountLimit); - outstandingElementCount.reducePermitLimit(actualStep); - } - - if (outstandingByteCount != null) { - long actualStep = - Math.min(byteSteps, outstandingByteCount.getPermitLimit() - minRequestBytesLimit); - outstandingByteCount.reducePermitLimit(actualStep); - } - } - } - - private static DynamicFlowControlSettings convertFlowControlSettings( - FlowControlSettings settings) { - return DynamicFlowControlSettings.newBuilder() - .setInitialOutstandingElementCount(settings.getMaxOutstandingElementCount()) - .setMinOutstandingElementCount(settings.getMaxOutstandingElementCount()) - .setMaxOutstandingElementCount(settings.getMaxOutstandingElementCount()) - .setInitialOutstandingRequestBytes(settings.getMaxOutstandingRequestBytes()) - .setMinOutstandingRequestBytes(settings.getMaxOutstandingRequestBytes()) - .setMaxOutstandingRequestBytes(settings.getMaxOutstandingRequestBytes()) - .setLimitExceededBehavior(settings.getLimitExceededBehavior()) - .build(); - } - - LimitExceededBehavior getLimitExceededBehavior() { - return limitExceededBehavior; - } - - @InternalApi("For internal use by google-cloud-java clients only") - @Nullable - public Long getMaxElementCountLimit() { - return maxElementCountLimit; - } - - @InternalApi("For internal use by google-cloud-java clients only") - @Nullable - public Long getMaxRequestBytesLimit() { - return maxRequestBytesLimit; - } - - @InternalApi("For google-cloud-java client use only") - @Nullable - public Long getMinElementCountLimit() { - return minElementCountLimit; - } - - @InternalApi("For google-cloud-java client use only") - @Nullable - public Long getMinRequestBytesLimit() { - return minRequestBytesLimit; - } - - @InternalApi("For google-cloud-java client use only") - @Nullable - public Long getCurrentElementCountLimit() { - return outstandingElementCount == null ? null : outstandingElementCount.getPermitLimit(); - } - - @InternalApi("For google-cloud-java client use only") - @Nullable - public Long getCurrentRequestBytesLimit() { - return outstandingByteCount == null ? null : outstandingByteCount.getPermitLimit(); - } - - @InternalApi("For google-cloud-java client use only") - public FlowControlEventStats getFlowControlEventStats() { - return flowControlEventStats; - } -} diff --git a/gax/src/main/java/com/google/api/gax/batching/NonBlockingSemaphore.java b/gax/src/main/java/com/google/api/gax/batching/NonBlockingSemaphore.java deleted file mode 100644 index 126d1bb7b..000000000 --- a/gax/src/main/java/com/google/api/gax/batching/NonBlockingSemaphore.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.gax.batching; - -import com.google.common.base.Preconditions; -import java.util.concurrent.atomic.AtomicLong; - -/** A {@link Semaphore64} that immediately returns with failure if permits are not available. */ -class NonBlockingSemaphore implements Semaphore64 { - private AtomicLong acquiredPermits; - private AtomicLong limit; - - private static void checkNotNegative(long l) { - Preconditions.checkArgument(l >= 0, "negative permits not allowed: %s", l); - } - - NonBlockingSemaphore(long permits) { - checkNotNegative(permits); - this.acquiredPermits = new AtomicLong(0); - this.limit = new AtomicLong(permits); - } - - @Override - public void release(long permits) { - checkNotNegative(permits); - while (true) { - long old = acquiredPermits.get(); - // TODO: throw exceptions when the permits overflow - long newAcquired = Math.max(0, old - permits); - if (acquiredPermits.compareAndSet(old, newAcquired)) { - return; - } - } - } - - @Override - public boolean acquire(long permits) { - checkNotNegative(permits); - while (true) { - long old = acquiredPermits.get(); - if (old + permits > limit.get()) { - return false; - } - if (acquiredPermits.compareAndSet(old, old + permits)) { - return true; - } - } - } - - @Override - public boolean acquirePartial(long permits) { - checkNotNegative(permits); - // To allow individual oversized requests to be sent, clamp the requested permits to the maximum - // limit. This will allow individual large requests to be sent. Please note that this behavior - // will result in acquiredPermits going over limit. - while (true) { - long old = acquiredPermits.get(); - if (old + permits > limit.get() && old > 0) { - return false; - } - if (acquiredPermits.compareAndSet(old, old + permits)) { - return true; - } - } - } - - @Override - public void increasePermitLimit(long permits) { - checkNotNegative(permits); - limit.addAndGet(permits); - } - - @Override - public void reducePermitLimit(long reduction) { - checkNotNegative(reduction); - - while (true) { - long oldLimit = limit.get(); - Preconditions.checkState(oldLimit - reduction > 0, "permit limit underflow"); - if (limit.compareAndSet(oldLimit, oldLimit - reduction)) { - return; - } - } - } - - @Override - public long getPermitLimit() { - return limit.get(); - } -} diff --git a/gax/src/main/java/com/google/api/gax/batching/NumericThreshold.java b/gax/src/main/java/com/google/api/gax/batching/NumericThreshold.java deleted file mode 100644 index 3012873ce..000000000 --- a/gax/src/main/java/com/google/api/gax/batching/NumericThreshold.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -import com.google.common.base.Preconditions; - -/** A threshold which accumulates a count based on the provided ElementCounter. */ -public final class NumericThreshold implements BatchingThreshold { - private final long threshold; - private final ElementCounter extractor; - private long sum; - - /** - * Constructs a NumericThreshold. - * - * @param threshold The value that allows an event to happen. - * @param extractor Object that extracts a numeric value from the value object. - */ - public NumericThreshold(long threshold, ElementCounter extractor) { - this.threshold = threshold; - this.extractor = Preconditions.checkNotNull(extractor); - this.sum = 0; - } - - @Override - public void accumulate(E e) { - sum += extractor.count(e); - } - - @Override - public boolean isThresholdReached() { - return sum >= threshold; - } - - @Override - public BatchingThreshold copyWithZeroedValue() { - return new NumericThreshold(threshold, extractor); - } -} diff --git a/gax/src/main/java/com/google/api/gax/batching/PartitionKey.java b/gax/src/main/java/com/google/api/gax/batching/PartitionKey.java deleted file mode 100644 index ad1ee483a..000000000 --- a/gax/src/main/java/com/google/api/gax/batching/PartitionKey.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.gax.batching; - -import com.google.common.collect.ImmutableList; - -public final class PartitionKey { - private final ImmutableList keys; - private final int hash; - - public PartitionKey(Object... keys) { - this.keys = ImmutableList.copyOf(keys); - - int hash = 1; - for (Object obj : keys) { - hash = hash * 31 + obj.hashCode(); - } - this.hash = hash; - } - - @Override - public int hashCode() { - return hash; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof PartitionKey)) { - return false; - } - PartitionKey other = (PartitionKey) obj; - - if (keys.size() != other.keys.size()) { - return false; - } - for (int i = 0; i < keys.size(); i++) { - if (!keys.get(i).equals(other.keys.get(i))) { - return false; - } - } - return true; - } -} diff --git a/gax/src/main/java/com/google/api/gax/batching/RequestBuilder.java b/gax/src/main/java/com/google/api/gax/batching/RequestBuilder.java deleted file mode 100644 index 1371069a8..000000000 --- a/gax/src/main/java/com/google/api/gax/batching/RequestBuilder.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -public interface RequestBuilder { - void appendRequest(RequestT request); - - RequestT build(); -} diff --git a/gax/src/main/java/com/google/api/gax/batching/Semaphore64.java b/gax/src/main/java/com/google/api/gax/batching/Semaphore64.java deleted file mode 100644 index f0e751846..000000000 --- a/gax/src/main/java/com/google/api/gax/batching/Semaphore64.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -/** - * Semaphore64 is similar to {@link java.util.concurrent.Semaphore} but allows up to {@code 2^63-1} - * permits. It also allows adding / reducing permits to the original limit and acquire partial - * permits. - * - *

Users who do not need such large number of permits and the extra functionalities are strongly - * encouraged to use Java's {@code Semaphore} instead. It is almost certainly faster and less error - * prone. - */ -interface Semaphore64 { - boolean acquire(long permits); - - void release(long permits); - - /** - * When try to acquire more permits than what's allowed, acquiring the limit instead of what's - * asked. - */ - boolean acquirePartial(long permits); - - void increasePermitLimit(long permits); - - void reducePermitLimit(long reduction); - - long getPermitLimit(); -} diff --git a/gax/src/main/java/com/google/api/gax/batching/ThresholdBatchReceiver.java b/gax/src/main/java/com/google/api/gax/batching/ThresholdBatchReceiver.java deleted file mode 100644 index 5f655a8b5..000000000 --- a/gax/src/main/java/com/google/api/gax/batching/ThresholdBatchReceiver.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -import com.google.api.core.ApiFuture; - -/** - * Interface representing an object that receives batches from a ThresholdBatcher and takes action - * on them. Implementations of ThresholdBatchReceiver should be thread-safe. - */ -public interface ThresholdBatchReceiver { - - /** - * Validate that the batch can be received by this ThresholdBatchReceiver. This is called to - * validate a batch before it is sent to the ThresholdBatcher. - */ - void validateBatch(BatchT message); - - /** Process the given batch asynchronously. */ - ApiFuture processBatch(BatchT batch); -} diff --git a/gax/src/main/java/com/google/api/gax/batching/ThresholdBatcher.java b/gax/src/main/java/com/google/api/gax/batching/ThresholdBatcher.java deleted file mode 100644 index 75d93ec14..000000000 --- a/gax/src/main/java/com/google/api/gax/batching/ThresholdBatcher.java +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -import static com.google.common.util.concurrent.MoreExecutors.directExecutor; - -import com.google.api.core.ApiFunction; -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutureCallback; -import com.google.api.core.ApiFutures; -import com.google.api.core.SettableApiFuture; -import com.google.api.gax.batching.FlowController.FlowControlException; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import java.util.ArrayList; -import java.util.Collection; -import java.util.concurrent.Future; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.ReentrantLock; -import org.threeten.bp.Duration; - -/** - * Queues up elements until either a duration of time has passed or any threshold in a given set of - * thresholds is breached, and then delivers the elements in a batch to the consumer. - */ -public final class ThresholdBatcher { - - private class ReleaseResourcesFunction implements ApiFunction { - private final E batch; - - private ReleaseResourcesFunction(E batch) { - this.batch = batch; - } - - @Override - public Void apply(T input) { - flowController.release(batch); - return null; - } - } - - private final Runnable pushCurrentBatchRunnable = - new Runnable() { - @Override - public void run() { - pushCurrentBatch(); - } - }; - - private final ArrayList> thresholds; - private final ScheduledExecutorService executor; - private final Duration maxDelay; - private final ThresholdBatchReceiver receiver; - private final BatchingFlowController flowController; - private final BatchMerger batchMerger; - - // Invariant: - // - lock gates all accesses to members below - // - currentOpenBatch and currentAlarmFuture are either both null or both non-null - private final ReentrantLock lock = new ReentrantLock(); - private E currentOpenBatch; - private Future currentAlarmFuture; - - private ThresholdBatcher(Builder builder) { - this.thresholds = new ArrayList<>(builder.thresholds); - this.executor = Preconditions.checkNotNull(builder.executor); - this.maxDelay = Preconditions.checkNotNull(builder.maxDelay); - this.receiver = Preconditions.checkNotNull(builder.receiver); - this.flowController = Preconditions.checkNotNull(builder.flowController); - this.batchMerger = Preconditions.checkNotNull(builder.batchMerger); - - resetThresholds(); - } - - /** Builder for a ThresholdBatcher. */ - public static class Builder { - private Collection> thresholds; - private ScheduledExecutorService executor; - private Duration maxDelay; - private ThresholdBatchReceiver receiver; - private BatchingFlowController flowController; - private BatchMerger batchMerger; - - private Builder() {} - - /** Set the executor for the ThresholdBatcher. */ - public Builder setExecutor(ScheduledExecutorService executor) { - this.executor = executor; - return this; - } - - /** Set the max delay for a batch. This is counted from the first item added to a batch. */ - public Builder setMaxDelay(Duration maxDelay) { - this.maxDelay = maxDelay; - return this; - } - - /** Set the thresholds for the ThresholdBatcher. */ - public Builder setThresholds(Collection> thresholds) { - this.thresholds = thresholds; - return this; - } - - /** Set the threshold batch receiver for the ThresholdBatcher. */ - public Builder setReceiver(ThresholdBatchReceiver receiver) { - this.receiver = receiver; - return this; - } - - /** Set the flow controller for the ThresholdBatcher. */ - public Builder setFlowController(BatchingFlowController flowController) { - this.flowController = flowController; - return this; - } - - /** Set the batch merger for the ThresholdBatcher. */ - public Builder setBatchMerger(BatchMerger batchMerger) { - this.batchMerger = batchMerger; - return this; - } - - /** Build the ThresholdBatcher. */ - public ThresholdBatcher build() { - return new ThresholdBatcher<>(this); - } - } - - /** Get a new builder for a ThresholdBatcher. */ - public static Builder newBuilder() { - return new Builder<>(); - } - - /** - * Adds an element to the batcher. If the element causes the collection to go past any of the - * thresholds, the batch will be sent to the {@code ThresholdBatchReceiver}. - */ - public void add(E e) throws FlowControlException { - // We need to reserve resources from flowController outside the lock, so that they can be - // released by pushCurrentBatch(). - flowController.reserve(e); - lock.lock(); - try { - receiver.validateBatch(e); - boolean anyThresholdReached = isAnyThresholdReached(e); - - if (currentOpenBatch == null) { - currentOpenBatch = e; - // Schedule a job only when no thresholds have been exceeded, otherwise it will be - // immediately cancelled - if (!anyThresholdReached) { - currentAlarmFuture = - executor.schedule( - pushCurrentBatchRunnable, maxDelay.toMillis(), TimeUnit.MILLISECONDS); - } - } else { - batchMerger.merge(currentOpenBatch, e); - } - - if (anyThresholdReached) { - pushCurrentBatch(); - } - } finally { - lock.unlock(); - } - } - - /** * Package-private for use in testing. */ - @VisibleForTesting - boolean isEmpty() { - lock.lock(); - try { - return currentOpenBatch == null; - } finally { - lock.unlock(); - } - } - - /** - * Push the current batch to the batch receiver. Returns an ApiFuture that completes once the - * batch has been processed by the batch receiver and the flow controller resources have been - * released. - * - *

Note that this future can complete for the current batch before previous batches have - * completed, so it cannot be depended upon for flushing. - */ - @VisibleForTesting - public ApiFuture pushCurrentBatch() { - final E batch = removeBatch(); - if (batch == null) { - return ApiFutures.immediateFuture(null); - } - - final SettableApiFuture retFuture = SettableApiFuture.create(); - - // It is tempting to use transform to both release and get ApiFuture. - // This is incorrect because we also need to release on failure. - // - // It is also tempting to transform to get ApiFuture and addListener - // separately to release. This probably works as most users expect, - // but makes this class hard to test: retFuture.get() returning - // won't guarantee that flow control has been released. - ApiFutures.addCallback( - receiver.processBatch(batch), - new ApiFutureCallback() { - @Override - public void onSuccess(Object obj) { - flowController.release(batch); - retFuture.set(null); - } - - @Override - public void onFailure(Throwable t) { - flowController.release(batch); - retFuture.setException(t); - } - }, - directExecutor()); - - return retFuture; - } - - private E removeBatch() { - lock.lock(); - try { - E batch = currentOpenBatch; - currentOpenBatch = null; - if (currentAlarmFuture != null) { - currentAlarmFuture.cancel(false); - currentAlarmFuture = null; - } - resetThresholds(); - return batch; - } finally { - lock.unlock(); - } - } - - private boolean isAnyThresholdReached(E e) { - for (BatchingThreshold threshold : thresholds) { - threshold.accumulate(e); - if (threshold.isThresholdReached()) { - return true; - } - } - return false; - } - - private void resetThresholds() { - for (int i = 0; i < thresholds.size(); i++) { - thresholds.set(i, thresholds.get(i).copyWithZeroedValue()); - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/core/BackgroundResource.java b/gax/src/main/java/com/google/api/gax/core/BackgroundResource.java deleted file mode 100644 index e279c2c03..000000000 --- a/gax/src/main/java/com/google/api/gax/core/BackgroundResource.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.core; - -import java.util.concurrent.TimeUnit; - -/** - * Represents a resource running in the background that needs to be shut down for resources to be - * released. - */ -public interface BackgroundResource extends AutoCloseable { - - /** - * Initiates an orderly shutdown in which previously submitted work is finished, but no new work - * will be accepted. Invocation has no additional effect if already shut down. - * - *

This method does not wait for previously submitted work to complete execution. Use - * awaitTermination to do that. - */ - void shutdown(); - - /** Returns true if this background resource has been shut down. */ - boolean isShutdown(); - - /** - * Returns true if all work has completed following shut down. Note that isTerminated is never - * true unless either shutdown or shutdownNow was called first. - */ - boolean isTerminated(); - - /** - * Attempts to stop all actively executing work and halts the processing of waiting work. - * - *

This method does not wait for actively executing work to terminate. Use awaitTermination to - * do that. - * - *

There are no guarantees beyond best-effort attempts to stop processing actively executing - * work. For example, typical implementations will cancel via Thread.interrupt(), so any task that - * fails to respond to interrupts may never terminate. - */ - void shutdownNow(); - - /** - * Blocks until all work has completed execution after a shutdown request, or the timeout occurs, - * or the current thread is interrupted, whichever happens first. - */ - boolean awaitTermination(long duration, TimeUnit unit) throws InterruptedException; - - // NEXT_MAJOR_VER: override close() to remove 'throws Exception' -} diff --git a/gax/src/main/java/com/google/api/gax/core/BackgroundResourceAggregation.java b/gax/src/main/java/com/google/api/gax/core/BackgroundResourceAggregation.java deleted file mode 100644 index d168e6186..000000000 --- a/gax/src/main/java/com/google/api/gax/core/BackgroundResourceAggregation.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.core; - -import java.util.List; -import java.util.concurrent.TimeUnit; - -/** Treats a collection of background resources as a single background resource. */ -public class BackgroundResourceAggregation implements BackgroundResource { - - private final List resources; - - public BackgroundResourceAggregation(List resources) { - this.resources = resources; - } - - @Override - public void shutdown() { - for (BackgroundResource resource : resources) { - resource.shutdown(); - } - } - - @Override - public boolean isShutdown() { - for (BackgroundResource resource : resources) { - if (!resource.isShutdown()) { - return false; - } - } - return true; - } - - @Override - public boolean isTerminated() { - for (BackgroundResource resource : resources) { - if (!resource.isTerminated()) { - return false; - } - } - return true; - } - - @Override - public void shutdownNow() { - for (BackgroundResource resource : resources) { - resource.shutdownNow(); - } - } - - @Override - public boolean awaitTermination(long duration, TimeUnit unit) throws InterruptedException { - for (BackgroundResource resource : resources) { - // TODO subtract time already used up from previous resources - boolean awaitResult = resource.awaitTermination(duration, unit); - if (!awaitResult) { - return false; - } - } - return true; - } - - // NEXT_MAJOR_VER: remove 'throws Exception' - @Override - public final void close() throws Exception { - shutdown(); - } -} diff --git a/gax/src/main/java/com/google/api/gax/core/BaseBackgroundResource.java b/gax/src/main/java/com/google/api/gax/core/BaseBackgroundResource.java deleted file mode 100644 index 83c697975..000000000 --- a/gax/src/main/java/com/google/api/gax/core/BaseBackgroundResource.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.core; - -import java.util.concurrent.TimeUnit; - -/** A Background resource that does nothing. */ -public class BaseBackgroundResource implements BackgroundResource { - - @Override - public void shutdown() { - // no-op - } - - @Override - public boolean isShutdown() { - return false; - } - - @Override - public boolean isTerminated() { - return false; - } - - @Override - public void shutdownNow() { - // no-op - } - - @Override - public boolean awaitTermination(long duration, TimeUnit unit) throws InterruptedException { - return false; - } - - // NEXT_MAJOR_VER: remove 'throws Exception' - @Override - public void close() throws Exception { - shutdown(); - } -} diff --git a/gax/src/main/java/com/google/api/gax/core/CredentialsProvider.java b/gax/src/main/java/com/google/api/gax/core/CredentialsProvider.java deleted file mode 100644 index f1db77004..000000000 --- a/gax/src/main/java/com/google/api/gax/core/CredentialsProvider.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.core; - -import com.google.auth.Credentials; -import java.io.IOException; - -/** - * Provides an interface to hold and acquire the credentials that will be used to call the service. - */ -public interface CredentialsProvider { - /** - * Gets the credentials which will be used to call the service. If the credentials have not been - * acquired yet, then they will be acquired when this function is called. - */ - Credentials getCredentials() throws IOException; -} diff --git a/gax/src/main/java/com/google/api/gax/core/Distribution.java b/gax/src/main/java/com/google/api/gax/core/Distribution.java deleted file mode 100644 index 71d17c549..000000000 --- a/gax/src/main/java/com/google/api/gax/core/Distribution.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.core; - -import com.google.common.base.MoreObjects; -import com.google.common.base.Preconditions; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLongArray; - -/** - * Distribution records values from {@code 0} (inclusive) to {@code endValue} (exclusive) and - * computes their percentiles. - * - *

Methods may be called concurrently. - */ -public class Distribution { - - private final AtomicLongArray buckets; - private final AtomicInteger count = new AtomicInteger(0); - - public Distribution(int endValue) { - Preconditions.checkArgument(endValue > 0); - buckets = new AtomicLongArray(endValue); - } - - // TODO(pongad): remove this when google-cloud-java no longer calls it. - @Deprecated - public long getNthPercentile(double percentile) { - return getPercentile(percentile); - } - - /** - * Get the percentile of recorded values. If called concurrently with {@link #record(int)}, the - * result is an approximate. - */ - public int getPercentile(double percentile) { - // NOTE: This implementation uses the nearest-rank method. - // https://en.wikipedia.org/wiki/Percentile#The_nearest-rank_method - // - // If called concurrently with record, this implementation biases low. - // Since we read count before iterating the array, more elements might have been recorded - // and we might not iterate far enough to be fair. - // Still, this probably won't matter greatly in practice. - - Preconditions.checkArgument(percentile > 0.0); - Preconditions.checkArgument(percentile <= 100.0); - - long targetRank = (long) Math.ceil(percentile * count.get() / 100); - long rank = 0; - for (int i = 0; i < buckets.length(); i++) { - rank += buckets.get(i); - if (rank >= targetRank) { - return i; - } - } - return buckets.length(); - } - - /** - * Records a new value. - * - *

The value must not be negative. To help with distributions with long tails, if the given - * value is greater than or equal to {@code endValue}, the value {@code endValue-1} is recorded - * instead. - */ - public void record(int value) { - Preconditions.checkArgument(value >= 0); - if (value >= buckets.length()) { - value = buckets.length() - 1; - } - buckets.incrementAndGet(value); - count.incrementAndGet(); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("endValue", buckets.length()) - .add("count", count.get()) - .toString(); - } -} diff --git a/gax/src/main/java/com/google/api/gax/core/ExecutorAsBackgroundResource.java b/gax/src/main/java/com/google/api/gax/core/ExecutorAsBackgroundResource.java deleted file mode 100644 index 4c67eec16..000000000 --- a/gax/src/main/java/com/google/api/gax/core/ExecutorAsBackgroundResource.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.core; - -import com.google.common.base.Preconditions; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.TimeUnit; - -/** - * ExecutorAsBackgroundResource wraps an {@link ExecutorService} so that it can be used as a {@link - * BackgroundResource}. - */ -public class ExecutorAsBackgroundResource implements BackgroundResource { - - private final ExecutorService executor; - - public ExecutorAsBackgroundResource(ExecutorService executor) { - this.executor = Preconditions.checkNotNull(executor); - } - - @Override - public void shutdown() { - executor.shutdown(); - } - - @Override - public boolean isShutdown() { - return executor.isShutdown(); - } - - @Override - public boolean isTerminated() { - return executor.isTerminated(); - } - - @Override - public void shutdownNow() { - executor.shutdownNow(); - } - - @Override - public boolean awaitTermination(long duration, TimeUnit unit) throws InterruptedException { - return executor.awaitTermination(duration, unit); - } - - // NEXT_MAJOR_VER: remove 'throws Exception' - @Override - public void close() throws Exception { - shutdown(); - } -} diff --git a/gax/src/main/java/com/google/api/gax/core/ExecutorProvider.java b/gax/src/main/java/com/google/api/gax/core/ExecutorProvider.java deleted file mode 100644 index ae8336036..000000000 --- a/gax/src/main/java/com/google/api/gax/core/ExecutorProvider.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.core; - -import java.util.concurrent.ScheduledExecutorService; - -/** - * Provides an interface to either build a ScheduledExecutorService or provide a fixed - * ScheduledExecutorService that will be used to make calls to a service. - */ -public interface ExecutorProvider { - /** Indicates whether the executor should be closed by the containing client class. */ - boolean shouldAutoClose(); - - /** Gets the executor to use. */ - ScheduledExecutorService getExecutor(); -} diff --git a/gax/src/main/java/com/google/api/gax/core/FixedCredentialsProvider.java b/gax/src/main/java/com/google/api/gax/core/FixedCredentialsProvider.java deleted file mode 100644 index e95e11304..000000000 --- a/gax/src/main/java/com/google/api/gax/core/FixedCredentialsProvider.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.core; - -import com.google.auth.Credentials; -import com.google.auto.value.AutoValue; -import javax.annotation.Nullable; - -/** FixedCredentialsProvider is a CredentialsProvider which always provides the same credentials. */ -@AutoValue -public abstract class FixedCredentialsProvider implements CredentialsProvider { - - @Override - @Nullable - public abstract Credentials getCredentials(); - - /** Creates a FixedCredentialsProvider. */ - public static FixedCredentialsProvider create(Credentials credentials) { - return new AutoValue_FixedCredentialsProvider(credentials); - } -} diff --git a/gax/src/main/java/com/google/api/gax/core/FixedExecutorProvider.java b/gax/src/main/java/com/google/api/gax/core/FixedExecutorProvider.java deleted file mode 100644 index b06ecbd53..000000000 --- a/gax/src/main/java/com/google/api/gax/core/FixedExecutorProvider.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.core; - -import java.util.concurrent.ScheduledExecutorService; - -/** FixedExecutorProvider is an ExecutorProvider which always returns the same executor. */ -public final class FixedExecutorProvider implements ExecutorProvider { - - private final ScheduledExecutorService executor; - - private FixedExecutorProvider(ScheduledExecutorService executor) { - this.executor = executor; - } - - @Override - public ScheduledExecutorService getExecutor() { - return executor; - } - - @Override - public boolean shouldAutoClose() { - return false; - } - - /** Creates a FixedExecutorProvider. */ - public static FixedExecutorProvider create(ScheduledExecutorService executor) { - return new FixedExecutorProvider(executor); - } -} diff --git a/gax/src/main/java/com/google/api/gax/core/GaxProperties.java b/gax/src/main/java/com/google/api/gax/core/GaxProperties.java deleted file mode 100644 index 483cbe9c8..000000000 --- a/gax/src/main/java/com/google/api/gax/core/GaxProperties.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.core; - -import static org.graalvm.nativeimage.ImageInfo.PROPERTY_IMAGE_CODE_KEY; -import static org.graalvm.nativeimage.ImageInfo.PROPERTY_IMAGE_CODE_VALUE_RUNTIME; - -import com.google.api.core.InternalApi; -import java.io.IOException; -import java.io.InputStream; -import java.util.Properties; - -/** Provides properties of the GAX library. */ -@InternalApi -public class GaxProperties { - - private static final String DEFAULT_VERSION = ""; - private static final String GAX_VERSION = getLibraryVersion(GaxProperties.class, "version.gax"); - private static final String JAVA_VERSION = getRuntimeVersion(); - - private GaxProperties() {} - - /** Returns the version of the library that the {@code libraryClass} belongs to */ - public static String getLibraryVersion(Class libraryClass) { - String version = libraryClass.getPackage().getImplementationVersion(); - return version != null ? version : DEFAULT_VERSION; - } - - /** - * Returns the version of the library that the {@code libraryClass} belongs to, or a property - * value in dependencies.properties resource file instead, if the version was not found. The - * method is doing I/O operations and is potentially inefficient, the values returned by this - * method are expected to be cached. - */ - public static String getLibraryVersion(Class libraryClass, String propertyName) { - String version = null; - // Always read GaxProperties' version from the properties file. - if (!libraryClass.equals(GaxProperties.class)) { - version = getLibraryVersion(libraryClass); - if (!DEFAULT_VERSION.equals(version)) { - return version; - } - } - - try (InputStream in = libraryClass.getResourceAsStream("/dependencies.properties")) { - if (in != null) { - Properties props = new Properties(); - props.load(in); - version = props.getProperty(propertyName); - } - } catch (IOException e) { - // ignore - } - - return version != null ? version : DEFAULT_VERSION; - } - - /** Returns the version of the running JVM */ - public static String getJavaVersion() { - // When running the application as a native image, append `-graalvm` to the - // version. - String imageCode = System.getProperty(PROPERTY_IMAGE_CODE_KEY); - if (imageCode != null && imageCode.equals(PROPERTY_IMAGE_CODE_VALUE_RUNTIME)) { - return System.getProperty("java.version") + "-graalvm"; - } - return JAVA_VERSION; - } - - /** Returns the current version of GAX. */ - public static String getGaxVersion() { - return GAX_VERSION; - } - - /** Returns the current runtime version */ - private static String getRuntimeVersion() { - return System.getProperty("java.version"); - } -} diff --git a/gax/src/main/java/com/google/api/gax/core/GoogleCredentialsProvider.java b/gax/src/main/java/com/google/api/gax/core/GoogleCredentialsProvider.java deleted file mode 100644 index 56642ecde..000000000 --- a/gax/src/main/java/com/google/api/gax/core/GoogleCredentialsProvider.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.core; - -import com.google.api.core.BetaApi; -import com.google.auth.Credentials; -import com.google.auth.oauth2.GoogleCredentials; -import com.google.auth.oauth2.ServiceAccountCredentials; -import com.google.auth.oauth2.ServiceAccountJwtAccessCredentials; -import com.google.auto.value.AutoValue; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.ImmutableList; -import java.io.IOException; -import java.util.List; -import javax.annotation.Nullable; - -/** - * GoogleCredentialsProvider acquires credentials using Application Default Credentials. - * - *

For more information on Application Default Credentials, see - * https://developers.google.com/identity/protocols/application-default-credentials. - */ -@AutoValue -public abstract class GoogleCredentialsProvider implements CredentialsProvider { - - public abstract List getScopesToApply(); - - @BetaApi - public abstract List getJwtEnabledScopes(); - - @BetaApi - public abstract boolean getUseJwtAccessWithScope(); - - @VisibleForTesting - @Nullable - abstract GoogleCredentials getOAuth2Credentials(); - - @Override - public Credentials getCredentials() throws IOException { - GoogleCredentials credentials = getOAuth2Credentials(); - if (credentials == null) { - credentials = GoogleCredentials.getApplicationDefault(); - } - - // Check if the current scopes permit JWT token use - boolean hasJwtEnabledScope = false; - for (String scope : getJwtEnabledScopes()) { - if (getScopesToApply().contains(scope)) { - hasJwtEnabledScope = true; - break; - } - } - // Use JWT tokens when using a service account with an appropriate scope. - if (credentials instanceof ServiceAccountCredentials && hasJwtEnabledScope) { - ServiceAccountCredentials serviceAccount = (ServiceAccountCredentials) credentials; - - return ServiceAccountJwtAccessCredentials.newBuilder() - .setClientEmail(serviceAccount.getClientEmail()) - .setClientId(serviceAccount.getClientId()) - .setPrivateKey(serviceAccount.getPrivateKey()) - .setPrivateKeyId(serviceAccount.getPrivateKeyId()) - .setQuotaProjectId(serviceAccount.getQuotaProjectId()) - .build(); - } - - if (credentials.createScopedRequired()) { - credentials = credentials.createScoped(getScopesToApply()); - } - - if (getUseJwtAccessWithScope() && credentials instanceof ServiceAccountCredentials) { - // See https://google.aip.dev/auth/4111 for self signed JWT. - ServiceAccountCredentials serviceAccount = (ServiceAccountCredentials) credentials; - return serviceAccount.createWithUseJwtAccessWithScope(true); - } - return credentials; - } - - public static Builder newBuilder() { - return new AutoValue_GoogleCredentialsProvider.Builder() - .setJwtEnabledScopes(ImmutableList.of()) - .setUseJwtAccessWithScope(false); - } - - public abstract Builder toBuilder(); - - @BetaApi - @AutoValue.Builder - public abstract static class Builder { - - /** - * Sets the scopes to apply to the credentials that are acquired from Application Default - * Credentials, before the credentials are sent to the service. - */ - public abstract Builder setScopesToApply(List val); - - /** The scopes previously provided. */ - public abstract List getScopesToApply(); - - @VisibleForTesting - abstract Builder setOAuth2Credentials(GoogleCredentials oauth2Credentials); - - /** - * Sets the scopes that are compatible with JWT tokens. - * - *

JWT Tokens don't support scopes, they only support audiences. Audiences allow access to - * the entire service as opposed some subset (ie. access can't be restricted to use the scope - * {@code https://www.googleapis.com/auth/bigtable.data.readonly}). A service client can opt-in - * to using JWT tokens by specifying which scopes encompass the entire service. If any of those - * scopes are present when the client is using {@link ServiceAccountCredentials}, then JWT - * tokens will be used for authentication. - */ - @BetaApi - public abstract Builder setJwtEnabledScopes(List val); - - /** The JWT enable scopes previously provided. */ - @BetaApi - public abstract List getJwtEnabledScopes(); - - /** Whether self signed JWT with scopes should be used for service account credentials. */ - @BetaApi - public abstract Builder setUseJwtAccessWithScope(boolean val); - - /** The UseJwtAccessWithScope value previously provided. */ - @BetaApi - public abstract boolean getUseJwtAccessWithScope(); - - public GoogleCredentialsProvider build() { - setScopesToApply(ImmutableList.copyOf(getScopesToApply())); - setJwtEnabledScopes(ImmutableList.copyOf(getJwtEnabledScopes())); - setUseJwtAccessWithScope(getUseJwtAccessWithScope()); - return autoBuild(); - } - - abstract GoogleCredentialsProvider autoBuild(); - } -} diff --git a/gax/src/main/java/com/google/api/gax/core/InstantiatingExecutorProvider.java b/gax/src/main/java/com/google/api/gax/core/InstantiatingExecutorProvider.java deleted file mode 100644 index c91b044cb..000000000 --- a/gax/src/main/java/com/google/api/gax/core/InstantiatingExecutorProvider.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.core; - -import com.google.auto.value.AutoValue; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * InstantiatingChannelProvider is an ExecutorProvider which constructs a new - * ScheduledExecutorService every time getExecutor() is called. - */ -@AutoValue -public abstract class InstantiatingExecutorProvider implements ExecutorProvider { - // Thread factory to use to create our worker threads - private static final ThreadFactory DEFAULT_THREAD_FACTORY = - new ThreadFactory() { - private final AtomicInteger threadCount = new AtomicInteger(); - - @Override - public Thread newThread(Runnable runnable) { - Thread thread = new Thread(runnable); - thread.setName("Gax-" + threadCount.incrementAndGet()); - thread.setDaemon(true); - return thread; - } - }; - - // Package-private constructor prevents others from subclassing. - InstantiatingExecutorProvider() {} - - @Override - public ScheduledExecutorService getExecutor() { - return new ScheduledThreadPoolExecutor(getExecutorThreadCount(), getThreadFactory()); - } - - @Override - public boolean shouldAutoClose() { - return true; - } - - /** The number of threads used by the executor created by this ExecutorProvider. */ - public abstract int getExecutorThreadCount(); - - /** Return a thread-factory to create gax processing threads so we can name them appropriately */ - public abstract ThreadFactory getThreadFactory(); - - public abstract Builder toBuilder(); - - public static Builder newBuilder() { - int numCpus = Runtime.getRuntime().availableProcessors(); - int numThreads = Math.max(4, numCpus); - - return new AutoValue_InstantiatingExecutorProvider.Builder() - .setExecutorThreadCount(numThreads) - .setThreadFactory(DEFAULT_THREAD_FACTORY); - } - - @AutoValue.Builder - public abstract static class Builder { - public abstract Builder setExecutorThreadCount(int value); - - public abstract int getExecutorThreadCount(); - - public abstract Builder setThreadFactory(ThreadFactory value); - - public abstract ThreadFactory getThreadFactory(); - - public abstract InstantiatingExecutorProvider build(); - } -} diff --git a/gax/src/main/java/com/google/api/gax/core/NoCredentialsProvider.java b/gax/src/main/java/com/google/api/gax/core/NoCredentialsProvider.java deleted file mode 100644 index 2817f363d..000000000 --- a/gax/src/main/java/com/google/api/gax/core/NoCredentialsProvider.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.core; - -import com.google.auth.Credentials; - -/** NoCredentialsProvider is a CredentialsProvider which always returns null. */ -public final class NoCredentialsProvider implements CredentialsProvider { - @Override - public Credentials getCredentials() { - return null; - } - - public static NoCredentialsProvider create() { - return new NoCredentialsProvider(); - } -} diff --git a/gax/src/main/java/com/google/api/gax/core/ResourceCloseException.java b/gax/src/main/java/com/google/api/gax/core/ResourceCloseException.java deleted file mode 100644 index 5ed9ca885..000000000 --- a/gax/src/main/java/com/google/api/gax/core/ResourceCloseException.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.core; - -/** An exception occurs when some background resource is not able to close properly. */ -public class ResourceCloseException extends RuntimeException { - - private static final long serialVersionUID = -283748743873637484L; - - public ResourceCloseException(Exception exception) { - super(exception); - } -} diff --git a/gax/src/main/java/com/google/api/gax/longrunning/OperationFuture.java b/gax/src/main/java/com/google/api/gax/longrunning/OperationFuture.java deleted file mode 100644 index 7c15ff9e4..000000000 --- a/gax/src/main/java/com/google/api/gax/longrunning/OperationFuture.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.longrunning; - -import com.google.api.core.ApiFuture; -import com.google.api.gax.retrying.RetryingFuture; -import java.util.concurrent.ExecutionException; - -/** - * An ApiFuture which tracks polling of a service. The polling is done periodically, based on the - * {@link com.google.api.gax.retrying.TimedRetryAlgorithm}. - * - *

Implementations are expected to be thread-safe. - */ -public interface OperationFuture extends ApiFuture { - /** - * Returns the value of the name of the operation from the initial operation object returned from - * the initial call to start the operation. Blocks if the initial call to start the operation - * hasn't returned yet. - */ - String getName() throws InterruptedException, ExecutionException; - - /** - * Returns the {@link OperationSnapshot} future of the initial request which started this {@code - * OperationFuture}. - */ - ApiFuture getInitialFuture(); - - /** Returns the {@link RetryingFuture} which continues to poll {@link OperationSnapshot}. */ - RetryingFuture getPollingFuture(); - - /** - * Peeks at the metadata of the operation tracked by this {@link OperationFuture}. If the initial - * future hasn't completed yet this method returns {@code null}, otherwise it returns the latest - * metadata returned from the server (i.e. either initial call metadata or the metadata received - * from the latest completed poll iteration). - * - *

If not {@code null}, the returned result is guaranteed to be an already completed future, so - * {@link ApiFuture#isDone()} will always be {@code true} and {@link ApiFuture#get()} will always - * be non-blocking. - * - *

Note, some APIs may return {@code null} in metadata response message. In such cases this - * method may return a non-null future whose {@code get()} method will return {@code null}. This - * behavior is API specific an should be considered a valid case, which indicates that the recent - * poll request has completed, but no specific metadata was provided by the server (i.e. most - * probably providing metadata for an intermediate result is not supported by the server). - * - *

This method should be used to check operation progress without blocking current thread. - * Since this method returns metadata from the latest completed poll, it is potentially slightly - * stale compared to the most recent data. To get the most recent data and/or get notified when - * the current scheduled poll request completes use the {@link #getMetadata()} method instead. - * - *

If this operation future is completed, this method always returns the metadata from the last - * poll request (which completed the operation future). - * - *

If this operation future failed, this method may (depending on the failure type) return a - * non-failing future, representing the metadata from the last poll request (which failed the - * operation future). - * - *

If this operation future was cancelled, this method returns a canceled metatata future as - * well. - * - *

In general this method behaves similarly to {@link RetryingFuture#peekAttemptResult()}. - */ - ApiFuture peekMetadata(); - - /** - * Gets the metadata of the operation tracked by this {@link OperationFuture}. This method returns - * the current poll metadata result (or the initial call metadata if it hasn't completed yet). The - * returned future completes once the current scheduled poll request (or the initial request if it - * hasn't completed yet) is executed and response is received from the server. The time when the - * polling request is executed is determined by the underlying polling algorithm. - * - *

Adding direct executor (same thread) callbacks to the future returned by this method is - * strongly not recommended, since the future is resolved under retrying future's internal lock - * and may affect the operation polling process. Adding separate thread callbacks is ok. - * - *

Note, some APIs may return {@code null} in metadata response message. In such cases this - * method may return a non-null future whose {@code get()} method will return {@code null}. This - * behavior is API specific an should be considered a valid case, which indicates that the recent - * poll request has completed, but no specific metadata was provided by the server. (i.e. most - * probably providing metadata for an intermediate result is not supported by the server). - * - *

In most cases this method returns a future which is not completed yet, so calling {@link - * ApiFuture#get()} is a potentially blocking operation. To get metadata without blocking the - * current thread use the {@link #peekMetadata()} method instead. - * - *

If this operation future is completed, this method always returns the metadata from the last - * poll request (which completed the operation future). - * - *

If this operation future failed, this method may (depending on the failure type) return a - * non-failing future, representing the metadata from the last poll request (which failed the - * operation future). - * - *

If this operation future was cancelled, this method returns a canceled metatata future as - * well. - * - *

In general this method behaves similarly to {@link RetryingFuture#getAttemptResult()}. - */ - ApiFuture getMetadata(); -} diff --git a/gax/src/main/java/com/google/api/gax/longrunning/OperationFutureImpl.java b/gax/src/main/java/com/google/api/gax/longrunning/OperationFutureImpl.java deleted file mode 100644 index 769ec2adc..000000000 --- a/gax/src/main/java/com/google/api/gax/longrunning/OperationFutureImpl.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.longrunning; - -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.util.concurrent.MoreExecutors.directExecutor; - -import com.google.api.core.ApiFunction; -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.api.core.InternalApi; -import com.google.api.gax.retrying.RetryingFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -/** - * An ApiFuture which tracks polling of a service. The polling is done periodically, based on the - * {@link com.google.api.gax.retrying.TimedRetryAlgorithm}. - * - *

This class is thread-safe. - * - *

This is public only for technical reasons, for advanced usage. - */ -@InternalApi -public final class OperationFutureImpl - implements OperationFuture { - private final Object lock = new Object(); - - private final RetryingFuture pollingFuture; - private final ApiFuture initialFuture; - private final ApiFuture resultFuture; - private final ApiFunction metadataTransformer; - - private volatile ApiFuture peekedAttemptResult; - private volatile ApiFuture peekedPollResult; - private volatile ApiFuture gottenAttemptResult; - private volatile ApiFuture gottenPollResult; - - /** - * Creates a new operation future instance. - * - * @param pollingFuture retrying future which tracks polling of the server operation (in most - * cases with exponential upper bounded intervals) - * @param initialFuture the initial future which started the operation on the server side - */ - public OperationFutureImpl( - RetryingFuture pollingFuture, - ApiFuture initialFuture, - ApiFunction responseTransformer, - ApiFunction metadataTransformer) { - this.pollingFuture = checkNotNull(pollingFuture); - this.initialFuture = checkNotNull(initialFuture); - this.resultFuture = ApiFutures.transform(pollingFuture, responseTransformer, directExecutor()); - this.metadataTransformer = checkNotNull(metadataTransformer); - } - - public OperationFutureImpl( - RetryingFuture pollingFuture, - ApiFuture initialFuture, - ApiFunction responseTransformer, - ApiFunction metadataTransformer, - ApiFunction exceptionTransformer) { - this.pollingFuture = checkNotNull(pollingFuture); - this.initialFuture = checkNotNull(initialFuture); - this.resultFuture = - ApiFutures.catching( - ApiFutures.transform(pollingFuture, responseTransformer, directExecutor()), - Exception.class, - exceptionTransformer, - directExecutor()); - this.metadataTransformer = checkNotNull(metadataTransformer); - } - - @Override - public void addListener(Runnable listener, Executor executor) { - pollingFuture.addListener(listener, executor); - } - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - return pollingFuture.cancel(mayInterruptIfRunning); - } - - @Override - public boolean isCancelled() { - return pollingFuture.isCancelled(); - } - - @Override - public boolean isDone() { - return pollingFuture.isDone(); - } - - @Override - public ResponseT get() throws InterruptedException, ExecutionException { - return resultFuture.get(); - } - - @Override - public ResponseT get(long timeout, TimeUnit unit) - throws InterruptedException, ExecutionException, TimeoutException { - return resultFuture.get(timeout, unit); - } - - @Override - public String getName() throws ExecutionException, InterruptedException { - return initialFuture.get().getName(); - } - - @Override - public ApiFuture getInitialFuture() { - return initialFuture; - } - - @Override - public RetryingFuture getPollingFuture() { - return pollingFuture; - } - - // Note, the following two methods are not duplicates of each other even though code checking - // tools may indicate so. They assign multiple different class fields. - @Override - public ApiFuture peekMetadata() { - ApiFuture future = pollingFuture.peekAttemptResult(); - synchronized (lock) { - if (peekedAttemptResult == future) { - return peekedPollResult; - } - peekedAttemptResult = future; - peekedPollResult = - ApiFutures.transform(peekedAttemptResult, metadataTransformer, directExecutor()); - return peekedPollResult; - } - } - - @Override - public ApiFuture getMetadata() { - ApiFuture future = pollingFuture.getAttemptResult(); - synchronized (lock) { - if (gottenAttemptResult == future) { - return gottenPollResult; - } - gottenAttemptResult = future; - gottenPollResult = - ApiFutures.transform(gottenAttemptResult, metadataTransformer, directExecutor()); - return gottenPollResult; - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/longrunning/OperationFutures.java b/gax/src/main/java/com/google/api/gax/longrunning/OperationFutures.java deleted file mode 100644 index 16d167bd3..000000000 --- a/gax/src/main/java/com/google/api/gax/longrunning/OperationFutures.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.longrunning; - -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.api.gax.retrying.RetryingFuture; -import com.google.api.gax.rpc.ApiException; -import com.google.api.gax.rpc.StatusCode; -import com.google.common.base.Preconditions; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executor; -import java.util.concurrent.TimeUnit; - -public class OperationFutures { - private OperationFutures() { - // Utility class - } - - /** - * Creates an already-completed {@code OperationFuture}, useful for testing. - * - *

{@code completedSnapshot.isDone()} must return true. The snapshot's {@code getResponse()} - * and {@code getMetadata()} must be instances of {@code ResponseT} and {@code MetadataT}, - * respectively. - */ - @SuppressWarnings("unchecked") - public static final - OperationFuture immediateOperationFuture( - final OperationSnapshot completedSnapshot) { - - Preconditions.checkArgument( - completedSnapshot.isDone(), "given snapshot must already be completed"); - final ApiFuture metadataFuture = - ApiFutures.immediateFuture((MetadataT) completedSnapshot.getMetadata()); - final ApiFuture initialFuture = - ApiFutures.immediateFuture(completedSnapshot); - - return new OperationFuture() { - @Override - public String getName() { - return completedSnapshot.getName(); - } - - @Override - public ApiFuture getMetadata() { - return metadataFuture; - } - - @Override - public ApiFuture peekMetadata() { - return metadataFuture; - } - - @Override - public ApiFuture getInitialFuture() { - return initialFuture; - } - - @Override - public RetryingFuture getPollingFuture() { - throw new UnsupportedOperationException("Not implemented: getPollingFuture()."); - } - - @Override - public void addListener(Runnable runnable, Executor executor) { - initialFuture.addListener(runnable, executor); - } - - @Override - public ResponseT get(long time, TimeUnit unit) throws ExecutionException { - return get(); - } - - @Override - public ResponseT get() throws ExecutionException { - if (completedSnapshot.getErrorCode().getCode().equals(StatusCode.Code.OK)) { - return (ResponseT) completedSnapshot.getResponse(); - } - throw new ExecutionException( - new ApiException(null, completedSnapshot.getErrorCode(), false)); - } - - @Override - public boolean isDone() { - return true; - } - - @Override - public boolean isCancelled() { - return false; - } - - @Override - public boolean cancel(boolean b) { - return false; - } - }; - } -} diff --git a/gax/src/main/java/com/google/api/gax/longrunning/OperationResponsePollAlgorithm.java b/gax/src/main/java/com/google/api/gax/longrunning/OperationResponsePollAlgorithm.java deleted file mode 100644 index 00c3389bb..000000000 --- a/gax/src/main/java/com/google/api/gax/longrunning/OperationResponsePollAlgorithm.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.longrunning; - -import com.google.api.gax.retrying.ResultRetryAlgorithm; -import com.google.api.gax.retrying.TimedAttemptSettings; - -/** - * Operation polling algorithm, which keeps retrying until {@link OperationSnapshot#isDone()} is - * true. - */ -public class OperationResponsePollAlgorithm implements ResultRetryAlgorithm { - @Override - public TimedAttemptSettings createNextAttempt( - Throwable prevThrowable, OperationSnapshot prevResponse, TimedAttemptSettings prevSettings) { - return null; - } - - @Override - public boolean shouldRetry(Throwable prevThrowable, OperationSnapshot prevResponse) { - return prevThrowable == null && prevResponse != null && !prevResponse.isDone(); - } -} diff --git a/gax/src/main/java/com/google/api/gax/longrunning/OperationSnapshot.java b/gax/src/main/java/com/google/api/gax/longrunning/OperationSnapshot.java deleted file mode 100644 index 7f275970e..000000000 --- a/gax/src/main/java/com/google/api/gax/longrunning/OperationSnapshot.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.longrunning; - -import com.google.api.gax.rpc.StatusCode; - -/** - * A snapshot of a long-running operation. - * - *

The metadata and response will have a structure defined by the particular long-running - * operation that was initiated. - */ -public interface OperationSnapshot { - - /** The name of the operation. This is used for identifying the operation on the server. */ - String getName(); - - /** Get metadata for the operation, which can change over the course of the operation. */ - Object getMetadata(); - - /** Returns true if the operation is complete or failed, false otherwise. */ - boolean isDone(); - - /** - * If the operation is done and successful, returns the response; if the operation is not done or - * if it is failed, returns null. - */ - Object getResponse(); - - /** - * If the operation is done and it failed, returns the failure status code; if the operation is - * not done or if it succeeded, returns null. - */ - StatusCode getErrorCode(); - - /** - * If the operation is done and it failed, returns the error message; if the operation is not done - * or if it succeeded, returns null. - */ - String getErrorMessage(); -} diff --git a/gax/src/main/java/com/google/api/gax/longrunning/OperationTimedPollAlgorithm.java b/gax/src/main/java/com/google/api/gax/longrunning/OperationTimedPollAlgorithm.java deleted file mode 100644 index ddc49f3c0..000000000 --- a/gax/src/main/java/com/google/api/gax/longrunning/OperationTimedPollAlgorithm.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.longrunning; - -import com.google.api.core.ApiClock; -import com.google.api.core.NanoClock; -import com.google.api.gax.retrying.ExponentialRetryAlgorithm; -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.retrying.TimedAttemptSettings; -import java.util.concurrent.CancellationException; - -/** - * Operation timed polling algorithm, which uses exponential backoff factor for determining when the - * next polling operation should be executed. If the polling exceeds the total timeout this - * algorithm cancels polling. - */ -public class OperationTimedPollAlgorithm extends ExponentialRetryAlgorithm { - /** - * Creates the polling algorithm, using the default {@code NanoClock} for time computations. - * - * @param globalSettings the settings - * @return timed poll algorithm - */ - public static OperationTimedPollAlgorithm create(RetrySettings globalSettings) { - return new OperationTimedPollAlgorithm(globalSettings, NanoClock.getDefaultClock()); - } - - public static OperationTimedPollAlgorithm create(RetrySettings globalSettings, ApiClock clock) { - return new OperationTimedPollAlgorithm(globalSettings, clock); - } - - private OperationTimedPollAlgorithm(RetrySettings globalSettings, ApiClock clock) { - super(globalSettings, clock); - } - - /** - * Returns {@code true} if another poll operation should be made or throws {@link - * CancellationException} otherwise. - * - * @param nextAttemptSettings attempt settings, which will be used for the next attempt, if - * accepted - * @return {@code true} if more attempts should be made, never returns {@code false} (throws - * {@code CancellationException} instead) - * @throws CancellationException if no more attempts should be made - */ - @Override - public boolean shouldRetry(TimedAttemptSettings nextAttemptSettings) - throws CancellationException { - if (super.shouldRetry(nextAttemptSettings)) { - return true; - } - throw new CancellationException(); - } -} diff --git a/gax/src/main/java/com/google/api/gax/nativeimage/GoogleJsonClientFeature.java b/gax/src/main/java/com/google/api/gax/nativeimage/GoogleJsonClientFeature.java deleted file mode 100644 index baa4bac92..000000000 --- a/gax/src/main/java/com/google/api/gax/nativeimage/GoogleJsonClientFeature.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.gax.nativeimage; - -import static com.google.api.gax.nativeimage.NativeImageUtils.registerClassForReflection; - -import org.graalvm.nativeimage.hosted.Feature; - -/** Configures Native Image settings for the Google JSON Client. */ -final class GoogleJsonClientFeature implements Feature { - - private static final String GOOGLE_API_CLIENT_CLASS = - "com.google.api.client.googleapis.services.json.AbstractGoogleJsonClient"; - - private static final String GOOGLE_API_CLIENT_REQUEST_CLASS = - "com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest"; - - private static final String GENERIC_JSON_CLASS = "com.google.api.client.json.GenericJson"; - - @Override - public void beforeAnalysis(BeforeAnalysisAccess access) { - loadApiClient(access); - loadHttpClient(access); - loadMiscClasses(access); - } - - private void loadApiClient(BeforeAnalysisAccess access) { - // For com.google.api-client:google-api-client - Class googleApiClientClass = access.findClassByName(GOOGLE_API_CLIENT_CLASS); - - if (googleApiClientClass != null) { - // All reachable instances of the AbstractGoogleJsonClient must be registered. - access.registerSubtypeReachabilityHandler( - (duringAccess, subtype) -> registerClassForReflection(access, subtype.getName()), - googleApiClientClass); - - // All reachable instances of the AbstractGoogleJsonClientRequest must be registered. - access.registerSubtypeReachabilityHandler( - (duringAccess, subtype) -> registerClassForReflection(access, subtype.getName()), - access.findClassByName(GOOGLE_API_CLIENT_REQUEST_CLASS)); - } - } - - private void loadHttpClient(BeforeAnalysisAccess access) { - // For com.google.http-client:google-http-client - Class genericJsonClass = access.findClassByName(GENERIC_JSON_CLASS); - - if (genericJsonClass != null) { - // All reachable instances of GenericJson must be registered. - access.registerSubtypeReachabilityHandler( - (duringAccess, subtype) -> registerClassForReflection(access, subtype.getName()), - genericJsonClass); - - registerClassForReflection(access, "com.google.api.client.util.GenericData"); - registerClassForReflection(access, "com.google.api.client.json.webtoken.JsonWebToken"); - registerClassForReflection(access, "com.google.api.client.json.webtoken.JsonWebToken$Header"); - registerClassForReflection( - access, "com.google.api.client.json.webtoken.JsonWebToken$Payload"); - registerClassForReflection( - access, "com.google.api.client.json.webtoken.JsonWebSignature$Header"); - registerClassForReflection(access, "com.google.api.client.json.webtoken.JsonWebSignature"); - registerClassForReflection(access, "com.google.api.client.http.UrlEncodedContent"); - registerClassForReflection(access, "com.google.api.client.http.GenericUrl"); - registerClassForReflection(access, "com.google.api.client.http.HttpRequest"); - registerClassForReflection(access, "com.google.api.client.http.HttpHeaders"); - } - } - - private void loadMiscClasses(BeforeAnalysisAccess access) { - registerClassForReflection(access, "com.google.common.util.concurrent.AbstractFuture"); - - registerClassForReflection(access, "com.google.common.util.concurrent.AbstractFuture$Waiter"); - } -} diff --git a/gax/src/main/java/com/google/api/gax/nativeimage/NativeImageUtils.java b/gax/src/main/java/com/google/api/gax/nativeimage/NativeImageUtils.java deleted file mode 100644 index 603d26e3c..000000000 --- a/gax/src/main/java/com/google/api/gax/nativeimage/NativeImageUtils.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.gax.nativeimage; - -import com.google.api.core.InternalApi; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.logging.Level; -import java.util.logging.Logger; -import org.graalvm.nativeimage.hosted.Feature.FeatureAccess; -import org.graalvm.nativeimage.hosted.RuntimeReflection; - -/** Internal class offering helper methods for registering methods/classes for reflection. */ -@InternalApi -public class NativeImageUtils { - - private static final Logger LOGGER = Logger.getLogger(NativeImageUtils.class.getName()); - private static final String CLASS_REFLECTION_ERROR_MESSAGE = - "Failed to find {0} on the classpath for reflection."; - - private NativeImageUtils() {} - - /** Returns the method of a class or fails if it is not present. */ - public static Method getMethodOrFail(Class clazz, String methodName, Class... params) { - try { - return clazz.getDeclaredMethod(methodName, params); - } catch (NoSuchMethodException e) { - throw new IllegalStateException( - String.format("Failed to find method %s for class %s", methodName, clazz.getName()), e); - } - } - - /** Registers a class for reflective construction via its default constructor. */ - public static void registerForReflectiveInstantiation(FeatureAccess access, String className) { - Class clazz = access.findClassByName(className); - if (clazz != null) { - RuntimeReflection.register(clazz); - RuntimeReflection.registerForReflectiveInstantiation(clazz); - } else { - LOGGER.log( - Level.WARNING, - "Failed to find {0} on the classpath for reflective instantiation.", - className); - } - } - - /** Registers all constructors of a class for reflection. */ - public static void registerConstructorsForReflection(FeatureAccess access, String name) { - Class clazz = access.findClassByName(name); - if (clazz != null) { - RuntimeReflection.register(clazz); - RuntimeReflection.register(clazz.getDeclaredConstructors()); - } else { - LOGGER.log(Level.WARNING, CLASS_REFLECTION_ERROR_MESSAGE, name); - } - } - - /** Registers an entire class for reflection use. */ - public static void registerClassForReflection(FeatureAccess access, String name) { - Class clazz = access.findClassByName(name); - if (clazz != null) { - RuntimeReflection.register(clazz); - RuntimeReflection.register(clazz.getDeclaredConstructors()); - RuntimeReflection.register(clazz.getDeclaredFields()); - RuntimeReflection.register(clazz.getDeclaredMethods()); - } else { - LOGGER.log(Level.WARNING, CLASS_REFLECTION_ERROR_MESSAGE, name); - } - } - - /** - * Registers the transitive class hierarchy of the provided {@code className} for reflection. - * - *

The transitive class hierarchy contains the class itself and its transitive set of - * *non-private* nested subclasses. - */ - public static void registerClassHierarchyForReflection(FeatureAccess access, String className) { - Class clazz = access.findClassByName(className); - if (clazz != null) { - registerClassForReflection(access, className); - for (Class nestedClass : clazz.getDeclaredClasses()) { - if (!Modifier.isPrivate(nestedClass.getModifiers())) { - registerClassHierarchyForReflection(access, nestedClass.getName()); - } - } - } else { - LOGGER.log(Level.WARNING, CLASS_REFLECTION_ERROR_MESSAGE, className); - } - } - - /** Registers a class for unsafe reflective field access. */ - public static void registerForUnsafeFieldAccess( - FeatureAccess access, String className, String... fields) { - Class clazz = access.findClassByName(className); - if (clazz != null) { - RuntimeReflection.register(clazz); - for (String fieldName : fields) { - try { - RuntimeReflection.register(clazz.getDeclaredField(fieldName)); - } catch (NoSuchFieldException ex) { - LOGGER.warning("Failed to register field " + fieldName + " for class " + className); - LOGGER.warning(ex.getMessage()); - } - } - } else { - LOGGER.log( - Level.WARNING, - "Failed to find {0} on the classpath for unsafe fields access registration.", - className); - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/nativeimage/OpenCensusFeature.java b/gax/src/main/java/com/google/api/gax/nativeimage/OpenCensusFeature.java deleted file mode 100644 index a32cac4b3..000000000 --- a/gax/src/main/java/com/google/api/gax/nativeimage/OpenCensusFeature.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.gax.nativeimage; - -import static com.google.api.gax.nativeimage.NativeImageUtils.registerForReflectiveInstantiation; - -import org.graalvm.nativeimage.hosted.Feature; - -/** Registers reflection usage in OpenCensus libraries. */ -final class OpenCensusFeature implements Feature { - - private static final String TAGS_COMPONENT_CLASS = "io.opencensus.impl.tags.TagsComponentImpl"; - private static final String STATS_COMPONENT_CLASS = "io.opencensus.impl.stats.StatsComponentImpl"; - - @Override - public void beforeAnalysis(BeforeAnalysisAccess access) { - if (access.findClassByName(STATS_COMPONENT_CLASS) != null) { - registerForReflectiveInstantiation(access, STATS_COMPONENT_CLASS); - } - if (access.findClassByName(TAGS_COMPONENT_CLASS) != null) { - registerForReflectiveInstantiation(access, "io.opencensus.impl.metrics.MetricsComponentImpl"); - registerForReflectiveInstantiation(access, TAGS_COMPONENT_CLASS); - registerForReflectiveInstantiation(access, "io.opencensus.impl.trace.TraceComponentImpl"); - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/paging/AbstractFixedSizeCollection.java b/gax/src/main/java/com/google/api/gax/paging/AbstractFixedSizeCollection.java deleted file mode 100644 index f843bc2dc..000000000 --- a/gax/src/main/java/com/google/api/gax/paging/AbstractFixedSizeCollection.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.paging; - -import com.google.api.client.util.Lists; -import com.google.api.pathtemplate.ValidationException; -import com.google.common.base.Preconditions; -import com.google.common.collect.AbstractIterator; -import java.util.Iterator; -import java.util.List; - -/** Partial implementation of {@link FixedSizeCollection}. */ -public abstract class AbstractFixedSizeCollection< - RequestT, - ResponseT, - ResourceT, - PageT extends AbstractPage, - CollectionT extends - AbstractFixedSizeCollection> - implements FixedSizeCollection { - - private final List pageList; - private final int collectionSize; - - protected AbstractFixedSizeCollection(List pages, int collectionSize) { - this.pageList = pages; - this.collectionSize = collectionSize; - } - - protected abstract CollectionT createCollection(List pages, int collectionSize); - - @Override - public Iterable getValues() { - return new Iterable() { - @Override - public Iterator iterator() { - return new CollectionResourcesIterator(); - } - }; - } - - @Override - public CollectionT getNextCollection() { - if (hasNextCollection()) { - PageT nextFirstPage = getLastPage().getNextPage(); - List pages = getPages(nextFirstPage, collectionSize); - return createCollection(pages, collectionSize); - } else { - return null; - } - } - - @Override - public boolean hasNextCollection() { - return getLastPage().hasNextPage(); - } - - @Override - public String getNextPageToken() { - return getLastPage().getNextPageToken(); - } - - @Override - public int getCollectionSize() { - int size = 0; - for (PageT page : pageList) { - size += page.getPageElementCount(); - } - return size; - } - - private PageT getLastPage() { - return pageList.get(pageList.size() - 1); - } - - /** - * Retrieve a list of pages with a total of collectionSize elements. - * - *

If the collectionSize parameter is greater than the number of elements in the firstPage - * object, additional pages will be retrieved from the underlying API. It is an error to choose a - * value of collectionSize that is less that the number of elements that already exist in the Page - * object. - */ - List getPages(final PageT firstPage, final int collectionSize) { - Preconditions.checkNotNull(firstPage); - Preconditions.checkState(collectionSize > 0); - Integer requestPageSize = - firstPage.getContext().getPageDescriptor().extractPageSize(firstPage.getRequest()); - if (requestPageSize == null) { - throw new ValidationException( - "Error while expanding Page to FixedSizeCollection: No pageSize " - + "parameter found. The pageSize parameter must be set on the request " - + "object, and must be less than the collectionSize " - + "parameter, in order to create a FixedSizeCollection object."); - } - if (requestPageSize > collectionSize) { - throw new ValidationException( - "Error while expanding Page to FixedSizeCollection: collectionSize " - + "parameter is less than the pageSize optional argument specified on " - + "the request object. collectionSize: " - + collectionSize - + ", pageSize: " - + requestPageSize); - } - if (firstPage.getPageElementCount() > collectionSize) { - throw new ValidationException( - "Cannot construct a FixedSizeCollection with collectionSize less than the number of " - + "elements in the first page"); - } - - int remainingCount = collectionSize - firstPage.getPageElementCount(); - List pages = Lists.newArrayList(); - pages.add(firstPage); - PageT currentPage = firstPage; - while (remainingCount > 0) { - currentPage = currentPage.getNextPage(remainingCount); - if (currentPage == null) { - break; - } else { - int rxElementCount = currentPage.getPageElementCount(); - if (rxElementCount > remainingCount) { - throw new ValidationException( - "API returned a number of elements exceeding the specified page_size limit. " - + "page_size: " - + collectionSize - + ", elements received: " - + rxElementCount); - } - remainingCount -= rxElementCount; - pages.add(currentPage); - } - } - return pages; - } - - private class CollectionResourcesIterator extends AbstractIterator { - - private final Iterator pageIterator = pageList.iterator(); - private Iterator resourceIterator = pageIterator.next().getValues().iterator(); - - @Override - protected ResourceT computeNext() { - while (true) { - if (resourceIterator.hasNext()) { - return resourceIterator.next(); - } else if (pageIterator.hasNext()) { - resourceIterator = pageIterator.next().getValues().iterator(); - } else { - return endOfData(); - } - } - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/paging/AbstractPage.java b/gax/src/main/java/com/google/api/gax/paging/AbstractPage.java deleted file mode 100644 index 805ec226e..000000000 --- a/gax/src/main/java/com/google/api/gax/paging/AbstractPage.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.paging; - -import static com.google.common.util.concurrent.MoreExecutors.directExecutor; - -import com.google.api.core.ApiFunction; -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.api.core.InternalApi; -import com.google.api.gax.rpc.ApiExceptions; -import com.google.api.gax.rpc.PageContext; -import com.google.common.base.Strings; -import com.google.common.collect.AbstractIterator; -import com.google.common.collect.Iterables; -import java.util.Iterator; - -/** Partial implementation of {@link AsyncPage}. */ -public abstract class AbstractPage< - RequestT, - ResponseT, - ResourceT, - PageT extends AbstractPage> - implements AsyncPage { - - private final PageContext context; - private final ResponseT response; - - protected AbstractPage(PageContext context, ResponseT response) { - this.context = context; - this.response = response; - } - - protected abstract PageT createPage( - PageContext context, ResponseT response); - - @InternalApi("Visible for testing") - public ApiFuture createPageAsync( - final PageContext context, - ApiFuture futureResponse) { - return ApiFutures.transform( - futureResponse, - new ApiFunction() { - @Override - public PageT apply(ResponseT input) { - return createPage(context, input); - } - }, - directExecutor()); - } - - @Override - public boolean hasNextPage() { - return !getNextPageToken().equals(context.getPageDescriptor().emptyToken()); - } - - @Override - public String getNextPageToken() { - return Strings.nullToEmpty(context.getPageDescriptor().extractNextToken(response)); - } - - @Override - public PageT getNextPage() { - return getNextPageImpl(null); - } - - public PageT getNextPage(int pageSize) { - return getNextPageImpl(pageSize); - } - - @Override - public ApiFuture getNextPageAsync() { - if (hasNextPage()) { - RequestT request = - context.getPageDescriptor().injectToken(context.getRequest(), getNextPageToken()); - final PageContext nextContext = context.withRequest(request); - return createPageAsync(nextContext, callApi(nextContext)); - } else { - return ApiFutures.immediateFuture(null); - } - } - - private PageT getNextPageImpl(Integer pageSize) { - if (hasNextPage()) { - RequestT request = - context.getPageDescriptor().injectToken(context.getRequest(), getNextPageToken()); - if (pageSize != null) { - request = context.getPageDescriptor().injectPageSize(request, pageSize); - } - PageContext nextContext = context.withRequest(request); - ResponseT response = ApiExceptions.callAndTranslateApiException(callApi(nextContext)); - return createPage(nextContext, response); - } else { - return null; - } - } - - private ApiFuture callApi(PageContext nextContext) { - return nextContext - .getCallable() - .futureCall(nextContext.getRequest(), nextContext.getCallContext()); - } - - @Override - public Iterable iterateAll() { - return new Iterable() { - @Override - public Iterator iterator() { - return new AllResourcesIterator(); - } - }; - } - - @Override - public Iterable getValues() { - return context.getPageDescriptor().extractResources(response); - } - - public ResponseT getResponse() { - return response; - } - - public RequestT getRequest() { - return context.getRequest(); - } - - public int getPageElementCount() { - return Iterables.size(context.getPageDescriptor().extractResources(response)); - } - - PageContext getContext() { - return context; - } - - private class AllResourcesIterator extends AbstractIterator { - private AbstractPage currentPage; - private Iterator currentIterator; - - private AllResourcesIterator() { - this.currentPage = AbstractPage.this; - this.currentIterator = this.currentPage.getValues().iterator(); - } - - @Override - protected ResourceT computeNext() { - while (true) { - if (currentIterator.hasNext()) { - return currentIterator.next(); - } - currentPage = currentPage.getNextPage(); - if (currentPage == null) { - return endOfData(); - } - currentIterator = currentPage.getValues().iterator(); - } - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/paging/AbstractPagedListResponse.java b/gax/src/main/java/com/google/api/gax/paging/AbstractPagedListResponse.java deleted file mode 100644 index 1d0597d4a..000000000 --- a/gax/src/main/java/com/google/api/gax/paging/AbstractPagedListResponse.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.paging; - -import com.google.common.base.Preconditions; -import com.google.common.collect.AbstractIterator; -import java.util.Iterator; -import java.util.List; - -/** Partial implementation of {@link com.google.api.gax.paging.PagedListResponse}. */ -public abstract class AbstractPagedListResponse< - RequestT, - ResponseT, - ResourceT, - PageT extends AbstractPage, - CollectionT extends - AbstractFixedSizeCollection> - implements PagedListResponse { - - private final PageT page; - private final CollectionT emptyCollection; - - protected AbstractPagedListResponse(PageT page, CollectionT emptyCollection) { - this.page = page; - this.emptyCollection = emptyCollection; - } - - @Override - public Iterable iterateAll() { - return getPage().iterateAll(); - } - - @Override - public PageT getPage() { - return page; - } - - @Override - public Iterable iteratePages() { - return new Iterable() { - @Override - public Iterator iterator() { - return new AllPagesIterator(page); - } - }; - } - - @Override - public String getNextPageToken() { - return getPage().getNextPageToken(); - } - - @Override - public CollectionT expandToFixedSizeCollection(int collectionSize) { - List pages = emptyCollection.getPages(page, collectionSize); - return emptyCollection.createCollection(pages, collectionSize); - } - - @Override - public Iterable iterateFixedSizeCollections(int collectionSize) { - final CollectionT firstCollection = expandToFixedSizeCollection(collectionSize); - return new Iterable() { - @Override - public Iterator iterator() { - return new AllCollectionsIterator(firstCollection); - } - }; - } - - private interface Next { - T next(T current); - } - - private class AllPagesIterator extends NextIterator { - private AllPagesIterator(PageT firstCollection) { - super( - firstCollection, - new Next() { - @Override - public PageT next(PageT current) { - return current.getNextPage(); - } - }); - } - } - - private class AllCollectionsIterator extends NextIterator { - private AllCollectionsIterator(CollectionT firstCollection) { - super( - firstCollection, - new Next() { - @Override - public CollectionT next(CollectionT current) { - return current.getNextCollection(); - } - }); - } - } - - private class NextIterator extends AbstractIterator { - - private T current; - private final Next fetcher; - private boolean computeFirst = true; - - private NextIterator(T first, Next fetcher) { - this.current = Preconditions.checkNotNull(first); - this.fetcher = fetcher; - } - - @Override - protected T computeNext() { - if (computeFirst) { - computeFirst = false; - return current; - } else { - current = fetcher.next(current); - if (current == null) { - return endOfData(); - } else { - return current; - } - } - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/paging/AsyncPage.java b/gax/src/main/java/com/google/api/gax/paging/AsyncPage.java deleted file mode 100644 index 9f139911c..000000000 --- a/gax/src/main/java/com/google/api/gax/paging/AsyncPage.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.paging; - -import com.google.api.core.ApiFuture; - -/** An AsyncPage extends a {@link Page} object with a getNextPageAsync method. */ -public interface AsyncPage extends Page { - - /** - * Returns a future for the Page object, retrieved using the next page token. If there are no more - * pages, returns a future which will immediately provide null. The hasNextPage() method can be - * used to check if a Page object is available. - */ - ApiFuture> getNextPageAsync(); -} diff --git a/gax/src/main/java/com/google/api/gax/paging/FixedSizeCollection.java b/gax/src/main/java/com/google/api/gax/paging/FixedSizeCollection.java deleted file mode 100644 index f3a7684e5..000000000 --- a/gax/src/main/java/com/google/api/gax/paging/FixedSizeCollection.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.paging; - -/** - * A FixedSizeCollection object wraps multiple API list method responses into a single collection - * with a fixed number of elements. - * - *

Callers can iterate over the FixedSizeCollection object to get all elements in the collection. - * The number of elements is guaranteed to be equal to the value of the collectionSize parameter - * passed to expandPage(), unless the API has no more elements to return. The FixedSizeCollection - * object also provides methods to retrieve additional FixedSizeCollections using the page token. - */ -public interface FixedSizeCollection { - - /** - * Returns the number of elements in the collection. This will be equal to the collectionSize - * parameter used at construction unless there are no elements remaining to be retrieved. - */ - int getCollectionSize(); - - /** Returns true if there are more elements that can be retrieved from the API. */ - boolean hasNextCollection(); - - /** - * Returns a page token that can be passed into the API list method to retrieve additional - * elements. - */ - String getNextPageToken(); - - /** Retrieves the next FixedSizeCollection using one or more API calls. */ - FixedSizeCollection getNextCollection(); - - /** Returns an iterable over the elements in this FixedSizeCollection. */ - Iterable getValues(); -} diff --git a/gax/src/main/java/com/google/api/gax/paging/Page.java b/gax/src/main/java/com/google/api/gax/paging/Page.java deleted file mode 100644 index abacde970..000000000 --- a/gax/src/main/java/com/google/api/gax/paging/Page.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.paging; - -/** - * A Page object wraps an API list method response. - * - *

Callers can iterate over the Page object to get all elements returned in the page. The Page - * object also provides methods to retrieve additional pages using the page token, and to get the - * API request and response objects. - */ -public interface Page { - /** Returns true if there are more pages that can be retrieved from the API. */ - boolean hasNextPage(); - - /** - * Returns the next page token from the response, or an empty string if there are no more pages. - */ - String getNextPageToken(); - - /** - * Retrieves the next Page object using the next page token, or {@code null} if there are no more - * pages. The hasNextPage() method can be used to check if a Page object is available. - */ - Page getNextPage(); - - /** - * Returns an iterable that traverses all of the elements of the underlying data source. The data - * is fetched lazily page by page, where each page may contain multiple elements. A new page is - * fetched whenever the elements of any particular page are exhausted. - */ - Iterable iterateAll(); - - /** Returns an iterable over the elements in this page. */ - Iterable getValues(); -} diff --git a/gax/src/main/java/com/google/api/gax/paging/PagedListResponse.java b/gax/src/main/java/com/google/api/gax/paging/PagedListResponse.java deleted file mode 100644 index 551808987..000000000 --- a/gax/src/main/java/com/google/api/gax/paging/PagedListResponse.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.paging; - -/** - * Response for paged results from a list API method - * - *

This class is used to access the results of a paged list API method. The management of page - * tokens can be handled automatically, or by the caller. Results can be accessed on a per-element - * or per-page basis. - */ -public interface PagedListResponse { - /** - * Returns an iterable that traverses all of the elements of the underlying data source. The data - * is fetched lazily page by page, where each page may contain multiple elements. A new page is - * fetched whenever the elements of any particular page are exhausted. This method is not - * thread-safe. - */ - Iterable iterateAll(); - - /** Returns the current page of results. Note: This method is not thread-safe. */ - Page getPage(); - - /** - * Return an iterable over all Page objects. Page objects are retrieved lazily via API calls until - * all elements have been retrieved. - */ - Iterable> iteratePages(); - - /** - * Returns the token for the next page or an empty string if no more results. Note: This method is - * not thread-safe. - */ - String getNextPageToken(); - - /** - * Returns a collection of elements with a fixed size set by the collectionSize parameter. The - * collection will only contain fewer than collectionSize elements if there are no more pages to - * be retrieved from the server. - * - *

NOTE: it is an error to call this method if the optional parameter 'page_size' has not been - * set in the original API call. It is also an error if the collectionSize parameter is less than - * the page_size. - */ - FixedSizeCollection expandToFixedSizeCollection(int collectionSize); - - /** - * Returns an iterable over fixed size collections of results. The collections are retrieved - * lazily from the underlying API. - * - *

Each collection will have collectionSize elements, with the exception of the final - * collection which may contain fewer elements. - * - *

NOTE: it is an error to call this method if the optional parameter 'page_size' has not been - * set in the original API call. It is also an error if the collectionSize parameter is less than - * the page_size. - */ - Iterable> iterateFixedSizeCollections( - int collectionSize); -} diff --git a/gax/src/main/java/com/google/api/gax/paging/Pages.java b/gax/src/main/java/com/google/api/gax/paging/Pages.java deleted file mode 100644 index fcd8a5932..000000000 --- a/gax/src/main/java/com/google/api/gax/paging/Pages.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.paging; - -import java.util.Collections; - -/** Utility class for {@link Page}s. */ -public class Pages { - private Pages() {} - - /** Returns a page that contains nothing. */ - public static Page empty() { - return new Page() { - @Override - public boolean hasNextPage() { - return false; - } - - @Override - public String getNextPageToken() { - return ""; - } - - @Override - public Page getNextPage() { - return null; - } - - @Override - public Iterable iterateAll() { - return Collections.emptyList(); - } - - @Override - public Iterable getValues() { - return Collections.emptyList(); - } - }; - } -} diff --git a/gax/src/main/java/com/google/api/gax/retrying/BasicResultRetryAlgorithm.java b/gax/src/main/java/com/google/api/gax/retrying/BasicResultRetryAlgorithm.java deleted file mode 100644 index b33f131be..000000000 --- a/gax/src/main/java/com/google/api/gax/retrying/BasicResultRetryAlgorithm.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -import java.util.concurrent.CancellationException; - -/** - * A basic implementation of {@link ResultRetryAlgorithm}. Using this implementation would mean that - * all exceptions should be retried, all responses should be accepted (including {@code null}) and - * no retrying process should ever be canceled. - * - * @param attempt response type - */ -public class BasicResultRetryAlgorithm - implements ResultRetryAlgorithmWithContext { - /** - * Always returns null, indicating that this algorithm does not provide any specific settings for - * the next attempt. - */ - @Override - public TimedAttemptSettings createNextAttempt( - Throwable previousThrowable, - ResponseT previousResponse, - TimedAttemptSettings previousSettings) { - return null; - } - - /** - * Always returns null, indicating that this algorithm does not provide any specific settings for - * the next attempt. - */ - @Override - public TimedAttemptSettings createNextAttempt( - RetryingContext context, - Throwable previousThrowable, - ResponseT previousResponse, - TimedAttemptSettings previousSettings) { - return createNextAttempt(previousThrowable, previousResponse, previousSettings); - } - - /** - * Returns {@code true} if an exception was thrown ({@code previousThrowable != null}), {@code - * false} otherwise. - */ - @Override - public boolean shouldRetry(Throwable previousThrowable, ResponseT previousResponse) { - return previousThrowable != null; - } - - /** - * Returns {@code true} if an exception was thrown ({@code previousThrowable != null}), {@code - * false} otherwise. - */ - @Override - public boolean shouldRetry( - RetryingContext context, Throwable previousThrowable, ResponseT previousResponse) - throws CancellationException { - return shouldRetry(previousThrowable, previousResponse); - } -} diff --git a/gax/src/main/java/com/google/api/gax/retrying/BasicRetryingFuture.java b/gax/src/main/java/com/google/api/gax/retrying/BasicRetryingFuture.java deleted file mode 100644 index de7b5b5ac..000000000 --- a/gax/src/main/java/com/google/api/gax/retrying/BasicRetryingFuture.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.gax.retrying; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.api.gax.tracing.ApiTracer; -import com.google.common.util.concurrent.AbstractFuture; -import com.google.common.util.concurrent.MoreExecutors; -import java.util.concurrent.Callable; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.RejectedExecutionException; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * For internal use only. - * - *

Basic implementation of {@link RetryingFuture} interface. On its own, suitable for usage in - * 'busy loop' retry implementations. Can be used as the basis for more advanced implementations. - * - *

This class is thread-safe. - */ -class BasicRetryingFuture extends AbstractFuture - implements RetryingFuture { - - final Object lock = new Object(); - - private final Callable callable; - - private final RetryAlgorithm retryAlgorithm; - private final RetryingContext retryingContext; - - private volatile TimedAttemptSettings attemptSettings; - - private volatile ApiFuture latestCompletedAttemptResult; - private volatile ApiFuture attemptResult; - - private static final Logger LOG = Logger.getLogger(BasicRetryingFuture.class.getName()); - - BasicRetryingFuture( - Callable callable, - RetryAlgorithm retryAlgorithm, - RetryingContext context) { - this.callable = checkNotNull(callable); - this.retryAlgorithm = checkNotNull(retryAlgorithm); - this.retryingContext = checkNotNull(context); - - this.attemptSettings = retryAlgorithm.createFirstAttempt(context); - - // A micro crime, letting "this" reference to escape from constructor before initialization is - // completed (via internal non-static class CompletionListener). But it is guaranteed to be ok, - // since listener is guaranteed to be called only after this future is - // completed and this future is guaranteed to be completed only after it is initialized. Also - // since "super" is called explicitly here there are no unexpected overrides of addListener - // here. - super.addListener(new CompletionListener(), MoreExecutors.directExecutor()); - } - - @Override - public void setAttemptFuture(ApiFuture attemptFuture) { - try { - if (isDone()) { - return; - } - ResponseT response = attemptFuture.get(); - handleAttempt(null, response); - } catch (ExecutionException e) { - handleAttempt(e.getCause(), null); - } catch (Throwable e) { - handleAttempt(e, null); - } - } - - @Override - public Callable getCallable() { - return callable; - } - - @Override - public TimedAttemptSettings getAttemptSettings() { - synchronized (lock) { - return attemptSettings; - } - } - - @Override - public ApiFuture peekAttemptResult() { - synchronized (lock) { - return latestCompletedAttemptResult; - } - } - - // Lazily initializes attempt result. This allows to prevent overhead of relatively - // heavy (and in most cases redundant) settable future instantiation on each attempt, plus reduces - // possibility of callback chaining going into an infinite loop in case of buggy external - // callbacks implementation. - @Override - public ApiFuture getAttemptResult() { - synchronized (lock) { - if (attemptResult == null) { - attemptResult = new NonCancellableFuture<>(); - } - return attemptResult; - } - } - - // Called in the beginning of handleAttempt() and completion listeners to cleanup all attempt - // service data (callbacks and stuff) - void clearAttemptServiceData() { - // no-op for the basic implementation - } - - // "super." is used here to avoid infinite loops of callback chains - void handleAttempt(Throwable throwable, ResponseT response) { - ApiTracer tracer = retryingContext.getTracer(); - - synchronized (lock) { - try { - clearAttemptServiceData(); - if (throwable instanceof CancellationException) { - // An attempt triggered cancellation. - // In almost all cases, the operation caller caused the attempt to trigger the - // cancellation by invoking cancel() on the CallbackChainRetryingFuture, which cancelled - // the current attempt. - // In a theoretical scenario, the attempt callable might've thrown the exception on its - // own volition. However it's currently impossible to disambiguate the 2 scenarios. - tracer.attemptCancelled(); - super.cancel(false); - } else if (throwable instanceof RejectedExecutionException) { - // external executor cannot continue retrying - tracer.attemptPermanentFailure(throwable); - super.setException(throwable); - } - if (isDone()) { - return; - } - - TimedAttemptSettings nextAttemptSettings = - retryAlgorithm.createNextAttempt(retryingContext, throwable, response, attemptSettings); - boolean shouldRetry = - retryAlgorithm.shouldRetry(retryingContext, throwable, response, nextAttemptSettings); - if (shouldRetry) { - // Log retry info - if (LOG.isLoggable(Level.FINEST)) { - LOG.log( - Level.FINEST, - "Retrying with:\n{0}\n{1}\n{2}\n{3}", - new Object[] { - "enclosingMethod: " - + (callable.getClass().getEnclosingMethod() != null - ? callable.getClass().getEnclosingMethod().getName() - : ""), - "attemptCount: " + attemptSettings.getAttemptCount(), - "delay: " + attemptSettings.getRetryDelay(), - "retriableException: " + throwable - }); - } - tracer.attemptFailed(throwable, nextAttemptSettings.getRandomizedRetryDelay()); - attemptSettings = nextAttemptSettings; - setAttemptResult(throwable, response, true); - // a new attempt will be (must be) scheduled by an external executor - } else if (throwable != null) { - if (retryAlgorithm.shouldRetryBasedOnResult(retryingContext, throwable, response)) { - tracer.attemptFailedRetriesExhausted(throwable); - } else { - tracer.attemptPermanentFailure(throwable); - } - super.setException(throwable); - } else { - tracer.attemptSucceeded(); - super.set(response); - } - } catch (CancellationException e) { - // A retry algorithm triggered cancellation. - tracer.attemptFailedRetriesExhausted(e); - super.cancel(false); - } catch (Exception e) { - // Should never happen, but still possible in case of buggy retry algorithm implementation. - // Any bugs/exceptions (except CancellationException) in retry algorithms immediately - // terminate retrying future and set the result to the thrown exception. - tracer.attemptPermanentFailure(e); - super.setException(e); - } - } - } - - // Sets attempt result futures. Note the "attempt result future" and "attempt future" are not same - // things because there are more attempt futures than attempt result futures. - // See AttemptCallable.call() for an example of such condition. - // - // The assignments order in this method is crucial. Wrong ordering may lead to infinite - // loops in callback chains. - // - // If this is not the last attempt this method sets attemptResult to null, so the next - // getAttemptResult() call will return a new future, tracking the new attempt. Otherwise - // attemptResult is set to the same result as the one returned by peekAttemptResult(), indicating - // that the ultimate unmodifiable result of the whole future was reached. - private void setAttemptResult(Throwable throwable, ResponseT response, boolean shouldRetry) { - ApiFuture prevAttemptResult = attemptResult; - try { - if (throwable instanceof CancellationException) { - NonCancellableFuture future = new NonCancellableFuture<>(); - future.cancelPrivately(); - latestCompletedAttemptResult = future; - attemptResult = shouldRetry ? null : latestCompletedAttemptResult; - if (prevAttemptResult instanceof NonCancellableFuture) { - ((NonCancellableFuture) prevAttemptResult).cancelPrivately(); - } - } else if (throwable != null) { - latestCompletedAttemptResult = ApiFutures.immediateFailedFuture(throwable); - attemptResult = shouldRetry ? null : latestCompletedAttemptResult; - if (prevAttemptResult instanceof NonCancellableFuture) { - ((NonCancellableFuture) prevAttemptResult).setExceptionPrivately(throwable); - } - } else { - latestCompletedAttemptResult = ApiFutures.immediateFuture(response); - attemptResult = shouldRetry ? null : latestCompletedAttemptResult; - if (prevAttemptResult instanceof NonCancellableFuture) { - ((NonCancellableFuture) prevAttemptResult).setPrivately(response); - } - } - } catch (Exception e) { - // Usually should not happen but is still possible, for example if one of the attempt result - // callbacks throws an exception. An example of such condition is the OperationFuture - // which uses ApiFutures.transform(), which actually assign callbacks to the attempt result - // futures, and those can fail, for example if metadata class is a wrong one. - // - // The exception is swallowed to avoid buggy callback implementations breaking retrying future - // execution. In case if a callback is executed in a separate thread executor (the recommended - // way) the exception will be thrown in a separate thread and will not be swallowed by this - // catch block anyways. - } - } - - private class CompletionListener implements Runnable { - @Override - public void run() { - synchronized (lock) { - try { - clearAttemptServiceData(); - ResponseT response = get(); - setAttemptResult(null, response, false); - } catch (ExecutionException e) { - setAttemptResult(e.getCause(), null, false); - } catch (Throwable e) { - setAttemptResult(e, null, false); - } - } - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/retrying/CallbackChainRetryingFuture.java b/gax/src/main/java/com/google/api/gax/retrying/CallbackChainRetryingFuture.java deleted file mode 100644 index f6714e23b..000000000 --- a/gax/src/main/java/com/google/api/gax/retrying/CallbackChainRetryingFuture.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.api.core.ApiFuture; -import com.google.common.util.concurrent.MoreExecutors; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; - -/** - * For internal use only. - * - *

Callback chaining implementation of {@link RetryingFuture} interface. Suitable for retry - * implementations, when each attempt is scheduled in a specific thread pool (i.e. each attempt may - * be executed by a different thread). - * - *

After each attempt, if it is determined as retriable by the retrying algorithm, this - * implementation schedules a new attempt using the provided retrying executor and assigns a - * callback to the new scheduled attempt (to examine it result in the future and either accept, - * reject or repeat the process again). - * - *

This class is thread-safe. - */ -class CallbackChainRetryingFuture extends BasicRetryingFuture { - private final ScheduledRetryingExecutor retryingExecutor; - private volatile AttemptCompletionListener attemptFutureCompletionListener; - - CallbackChainRetryingFuture( - Callable callable, - RetryAlgorithm retryAlgorithm, - ScheduledRetryingExecutor retryingExecutor, - RetryingContext context) { - super(callable, retryAlgorithm, context); - this.retryingExecutor = checkNotNull(retryingExecutor); - } - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - synchronized (lock) { - if (attemptFutureCompletionListener == null) { - // explicit retry future cancellation, most probably even before the first attempt started - return super.cancel(mayInterruptIfRunning); - } - // will result in attempt triggered cancellation of the whole future via callback chain - attemptFutureCompletionListener.attemptFuture.cancel(mayInterruptIfRunning); - return isCancelled(); - } - } - - @Override - public void setAttemptFuture(ApiFuture attemptFuture) { - if (isDone()) { - return; - } - synchronized (lock) { - if (isDone()) { - return; - } - attemptFutureCompletionListener = new AttemptCompletionListener(attemptFuture); - // Using direct addListener instead of ApiFutures.addCallback allows greatly reduce - // layering. Also listener is more suitable here (as we don't really need two methods - - // one for failure and one for success). - attemptFuture.addListener(attemptFutureCompletionListener, MoreExecutors.directExecutor()); - } - } - - @Override - void clearAttemptServiceData() { - synchronized (lock) { - attemptFutureCompletionListener = null; - } - } - - private class AttemptCompletionListener implements Runnable { - private final Future attemptFuture; - - AttemptCompletionListener(Future attemptFuture) { - this.attemptFuture = attemptFuture; - } - - @Override - public void run() { - try { - ResponseT response = attemptFuture.get(); - handle(null, response); - } catch (ExecutionException e) { - handle(e.getCause(), null); - } catch (Throwable e) { - handle(e, null); - } - } - - private void handle(Throwable t, ResponseT response) { - // Essential check, to ensure that we do not execute callback of an abandoned attempt. - // First before the lock, to increase performance and reduce chance of deadlocking - // (should never happen, but being extra cautious is appropriate here). - if (this != attemptFutureCompletionListener || isDone()) { - return; - } - synchronized (lock) { - // same check as before, now under lock - if (this != attemptFutureCompletionListener || isDone()) { - return; - } - handleAttempt(t, response); - if (!isDone()) { - ApiFuture attempt = retryingExecutor.submit(CallbackChainRetryingFuture.this); - setAttemptFuture(attempt); - } - } - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/retrying/DirectRetryingExecutor.java b/gax/src/main/java/com/google/api/gax/retrying/DirectRetryingExecutor.java deleted file mode 100644 index 54b7750ca..000000000 --- a/gax/src/main/java/com/google/api/gax/retrying/DirectRetryingExecutor.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import java.io.InterruptedIOException; -import java.nio.channels.ClosedByInterruptException; -import java.util.concurrent.Callable; -import org.threeten.bp.Duration; - -/** - * The retry executor which executes attempts in the current thread, potentially causing the current - * thread to sleep for the specified amount of time before execution. - * - *

This class is thread-safe. - * - * @param response type - */ -public class DirectRetryingExecutor implements RetryingExecutorWithContext { - - private final RetryAlgorithm retryAlgorithm; - - /** - * Creates a new direct retrying executor instance, which will be using {@code retryAlgorithm} to - * determine retrying strategy. - * - * @param retryAlgorithm retry algorithm to use for attempts execution - * @throws NullPointerException if {@code retryAlgorithm} is null - */ - public DirectRetryingExecutor(RetryAlgorithm retryAlgorithm) { - this.retryAlgorithm = checkNotNull(retryAlgorithm); - } - - /** - * Creates a {@link RetryingFuture}, which is a facade, returned to the client code to wait for - * any retriable operation to complete. The future is bounded to {@code this} executor instance. - * - * @param callable the actual callable, which should be executed in a retriable context - * @return retrying future facade - */ - @Override - public RetryingFuture createFuture(Callable callable) { - return createFuture(callable, NoopRetryingContext.create()); - } - - /** - * Creates a {@link RetryingFuture}, which is a facade, returned to the client code to wait for - * any retriable operation to complete. The future is bounded to {@code this} executor instance. - * - * @param callable the actual callable, which should be executed in a retriable context - * @return retrying future facade - */ - @Override - public RetryingFuture createFuture( - Callable callable, RetryingContext context) { - return new BasicRetryingFuture<>(callable, retryAlgorithm, context); - } - - /** - * Submits an attempt for execution in the current thread, causing the current thread to sleep for - * the specified by the {@link RetryingFuture#getAttemptSettings()} amount of time. As result, - * this method completes execution only after the specified {@code retryingFuture} completes. - * - * @param retryingFuture the future previously returned by {@link #createFuture(Callable, - * RetryingContext)} - * @return returns completed {@code retryingFuture} - */ - @Override - public ApiFuture submit(RetryingFuture retryingFuture) { - while (!retryingFuture.isDone()) { - try { - sleep(retryingFuture.getAttemptSettings().getRandomizedRetryDelay()); - ResponseT response = retryingFuture.getCallable().call(); - retryingFuture.setAttemptFuture(ApiFutures.immediateFuture(response)); - } catch (InterruptedException | InterruptedIOException | ClosedByInterruptException e) { - Thread.currentThread().interrupt(); - retryingFuture.setAttemptFuture(ApiFutures.immediateFailedFuture(e)); - } catch (Exception e) { - retryingFuture.setAttemptFuture(ApiFutures.immediateFailedFuture(e)); - } - } - return retryingFuture; - } - - /** - * This method simply calls {@link Thread#sleep(long)}. - * - * @param delay time to sleep - * @throws InterruptedException if any thread has interrupted the current thread - */ - protected void sleep(Duration delay) throws InterruptedException { - if (Duration.ZERO.compareTo(delay) < 0) { - Thread.sleep(delay.toMillis()); - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/retrying/ExponentialPollAlgorithm.java b/gax/src/main/java/com/google/api/gax/retrying/ExponentialPollAlgorithm.java deleted file mode 100644 index 5a68da1a5..000000000 --- a/gax/src/main/java/com/google/api/gax/retrying/ExponentialPollAlgorithm.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -import com.google.api.core.ApiClock; - -/** - * The timed poll algorithm which uses jittered exponential backoff factor for calculating the next - * poll execution time and throws {@link PollException} in case if total timeout or total number of - * attempts is reached. - * - *

This class is thread-safe. - */ -public class ExponentialPollAlgorithm extends ExponentialRetryAlgorithm { - /** - * Creates a new exponential poll algorithm instance. - * - * @param globalSettings global poll settings (attempt independent) - * @param clock clock to use for time-specific calculations - * @throws NullPointerException if either {@code globalSettings} or {@code clock} is null - */ - public ExponentialPollAlgorithm(RetrySettings globalSettings, ApiClock clock) { - super(globalSettings, clock); - } - - /** - * Returns {@code true} if another poll operation should be made or throws {@link PollException}, - * if either total timeout or total number of attempts is exceeded. - * - * @param nextAttemptSettings attempt settings, which will be used for the next attempt, if - * accepted - * @return {@code true} if more attempts should be made, never returns {@code false} (throws - * {@code PollException} instead) - * @throws PollException if no more attempts should be made - */ - @Override - public boolean shouldRetry(TimedAttemptSettings nextAttemptSettings) throws PollException { - if (super.shouldRetry(nextAttemptSettings)) { - return true; - } - throw new PollException( - "total timeout or maximum number of attempts exceeded; current settings: " - + nextAttemptSettings.getGlobalSettings()); - } -} diff --git a/gax/src/main/java/com/google/api/gax/retrying/ExponentialRetryAlgorithm.java b/gax/src/main/java/com/google/api/gax/retrying/ExponentialRetryAlgorithm.java deleted file mode 100644 index 26beb8f0b..000000000 --- a/gax/src/main/java/com/google/api/gax/retrying/ExponentialRetryAlgorithm.java +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.api.core.ApiClock; -import java.util.concurrent.ThreadLocalRandom; -import org.threeten.bp.Duration; - -/** - * The timed retry algorithm which uses jittered exponential backoff factor for calculating the next - * attempt execution time. - * - *

This class is thread-safe. - */ -public class ExponentialRetryAlgorithm implements TimedRetryAlgorithmWithContext { - - private final RetrySettings globalSettings; - private final ApiClock clock; - - /** - * Creates a new exponential retry algorithm instance. - * - * @param globalSettings global retry settings (attempt independent) - * @param clock clock to use for time-specific calculations - * @throws NullPointerException if either {@code globalSettings} or {@code clock} is null - */ - public ExponentialRetryAlgorithm(RetrySettings globalSettings, ApiClock clock) { - this.globalSettings = checkNotNull(globalSettings); - this.clock = checkNotNull(clock); - } - - /** - * Creates a first attempt {@link TimedAttemptSettings}. The first attempt is configured to be - * executed immediately. - * - * @return first attempt settings - */ - @Override - public TimedAttemptSettings createFirstAttempt() { - return TimedAttemptSettings.newBuilder() - .setGlobalSettings(globalSettings) - .setRetryDelay(Duration.ZERO) - .setRpcTimeout(globalSettings.getInitialRpcTimeout()) - .setRandomizedRetryDelay(Duration.ZERO) - .setAttemptCount(0) - .setOverallAttemptCount(0) - .setFirstAttemptStartTimeNanos(clock.nanoTime()) - .build(); - } - - /** - * Creates a first attempt {@link TimedAttemptSettings}. The first attempt is configured to be - * executed immediately. - * - * @param context a {@link RetryingContext} that can contain custom {@link RetrySettings} and - * retryable codes - * @return first attempt settings - */ - @Override - public TimedAttemptSettings createFirstAttempt(RetryingContext context) { - if (context.getRetrySettings() == null) { - return createFirstAttempt(); - } - - RetrySettings retrySettings = context.getRetrySettings(); - return TimedAttemptSettings.newBuilder() - // Use the given retrySettings rather than the settings this was created with. - // Attempts created using the TimedAttemptSettings built here will use these - // retrySettings, but a new call will not (unless overridden again). - .setGlobalSettings(retrySettings) - .setRpcTimeout(retrySettings.getInitialRpcTimeout()) - .setRetryDelay(Duration.ZERO) - .setRandomizedRetryDelay(Duration.ZERO) - .setAttemptCount(0) - .setOverallAttemptCount(0) - .setFirstAttemptStartTimeNanos(clock.nanoTime()) - .build(); - } - - /** - * Creates a next attempt {@link TimedAttemptSettings}. The implementation increments the current - * attempt count and uses randomized exponential backoff factor for calculating next attempt - * execution time. - * - * @param previousSettings previous attempt settings - * @return next attempt settings - */ - @Override - public TimedAttemptSettings createNextAttempt(TimedAttemptSettings previousSettings) { - RetrySettings settings = previousSettings.getGlobalSettings(); - - // The retry delay is determined as follows: - // attempt #0 - not used (initial attempt is always made immediately); - // attempt #1 - use initialRetryDelay; - // attempt #2+ - use the calculated value (i.e. the following if statement is true only - // if we are about to calculate the value for the upcoming 2nd+ attempt). - long newRetryDelay = settings.getInitialRetryDelay().toMillis(); - if (previousSettings.getAttemptCount() > 0) { - newRetryDelay = - (long) (settings.getRetryDelayMultiplier() * previousSettings.getRetryDelay().toMillis()); - newRetryDelay = Math.min(newRetryDelay, settings.getMaxRetryDelay().toMillis()); - } - Duration randomDelay = Duration.ofMillis(nextRandomLong(newRetryDelay)); - - // The rpc timeout is determined as follows: - // attempt #0 - use the initialRpcTimeout; - // attempt #1+ - use the calculated value, or the time remaining in totalTimeout if the - // calculated value would exceed the totalTimeout. - long newRpcTimeout = - (long) (settings.getRpcTimeoutMultiplier() * previousSettings.getRpcTimeout().toMillis()); - newRpcTimeout = Math.min(newRpcTimeout, settings.getMaxRpcTimeout().toMillis()); - - // The totalTimeout could be zero if a callable is only using maxAttempts to limit retries. - // If set, calculate time remaining in the totalTimeout since the start, taking into account the - // next attempt's delay, in order to truncate the RPC timeout should it exceed the totalTimeout. - if (!settings.getTotalTimeout().isZero()) { - Duration timeElapsed = - Duration.ofNanos(clock.nanoTime()) - .minus(Duration.ofNanos(previousSettings.getFirstAttemptStartTimeNanos())); - Duration timeLeft = settings.getTotalTimeout().minus(timeElapsed).minus(randomDelay); - - // If timeLeft at this point is < 0, the shouldRetry logic will prevent - // the attempt from being made as it would exceed the totalTimeout. A negative RPC timeout - // will result in a deadline in the past, which should will always fail prior to making a - // network call. - newRpcTimeout = Math.min(newRpcTimeout, timeLeft.toMillis()); - } - - return TimedAttemptSettings.newBuilder() - .setGlobalSettings(previousSettings.getGlobalSettings()) - .setRetryDelay(Duration.ofMillis(newRetryDelay)) - .setRpcTimeout(Duration.ofMillis(newRpcTimeout)) - .setRandomizedRetryDelay(randomDelay) - .setAttemptCount(previousSettings.getAttemptCount() + 1) - .setOverallAttemptCount(previousSettings.getOverallAttemptCount() + 1) - .setFirstAttemptStartTimeNanos(previousSettings.getFirstAttemptStartTimeNanos()) - .build(); - } - - /** - * Creates a next attempt {@link TimedAttemptSettings}. The implementation increments the current - * attempt count and uses randomized exponential backoff factor for calculating next attempt - * execution time. - * - * @param context a {@link RetryingContext} that can contain custom {@link RetrySettings} and - * retryable codes - * @param previousSettings previous attempt settings - * @return next attempt settings - */ - @Override - public TimedAttemptSettings createNextAttempt( - RetryingContext context, TimedAttemptSettings previousSettings) { - // The RetrySettings from the context are not used here, as they have already been set as the - // global settings during the creation of the initial attempt. - return createNextAttempt(previousSettings); - } - - /** - * Returns {@code true} if another attempt should be made, or {@code false} otherwise. - * - * @param nextAttemptSettings attempt settings, which will be used for the next attempt, if - * accepted - * @return {@code true} if {@code nextAttemptSettings} does not exceed either maxAttempts limit or - * totalTimeout limit, or {@code false} otherwise - */ - @Override - public boolean shouldRetry(TimedAttemptSettings nextAttemptSettings) { - RetrySettings globalSettings = nextAttemptSettings.getGlobalSettings(); - - int maxAttempts = globalSettings.getMaxAttempts(); - long totalTimeout = globalSettings.getTotalTimeout().toNanos(); - - // If total timeout and maxAttempts is not set then do not attempt retry. - if (totalTimeout == 0 && maxAttempts == 0) { - return false; - } - - long totalTimeSpentNanos = - clock.nanoTime() - - nextAttemptSettings.getFirstAttemptStartTimeNanos() - + nextAttemptSettings.getRandomizedRetryDelay().toNanos(); - - // If totalTimeout limit is defined, check that it hasn't been crossed. - // - // Note: if the potential time spent is exactly equal to the totalTimeout, - // the attempt will still be allowed. This might not be desired, but if we - // enforce it, it could have potentially negative side effects on LRO polling. - // Specifically, if a polling retry attempt is denied, the LRO is canceled, and - // if a polling retry attempt is denied because its delay would *reach* the - // totalTimeout, the LRO would be canceled prematurely. The problem here is that - // totalTimeout doubles as the polling threshold and also the time limit for an - // operation to finish. - if (totalTimeout > 0 && totalTimeSpentNanos > totalTimeout) { - return false; - } - - // If maxAttempts limit is defined, check that it hasn't been crossed - if (maxAttempts > 0 && nextAttemptSettings.getAttemptCount() >= maxAttempts) { - return false; - } - - // No limits crossed - return true; - } - - /** - * Returns {@code true} if another attempt should be made, or {@code false} otherwise. - * - * @param context a {@link RetryingContext} that can contain custom {@link RetrySettings} and - * retryable codes. Ignored by this implementation. - * @param nextAttemptSettings attempt settings, which will be used for the next attempt, if - * accepted - * @return {@code true} if {@code nextAttemptSettings} does not exceed either maxAttempts limit or - * totalTimeout limit, or {@code false} otherwise - */ - @Override - public boolean shouldRetry(RetryingContext context, TimedAttemptSettings nextAttemptSettings) { - // The RetrySettings from the context are not used here, as they have already been set as the - // global settings during the creation of the initial attempt. - return shouldRetry(nextAttemptSettings); - } - - // Injecting Random is not possible here, as Random does not provide nextLong(long bound) method - protected long nextRandomLong(long bound) { - return bound > 0 && globalSettings.isJittered() // Jitter check needed for testing purposes. - ? ThreadLocalRandom.current().nextLong(bound) - : bound; - } -} diff --git a/gax/src/main/java/com/google/api/gax/retrying/NonCancellableFuture.java b/gax/src/main/java/com/google/api/gax/retrying/NonCancellableFuture.java deleted file mode 100644 index 19e3587a4..000000000 --- a/gax/src/main/java/com/google/api/gax/retrying/NonCancellableFuture.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -import com.google.api.core.AbstractApiFuture; -import com.google.api.core.InternalApi; - -/** - * A future which cannot be cancelled from the external package. - * - *

For internal use, public for technical reasons. - * - * @param future response type - */ -@InternalApi -public final class NonCancellableFuture extends AbstractApiFuture { - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - return false; - } - - void cancelPrivately() { - super.cancel(false); - } - - boolean setPrivately(ResponseT value) { - return super.set(value); - } - - boolean setExceptionPrivately(Throwable throwable) { - return super.setException(throwable); - } -} diff --git a/gax/src/main/java/com/google/api/gax/retrying/NoopRetryingContext.java b/gax/src/main/java/com/google/api/gax/retrying/NoopRetryingContext.java deleted file mode 100644 index 840918ed3..000000000 --- a/gax/src/main/java/com/google/api/gax/retrying/NoopRetryingContext.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -// TODO(igorbernstein2): Remove this class once RetryingExecutor#createFuture(Callable) is -// deprecated and removed. - -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.api.gax.tracing.ApiTracer; -import com.google.api.gax.tracing.BaseApiTracer; -import java.util.Set; -import javax.annotation.Nonnull; - -/** - * Backwards compatibility class to aid in transition to adding operation state to {@link - * RetryingFuture} implementations. - */ -class NoopRetryingContext implements RetryingContext { - public static RetryingContext create() { - return new NoopRetryingContext(); - } - - /** {@inheritDoc} */ - @Nonnull - @Override - public ApiTracer getTracer() { - return BaseApiTracer.getInstance(); - } - - @Override - public RetrySettings getRetrySettings() { - return null; - } - - @Override - public Set getRetryableCodes() { - return null; - } -} diff --git a/gax/src/main/java/com/google/api/gax/retrying/PollException.java b/gax/src/main/java/com/google/api/gax/retrying/PollException.java deleted file mode 100644 index 4534e100c..000000000 --- a/gax/src/main/java/com/google/api/gax/retrying/PollException.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -/** - * {@code PollException} is thrown when polling algorithm exceeds total timeout or total number of - * attempts. - */ -public class PollException extends RuntimeException { - - private static final long serialVersionUID = -3666617975087303999L; - - /** Constructs a {@code PollException} with no specified detail message. */ - public PollException() { - super(); - } - - /** - * Constructs a new poll timeout exception with the specified detail message. - * - * @param message the detail message - */ - public PollException(String message) { - super(message); - } -} diff --git a/gax/src/main/java/com/google/api/gax/retrying/ResultRetryAlgorithm.java b/gax/src/main/java/com/google/api/gax/retrying/ResultRetryAlgorithm.java deleted file mode 100644 index 53363f37a..000000000 --- a/gax/src/main/java/com/google/api/gax/retrying/ResultRetryAlgorithm.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -import java.util.concurrent.CancellationException; - -/** - * Same as {@link ResultRetryAlgorithmWithContext}, but without methods that accept a {@link - * RetryingContext}. Use {@link ResultRetryAlgorithmWithContext} instead of this interface when - * possible. - */ -public interface ResultRetryAlgorithm { - /** - * Same as {@link ResultRetryAlgorithmWithContext#createNextAttempt(RetryingContext, Throwable, - * Object, TimedAttemptSettings)}, but without a {@link RetryingContext}. - * - *

Use {@link ResultRetryAlgorithmWithContext#createNextAttempt(RetryingContext, Throwable, - * Object, TimedAttemptSettings)} instead of this method when possible. - */ - TimedAttemptSettings createNextAttempt( - Throwable prevThrowable, ResponseT prevResponse, TimedAttemptSettings prevSettings); - - /** - * Same as {@link ResultRetryAlgorithmWithContext#shouldRetry(Throwable, Object)}, but without a - * {@link RetryingContext}. - * - *

Use {@link ResultRetryAlgorithmWithContext#shouldRetry(RetryingContext, Throwable, Object)} - * instead of this method when possible. - */ - boolean shouldRetry(Throwable prevThrowable, ResponseT prevResponse) throws CancellationException; -} diff --git a/gax/src/main/java/com/google/api/gax/retrying/ResultRetryAlgorithmWithContext.java b/gax/src/main/java/com/google/api/gax/retrying/ResultRetryAlgorithmWithContext.java deleted file mode 100644 index 2a347b13a..000000000 --- a/gax/src/main/java/com/google/api/gax/retrying/ResultRetryAlgorithmWithContext.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -import java.util.concurrent.CancellationException; - -/** - * A result retry algorithm is responsible for the following operations (based on the response - * returned by the previous attempt or on the thrown exception): - * - *

    - *
  1. Accepting a task for retry so another attempt will be made. - *
  2. Canceling retrying process so the related {@link java.util.concurrent.Future} will be - * canceled. - *
  3. Creating {@link TimedAttemptSettings} for each subsequent retry attempt. - *
- * - * Implementations of this interface receive a {@link RetryingContext} that can contain specific - * {@link RetrySettings} and retryable codes that should be used to determine the retry behavior. - * - *

Implementations of this interface must be thread-safe. - * - * @param response type - */ -public interface ResultRetryAlgorithmWithContext - extends ResultRetryAlgorithm { - - /** - * Creates a next attempt {@link TimedAttemptSettings}. - * - * @param context the retrying context of this invocation that can be used to determine the - * settings for the next attempt. - * @param previousThrowable exception thrown by the previous attempt ({@code null}, if none) - * @param previousResponse response returned by the previous attempt - * @param previousSettings previous attempt settings - */ - TimedAttemptSettings createNextAttempt( - RetryingContext context, - Throwable previousThrowable, - ResponseT previousResponse, - TimedAttemptSettings previousSettings); - - /** - * Returns {@code true} if another attempt should be made, or {@code false} otherwise. - * - * @param context the retrying context of this invocation that can be used to determine whether - * the call should be retried. - * @param previousThrowable exception thrown by the previous attempt ({@code null}, if none) - * @param previousResponse response returned by the previous attempt. - */ - boolean shouldRetry( - RetryingContext context, Throwable previousThrowable, ResponseT previousResponse) - throws CancellationException; -} diff --git a/gax/src/main/java/com/google/api/gax/retrying/RetryAlgorithm.java b/gax/src/main/java/com/google/api/gax/retrying/RetryAlgorithm.java deleted file mode 100644 index 16d60d148..000000000 --- a/gax/src/main/java/com/google/api/gax/retrying/RetryAlgorithm.java +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.api.core.BetaApi; -import java.util.concurrent.CancellationException; - -/** - * The retry algorithm, which makes decision based either on the thrown exception or the returned - * response, and the execution time settings of the previous attempt. - * - *

This class is thread-safe. - * - * @param response type - */ -public class RetryAlgorithm { - private final ResultRetryAlgorithm resultAlgorithm; - private final TimedRetryAlgorithm timedAlgorithm; - private final ResultRetryAlgorithmWithContext resultAlgorithmWithContext; - private final TimedRetryAlgorithmWithContext timedAlgorithmWithContext; - - /** - * Creates a new retry algorithm instance, which uses thrown exception or returned response and - * timed algorithms to make a decision. The result algorithm has higher priority than the timed - * algorithm. - * - *

Instances that are created using this constructor will ignore the {@link RetryingContext} - * that is passed in to the retrying methods. Use {@link - * #RetryAlgorithm(ResultRetryAlgorithmWithContext, TimedRetryAlgorithmWithContext)} to create an - * instance that will respect the {@link RetryingContext}. - * - * @param resultAlgorithm result algorithm to use - * @param timedAlgorithm timed algorithm to use - * @deprecated use {@link RetryAlgorithm#RetryAlgorithm(ResultRetryAlgorithmWithContext, - * TimedRetryAlgorithmWithContext)} instead - */ - @Deprecated - public RetryAlgorithm( - ResultRetryAlgorithm resultAlgorithm, TimedRetryAlgorithm timedAlgorithm) { - this.resultAlgorithm = checkNotNull(resultAlgorithm); - this.timedAlgorithm = checkNotNull(timedAlgorithm); - this.resultAlgorithmWithContext = null; - this.timedAlgorithmWithContext = null; - } - - /** - * Creates a new retry algorithm instance, which uses thrown exception or returned response and - * timed algorithms to make a decision. The result algorithm has higher priority than the timed - * algorithm. - * - * @param resultAlgorithm result algorithm to use - * @param timedAlgorithm timed algorithm to use - */ - public RetryAlgorithm( - ResultRetryAlgorithmWithContext resultAlgorithm, - TimedRetryAlgorithmWithContext timedAlgorithm) { - this.resultAlgorithm = null; - this.timedAlgorithm = null; - this.resultAlgorithmWithContext = checkNotNull(resultAlgorithm); - this.timedAlgorithmWithContext = checkNotNull(timedAlgorithm); - } - - /** - * Creates a first attempt {@link TimedAttemptSettings}. - * - * @return first attempt settings - * @deprecated use {@link #createFirstAttempt(RetryingContext)} instead - */ - @Deprecated - public TimedAttemptSettings createFirstAttempt() { - return createFirstAttempt(null); - } - - /** - * Creates a first attempt {@link TimedAttemptSettings}. - * - * @param context the {@link RetryingContext} that can be used to get the initial {@link - * RetrySettings} - * @return first attempt settings - */ - public TimedAttemptSettings createFirstAttempt(RetryingContext context) { - if (timedAlgorithmWithContext != null && context != null) { - return timedAlgorithmWithContext.createFirstAttempt(context); - } - return getTimedAlgorithm().createFirstAttempt(); - } - - /** - * Creates a next attempt {@link TimedAttemptSettings}. This method will return first non-null - * value, returned by either result or timed retry algorithms in that particular order. - * - * @param previousThrowable exception thrown by the previous attempt or null if a result was - * returned instead - * @param previousResponse response returned by the previous attempt or null if an exception was - * thrown instead - * @param previousSettings previous attempt settings - * @return next attempt settings, can be {@code null}, if no there should be no new attempt - * @deprecated use {@link #createNextAttempt(RetryingContext, Throwable, Object, - * TimedAttemptSettings)} instead - */ - @Deprecated - public TimedAttemptSettings createNextAttempt( - Throwable previousThrowable, - ResponseT previousResponse, - TimedAttemptSettings previousSettings) { - return createNextAttempt(null, previousThrowable, previousResponse, previousSettings); - } - - /** - * Creates a next attempt {@link TimedAttemptSettings}. This method will return first non-null - * value, returned by either result or timed retry algorithms in that particular order. - * - * @param context the {@link RetryingContext} that can be used to determine the {@link - * RetrySettings} for the next attempt - * @param previousThrowable exception thrown by the previous attempt or null if a result was - * returned instead - * @param previousResponse response returned by the previous attempt or null if an exception was - * thrown instead - * @param previousSettings previous attempt settings - * @return next attempt settings, can be {@code null}, if there should be no new attempt - */ - public TimedAttemptSettings createNextAttempt( - RetryingContext context, - Throwable previousThrowable, - ResponseT previousResponse, - TimedAttemptSettings previousSettings) { - // a small optimization that avoids calling relatively heavy methods - // like timedAlgorithm.createNextAttempt(), when it is not necessary. - if (!shouldRetryBasedOnResult(context, previousThrowable, previousResponse)) { - return null; - } - - TimedAttemptSettings newSettings = - createNextAttemptBasedOnResult( - context, previousThrowable, previousResponse, previousSettings); - if (newSettings == null) { - newSettings = createNextAttemptBasedOnTiming(context, previousSettings); - } - return newSettings; - } - - private TimedAttemptSettings createNextAttemptBasedOnResult( - RetryingContext context, - Throwable previousThrowable, - ResponseT previousResponse, - TimedAttemptSettings previousSettings) { - if (resultAlgorithmWithContext != null && context != null) { - return resultAlgorithmWithContext.createNextAttempt( - context, previousThrowable, previousResponse, previousSettings); - } - return getResultAlgorithm() - .createNextAttempt(previousThrowable, previousResponse, previousSettings); - } - - private TimedAttemptSettings createNextAttemptBasedOnTiming( - RetryingContext context, TimedAttemptSettings previousSettings) { - if (timedAlgorithmWithContext != null && context != null) { - return timedAlgorithmWithContext.createNextAttempt(context, previousSettings); - } - return getTimedAlgorithm().createNextAttempt(previousSettings); - } - - /** - * Returns {@code true} if another attempt should be made, or {@code false} otherwise. - * - * @param previousThrowable exception thrown by the previous attempt or null if a result was - * returned instead - * @param previousResponse response returned by the previous attempt or null if an exception was - * thrown instead - * @param nextAttemptSettings attempt settings, which will be used for the next attempt, if - * accepted - * @throws CancellationException if the retrying process should be canceled - * @return {@code true} if another attempt should be made, or {@code false} otherwise - * @deprecated use {@link #shouldRetry(RetryingContext, Throwable, Object, TimedAttemptSettings)} - * instead - */ - @Deprecated - public boolean shouldRetry( - Throwable previousThrowable, - ResponseT previousResponse, - TimedAttemptSettings nextAttemptSettings) - throws CancellationException { - return shouldRetry(null, previousThrowable, previousResponse, nextAttemptSettings); - } - - /** - * Returns {@code true} if another attempt should be made, or {@code false} otherwise. - * - * @param context the {@link RetryingContext} that can be used to determine whether another - * attempt should be made - * @param previousThrowable exception thrown by the previous attempt or null if a result was - * returned instead - * @param previousResponse response returned by the previous attempt or null if an exception was - * thrown instead - * @param nextAttemptSettings attempt settings, which will be used for the next attempt, if - * accepted - * @throws CancellationException if the retrying process should be cancelled - * @return {@code true} if another attempt should be made, or {@code false} otherwise - */ - public boolean shouldRetry( - RetryingContext context, - Throwable previousThrowable, - ResponseT previousResponse, - TimedAttemptSettings nextAttemptSettings) - throws CancellationException { - return shouldRetryBasedOnResult(context, previousThrowable, previousResponse) - && shouldRetryBasedOnTiming(context, nextAttemptSettings); - } - - boolean shouldRetryBasedOnResult( - RetryingContext context, Throwable previousThrowable, ResponseT previousResponse) { - if (resultAlgorithmWithContext != null && context != null) { - return resultAlgorithmWithContext.shouldRetry(context, previousThrowable, previousResponse); - } - return getResultAlgorithm().shouldRetry(previousThrowable, previousResponse); - } - - private boolean shouldRetryBasedOnTiming( - RetryingContext context, TimedAttemptSettings nextAttemptSettings) { - if (nextAttemptSettings == null) { - return false; - } - if (timedAlgorithmWithContext != null && context != null) { - return timedAlgorithmWithContext.shouldRetry(context, nextAttemptSettings); - } - return getTimedAlgorithm().shouldRetry(nextAttemptSettings); - } - - @BetaApi("Surface for inspecting the a RetryAlgorithm is not yet stable") - public ResultRetryAlgorithm getResultAlgorithm() { - return resultAlgorithmWithContext != null ? resultAlgorithmWithContext : resultAlgorithm; - } - - @BetaApi("Surface for inspecting the a RetryAlgorithm is not yet stable") - public TimedRetryAlgorithm getTimedAlgorithm() { - return timedAlgorithmWithContext != null ? timedAlgorithmWithContext : timedAlgorithm; - } -} diff --git a/gax/src/main/java/com/google/api/gax/retrying/RetrySettings.java b/gax/src/main/java/com/google/api/gax/retrying/RetrySettings.java deleted file mode 100644 index f5722f1ae..000000000 --- a/gax/src/main/java/com/google/api/gax/retrying/RetrySettings.java +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -import com.google.api.core.BetaApi; -import com.google.auto.value.AutoValue; -import com.google.common.annotations.VisibleForTesting; -import java.io.Serializable; -import org.threeten.bp.Duration; - -/** - * Holds the parameters for retry or poll logic with jitter, timeout and exponential - * backoff. Actual implementation of the logic is elsewhere. - * - *

The intent of these settings is to be used with a call to a remote server, which could either - * fail (and return an error code) or not respond (and cause a timeout). When there is a failure or - * timeout, the logic should keep trying until the total timeout has passed. - * - *

The "total timeout" and "max attempts" settings have ultimate control over how long the logic - * should keep trying the remote call until it gives up completely. The remote call will be retried - * until one of those thresholds is crossed. To avoid unbounded rpc calls, it is required to - * configure one of those settings. If both are 0, then retries will be disabled. The other settings - * are considered more advanced. - * - *

Retry delay and timeout start at specific values, and are tracked separately from each other. - * The very first call (before any retries) will use the initial timeout. - * - *

If the last remote call is a failure, then the retrier will wait for the current retry delay - * before attempting another call, and then the retry delay will be multiplied by the retry delay - * multiplier for the next failure. The timeout will not be affected, except in the case where the - * timeout would result in a deadline past the total timeout; in that circumstance, a new timeout - * value is computed which will terminate the call when the total time is up. - * - *

If the last remote call is a timeout, then the retrier will compute a new timeout and make - * another call. The new timeout is computed by multiplying the current timeout by the timeout - * multiplier, but if that results in a deadline after the total timeout, then a new timeout value - * is computed which will terminate the call when the total time is up. - * - *

Server streaming RPCs interpret RPC timeouts a bit differently. For server streaming RPCs, the - * RPC timeout gets converted into a wait timeout {@link - * com.google.api.gax.rpc.ApiCallContext#withStreamWaitTimeout(Duration)}. - */ -@AutoValue -public abstract class RetrySettings implements Serializable { - - private static final long serialVersionUID = 8258475264439710899L; - - /** - * TotalTimeout has ultimate control over how long the logic should keep trying the remote call - * until it gives up completely. The higher the total timeout, the more retries can be attempted. - * The default value is {@code Duration.ZERO}. - */ - public abstract Duration getTotalTimeout(); - - /** - * InitialRetryDelay controls the delay before the first retry. Subsequent retries will use this - * value adjusted according to the RetryDelayMultiplier. The default value is {@code - * Duration.ZERO}. - */ - public abstract Duration getInitialRetryDelay(); - - /** - * RetryDelayMultiplier controls the change in retry delay. The retry delay of the previous call - * is multiplied by the RetryDelayMultiplier to calculate the retry delay for the next call. The - * default value is {@code 1.0}. - */ - public abstract double getRetryDelayMultiplier(); - - /** - * MaxRetryDelay puts a limit on the value of the retry delay, so that the RetryDelayMultiplier - * can't increase the retry delay higher than this amount. The default value is {@code - * Duration.ZERO}. - */ - public abstract Duration getMaxRetryDelay(); - - /** - * MaxAttempts defines the maximum number of attempts to perform. The default value is {@code 0}. - * If this value is greater than 0, and the number of attempts reaches this limit, the logic will - * give up retrying even if the total retry time is still lower than TotalTimeout. - */ - public abstract int getMaxAttempts(); - - /** - * Jitter determines if the delay time should be randomized. In most cases, if jitter is set to - * {@code true} the actual delay time is calculated in the following way: - * - *

{@code actualDelay = rand_between(0, min(maxRetryDelay, delay))}
- * - * The default value is {@code true}. - * - * @deprecated Retries always jitter. - */ - @Deprecated - @VisibleForTesting - public abstract boolean isJittered(); - - /** - * InitialRpcTimeout controls the timeout for the initial RPC. Subsequent calls will use this - * value adjusted according to the RpcTimeoutMultiplier. The default value is {@code - * Duration.ZERO}. - */ - public abstract Duration getInitialRpcTimeout(); - - /** - * RpcTimeoutMultiplier controls the change in RPC timeout. The timeout of the previous call is - * multiplied by the RpcTimeoutMultiplier to calculate the timeout for the next call. The default - * value is {@code 1.0}. - */ - public abstract double getRpcTimeoutMultiplier(); - - /** - * MaxRpcTimeout puts a limit on the value of the RPC timeout, so that the RpcTimeoutMultiplier - * can't increase the RPC timeout higher than this amount. The default value is {@code - * Duration.ZERO}. - */ - public abstract Duration getMaxRpcTimeout(); - - public static Builder newBuilder() { - return new AutoValue_RetrySettings.Builder() - .setTotalTimeout(Duration.ZERO) - .setInitialRetryDelay(Duration.ZERO) - .setRetryDelayMultiplier(1.0) - .setMaxRetryDelay(Duration.ZERO) - .setMaxAttempts(0) - .setJittered(true) - .setInitialRpcTimeout(Duration.ZERO) - .setRpcTimeoutMultiplier(1.0) - .setMaxRpcTimeout(Duration.ZERO); - } - - public abstract Builder toBuilder(); - - /** - * A base builder class for {@link RetrySettings}. See the class documentation of {@link - * RetrySettings} for a description of the different values that can be set. - */ - @AutoValue.Builder - public abstract static class Builder { - - /** - * TotalTimeout has ultimate control over how long the logic should keep trying the remote call - * until it gives up completely. The higher the total timeout, the more retries can be - * attempted. The default value is {@code Duration.ZERO}. - */ - public abstract Builder setTotalTimeout(Duration totalTimeout); - - /** - * InitialRetryDelay controls the delay before the first retry. Subsequent retries will use this - * value adjusted according to the RetryDelayMultiplier. The default value is {@code - * Duration.ZERO}. - */ - public abstract Builder setInitialRetryDelay(Duration initialDelay); - - /** - * RetryDelayMultiplier controls the change in retry delay. The retry delay of the previous call - * is multiplied by the RetryDelayMultiplier to calculate the retry delay for the next call. The - * default value is {@code 1.0}. - */ - public abstract Builder setRetryDelayMultiplier(double multiplier); - - /** - * MaxRetryDelay puts a limit on the value of the retry delay, so that the RetryDelayMultiplier - * can't increase the retry delay higher than this amount. The default value is {@code - * Duration.ZERO}. - */ - public abstract Builder setMaxRetryDelay(Duration maxDelay); - - /** - * MaxAttempts defines the maximum number of attempts to perform. The default value is {@code - * 0}. If this value is greater than 0, and the number of attempts reaches this limit, the logic - * will give up retrying even if the total retry time is still lower than TotalTimeout. - */ - public abstract Builder setMaxAttempts(int maxAttempts); - - /** - * Jitter determines if the delay time should be randomized. If jitter is set to {@code true} - * the actual delay time is calculated in the following way: - * - *
{@code actualDelay = rand_between(0, min(maxRetryDelay, exponentialDelay))}
- * - * The default value is {@code true}, and this method will be a no-op soon. - * - * @deprecated Retries always jitter. - */ - @Deprecated - @VisibleForTesting - public abstract Builder setJittered(boolean jittered); - - /** - * InitialRpcTimeout controls the timeout for the initial RPC. Subsequent calls will use this - * value adjusted according to the RpcTimeoutMultiplier. The default value is {@code - * Duration.ZERO}. - */ - public abstract Builder setInitialRpcTimeout(Duration initialTimeout); - - /** - * See the class documentation of {@link RetrySettings} for a description of what this value - * does. The default value is {@code 1.0}. - */ - public abstract Builder setRpcTimeoutMultiplier(double multiplier); - - /** - * MaxRpcTimeout puts a limit on the value of the RPC timeout, so that the RpcTimeoutMultiplier - * can't increase the RPC timeout higher than this amount. The default value is {@code - * Duration.ZERO}. - */ - public abstract Builder setMaxRpcTimeout(Duration maxTimeout); - - /** - * TotalTimeout has ultimate control over how long the logic should keep trying the remote call - * until it gives up completely. The higher the total timeout, the more retries can be - * attempted. The default value is {@code Duration.ZERO}. - */ - public abstract Duration getTotalTimeout(); - - /** - * InitialRetryDelay controls the delay before the first retry. Subsequent retries will use this - * value adjusted according to the RetryDelayMultiplier. The default value is {@code - * Duration.ZERO}. - */ - public abstract Duration getInitialRetryDelay(); - - /** - * RetryDelayMultiplier controls the change in retry delay. The retry delay of the previous call - * is multiplied by the RetryDelayMultiplier to calculate the retry delay for the next call. The - * default value is {@code 1.0}. - */ - public abstract double getRetryDelayMultiplier(); - - /** - * MaxAttempts defines the maximum number of attempts to perform. The default value is {@code - * 0}. If this value is greater than 0, and the number of attempts reaches this limit, the logic - * will give up retrying even if the total retry time is still lower than TotalTimeout. - */ - public abstract int getMaxAttempts(); - - /** - * Jitter determines if the delay time should be randomized. In most cases, if jitter is set to - * {@code true} the actual delay time is calculated in the following way: - * - *
{@code actualDelay = rand_between(0, min(maxRetryDelay, exponentialDelay))}
- * - * The default value is {@code true}. - */ - public abstract boolean isJittered(); - - /** - * MaxRetryDelay puts a limit on the value of the retry delay, so that the RetryDelayMultiplier - * can't increase the retry delay higher than this amount. The default value is {@code - * Duration.ZERO}. - */ - public abstract Duration getMaxRetryDelay(); - - /** - * InitialRpcTimeout controls the timeout for the initial RPC. Subsequent calls will use this - * value adjusted according to the RpcTimeoutMultiplier. The default value is {@code - * Duration.ZERO}. - */ - public abstract Duration getInitialRpcTimeout(); - - /** - * See the class documentation of {@link RetrySettings} for a description of what this value - * does. The default value is {@code 1.0}. - */ - public abstract double getRpcTimeoutMultiplier(); - - /** - * MaxRpcTimeout puts a limit on the value of the RPC timeout, so that the RpcTimeoutMultiplier - * can't increase the RPC timeout higher than this amount. - */ - public abstract Duration getMaxRpcTimeout(); - - /** - * Configures the timeout settings with the given timeout such that the logical call will take - * no longer than the given timeout and each RPC attempt will use only the time remaining in the - * logical call as a timeout. - * - *

Using this method in conjunction with individual {@link RetrySettings} timeout field - * setters is not advised, because only the order in which they are invoked determines which - * setter is respected. - */ - @BetaApi - public Builder setLogicalTimeout(Duration timeout) { - return setRpcTimeoutMultiplier(1) - .setInitialRpcTimeout(timeout) - .setMaxRpcTimeout(timeout) - .setTotalTimeout(timeout); - } - - abstract RetrySettings autoBuild(); - - public RetrySettings build() { - RetrySettings params = autoBuild(); - if (params.getTotalTimeout().toMillis() < 0) { - throw new IllegalStateException("total timeout must not be negative"); - } - if (params.getInitialRetryDelay().toMillis() < 0) { - throw new IllegalStateException("initial retry delay must not be negative"); - } - if (params.getRetryDelayMultiplier() < 1.0) { - throw new IllegalStateException("retry delay multiplier must be at least 1"); - } - if (params.getMaxRetryDelay().compareTo(params.getInitialRetryDelay()) < 0) { - throw new IllegalStateException("max retry delay must not be shorter than initial delay"); - } - if (params.getMaxAttempts() < 0) { - throw new IllegalStateException("max attempts must be non-negative"); - } - if (params.getInitialRpcTimeout().toMillis() < 0) { - throw new IllegalStateException("initial rpc timeout must not be negative"); - } - if (params.getMaxRpcTimeout().compareTo(params.getInitialRpcTimeout()) < 0) { - throw new IllegalStateException("max rpc timeout must not be shorter than initial timeout"); - } - if (params.getRpcTimeoutMultiplier() < 1.0) { - throw new IllegalStateException("rpc timeout multiplier must be at least 1"); - } - return params; - } - - public RetrySettings.Builder merge(RetrySettings.Builder newSettings) { - if (newSettings.getTotalTimeout() != null) { - setTotalTimeout(newSettings.getTotalTimeout()); - } - if (newSettings.getInitialRetryDelay() != null) { - setInitialRetryDelay(newSettings.getInitialRetryDelay()); - } - if (newSettings.getRetryDelayMultiplier() >= 1) { - setRetryDelayMultiplier(newSettings.getRetryDelayMultiplier()); - } - if (newSettings.getMaxRetryDelay() != null) { - setMaxRetryDelay(newSettings.getMaxRetryDelay()); - } - setMaxAttempts(newSettings.getMaxAttempts()); - setJittered(newSettings.isJittered()); - if (newSettings.getInitialRpcTimeout() != null) { - setInitialRpcTimeout(newSettings.getInitialRpcTimeout()); - } - if (newSettings.getRpcTimeoutMultiplier() >= 1) { - setRpcTimeoutMultiplier(newSettings.getRpcTimeoutMultiplier()); - } - if (newSettings.getMaxRpcTimeout() != null) { - setMaxRpcTimeout(newSettings.getMaxRpcTimeout()); - } - return this; - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/retrying/RetryingContext.java b/gax/src/main/java/com/google/api/gax/retrying/RetryingContext.java deleted file mode 100644 index 6db53c4e2..000000000 --- a/gax/src/main/java/com/google/api/gax/retrying/RetryingContext.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -import com.google.api.core.BetaApi; -import com.google.api.gax.rpc.StatusCode; -import com.google.api.gax.tracing.ApiTracer; -import java.util.Set; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -/** - * Context for a retryable operation. - * - *

It provides state to individual {@link RetryingFuture}s via the {@link RetryingExecutor}. - */ -@BetaApi("The surface for passing per operation state is not yet stable") -public interface RetryingContext { - /** Returns the {@link ApiTracer} associated with the current operation. */ - @Nonnull - ApiTracer getTracer(); - - /** - * Returns the {@link RetrySettings} to use with this context, or null if the default - * {@link RetrySettings} should be used. - */ - @Nullable - RetrySettings getRetrySettings(); - - /** - * Returns the retryable codes to use with this context, or null if the default - * retryable codes should be used. - */ - @Nullable - Set getRetryableCodes(); -} diff --git a/gax/src/main/java/com/google/api/gax/retrying/RetryingExecutor.java b/gax/src/main/java/com/google/api/gax/retrying/RetryingExecutor.java deleted file mode 100644 index e8bab994a..000000000 --- a/gax/src/main/java/com/google/api/gax/retrying/RetryingExecutor.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -import com.google.api.core.ApiFuture; -import java.util.concurrent.Callable; - -/** - * A retrying executor is responsible for the following operations: - * - *

    - *
  1. Creating first attempt {@link RetryingFuture}, which acts as a facade, hiding from client - * code the actual execution of scheduled retry attempts. - *
  2. Executing the actual {@link Callable} in a retriable context. - *
- * - * This interface is for internal/advanced use only. - * - * @param response type - */ -public interface RetryingExecutor { - /** - * Creates the {@link RetryingFuture}, which is a facade, returned to the client code to wait for - * any retriable operation to complete. - * - * @param callable the actual callable, which should be executed in a retriable context - * @return retrying future facade - */ - RetryingFuture createFuture(Callable callable); - - /** - * Submits an attempt for execution. A typical implementation will either try to execute the - * attempt in the current thread or schedule it for an execution, using some sort of async - * execution service. - * - * @param retryingFuture the future previously returned by {@link #createFuture(Callable)} and - * reused for each subsequent attempt of same operation. - * @return submitted attempt future - */ - ApiFuture submit(RetryingFuture retryingFuture); -} diff --git a/gax/src/main/java/com/google/api/gax/retrying/RetryingExecutorWithContext.java b/gax/src/main/java/com/google/api/gax/retrying/RetryingExecutorWithContext.java deleted file mode 100644 index f19ba5607..000000000 --- a/gax/src/main/java/com/google/api/gax/retrying/RetryingExecutorWithContext.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -import com.google.api.core.BetaApi; -import com.google.api.core.InternalExtensionOnly; -import java.util.concurrent.Callable; -import javax.annotation.Nonnull; - -/** - * A {@link RetryingExecutor} that accepts a per-operation context. - * - * @see RetryingExecutor - */ -// TODO(igorbernstein2): Consider replacing this with a default implementation in RetryingExecutor -// once support for java 7 is dropped -@BetaApi("The surface for per invocation state is unstable and will probably change in the future") -@InternalExtensionOnly -public interface RetryingExecutorWithContext extends RetryingExecutor { - RetryingFuture createFuture( - @Nonnull Callable callable, @Nonnull RetryingContext context); -} diff --git a/gax/src/main/java/com/google/api/gax/retrying/RetryingFuture.java b/gax/src/main/java/com/google/api/gax/retrying/RetryingFuture.java deleted file mode 100644 index 86b16eac6..000000000 --- a/gax/src/main/java/com/google/api/gax/retrying/RetryingFuture.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -import com.google.api.core.ApiFuture; -import java.util.concurrent.Callable; - -/** - * Represents a retrying future. This is a facade hiding all the complications of an - * asynchronous/synchronous execution of a retriable task. - * - *

This interface is for advanced/internal use only. - * - * @param response type - */ -public interface RetryingFuture extends ApiFuture { - /** - * Sets the attempt in a form of a future. This future represents a concrete retry attempt, - * potentially scheduled for execution in a some form of {@link - * java.util.concurrent.ScheduledExecutorService}, or an already completed future if the attempts - * are executed synchronously. - * - * @param attemptFuture the attempt future - */ - void setAttemptFuture(ApiFuture attemptFuture); - - /** Returns callable tracked by this future. */ - Callable getCallable(); - - /** Returns current (active) attempt settings. */ - TimedAttemptSettings getAttemptSettings(); - - /** - * Returns latest completed attempt result or {@code null} if the first attempt hasn't completed - * yet. - * - *

This method is for internal/advanced use only. - * - *

If not null, the returned value is guaranteed to be an already completed future, so {@link - * ApiFuture#isDone()} will always be {@code true} and {@link ApiFuture#get()} will always be - * non-blocking. - * - *

In case if the whole retrying future is completed, this method returns the same result as - * the retrying future itself. - * - *

The number of attempt results may be (and usually is) lower than the number of actual - * attempts, since only a completed attempt has a result and not all attempts complete (some of - * the service attempts, needed for proper execution of the actual attempts). - * - *

For each execution the following invariants hold: - * - *

    - *
  • If the first attempt hasn't completed yet, this method returns {@code null}. - *
  • Right after completion of each attempt this method starts returning a new already - * completed future, which represents the result of the latest completed attempt. - *
  • If it was the last attempt, the events happen in the following order: 1) the attempt - * future completes; 2) the whole retrying future completes; 3) this method starts returning - * a new already completed future, which represents the result of the last completed - * attempt. - *
  • After completion of the whole retrying future this method always returns exactly same - * future object. - *
- */ - ApiFuture peekAttemptResult(); - - /** - * Returns the current (active on the moment of the execution of this method) attempt result - * future, allowing to track progress of the retrying future execution. - * - *

Adding direct executor (same thread) callbacks to the future returned by this method is - * strongly not recommended, since the future is resolved under retrying future's internal lock - * and may affect the whole retrying process. Adding separate thread callbacks is ok. - * - *

This method is for internal/advanced use only. - * - *

The returned future completes right after the corresponding attempt which it tracks, so - * calling {@link ApiFuture#get()} is potentially a blocking operation. This method returns - * exactly same future object until it completes (meaning that the corresponding attempt has - * completed). If there is another attempt made after completion of the current attempt, the - * subsequent call to this method will return a new future which will track the new attempt. - * - *

In case if the whole retrying future is completed, this method returns the same result as - * the retrying future itself. - * - *

The returned future is non-cancellable, so calling {@link ApiFuture#cancel(boolean)} will - * have no effect and will always return {@code false}. - * - *

The number of attempt results may be (and usually is) lower than the number of actual - * attempts, since only a completed attempt has a result and not all attempts complete (some of - * the service attempts, needed for proper execution of the actual attempts). - * - *

For each execution the following invariants hold: - * - *

    - *
  • The future returned by this method completes soon after the attempt it tracks. - *
  • If it was the last attempt, the futures complete in the following order: 1) the attempt - * future; 2) the whole retrying future; 3) the attempt result future returned by this - * method. - *
  • After completion of the whole retrying future this method always returns exactly same - * future object. - *
- */ - ApiFuture getAttemptResult(); -} diff --git a/gax/src/main/java/com/google/api/gax/retrying/ScheduledRetryingExecutor.java b/gax/src/main/java/com/google/api/gax/retrying/ScheduledRetryingExecutor.java deleted file mode 100644 index b6ee0a0c1..000000000 --- a/gax/src/main/java/com/google/api/gax/retrying/ScheduledRetryingExecutor.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.api.core.BetaApi; -import com.google.api.core.ListenableFutureToApiFuture; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.ListeningScheduledExecutorService; -import com.google.common.util.concurrent.MoreExecutors; -import java.util.concurrent.Callable; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -/** - * The retry executor which uses {@link ScheduledExecutorService} to schedule an attempt tasks. - * - *

This implementation does not manage the lifecycle of the underlying {@link - * ScheduledExecutorService}, so it should be managed outside of this class (like calling the {@link - * ScheduledExecutorService#shutdown()} when the pool is not needed anymore). In a typical usage - * pattern there are usually multiple instances of this class sharing same instance of the - * underlying {@link ScheduledExecutorService}. - * - *

This class is thread-safe. - * - * @param response type - */ -public class ScheduledRetryingExecutor - implements RetryingExecutorWithContext { - - private final RetryAlgorithm retryAlgorithm; - private final ListeningScheduledExecutorService scheduler; - - /** - * Creates a new scheduled retry executor, which will be using {@code scheduler} for actual - * attempts scheduling and {@code retryAlgorithm} for retrying strategy. - * - * @param retryAlgorithm retry algorithm to use - * @param scheduler scheduler - */ - public ScheduledRetryingExecutor( - RetryAlgorithm retryAlgorithm, ScheduledExecutorService scheduler) { - this.retryAlgorithm = retryAlgorithm; - this.scheduler = MoreExecutors.listeningDecorator(scheduler); - } - - /** - * Creates a {@link RetryingFuture}, which is a facade, returned to the client code to wait for - * any retriable operation to complete. The returned future is bounded to {@code this} executor - * instance. - * - * @param callable the actual callable, which should be executed in a retriable context - * @return retrying future facade - */ - @Override - public RetryingFuture createFuture(Callable callable) { - return createFuture(callable, NoopRetryingContext.create()); - } - - /** - * Creates a {@link RetryingFuture}, which is a facade, returned to the client code to wait for - * any retriable operation to complete. The returned future is bounded to {@code this} executor - * instance. - * - * @param callable the actual callable, which should be executed in a retriable context - * @param context the context for this operation - * @return retrying future facade - */ - @BetaApi("The surface for passing per operation state is not yet stable") - @Override - public RetryingFuture createFuture( - Callable callable, RetryingContext context) { - return new CallbackChainRetryingFuture<>(callable, retryAlgorithm, this, context); - } - - /** - * Submits an attempt for execution in a different thread. - * - * @param retryingFuture the future previously returned by {@link #createFuture(Callable, - * RetryingContext)} - * @return submitted attempt future - */ - @Override - public ApiFuture submit(RetryingFuture retryingFuture) { - try { - ListenableFuture attemptFuture = - scheduler.schedule( - retryingFuture.getCallable(), - retryingFuture.getAttemptSettings().getRandomizedRetryDelay().toMillis(), - TimeUnit.MILLISECONDS); - return new ListenableFutureToApiFuture<>(attemptFuture); - } catch (RejectedExecutionException e) { - return ApiFutures.immediateFailedFuture(e); - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/retrying/ServerStreamingAttemptException.java b/gax/src/main/java/com/google/api/gax/retrying/ServerStreamingAttemptException.java deleted file mode 100644 index b54776f0b..000000000 --- a/gax/src/main/java/com/google/api/gax/retrying/ServerStreamingAttemptException.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -import com.google.api.core.InternalApi; - -/** - * A wrapper exception thrown by {@code ServerStreamingAttemptCallable} to communicate additional - * context to the {@link StreamingRetryAlgorithm} and to pass the original cancellation stack trace - * to {@code RetryingServerStreamingCallable}. - * - *

For internal use only - public for technical reasons. - */ -@InternalApi -public class ServerStreamingAttemptException extends RuntimeException { - private final boolean canResume; - private final boolean seenResponses; - - public ServerStreamingAttemptException( - Throwable cause, boolean canResume, boolean seenResponses) { - super(cause.getMessage(), cause); - this.canResume = canResume; - this.seenResponses = seenResponses; - } - - /** If the {@link StreamResumptionStrategy} supports resuming after this error. */ - public boolean canResume() { - return canResume; - } - - /** - * If the current RPC attempt has seen any streamed messages. This is used as a signal by {@link - * StreamingRetryAlgorithm} to reset timers. - */ - public boolean hasSeenResponses() { - return seenResponses; - } -} diff --git a/gax/src/main/java/com/google/api/gax/retrying/SimpleStreamResumptionStrategy.java b/gax/src/main/java/com/google/api/gax/retrying/SimpleStreamResumptionStrategy.java deleted file mode 100644 index 7c5902129..000000000 --- a/gax/src/main/java/com/google/api/gax/retrying/SimpleStreamResumptionStrategy.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -import com.google.common.base.Preconditions; - -/** - * Simplest implementation of a {@link StreamResumptionStrategy} which returns the initial request - * for unstarted streams. - */ -public final class SimpleStreamResumptionStrategy - implements StreamResumptionStrategy { - private boolean seenFirstResponse; - - @Override - public StreamResumptionStrategy createNew() { - return new SimpleStreamResumptionStrategy<>(); - } - - @Override - public ResponseT processResponse(ResponseT response) { - seenFirstResponse = true; - return response; - } - - @Override - public RequestT getResumeRequest(RequestT originalRequest) { - Preconditions.checkState(!seenFirstResponse, "Tried to resume an unresumeable stream."); - return originalRequest; - } - - @Override - public boolean canResume() { - return !seenFirstResponse; - } -} diff --git a/gax/src/main/java/com/google/api/gax/retrying/StreamResumptionStrategy.java b/gax/src/main/java/com/google/api/gax/retrying/StreamResumptionStrategy.java deleted file mode 100644 index 227b4b0ce..000000000 --- a/gax/src/main/java/com/google/api/gax/retrying/StreamResumptionStrategy.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -/** - * This is part of the server streaming retry api. Its implementers are responsible for tracking the - * progress of the stream and calculating a request to resume it in case of an error. - * - *

Implementations don't have to be threadsafe because all of the calls will be serialized. - */ -public interface StreamResumptionStrategy { - - /** Creates a new instance of this StreamResumptionStrategy without accumulated state */ - @Nonnull - StreamResumptionStrategy createNew(); - - /** - * Called by the {@code ServerStreamingAttemptCallable} when a response has been successfully - * received. This method accomplishes two goals: - * - *

    - *
  1. It allows the strategy implementation to update its internal state so that it can compose - * the resume request - *
  2. It allows the strategy to alter the incoming responses to adjust for after resume. For - * example, if the responses are numbered sequentially from the start of the stream, upon - * resume, the strategy could rewrite the messages to continue the sequence from where it - * left off. Please note that all messages (even for the first attempt) will be passed - * through this method. - *
- */ - @Nonnull - ResponseT processResponse(ResponseT response); - - /** - * Called when a stream needs to be restarted, the implementation should generate a request that - * will yield a new stream whose first response would come right after the last response received - * by processResponse. - * - * @return A request that can be used to resume the stream. - */ - @Nullable - RequestT getResumeRequest(RequestT originalRequest); - - /** If a resume request can be created. */ - boolean canResume(); -} diff --git a/gax/src/main/java/com/google/api/gax/retrying/StreamingRetryAlgorithm.java b/gax/src/main/java/com/google/api/gax/retrying/StreamingRetryAlgorithm.java deleted file mode 100644 index 272fe3ba1..000000000 --- a/gax/src/main/java/com/google/api/gax/retrying/StreamingRetryAlgorithm.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -import com.google.api.core.InternalApi; -import java.util.concurrent.CancellationException; - -/** - * The streaming retry algorithm, which makes decision based either on the thrown exception and the - * execution time settings of the previous attempt. This extends {@link RetryAlgorithm} to take - * additional information (provided by {@code ServerStreamingAttemptCallable}) into account. - * - *

This class is thread-safe. - * - *

Internal use only - public for technical reasons. - */ -@InternalApi("For internal use only") -public final class StreamingRetryAlgorithm extends RetryAlgorithm { - - /** - * Instances that are created using this constructor will ignore the {@link RetryingContext} that - * is passed in to the retrying methods. Use {@link - * #StreamingRetryAlgorithm(ResultRetryAlgorithmWithContext, TimedRetryAlgorithmWithContext)} to - * create an instance that will respect the {@link RetryingContext}. - * - * @deprecated use {@link #StreamingRetryAlgorithm(ResultRetryAlgorithmWithContext, - * TimedRetryAlgorithmWithContext)} instead - */ - @Deprecated - public StreamingRetryAlgorithm( - ResultRetryAlgorithm resultAlgorithm, TimedRetryAlgorithm timedAlgorithm) { - super(resultAlgorithm, timedAlgorithm); - } - - /** - * Creates a {@link StreamingRetryAlgorithm} that will use the settings (if any) in the {@link - * RetryingContext} that is passed in to the retrying methods. - */ - public StreamingRetryAlgorithm( - ResultRetryAlgorithmWithContext resultAlgorithm, - TimedRetryAlgorithmWithContext timedAlgorithm) { - super(resultAlgorithm, timedAlgorithm); - } - - /** - * {@inheritDoc} - * - *

The attempt settings will be reset if the stream attempt produced any messages. - */ - @Override - public TimedAttemptSettings createNextAttempt( - Throwable previousThrowable, - ResponseT previousResponse, - TimedAttemptSettings previousSettings) { - return createNextAttempt(null, previousThrowable, previousResponse, previousSettings); - } - - /** - * {@inheritDoc} - * - *

The attempt settings will be reset if the stream attempt produced any messages. - */ - @Override - public TimedAttemptSettings createNextAttempt( - RetryingContext context, - Throwable previousThrowable, - ResponseT previousResponse, - TimedAttemptSettings previousSettings) { - - if (previousThrowable instanceof ServerStreamingAttemptException) { - ServerStreamingAttemptException attemptException = - (ServerStreamingAttemptException) previousThrowable; - previousThrowable = previousThrowable.getCause(); - - // If we have made progress in the last attempt, then reset the delays - if (attemptException.hasSeenResponses()) { - previousSettings = - createFirstAttempt(context) - .toBuilder() - .setFirstAttemptStartTimeNanos(previousSettings.getFirstAttemptStartTimeNanos()) - .setOverallAttemptCount(previousSettings.getOverallAttemptCount()) - .build(); - } - } - - return super.createNextAttempt(context, previousThrowable, previousResponse, previousSettings); - } - - /** - * {@inheritDoc} - * - *

Ensures retries are only scheduled if the {@link StreamResumptionStrategy} in the {@code - * ServerStreamingAttemptCallable} supports it. - */ - @Override - public boolean shouldRetry( - Throwable previousThrowable, - ResponseT previousResponse, - TimedAttemptSettings nextAttemptSettings) - throws CancellationException { - return shouldRetry(null, previousThrowable, previousResponse, nextAttemptSettings); - } - - /** - * {@inheritDoc} - * - *

Schedules retries only if the {@link StreamResumptionStrategy} in the {@code - * ServerStreamingAttemptCallable} supports it. - */ - @Override - public boolean shouldRetry( - RetryingContext context, - Throwable previousThrowable, - ResponseT previousResponse, - TimedAttemptSettings nextAttemptSettings) - throws CancellationException { - - // Unwrap - if (previousThrowable instanceof ServerStreamingAttemptException) { - ServerStreamingAttemptException attemptException = - (ServerStreamingAttemptException) previousThrowable; - previousThrowable = previousThrowable.getCause(); - - if (!attemptException.canResume()) { - return false; - } - } - - return super.shouldRetry(context, previousThrowable, previousResponse, nextAttemptSettings); - } -} diff --git a/gax/src/main/java/com/google/api/gax/retrying/TimedAttemptSettings.java b/gax/src/main/java/com/google/api/gax/retrying/TimedAttemptSettings.java deleted file mode 100644 index 2f9028a2e..000000000 --- a/gax/src/main/java/com/google/api/gax/retrying/TimedAttemptSettings.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -import com.google.api.core.ApiClock; -import com.google.auto.value.AutoValue; -import org.threeten.bp.Duration; - -/** Timed attempt execution settings. Defines time-specific properties of a retry attempt. */ -@AutoValue -public abstract class TimedAttemptSettings { - - /** Returns global (attempt-independent) retry settings. */ - public abstract RetrySettings getGlobalSettings(); - - /** - * Returns the calculated retry delay. Note that the actual delay used for retry scheduling may be - * different (randomized, based on this value). - */ - public abstract Duration getRetryDelay(); - - /** Returns rpc timeout used for this attempt. */ - public abstract Duration getRpcTimeout(); - - /** - * Returns randomized attempt delay. By default this value is calculated based on the {@code - * retryDelay} value, and is used as the actual attempt execution delay. - */ - public abstract Duration getRandomizedRetryDelay(); - - /** - * The attempt count. It is a zero-based value (first attempt will have this value set to 0). For - * streamed RPCs this will be reset after every successful message. - */ - public abstract int getAttemptCount(); - - /** - * The overall attempt count. It is a zero-based value (first attempt will have this value set to - * 0). This will be the sum of all attempt counts for a streaming RPC and will be equal to {@link - * #getAttemptCount()} for unary RPCs. - */ - public abstract int getOverallAttemptCount(); - - /** - * The start time of the first attempt. Note that this value is dependent on the actual {@link - * ApiClock} used during the process. - */ - public abstract long getFirstAttemptStartTimeNanos(); - - public abstract Builder toBuilder(); - - public static Builder newBuilder() { - return new AutoValue_TimedAttemptSettings.Builder().setOverallAttemptCount(0); - } - - @AutoValue.Builder - public abstract static class Builder { - /** Sets global (attempt-independent) retry settings. */ - public abstract Builder setGlobalSettings(RetrySettings value); - - /** - * Sets the calculated retry delay. Note that the actual delay used for retry scheduling may be - * different (randomized, based on this value). - */ - public abstract Builder setRetryDelay(Duration value); - - /** Sets rpc timeout used for this attempt. */ - public abstract Builder setRpcTimeout(Duration value); - - /** - * Sets randomized attempt delay. By default this value is calculated based on the {@code - * retryDelay} value, and is used as the actual attempt execution delay. - */ - public abstract Builder setRandomizedRetryDelay(Duration value); - - /** - * Set the attempt count. It is a zero-based value (first attempt will have this value set to - * 0). - */ - public abstract Builder setAttemptCount(int value); - - /** - * Set the overall attempt count. It is a zero-based value (first attempt will have this value - * set to 0). - */ - public abstract Builder setOverallAttemptCount(int value); - - /** - * Set the start time of the first attempt. Note that this value is dependent on the actual - * {@link ApiClock} used during the process. - */ - public abstract Builder setFirstAttemptStartTimeNanos(long value); - - public abstract TimedAttemptSettings build(); - } -} diff --git a/gax/src/main/java/com/google/api/gax/retrying/TimedRetryAlgorithm.java b/gax/src/main/java/com/google/api/gax/retrying/TimedRetryAlgorithm.java deleted file mode 100644 index 5cae22b20..000000000 --- a/gax/src/main/java/com/google/api/gax/retrying/TimedRetryAlgorithm.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.gax.retrying; - -import java.util.concurrent.CancellationException; - -/** - * Same as {@link TimedRetryAlgorithmWithContext}, but without methods that accept a {@link - * RetryingContext}. Use {@link TimedRetryAlgorithmWithContext} instead of this interface when - * possible. - */ -public interface TimedRetryAlgorithm { - - /** - * Same as {@link TimedRetryAlgorithmWithContext#createFirstAttempt(RetryingContext)}, but without - * a {@link RetryingContext}. - * - *

Use {@link TimedRetryAlgorithmWithContext#createFirstAttempt(RetryingContext)} instead of - * this method when possible. - */ - TimedAttemptSettings createFirstAttempt(); - - /** - * Same as {@link TimedRetryAlgorithmWithContext#createNextAttempt(RetryingContext, - * TimedAttemptSettings)}, but without a {@link RetryingContext}. - * - *

Use {@link TimedRetryAlgorithmWithContext#createNextAttempt(RetryingContext, - * TimedAttemptSettings)} instead of this method when possible. - */ - TimedAttemptSettings createNextAttempt(TimedAttemptSettings prevSettings); - - /** - * Same as {@link TimedRetryAlgorithmWithContext#shouldRetry(RetryingContext, - * TimedAttemptSettings)}, but without a {@link RetryingContext}. - * - *

Use {@link TimedRetryAlgorithmWithContext#shouldRetry(RetryingContext, - * TimedAttemptSettings)} instead of this method when possible. - */ - boolean shouldRetry(TimedAttemptSettings nextAttemptSettings) throws CancellationException; -} diff --git a/gax/src/main/java/com/google/api/gax/retrying/TimedRetryAlgorithmWithContext.java b/gax/src/main/java/com/google/api/gax/retrying/TimedRetryAlgorithmWithContext.java deleted file mode 100644 index 72efda7f4..000000000 --- a/gax/src/main/java/com/google/api/gax/retrying/TimedRetryAlgorithmWithContext.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.gax.retrying; - -import java.util.concurrent.CancellationException; - -/** - * A timed retry algorithm is responsible for the following operations, based on the previous - * attempt settings and current time: - * - *

    - *
  1. Creating first attempt {@link TimedAttemptSettings}. - *
  2. Accepting a task for retry so another attempt will be made. - *
  3. Canceling retrying process so the related {@link java.util.concurrent.Future} will be - * canceled. - *
  4. Creating {@link TimedAttemptSettings} for each subsequent retry attempt. - *
- * - * Implementations of this interface receive a {@link RetryingContext} that can contain specific - * {@link RetrySettings} and retryable codes that should be used to determine the retry behavior. - * - *

Implementations of this interface must be be thread-save. - */ -public interface TimedRetryAlgorithmWithContext extends TimedRetryAlgorithm { - - /** - * Creates a first attempt {@link TimedAttemptSettings}. - * - * @param context a {@link RetryingContext} that can contain custom {@link RetrySettings} and - * retryable codes - * @return first attempt settings - */ - TimedAttemptSettings createFirstAttempt(RetryingContext context); - - /** - * Creates a next attempt {@link TimedAttemptSettings}, which defines properties of the next - * attempt. - * - * @param context a {@link RetryingContext} that can contain custom {@link RetrySettings} and - * retryable codes - * @param previousSettings previous attempt settings - * @return next attempt settings or {@code null} if the implementing algorithm does not provide - * specific settings for the next attempt - */ - TimedAttemptSettings createNextAttempt( - RetryingContext context, TimedAttemptSettings previousSettings); - - /** - * Returns {@code true} if another attempt should be made, or {@code false} otherwise. - * - * @param context a {@link RetryingContext} that can contain custom {@link RetrySettings} and - * retryable codes. - * @param nextAttemptSettings attempt settings, which will be used for the next attempt, if - * accepted - * @throws CancellationException if the retrying process should be canceled - */ - boolean shouldRetry(RetryingContext context, TimedAttemptSettings nextAttemptSettings); -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/AbortedException.java b/gax/src/main/java/com/google/api/gax/rpc/AbortedException.java deleted file mode 100644 index 4cd2e31b6..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/AbortedException.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -/** - * Exception thrown when the operation was aborted, typically due to a concurrency issue like - * sequencer check failures, transaction aborts, etc. - */ -public class AbortedException extends ApiException { - public AbortedException(Throwable cause, StatusCode statusCode, boolean retryable) { - super(cause, statusCode, retryable); - } - - public AbortedException( - String message, Throwable cause, StatusCode statusCode, boolean retryable) { - super(message, cause, statusCode, retryable); - } - - public AbortedException( - Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { - super(cause, statusCode, retryable, errorDetails); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/AlreadyExistsException.java b/gax/src/main/java/com/google/api/gax/rpc/AlreadyExistsException.java deleted file mode 100644 index 6ee118898..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/AlreadyExistsException.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -/** - * Exception thrown when some entity that we attempted to create (e.g., file or directory) already - * exists. - */ -public class AlreadyExistsException extends ApiException { - public AlreadyExistsException(Throwable cause, StatusCode statusCode, boolean retryable) { - super(cause, statusCode, retryable); - } - - public AlreadyExistsException( - String message, Throwable cause, StatusCode statusCode, boolean retryable) { - super(message, cause, statusCode, retryable); - } - - public AlreadyExistsException( - Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { - super(cause, statusCode, retryable, errorDetails); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/ApiCallContext.java b/gax/src/main/java/com/google/api/gax/rpc/ApiCallContext.java deleted file mode 100644 index 5a34b58e3..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/ApiCallContext.java +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.BetaApi; -import com.google.api.core.InternalExtensionOnly; -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.retrying.RetryingContext; -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.api.gax.tracing.ApiTracer; -import com.google.auth.Credentials; -import com.google.common.base.Preconditions; -import java.util.List; -import java.util.Map; -import java.util.Set; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import org.threeten.bp.Duration; - -/** - * Context for an API call. - * - *

An API call can be composed of many RPCs (in case of retries). This class contains settings - * for both: API calls and RPCs. - * - *

Implementations need to be immutable because default instances are stored in callable objects. - * - *

This is transport specific and each transport has an implementation with its own options. - */ -@InternalExtensionOnly -public interface ApiCallContext extends RetryingContext { - - /** Returns a new ApiCallContext with the given credentials set. */ - ApiCallContext withCredentials(Credentials credentials); - - /** Returns a new ApiCallContext with the given channel set. */ - ApiCallContext withTransportChannel(TransportChannel channel); - - /** - * Returns a new ApiCallContext with the given timeout set. - * - *

This sets the maximum amount of time a single unary RPC attempt can take. If retries are - * enabled, then this can take much longer, as each RPC attempt will have the same constant - * timeout. Unlike a deadline, timeouts are relative durations that are measure from the beginning - * of each RPC attempt. Please note that this limits the duration of a server streaming RPC as - * well. - * - *

If a method has default {@link com.google.api.gax.retrying.RetrySettings}, the max attempts - * and/or total timeout is still respected when scheduling each RPC attempt. - */ - ApiCallContext withTimeout(@Nullable Duration timeout); - - /** Returns the configured per-RPC timeout. */ - @Nullable - Duration getTimeout(); - - /** - * Returns a new ApiCallContext with the given stream timeout set. - * - *

This timeout only applies to a {@link ServerStreamingCallable}s. It limits the maximum - * amount of time that can pass between demand being signaled via {@link - * StreamController#request(int)} and actual message delivery to {@link - * ResponseObserver#onResponse(Object)}. Or, in the case of automatic flow control, since the last - * message was delivered to {@link ResponseObserver#onResponse(Object)}. This is useful to detect - * server or connection stalls. When the timeout has been reached, the stream will be closed with - * a retryable {@link WatchdogTimeoutException} and a status of {@link StatusCode.Code#ABORTED}. - * - *

A value of {@link Duration#ZERO}, disables the streaming wait timeout and a null value will - * use the default in the callable. - * - *

Please note that this timeout is best effort and the maximum resolution is configured in - * {@link StubSettings#getStreamWatchdogCheckInterval()}. - */ - ApiCallContext withStreamWaitTimeout(@Nullable Duration streamWaitTimeout); - - /** - * Return the stream wait timeout set for this context. - * - * @see #withStreamWaitTimeout(Duration) - */ - @Nullable - Duration getStreamWaitTimeout(); - - /** - * Returns a new ApiCallContext with the given stream idle timeout set. - * - *

This timeout only applies to a {@link ServerStreamingCallable}s. It limits the maximum - * amount of timeout that can pass between a message being received by {@link - * ResponseObserver#onResponse(Object)} and demand being signaled via {@link - * StreamController#request(int)}. Please note that this timeout is best effort and the maximum - * resolution configured in {@link StubSettings#getStreamWatchdogCheckInterval()}. This is useful - * to clean up streams that were partially read but never closed. When the timeout has been - * reached, the stream will be closed with a nonretryable {@link WatchdogTimeoutException} and a - * status of {@link StatusCode.Code#ABORTED}. - * - *

A value of {@link Duration#ZERO}, disables the streaming idle timeout and a null value will - * use the default in the callable. - * - *

Please note that this timeout is best effort and the maximum resolution is configured in - * {@link StubSettings#getStreamWatchdogCheckInterval()}. - */ - ApiCallContext withStreamIdleTimeout(@Nullable Duration streamIdleTimeout); - - /** - * The stream idle timeout set for this context. - * - * @see #withStreamIdleTimeout(Duration) - */ - @Nullable - Duration getStreamIdleTimeout(); - - /** - * The {@link ApiTracer} that was previously set for this context. - * - *

The {@link ApiTracer} will be used to trace the current operation and to annotate various - * events like retries. - */ - @BetaApi("The surface for tracing is not stable yet and may change in the future") - @Nonnull - ApiTracer getTracer(); - - /** - * Returns a new {@link ApiCallContext} with the given {@link ApiTracer}. - * - *

The {@link ApiTracer} will be used to trace the current operation and to annotate various - * events like retries. - * - * @param tracer the {@link ApiTracer} to set. - */ - @BetaApi("The surface for tracing is not stable yet and may change in the future") - ApiCallContext withTracer(@Nonnull ApiTracer tracer); - - /** - * Returns a new ApiCallContext with the given {@link RetrySettings} set. - * - *

This sets the {@link RetrySettings} to use for the RPC. These settings will work in - * combination with either the default retryable codes for the RPC, or the retryable codes - * supplied through {@link #withRetryableCodes(Set)}. Calling {@link - * #withRetrySettings(RetrySettings)} on an RPC that does not include {@link - * Code#DEADLINE_EXCEEDED} as one of its retryable codes (or without calling {@link - * #withRetryableCodes(Set)} with a set that includes at least {@link Code#DEADLINE_EXCEEDED}) - * will effectively only set a single timeout that is equal to {@link - * RetrySettings#getInitialRpcTimeout()}. If this timeout is exceeded, the RPC will not be retried - * and will fail with {@link Code#DEADLINE_EXCEEDED}. - * - *

Example usage: - * - *

{@code
-   * ApiCallContext context = GrpcCallContext.createDefault()
-   *   .withRetrySettings(RetrySettings.newBuilder()
-   *     .setInitialRetryDelay(Duration.ofMillis(10L))
-   *     .setInitialRpcTimeout(Duration.ofMillis(100L))
-   *     .setMaxAttempts(10)
-   *     .setMaxRetryDelay(Duration.ofSeconds(10L))
-   *     .setMaxRpcTimeout(Duration.ofSeconds(30L))
-   *     .setRetryDelayMultiplier(1.4)
-   *     .setRpcTimeoutMultiplier(1.5)
-   *     .setTotalTimeout(Duration.ofMinutes(10L))
-   *     .build())
-   *   .withRetryableCodes(Sets.newSet(
-   *     StatusCode.Code.UNAVAILABLE,
-   *     StatusCode.Code.DEADLINE_EXCEEDED));
-   * }
- * - * Setting a logical call timeout for the context can be done similarly with {@link - * RetrySettings.Builder#setLogicalTimeout(Duration timeout)}. - * - *

Example usage: - * - *

{@code
-   * ApiCallContext context = GrpcCallContext.createDefault()
-   *   .withRetrySettings(RetrySettings.newBuilder()
-   *     .setInitialRetryDelay(Duration.ofMillis(10L))
-   *     .setMaxRetryDelay(Duration.ofSeconds(10L))
-   *     .setRetryDelayMultiplier(1.4)
-   *     .setMaxAttempts(10)
-   *     .setLogicalTimeout(Duration.ofSeconds(30L))
-   *     .build());
-   * }
- */ - @BetaApi - ApiCallContext withRetrySettings(RetrySettings retrySettings); - - /** - * Returns a new ApiCallContext with the given retryable codes set. - * - *

This sets the retryable codes to use for the RPC. These settings will work in combination - * with either the default {@link RetrySettings} for the RPC, or the {@link RetrySettings} - * supplied through {@link #withRetrySettings(RetrySettings)}. - * - *

Setting a non-empty set of retryable codes for an RPC that is not already retryable by - * default, will not have any effect and the RPC will NOT be retried. This option can only be used - * to change which codes are considered retryable for an RPC that already has at least one - * retryable code in its default settings. - */ - @BetaApi - ApiCallContext withRetryableCodes(Set retryableCodes); - - /** If inputContext is not null, returns it; if it is null, returns the present instance. */ - ApiCallContext nullToSelf(ApiCallContext inputContext); - - /** - * For any values in {@code inputCallContext} that are not null, override the corresponding values - * in the present instance. - */ - ApiCallContext merge(ApiCallContext inputCallContext); - - /** Return a new ApiCallContext with the extraHeaders merged into the present instance. */ - @BetaApi("The surface for extra headers is not stable yet and may change in the future.") - ApiCallContext withExtraHeaders(Map> extraHeaders); - - /** Return the extra headers set for this context. */ - @BetaApi("The surface for extra headers is not stable yet and may change in the future.") - Map> getExtraHeaders(); - - /** - * Return a new ApiCallContext with additional option merged into the present instance. Any - * existing value of the key is overwritten. - */ - @BetaApi("The surface for call context options is not stable yet and may change in the future.") - ApiCallContext withOption(Key key, T value); - - /** Return the api call context option set for this context. */ - @SuppressWarnings("unchecked") - @BetaApi("The surface for call context options is not stable yet and may change in the future.") - T getOption(Key key); - - /** Key for api call context options key-value pair. */ - final class Key { - private final String name; - - private Key(String name) { - this.name = name; - } - - /** Factory method for creating instances of {@link Key}. */ - public static Key create(String name) { - Preconditions.checkNotNull(name, "Key name cannot be null."); - return new Key<>(name); - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/ApiClientHeaderProvider.java b/gax/src/main/java/com/google/api/gax/rpc/ApiClientHeaderProvider.java deleted file mode 100644 index 34d00d0f3..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/ApiClientHeaderProvider.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.gax.core.GaxProperties; -import com.google.common.collect.ImmutableMap; -import java.io.Serializable; -import java.util.Map; - -/** - * Implementation of HeaderProvider that provides headers describing the API client library making - * API calls. - */ -public class ApiClientHeaderProvider implements HeaderProvider, Serializable { - private static final long serialVersionUID = -8876627296793342119L; - static final String QUOTA_PROJECT_ID_HEADER_KEY = "x-goog-user-project"; - - private final Map headers; - - protected ApiClientHeaderProvider(Builder builder) { - ImmutableMap.Builder headersBuilder = ImmutableMap.builder(); - - if (builder.getApiClientHeaderKey() != null) { - StringBuilder apiClientHeaderValue = new StringBuilder(); - // Order of tokens matters!!! - appendToken(apiClientHeaderValue, builder.getJvmToken()); - appendToken(apiClientHeaderValue, builder.getClientLibToken()); - appendToken(apiClientHeaderValue, builder.getGeneratedLibToken()); - appendToken(apiClientHeaderValue, builder.getGeneratedRuntimeToken()); - appendToken(apiClientHeaderValue, builder.getTransportToken()); - if (apiClientHeaderValue.length() > 0) { - headersBuilder.put(builder.getApiClientHeaderKey(), apiClientHeaderValue.toString()); - } - } - - if (builder.getResourceHeaderKey() != null && builder.getResourceToken() != null) { - headersBuilder.put(builder.getResourceHeaderKey(), builder.getResourceToken()); - } - - if (builder.getQuotaProjectIdToken() != null) { - headersBuilder.put(QUOTA_PROJECT_ID_HEADER_KEY, builder.getQuotaProjectIdToken()); - } - - this.headers = headersBuilder.build(); - } - - @Override - public Map getHeaders() { - return headers; - } - - protected static void appendToken(StringBuilder sb, String token) { - if (token != null) { - if (sb.length() > 0) { - sb.append(' '); - } - sb.append(token); - } - } - - public static Builder newBuilder() { - return new Builder(); - } - - public static String getDefaultApiClientHeaderKey() { - return "x-goog-api-client"; - } - - public static String getDefaultResourceHeaderKey() { - return "google-cloud-resource-prefix"; - } - - public static class Builder { - private String apiClientHeaderKey; - private String jvmToken; - private String clientLibToken; - private String generatedLibToken; - private String generatedRuntimeToken; - private String transportToken; - private String quotaProjectIdToken; - - private String resourceHeaderKey; - private String resourceToken; - - protected Builder() { - // Initialize with default values - apiClientHeaderKey = getDefaultApiClientHeaderKey(); - setJvmToken(GaxProperties.getJavaVersion()); - clientLibToken = null; - generatedLibToken = null; - setClientRuntimeToken(GaxProperties.getGaxVersion()); - transportToken = null; - quotaProjectIdToken = null; - - resourceHeaderKey = getDefaultResourceHeaderKey(); - resourceToken = null; - } - - public String getApiClientHeaderKey() { - return apiClientHeaderKey; - } - - public Builder setApiClientHeaderKey(String apiClientHeaderKey) { - this.apiClientHeaderKey = apiClientHeaderKey; - return this; - } - - public String getJvmToken() { - return jvmToken; - } - - public Builder setJvmToken(String version) { - this.jvmToken = constructToken("gl-java", version); - return this; - } - - public String getClientLibToken() { - return clientLibToken; - } - - public Builder setClientLibToken(String name, String version) { - this.clientLibToken = constructToken(name, version); - return this; - } - - public String getGeneratedLibToken() { - return generatedLibToken; - } - - public Builder setGeneratedLibToken(String name, String version) { - this.generatedLibToken = constructToken(name, version); - return this; - } - - public String getGeneratedRuntimeToken() { - return generatedRuntimeToken; - } - - public Builder setClientRuntimeToken(String version) { - this.generatedRuntimeToken = constructToken("gax", version); - return this; - } - - public String getTransportToken() { - return transportToken; - } - - public Builder setTransportToken(String name, String version) { - this.transportToken = constructToken(name, version); - return this; - } - - /** @return the quotaProjectIdToken used for quota and billing purposes. */ - public String getQuotaProjectIdToken() { - return quotaProjectIdToken; - } - - /** Sets the project ID used for quota and billing purposes. */ - public Builder setQuotaProjectIdToken(String quotaProjectIdToken) { - this.quotaProjectIdToken = quotaProjectIdToken; - return this; - } - - public String getResourceHeaderKey() { - return resourceHeaderKey; - } - - public Builder setResourceHeaderKey(String resourceHeaderKey) { - this.resourceHeaderKey = resourceHeaderKey; - return this; - } - - public String getResourceToken() { - return resourceToken; - } - - public Builder setResourceToken(String resourceToken) { - this.resourceToken = resourceToken; - return this; - } - - private String constructToken(String name, String version) { - if (version == null) { - return null; - } - if (name == null) { - throw new IllegalArgumentException("Token name cannot be null"); - } - return name + '/' + version; - } - - public ApiClientHeaderProvider build() { - return new ApiClientHeaderProvider(this); - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/ApiException.java b/gax/src/main/java/com/google/api/gax/rpc/ApiException.java deleted file mode 100644 index 3722b894e..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/ApiException.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.common.base.Preconditions; -import java.util.Map; - -/** Represents an exception thrown during an RPC call. */ -public class ApiException extends RuntimeException { - - private static final long serialVersionUID = -4375114339928877996L; - - private final ErrorDetails errorDetails; - private final StatusCode statusCode; - private final boolean retryable; - - public ApiException(Throwable cause, StatusCode statusCode, boolean retryable) { - this(cause, statusCode, retryable, null); - } - - public ApiException(String message, Throwable cause, StatusCode statusCode, boolean retryable) { - super(message, cause); - this.statusCode = Preconditions.checkNotNull(statusCode); - this.retryable = retryable; - this.errorDetails = null; - } - - public ApiException( - Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { - super(cause); - this.statusCode = Preconditions.checkNotNull(statusCode); - this.retryable = retryable; - this.errorDetails = errorDetails; - } - - /** Returns whether the failed request can be retried. */ - public boolean isRetryable() { - return retryable; - } - - /** Returns the status code of the underlying exception. */ - public StatusCode getStatusCode() { - return statusCode; - } - - /** - * Returns the reason of the exception. This is a constant value that identifies the proximate - * cause of the error. e.g. SERVICE_DISABLED - */ - public String getReason() { - if (isErrorInfoEmpty()) { - return null; - } - return errorDetails.getErrorInfo().getReason(); - } - - /** - * Returns the logical grouping to which the "reason" belongs. The error domain is typically the - * registered service name of the tool or product that generates the error. e.g. googleapis.com - */ - public String getDomain() { - if (isErrorInfoEmpty()) { - return null; - } - return errorDetails.getErrorInfo().getDomain(); - } - - /** Returns additional structured details about this exception. */ - public Map getMetadata() { - if (isErrorInfoEmpty()) { - return null; - } - return errorDetails.getErrorInfo().getMetadataMap(); - } - - /** Returns all standard error messages that server sends. */ - public ErrorDetails getErrorDetails() { - return errorDetails; - } - - private boolean isErrorInfoEmpty() { - return errorDetails == null || errorDetails.getErrorInfo() == null; - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/ApiExceptionFactory.java b/gax/src/main/java/com/google/api/gax/rpc/ApiExceptionFactory.java deleted file mode 100644 index 4ca5f41c7..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/ApiExceptionFactory.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -/** - * A factory class that returns the corresponding type of exception class from the given status - * code. - */ -public class ApiExceptionFactory { - private ApiExceptionFactory() {} - - public static ApiException createException( - Throwable cause, StatusCode statusCode, boolean retryable) { - return createException(cause, statusCode, retryable, null); - } - - public static ApiException createException( - String message, Throwable cause, StatusCode statusCode, boolean retryable) { - switch (statusCode.getCode()) { - case CANCELLED: - return new CancelledException(message, cause, statusCode, retryable); - case NOT_FOUND: - return new NotFoundException(message, cause, statusCode, retryable); - case INVALID_ARGUMENT: - return new InvalidArgumentException(message, cause, statusCode, retryable); - case DEADLINE_EXCEEDED: - return new DeadlineExceededException(message, cause, statusCode, retryable); - case ALREADY_EXISTS: - return new AlreadyExistsException(message, cause, statusCode, retryable); - case PERMISSION_DENIED: - return new PermissionDeniedException(message, cause, statusCode, retryable); - case RESOURCE_EXHAUSTED: - return new ResourceExhaustedException(message, cause, statusCode, retryable); - case FAILED_PRECONDITION: - return new FailedPreconditionException(message, cause, statusCode, retryable); - case ABORTED: - return new AbortedException(message, cause, statusCode, retryable); - case OUT_OF_RANGE: - return new OutOfRangeException(message, cause, statusCode, retryable); - case UNIMPLEMENTED: - return new UnimplementedException(message, cause, statusCode, retryable); - case INTERNAL: - return new InternalException(message, cause, statusCode, retryable); - case UNAVAILABLE: - return new UnavailableException(message, cause, statusCode, retryable); - case DATA_LOSS: - return new DataLossException(message, cause, statusCode, retryable); - case UNAUTHENTICATED: - return new UnauthenticatedException(message, cause, statusCode, retryable); - - case UNKNOWN: // Fall through. - default: - return new UnknownException(message, cause, statusCode, retryable); - } - } - - public static ApiException createException( - Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { - switch (statusCode.getCode()) { - case CANCELLED: - return new CancelledException(cause, statusCode, retryable, errorDetails); - case NOT_FOUND: - return new NotFoundException(cause, statusCode, retryable, errorDetails); - case INVALID_ARGUMENT: - return new InvalidArgumentException(cause, statusCode, retryable, errorDetails); - case DEADLINE_EXCEEDED: - return new DeadlineExceededException(cause, statusCode, retryable, errorDetails); - case ALREADY_EXISTS: - return new AlreadyExistsException(cause, statusCode, retryable, errorDetails); - case PERMISSION_DENIED: - return new PermissionDeniedException(cause, statusCode, retryable, errorDetails); - case RESOURCE_EXHAUSTED: - return new ResourceExhaustedException(cause, statusCode, retryable, errorDetails); - case FAILED_PRECONDITION: - return new FailedPreconditionException(cause, statusCode, retryable, errorDetails); - case ABORTED: - return new AbortedException(cause, statusCode, retryable, errorDetails); - case OUT_OF_RANGE: - return new OutOfRangeException(cause, statusCode, retryable, errorDetails); - case UNIMPLEMENTED: - return new UnimplementedException(cause, statusCode, retryable, errorDetails); - case INTERNAL: - return new InternalException(cause, statusCode, retryable, errorDetails); - case UNAVAILABLE: - return new UnavailableException(cause, statusCode, retryable, errorDetails); - case DATA_LOSS: - return new DataLossException(cause, statusCode, retryable, errorDetails); - case UNAUTHENTICATED: - return new UnauthenticatedException(cause, statusCode, retryable, errorDetails); - case UNKNOWN: // Fall through. - default: - return new UnknownException(cause, statusCode, retryable, errorDetails); - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/ApiExceptions.java b/gax/src/main/java/com/google/api/gax/rpc/ApiExceptions.java deleted file mode 100644 index 1559988e0..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/ApiExceptions.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.ApiFuture; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.UncheckedExecutionException; - -/** A utility class for working with {@link ApiException}. */ -public class ApiExceptions { - private ApiExceptions() {} - - /** - * Invokes {@link ApiFuture#get()} on the given future, and if the call throws an exception (which - * will be {@link UncheckedExecutionException}), the exception is processed in the following way: - * - *

    - *
  1. If the exception cause is a RuntimeException, the RuntimeException is rethrown. To ease - * debugging, the a {@link AsyncTaskException} is added as a suppressed exception to - * maintain the callsite. - *
  2. Otherwise, the UncheckedExecutionException is rethrown. - *
- */ - public static ResponseT callAndTranslateApiException(ApiFuture future) { - try { - return Futures.getUnchecked(future); - } catch (UncheckedExecutionException exception) { - if (exception.getCause() instanceof RuntimeException) { - RuntimeException cause = (RuntimeException) exception.getCause(); - cause.addSuppressed(new AsyncTaskException()); - throw cause; - } - - throw exception; - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/ApiResultRetryAlgorithm.java b/gax/src/main/java/com/google/api/gax/rpc/ApiResultRetryAlgorithm.java deleted file mode 100644 index 688fc32cd..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/ApiResultRetryAlgorithm.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.gax.retrying.BasicResultRetryAlgorithm; -import com.google.api.gax.retrying.RetryingContext; - -/* Package-private for internal use. */ -class ApiResultRetryAlgorithm extends BasicResultRetryAlgorithm { - - /** Returns true if previousThrowable is an {@link ApiException} that is retryable. */ - @Override - public boolean shouldRetry(Throwable previousThrowable, ResponseT previousResponse) { - return (previousThrowable instanceof ApiException) - && ((ApiException) previousThrowable).isRetryable(); - } - - /** - * If {@link RetryingContext#getRetryableCodes()} is not null: Returns true if the status code of - * previousThrowable is in the list of retryable code of the {@link RetryingContext}. - * - *

Otherwise it returns the result of {@link #shouldRetry(Throwable, Object)}. - */ - @Override - public boolean shouldRetry( - RetryingContext context, Throwable previousThrowable, ResponseT previousResponse) { - if (context.getRetryableCodes() != null) { - // Ignore the isRetryable() value of the throwable if the RetryingContext has a specific list - // of codes that should be retried. - return (previousThrowable instanceof ApiException) - && context - .getRetryableCodes() - .contains(((ApiException) previousThrowable).getStatusCode().getCode()); - } - return shouldRetry(previousThrowable, previousResponse); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/ApiStreamObserver.java b/gax/src/main/java/com/google/api/gax/rpc/ApiStreamObserver.java deleted file mode 100644 index 6dd12c311..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/ApiStreamObserver.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -/** - * Receives notifications from an observable stream of messages. - * - *

It is used for sending messages in bidi (bidirectional) or client-streaming calls, or for - * receiving messages in bidi or server-streaming calls. - * - *

For outgoing messages, an {@code ApiStreamObserver} is provided by GAX to the application, and - * the application then provides the messages to send. For incoming messages, the application - * implements the {@code ApiStreamObserver} and passes it to GAX, which then calls the observer with - * the messages for the application to receive them. - * - *

Implementations are expected to be thread-compatible. Separate - * {@code ApiStreamObserver}s do not need to be synchronized together; incoming and outgoing - * directions are independent. Since individual {@code ApiStreamObserver}s are not thread-safe, if - * multiple threads will be writing to a {@code ApiStreamObserver} concurrently, the application - * must synchronize calls. - * - *

This interface is a fork of io.grpc.stub.StreamObserver to enable shadowing of Guava, and also - * to allow for a transport-agnostic interface that doesn't depend on gRPC. - */ -public interface ApiStreamObserver { - /** - * Receives a value from the stream. - * - *

Can be called many times but is never called after {@link #onError(Throwable)} or {@link - * #onCompleted()} are called. - * - *

Clients may invoke onNext at most once for server streaming calls, but may receive many - * onNext callbacks. Servers may invoke onNext at most once for client streaming calls, but may - * receive many onNext callbacks. - * - *

If an exception is thrown by an implementation the caller is expected to terminate the - * stream by calling {@link #onError(Throwable)} with the caught exception prior to propagating - * it. - * - * @param value the value passed to the stream - */ - void onNext(V value); - - /** - * Receives a terminating error from the stream. - * - *

May only be called once and if called, it must be the last method called. In particular if - * an exception is thrown by an implementation of {@code onError}, no further calls to any method - * are allowed. - * - * @param t the error occurred on the stream - */ - void onError(Throwable t); - - /** - * Receives a notification of successful stream completion. - * - *

May only be called once, and if called it must be the last method called. In particular if - * an exception is thrown by an implementation of {@code onCompleted}, no further calls to any - * method are allowed. - */ - void onCompleted(); -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/ApiStreamObserverAdapter.java b/gax/src/main/java/com/google/api/gax/rpc/ApiStreamObserverAdapter.java deleted file mode 100644 index 7df0e58b8..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/ApiStreamObserverAdapter.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -/** - * Backwards compatibility bridge from the new {@link ResponseObserver} api to the old {@link - * ApiStreamObserver} api. - * - *

Package-private for internal use. - * - * @param The type of the response. - * @deprecated Use ResponseObserver directly - */ -@Deprecated -class ApiStreamObserverAdapter extends StateCheckingResponseObserver { - private final ApiStreamObserver delegate; - - ApiStreamObserverAdapter(ApiStreamObserver delegate) { - this.delegate = delegate; - } - - @Override - protected void onStartImpl(StreamController controller) { - // Noop: the old style assumes automatic flow control and doesn't support cancellation. - } - - @Override - protected void onResponseImpl(T response) { - delegate.onNext(response); - } - - @Override - protected void onErrorImpl(Throwable t) { - delegate.onError(t); - } - - @Override - protected void onCompleteImpl() { - delegate.onCompleted(); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/AsyncTaskException.java b/gax/src/main/java/com/google/api/gax/rpc/AsyncTaskException.java deleted file mode 100644 index ef3afb1d2..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/AsyncTaskException.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -/** - * This exception is used to preserve the caller's stacktrace when invoking an async task in a sync - * context. It will be added as a suppressed exception when propagating the async exception. This - * allows callers to catch ApiException thrown in an async operation, while still maintaining the - * call site. - */ -public class AsyncTaskException extends RuntimeException { - AsyncTaskException() { - super("Asynchronous task failed"); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/AttemptCallable.java b/gax/src/main/java/com/google/api/gax/rpc/AttemptCallable.java deleted file mode 100644 index 6b419f1d4..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/AttemptCallable.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.api.gax.retrying.NonCancellableFuture; -import com.google.api.gax.retrying.RetryingFuture; -import com.google.common.base.Preconditions; -import java.util.concurrent.Callable; -import org.threeten.bp.Duration; - -/** - * A callable representing an attempt to make an RPC call. This class is used from {@link - * RetryingCallable}. - * - *

Package-private for internal use. - * - * @param request type - * @param response type - */ -class AttemptCallable implements Callable { - private final UnaryCallable callable; - private final RequestT request; - private final ApiCallContext originalCallContext; - - private volatile RetryingFuture externalFuture; - - AttemptCallable( - UnaryCallable callable, RequestT request, ApiCallContext callContext) { - this.callable = Preconditions.checkNotNull(callable); - this.request = Preconditions.checkNotNull(request); - this.originalCallContext = Preconditions.checkNotNull(callContext); - } - - public void setExternalFuture(RetryingFuture externalFuture) { - this.externalFuture = Preconditions.checkNotNull(externalFuture); - } - - @Override - public ResponseT call() { - ApiCallContext callContext = originalCallContext; - - try { - // Set the RPC timeout if the caller did not provide their own. - Duration rpcTimeout = externalFuture.getAttemptSettings().getRpcTimeout(); - if (!rpcTimeout.isZero() && callContext.getTimeout() == null) { - callContext = callContext.withTimeout(rpcTimeout); - } - - externalFuture.setAttemptFuture(new NonCancellableFuture()); - if (externalFuture.isDone()) { - return null; - } - - callContext - .getTracer() - .attemptStarted(request, externalFuture.getAttemptSettings().getOverallAttemptCount()); - - ApiFuture internalFuture = callable.futureCall(request, callContext); - externalFuture.setAttemptFuture(internalFuture); - } catch (Throwable e) { - externalFuture.setAttemptFuture(ApiFutures.immediateFailedFuture(e)); - } - - return null; - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/Batch.java b/gax/src/main/java/com/google/api/gax/rpc/Batch.java deleted file mode 100644 index b23069e89..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/Batch.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.InternalApi; -import com.google.api.gax.batching.BatchMerger; -import com.google.api.gax.batching.ElementCounter; -import com.google.api.gax.batching.RequestBuilder; -import java.util.ArrayList; -import java.util.List; - -/** - * A Batch contains a collection of requests that are to be batched into a single API call. - * - *

A Batch contains a single {@link UnaryCallable} object, which will be used to make the API - * call, and a list of {@link BatchedRequestIssuer} objects, which represent the individual requests - * in the batch. - * - *

Additional batches can be merged into an existing batch using the {@link #merge(Batch)} - * method. Request objects are combined using a {@link RequestBuilder} into a single request. - * - *

This is public only for technical reasons, for advanced usage. - */ -@InternalApi -public class Batch { - private final List> requestIssuerList; - - private final RequestBuilder requestBuilder; - private UnaryCallable callable; - private long byteCount; - - public Batch( - BatchingDescriptor descriptor, - RequestT request, - UnaryCallable callable, - BatchedFuture batchedFuture) { - this.requestBuilder = descriptor.getRequestBuilder(); - this.requestIssuerList = new ArrayList<>(); - this.requestBuilder.appendRequest(request); - this.callable = callable; - this.requestIssuerList.add( - new BatchedRequestIssuer<>(batchedFuture, descriptor.countElements(request))); - this.byteCount = descriptor.countBytes(request); - } - - public RequestT getRequest() { - return requestBuilder.build(); - } - - public UnaryCallable getCallable() { - return callable; - } - - public List> getRequestIssuerList() { - return requestIssuerList; - } - - public long getByteCount() { - return byteCount; - } - - /** Merge the given batch into this batch. */ - public void merge(Batch batch) { - requestBuilder.appendRequest(batch.getRequest()); - requestIssuerList.addAll(batch.requestIssuerList); - if (this.callable == null) { - this.callable = batch.callable; - } - this.byteCount += batch.byteCount; - } - - static class BatchElementCounter - implements ElementCounter> { - private final BatchingDescriptor batchingDescriptor; - - BatchElementCounter(BatchingDescriptor batchingDescriptor) { - this.batchingDescriptor = batchingDescriptor; - } - - @Override - public long count(Batch batch) { - return batchingDescriptor.countElements(batch.getRequest()); - } - } - - static class BatchByteCounter - implements ElementCounter> { - @Override - public long count(Batch batch) { - return batch.getByteCount(); - } - } - - static class BatchMergerImpl - implements BatchMerger> { - @Override - public void merge(Batch batch, Batch newBatch) { - batch.merge(newBatch); - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/BatchExecutor.java b/gax/src/main/java/com/google/api/gax/rpc/BatchExecutor.java deleted file mode 100644 index c8d6405ca..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/BatchExecutor.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static com.google.common.util.concurrent.MoreExecutors.directExecutor; - -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutureCallback; -import com.google.api.core.ApiFutures; -import com.google.api.gax.batching.PartitionKey; -import com.google.api.gax.batching.ThresholdBatchReceiver; -import com.google.common.base.Preconditions; -import java.util.List; - -/** - * A ThresholdBatchReceiver which uses a provided {@link BatchingDescriptor} to merge the items from - * the Batch into a single request, invoke the callable from the Batch to issue the request, split - * the batch response into the components matching each incoming request, and finally send the - * result back to the listener for each request. - * - *

BatchExecutor methods validateBatch and processBatch use the thread-safe guarantee of - * BatchingDescriptor to achieve thread safety. - * - *

Package-private for internal use. - */ -class BatchExecutor - implements ThresholdBatchReceiver> { - - private final BatchingDescriptor batchingDescriptor; - private final PartitionKey partitionKey; - - public BatchExecutor( - BatchingDescriptor batchingDescriptor, PartitionKey partitionKey) { - this.batchingDescriptor = Preconditions.checkNotNull(batchingDescriptor); - this.partitionKey = Preconditions.checkNotNull(partitionKey); - } - - @Override - public void validateBatch(Batch item) { - PartitionKey itemPartitionKey = batchingDescriptor.getBatchPartitionKey(item.getRequest()); - if (!itemPartitionKey.equals(partitionKey)) { - String requestClassName = item.getRequest().getClass().getSimpleName(); - throw new IllegalArgumentException( - String.format( - "For type %s, invalid partition key: %s, should be: %s", - requestClassName, itemPartitionKey, partitionKey)); - } - } - - @Override - public ApiFuture processBatch(Batch batch) { - UnaryCallable callable = batch.getCallable(); - RequestT request = batch.getRequest(); - final List> requestIssuerList = batch.getRequestIssuerList(); - ApiFuture future = callable.futureCall(request); - ApiFutures.addCallback( - future, - new ApiFutureCallback() { - @Override - public void onSuccess(ResponseT result) { - batchingDescriptor.splitResponse(result, requestIssuerList); - for (BatchedRequestIssuer requestIssuer : requestIssuerList) { - requestIssuer.sendResult(); - } - } - - @Override - public void onFailure(Throwable t) { - batchingDescriptor.splitException(t, requestIssuerList); - for (BatchedRequestIssuer requestIssuer : requestIssuerList) { - requestIssuer.sendResult(); - } - } - }, - directExecutor()); - return future; - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/BatchedFuture.java b/gax/src/main/java/com/google/api/gax/rpc/BatchedFuture.java deleted file mode 100644 index 6f91230f8..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/BatchedFuture.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.AbstractApiFuture; -import com.google.api.core.InternalApi; - -/** - * An ApiFuture to be used with batching. - * - *

This is public only for technical reasons, for advanced usage. - */ -@InternalApi -public class BatchedFuture extends AbstractApiFuture { - - /** Get a new instance. */ - public static BatchedFuture create() { - return new BatchedFuture<>(); - } - - @Override - public boolean set(ResponseT value) { - return super.set(value); - } - - @Override - public boolean setException(Throwable throwable) { - return super.setException(throwable); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/BatchedRequestIssuer.java b/gax/src/main/java/com/google/api/gax/rpc/BatchedRequestIssuer.java deleted file mode 100644 index 599fa5183..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/BatchedRequestIssuer.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.common.base.Preconditions; - -/** - * BatchedRequestIssuer receives a response or an exception and waits to set the given batchedFuture - * until sendResult() is called. - * - *

This class is designed to be used by generated code. - */ -public final class BatchedRequestIssuer { - private final BatchedFuture batchedFuture; - private final long messageCount; - private ResponseT responseToSend; - private boolean hasResponse; - private Throwable throwableToSend; - - public BatchedRequestIssuer(BatchedFuture batchedFuture, long messageCount) { - this.batchedFuture = batchedFuture; - this.messageCount = messageCount; - this.responseToSend = null; - this.throwableToSend = null; - } - - public long getMessageCount() { - return messageCount; - } - - /** - * Set the response to set on the batched future. If this is called, setException cannot be - * called. - */ - public void setResponse(ResponseT response) { - Preconditions.checkState(throwableToSend == null, "Cannot set both exception and response"); - hasResponse = true; - responseToSend = response; - } - - /** - * Set the exception to set on the batched future. If this is called, setResponse cannot be - * called. - */ - public void setException(Throwable throwable) { - Preconditions.checkState(!hasResponse, "Cannot set both exception and response"); - throwableToSend = throwable; - } - - /** Sends back the result that was stored by either setResponse or setException */ - public void sendResult() { - if (hasResponse) { - batchedFuture.set(responseToSend); - } else if (throwableToSend != null) { - batchedFuture.setException(throwableToSend); - } else { - throw new IllegalStateException( - "Neither response nor exception were set in BatchedRequestIssuer"); - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/BatcherFactory.java b/gax/src/main/java/com/google/api/gax/rpc/BatcherFactory.java deleted file mode 100644 index 8ac809399..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/BatcherFactory.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.InternalApi; -import com.google.api.gax.batching.BatchingFlowController; -import com.google.api.gax.batching.BatchingSettings; -import com.google.api.gax.batching.BatchingThreshold; -import com.google.api.gax.batching.ElementCounter; -import com.google.api.gax.batching.FlowController; -import com.google.api.gax.batching.NumericThreshold; -import com.google.api.gax.batching.PartitionKey; -import com.google.api.gax.batching.ThresholdBatcher; -import com.google.api.gax.rpc.Batch.BatchByteCounter; -import com.google.api.gax.rpc.Batch.BatchElementCounter; -import com.google.api.gax.rpc.Batch.BatchMergerImpl; -import com.google.common.collect.ImmutableList; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ScheduledExecutorService; - -/** - * A Factory class which, for each unique partitionKey, creates a trio including a ThresholdBatcher, - * BatchExecutor, and ThresholdBatchingForwarder. The ThresholdBatchingForwarder pulls items from - * the ThresholdBatcher and forwards them to the BatchExecutor for processing. - * - *

This is public only for technical reasons, for advanced usage. - */ -@InternalApi -public final class BatcherFactory { - private final Map>> batchers = - new ConcurrentHashMap<>(); - private final ScheduledExecutorService executor; - private final BatchingDescriptor batchingDescriptor; - private final FlowController flowController; - private final BatchingSettings batchingSettings; - private final Object lock = new Object(); - - public BatcherFactory( - BatchingDescriptor batchingDescriptor, - BatchingSettings batchingSettings, - ScheduledExecutorService executor, - FlowController flowController) { - this.batchingDescriptor = batchingDescriptor; - this.batchingSettings = batchingSettings; - this.executor = executor; - this.flowController = flowController; - } - - /** - * Provides the ThresholdBatcher corresponding to the given partitionKey, or constructs one if it - * doesn't exist yet. The implementation is thread-safe. - */ - public ThresholdBatcher> getPushingBatcher(PartitionKey partitionKey) { - ThresholdBatcher> batcher = batchers.get(partitionKey); - if (batcher == null) { - synchronized (lock) { - batcher = batchers.get(partitionKey); - if (batcher == null) { - batcher = createBatcher(partitionKey); - batchers.put(partitionKey, batcher); - } - } - } - return batcher; - } - - /** - * Returns the BatchingSettings object that is associated with this factory. - * - *

This is public only for technical reasons, for advanced usage. - */ - @InternalApi - public BatchingSettings getBatchingSettings() { - return batchingSettings; - } - - private ThresholdBatcher> createBatcher(PartitionKey partitionKey) { - BatchExecutor processor = - new BatchExecutor<>(batchingDescriptor, partitionKey); - BatchingFlowController> batchingFlowController = - new BatchingFlowController<>( - flowController, - new BatchElementCounter<>(batchingDescriptor), - new BatchByteCounter()); - return ThresholdBatcher.>newBuilder() - .setThresholds(getThresholds(batchingSettings)) - .setExecutor(executor) - .setMaxDelay(batchingSettings.getDelayThreshold()) - .setReceiver(processor) - .setFlowController(batchingFlowController) - .setBatchMerger(new BatchMergerImpl()) - .build(); - } - - private ImmutableList>> getThresholds( - BatchingSettings batchingSettings) { - ImmutableList.Builder>> listBuilder = - ImmutableList.builder(); - - if (batchingSettings.getElementCountThreshold() != null) { - ElementCounter> elementCounter = - new BatchElementCounter<>(batchingDescriptor); - - BatchingThreshold> countThreshold = - new NumericThreshold<>(batchingSettings.getElementCountThreshold(), elementCounter); - listBuilder.add(countThreshold); - } - - if (batchingSettings.getRequestByteThreshold() != null) { - ElementCounter> requestByteCounter = - new BatchByteCounter(); - - BatchingThreshold> byteThreshold = - new NumericThreshold<>(batchingSettings.getRequestByteThreshold(), requestByteCounter); - listBuilder.add(byteThreshold); - } - - return listBuilder.build(); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/BatchingCallSettings.java b/gax/src/main/java/com/google/api/gax/rpc/BatchingCallSettings.java deleted file mode 100644 index 922f48640..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/BatchingCallSettings.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.InternalExtensionOnly; -import com.google.api.gax.batching.BatchingSettings; -import com.google.api.gax.batching.FlowController; -import com.google.api.gax.retrying.RetrySettings; -import com.google.common.base.MoreObjects; -import com.google.common.base.Preconditions; -import java.util.Set; - -/** - * A settings class to configure a {@link UnaryCallable} for calls to an API method that supports - * batching. The settings are provided using an instance of {@link BatchingSettings}. - */ -@InternalExtensionOnly -public final class BatchingCallSettings - extends UnaryCallSettings { - private final BatchingDescriptor batchingDescriptor; - private final BatchingSettings batchingSettings; - private final FlowController flowController; - - public BatchingDescriptor getBatchingDescriptor() { - return batchingDescriptor; - } - - public BatchingSettings getBatchingSettings() { - return batchingSettings; - } - - public FlowController getFlowController() { - return flowController; - } - - private BatchingCallSettings(Builder builder) { - super(builder); - this.batchingDescriptor = builder.batchingDescriptor; - this.batchingSettings = Preconditions.checkNotNull(builder.batchingSettings); - FlowController flowControllerToUse = builder.flowController; - if (flowControllerToUse == null) { - flowControllerToUse = new FlowController(batchingSettings.getFlowControlSettings()); - } - this.flowController = flowControllerToUse; - } - - public static Builder newBuilder( - BatchingDescriptor batchingDescriptor) { - return new Builder<>(batchingDescriptor); - } - - @Override - public final Builder toBuilder() { - return new Builder<>(this); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("retryableCodes", getRetryableCodes()) - .add("retrySettings", getRetrySettings()) - .add("batchingSettings", batchingSettings) - .toString(); - } - - public static class Builder - extends UnaryCallSettings.Builder { - - private BatchingDescriptor batchingDescriptor; - private BatchingSettings batchingSettings; - private FlowController flowController; - - public Builder(BatchingDescriptor batchingDescriptor) { - this.batchingDescriptor = batchingDescriptor; - } - - public Builder(BatchingCallSettings settings) { - super(settings); - this.batchingDescriptor = settings.batchingDescriptor; - this.batchingSettings = settings.batchingSettings; - // TODO decide if a copy should be made - this.flowController = settings.flowController; - } - - public BatchingDescriptor getBatchingDescriptor() { - return batchingDescriptor; - } - - public Builder setBatchingSettings(BatchingSettings batchingSettings) { - this.batchingSettings = batchingSettings; - return this; - } - - public BatchingSettings getBatchingSettings() { - return batchingSettings; - } - - public Builder setFlowController(FlowController flowController) { - this.flowController = flowController; - return this; - } - - public FlowController getFlowController() { - return flowController; - } - - @Override - public Builder setRetryableCodes(Set retryableCodes) { - super.setRetryableCodes(retryableCodes); - return this; - } - - @Override - public Builder setRetryableCodes(StatusCode.Code... codes) { - super.setRetryableCodes(codes); - return this; - } - - @Override - public Builder setRetrySettings(RetrySettings retrySettings) { - super.setRetrySettings(retrySettings); - return this; - } - - @Override - public BatchingCallSettings build() { - return new BatchingCallSettings<>(this); - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/BatchingCallable.java b/gax/src/main/java/com/google/api/gax/rpc/BatchingCallable.java deleted file mode 100644 index 2d6a1f37a..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/BatchingCallable.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.ApiFuture; -import com.google.api.core.InternalApi; -import com.google.api.gax.batching.FlowController.FlowControlException; -import com.google.api.gax.batching.FlowController.FlowControlRuntimeException; -import com.google.api.gax.batching.PartitionKey; -import com.google.api.gax.batching.ThresholdBatcher; -import com.google.common.base.Preconditions; - -/** - * A {@link UnaryCallable} which will batch requests based on the given BatchingDescriptor and - * BatcherFactory. The BatcherFactory provides a distinct Batcher for each partition as specified by - * the BatchingDescriptor. An example of a batching partition would be a pubsub topic. - * - *

This is public only for technical reasons, for advanced usage. - */ -@InternalApi("For use by transport-specific implementations") -public class BatchingCallable extends UnaryCallable { - private final UnaryCallable callable; - private final BatchingDescriptor batchingDescriptor; - private final BatcherFactory batcherFactory; - - public BatchingCallable( - UnaryCallable callable, - BatchingDescriptor batchingDescriptor, - BatcherFactory batcherFactory) { - this.callable = Preconditions.checkNotNull(callable); - this.batchingDescriptor = Preconditions.checkNotNull(batchingDescriptor); - this.batcherFactory = Preconditions.checkNotNull(batcherFactory); - } - - @Override - public ApiFuture futureCall(RequestT request, ApiCallContext context) { - if (batcherFactory.getBatchingSettings().getIsEnabled()) { - BatchedFuture result = BatchedFuture.create(); - UnaryCallable unaryCallable = callable.withDefaultCallContext(context); - Batch batchableMessage = - new Batch(batchingDescriptor, request, unaryCallable, result); - PartitionKey partitionKey = batchingDescriptor.getBatchPartitionKey(request); - ThresholdBatcher> batcher = - batcherFactory.getPushingBatcher(partitionKey); - try { - batcher.add(batchableMessage); - return result; - } catch (FlowControlException e) { - throw FlowControlRuntimeException.fromFlowControlException(e); - } - } else { - return callable.futureCall(request, context); - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/BatchingDescriptor.java b/gax/src/main/java/com/google/api/gax/rpc/BatchingDescriptor.java deleted file mode 100644 index ce4cf737c..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/BatchingDescriptor.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.gax.batching.PartitionKey; -import com.google.api.gax.batching.RequestBuilder; -import java.util.Collection; - -/** - * Interface which represents an object that transforms request/response data for the purposes of - * batching. - * - *

Implementations of BatchingDescriptor must guarantee that all methods are stateless and thread - * safe. - * - *

This class is designed to be used by generated code. - */ -public interface BatchingDescriptor { - - /** Returns the value of the partition key for the given request. */ - PartitionKey getBatchPartitionKey(RequestT request); - - /** Get the Builder object for the request type RequestT. */ - RequestBuilder getRequestBuilder(); - - /** - * Splits the result from a batched call into an individual setResponse call on each - * RequestIssuer. - */ - void splitResponse( - ResponseT batchResponse, Collection> batch); - - /** - * Splits the exception that resulted from a batched call into an individual setException call on - * each RequestIssuer. - */ - void splitException( - Throwable throwable, Collection> batch); - - /** Returns the number of elements contained in this request. */ - long countElements(RequestT request); - - /** Returns the size in bytes of this request. */ - long countBytes(RequestT request); -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/BidiStream.java b/gax/src/main/java/com/google/api/gax/rpc/BidiStream.java deleted file mode 100644 index a47468567..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/BidiStream.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.InternalApi; - -/** - * A wrapper around a bidirectional stream. - * - *

This class asynchronously pulls responses from upstream via {@link - * StreamController#request(int)} and exposes them via its Iterator. The implementation is back - * pressure aware and uses a constant buffer of 1 item. - * - *

Please note that the stream can only be consumed once and must either be fully consumed or be - * canceled. - * - *

This class can also be used to send requests to the server using {@link #send(Object)}. - * - *

Neither this class nor the iterator it returns is thread-safe. - * - *

In the example below, we iterate through responses from the server and echo back the items we - * see: - * - *

{@code
- * BidiStream stream = ...;
- *
- * for (Item item : stream) {
- *   System.out.println(item.id());
- *
- *   stream.send(item.id());
- *
- *   // Allow for early termination
- *   if (item.id().equals("needle")) {
- *     // Cancelling the stream will cause `hasNext()` to return false on the next iteration,
- *     // naturally breaking the loop.
- *     stream.cancel();
- *   }
- * }
- * }
- * - * @param The type of each request. - * @param The type of each response. - */ -public class BidiStream extends ServerStream - implements ClientStream { - - private ClientStream clientStream; - - @InternalApi("For use by BidiStreamingCallable only.") - BidiStream() {} - - @InternalApi("For use by BidiStreamingCallable only.") - void setClientStream(ClientStream clientStream) { - this.clientStream = clientStream; - } - - /** Send {@code req} to the server. */ - @Override - public void send(RequestT req) { - clientStream.send(req); - } - - /** - * Reports whether a message can be sent without requiring excessive buffering internally. - * - *

This method only provides a hint. It is still correct for the user to call {@link - * #send(Object)} even when this method returns {@code false}. - */ - @Override - public boolean isSendReady() { - return clientStream.isSendReady(); - } - - /** - * Closes the sending side of the stream. Once called, no further calls to {@link #send(Object)}, - * {@link #closeSend()}, or {@link #closeSendWithError(Throwable)} are allowed. - * - *

Calling this method does not affect the receiving side, the iterator will continue to yield - * responses from the server. - */ - @Override - public void closeSend() { - clientStream.closeSend(); - } - - /** - * Closes the sending side of the stream with error. The error is propagated to the server. Once - * called, no further calls to {@link #send(Object)}, {@link #closeSend()}, or {@link - * #closeSendWithError(Throwable)} are allowed. - * - *

Calling this method does not affect the receiving side, the iterator will continue to yield - * responses from the server. - */ - @Override - public void closeSendWithError(Throwable t) { - clientStream.closeSendWithError(t); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/BidiStreamObserver.java b/gax/src/main/java/com/google/api/gax/rpc/BidiStreamObserver.java deleted file mode 100644 index 427a68068..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/BidiStreamObserver.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -public interface BidiStreamObserver - extends ResponseObserver, ClientStreamReadyObserver {} diff --git a/gax/src/main/java/com/google/api/gax/rpc/BidiStreamingCallable.java b/gax/src/main/java/com/google/api/gax/rpc/BidiStreamingCallable.java deleted file mode 100644 index c97367588..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/BidiStreamingCallable.java +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -/** - * A BidiStreamingCallable is an immutable object which is capable of making RPC calls to - * bidirectional streaming API methods. Not all transports support streaming. - * - *

It is considered advanced usage for a user to create a BidiStreamingCallable themselves. This - * class is intended to be created by a generated client class, and configured by instances of - * StreamingCallSettings.Builder which are exposed through the client settings class. - */ -public abstract class BidiStreamingCallable { - - protected BidiStreamingCallable() {} - - /** - * The "base" method from which other forms of {@code call}s are derived. Most users will not need - * to call this method directly. - * - *

However, it is {@code public}, since library authors might want to call this method in - * adaptor classes. - */ - public abstract ClientStream internalCall( - ResponseObserver responseObserver, - ClientStreamReadyObserver onReady, - ApiCallContext context); - - /** - * Listens to server responses and send requests when the network is free. Example usage: - * - *

{@code
-   * final Iterator sourceDataIterator = intCollection.iterator();
-   * BidiStreamObserver bidiStreamObserver = new BidiStreamObserver() {
-   *   public void onStart(StreamController controller) {
-   *     // no-op
-   *   }
-   *
-   *   public void onResponse(String response) {
-   *     System.out.println(response);
-   *   }
-   *
-   *   public void onComplete() {
-   *     System.out.println("done!");
-   *   }
-   *
-   *   public void onError(Throwable t) {
-   *     System.out.println("error: " + t);
-   *   }
-   *
-   *   public void onReady(ClientStream stream) {
-   *     while (sourceDataIterator.hasNext()) {
-   *       if (stream.isReady()) {
-   *         stream.send(sourceDataIterator.next());
-   *       } else {
-   *         // It's OK we haven't consumed the whole iterator;
-   *         // onReady will be called again when the network becomes free.
-   *         return;
-   *       }
-   *     }
-   *     // We ran out of things to send.
-   *     stream.close();
-   *   }
-   * };
-   *
-   * bidiStreamingCallable.call(bidiStreamObserver);
-   * }
- */ - public void call(final BidiStreamObserver bidiObserver) { - call(bidiObserver, null); - } - - /** Listens to server responses and send requests when the network is free. */ - public void call( - final BidiStreamObserver bidiObserver, ApiCallContext context) { - internalCall( - bidiObserver, - new ClientStreamReadyObserver() { - @Override - public void onReady(ClientStream stream) { - bidiObserver.onReady(stream); - } - }, - context); - } - - /** - * Send requests and iterate over server responses. - * - *

This returns a live stream that must either be fully consumed or cancelled. Example usage: - * - *

{@code
-   * BidiStream stream = bidiStreamingCallable.call()
-   * for (String s : stream) {
-   *   if ("needle".equals(s)) {
-   *     // Cancelling the stream will cause `hasNext()` to return false on the next iteration,
-   *     // naturally breaking the loop.
-   *     stream.cancel();
-   *   }
-   *   stream.send(s);
-   * }
-   * }
- */ - public BidiStream call() { - return call((ApiCallContext) null); - } - - /** - * Send requests and iterate over server responses. - * - *

This returns a live stream that must either be fully consumed or cancelled. - */ - public BidiStream call(ApiCallContext context) { - BidiStream stream = new BidiStream<>(); - ClientStream clientStream = splitCall(stream.observer(), context); - stream.setClientStream(clientStream); - return stream; - } - - /** - * Send requests to the server and listens to responses. - * - *

Example usage: - * - *

{@code
-   * ResponseObserver responseObserver = new ResponseObserver() {
-   *   public void onStart(StreamController controller) {
-   *     // no-op
-   *   }
-   *
-   *  public void onResponse(String response) {
-   *    System.out.println(response);
-   *  }
-   *
-   *  public void onComplete() {
-   *    System.out.println("done!");
-   *  }
-   *
-   *  public void onError(Throwable t) {
-   *    System.out.println("error: " + t);
-   *  }
-   * };
-   *
-   * ClientStream clientStream = bidiStreamingCallable.splitCall(responseObserver);
-   * clientStream.send(42);
-   * clientStream.send(43);
-   * clientStream.close();
-   * }
- */ - public ClientStream splitCall(ResponseObserver responseObserver) { - return splitCall(responseObserver, null); - } - - /** Send requests to the server and listens to responses. */ - public ClientStream splitCall( - ResponseObserver responseObserver, ApiCallContext context) { - return internalCall( - responseObserver, - new ClientStreamReadyObserver() { - @Override - public void onReady(ClientStream stream) { - // no op - } - }, - context); - } - - /** - * Conduct a bidirectional streaming call with the given {@link ApiCallContext}. - * - * @param responseObserver {@link ApiStreamObserver} to observe the streaming responses - * @param context {@link ApiCallContext} to provide context information for the RPC call. - * @return {@link ApiStreamObserver} which is used for making streaming requests. - * @deprecated Please use {@link #splitCall(ResponseObserver, ApiCallContext)} instead. - */ - @Deprecated - public ApiStreamObserver bidiStreamingCall( - ApiStreamObserver responseObserver, ApiCallContext context) { - final ClientStream stream = - splitCall(new ApiStreamObserverAdapter<>(responseObserver), context); - return new ApiStreamObserver() { - @Override - public void onNext(RequestT request) { - stream.send(request); - } - - @Override - public void onError(Throwable t) { - stream.closeSendWithError(t); - } - - @Override - public void onCompleted() { - stream.closeSend(); - } - }; - } - - /** - * Conduct a bidirectional streaming call - * - * @param responseObserver {@link ApiStreamObserver} to observe the streaming responses - * @return {@link ApiStreamObserver} which is used for making streaming requests. - * @deprecated Please use {@link #splitCall(ResponseObserver)} instead. - */ - @Deprecated - public ApiStreamObserver bidiStreamingCall( - ApiStreamObserver responseObserver) { - return bidiStreamingCall(responseObserver, null); - } - - /** - * Returns a new {@code BidiStreamingCallable} with an {@link ApiCallContext} that is used as a - * default when none is supplied in individual calls. - * - * @param defaultCallContext the default {@link ApiCallContext}. - */ - public BidiStreamingCallable withDefaultCallContext( - final ApiCallContext defaultCallContext) { - return new BidiStreamingCallable() { - @Override - public ClientStream internalCall( - ResponseObserver responseObserver, - ClientStreamReadyObserver onReady, - ApiCallContext thisCallContext) { - return BidiStreamingCallable.this.internalCall( - responseObserver, onReady, defaultCallContext.merge(thisCallContext)); - } - }; - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/Callables.java b/gax/src/main/java/com/google/api/gax/rpc/Callables.java deleted file mode 100644 index 413a11649..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/Callables.java +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.BetaApi; -import com.google.api.gax.batching.BatchingSettings; -import com.google.api.gax.longrunning.OperationResponsePollAlgorithm; -import com.google.api.gax.longrunning.OperationSnapshot; -import com.google.api.gax.retrying.ExponentialRetryAlgorithm; -import com.google.api.gax.retrying.RetryAlgorithm; -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.retrying.ScheduledRetryingExecutor; -import com.google.api.gax.retrying.StreamingRetryAlgorithm; -import java.util.Collection; - -/** - * Class with utility methods to create callable objects using provided settings. - * - *

The callable objects wrap a given direct callable with features like retry and exception - * translation. - */ -@BetaApi -public class Callables { - - private Callables() {} - - public static UnaryCallable retrying( - UnaryCallable innerCallable, - UnaryCallSettings callSettings, - ClientContext clientContext) { - - UnaryCallSettings settings = callSettings; - - if (areRetriesDisabled(settings.getRetryableCodes(), settings.getRetrySettings())) { - // When retries are disabled, the total timeout can be treated as the rpc timeout. - settings = - settings - .toBuilder() - .setSimpleTimeoutNoRetries(settings.getRetrySettings().getTotalTimeout()) - .build(); - } - - RetryAlgorithm retryAlgorithm = - new RetryAlgorithm<>( - new ApiResultRetryAlgorithm(), - new ExponentialRetryAlgorithm(settings.getRetrySettings(), clientContext.getClock())); - ScheduledRetryingExecutor retryingExecutor = - new ScheduledRetryingExecutor<>(retryAlgorithm, clientContext.getExecutor()); - return new RetryingCallable<>( - clientContext.getDefaultCallContext(), innerCallable, retryingExecutor); - } - - public static ServerStreamingCallable retrying( - ServerStreamingCallable innerCallable, - ServerStreamingCallSettings callSettings, - ClientContext clientContext) { - - ServerStreamingCallSettings settings = callSettings; - if (areRetriesDisabled(settings.getRetryableCodes(), settings.getRetrySettings())) { - // When retries are disabled, the total timeout can be treated as the rpc timeout. - settings = - settings - .toBuilder() - .setSimpleTimeoutNoRetries(settings.getRetrySettings().getTotalTimeout()) - .build(); - } - - StreamingRetryAlgorithm retryAlgorithm = - new StreamingRetryAlgorithm<>( - new ApiResultRetryAlgorithm(), - new ExponentialRetryAlgorithm(settings.getRetrySettings(), clientContext.getClock())); - - ScheduledRetryingExecutor retryingExecutor = - new ScheduledRetryingExecutor<>(retryAlgorithm, clientContext.getExecutor()); - - return new RetryingServerStreamingCallable<>( - innerCallable, retryingExecutor, settings.getResumptionStrategy()); - } - - public static ServerStreamingCallable watched( - ServerStreamingCallable callable, - ServerStreamingCallSettings callSettings, - ClientContext clientContext) { - - callable = new WatchdogServerStreamingCallable<>(callable, clientContext.getStreamWatchdog()); - - callable = - callable.withDefaultCallContext( - clientContext - .getDefaultCallContext() - .withStreamIdleTimeout(callSettings.getIdleTimeout())); - - return callable; - } - - /** - * Create a callable object that represents a batching API method. Designed for use by generated - * code. - * - * @param innerCallable the callable to issue calls - * @param batchingCallSettings {@link BatchingSettings} to configure the batching related settings - * with. - * @param context {@link ClientContext} to use to connect to the service. - * @return {@link UnaryCallable} callable object. - */ - public static UnaryCallable batching( - UnaryCallable innerCallable, - BatchingCallSettings batchingCallSettings, - ClientContext context) { - return batchingImpl(innerCallable, batchingCallSettings, context).unaryCallable; - } - - /** This only exists to give tests access to batcherFactory for flushing purposes. */ - static class BatchingCreateResult { - private final BatcherFactory batcherFactory; - private final UnaryCallable unaryCallable; - - private BatchingCreateResult( - BatcherFactory batcherFactory, - UnaryCallable unaryCallable) { - this.batcherFactory = batcherFactory; - this.unaryCallable = unaryCallable; - } - - public BatcherFactory getBatcherFactory() { - return batcherFactory; - } - - public UnaryCallable getUnaryCallable() { - return unaryCallable; - } - } - - static BatchingCreateResult batchingImpl( - UnaryCallable innerCallable, - BatchingCallSettings batchingCallSettings, - ClientContext clientContext) { - BatcherFactory batcherFactory = - new BatcherFactory<>( - batchingCallSettings.getBatchingDescriptor(), - batchingCallSettings.getBatchingSettings(), - clientContext.getExecutor(), - batchingCallSettings.getFlowController()); - UnaryCallable callable = - new BatchingCallable<>( - innerCallable, batchingCallSettings.getBatchingDescriptor(), batcherFactory); - return new BatchingCreateResult<>(batcherFactory, callable); - } - - /** - * Create a paged callable object that represents a paged API method. Designed for use by - * generated code. - * - * @param innerCallable the callable to issue calls - * @param pagedCallSettings {@link PagedCallSettings} to configure the paged settings with. - * @return {@link UnaryCallable} callable object. - */ - public static - UnaryCallable paged( - UnaryCallable innerCallable, - PagedCallSettings pagedCallSettings) { - return new PagedCallable<>(innerCallable, pagedCallSettings.getPagedListResponseFactory()); - } - - /** - * Creates a callable object that represents a long-running operation. Designed for use by - * generated code. - * - * @param initialCallable the callable that initiates the operation - * @param operationCallSettings {@link OperationCallSettings} to configure the method-level - * settings with. - * @param clientContext {@link ClientContext} to use to connect to the service. - * @param longRunningClient {@link LongRunningClient} to use to poll for updates on the Operation. - * @return {@link OperationCallable} callable object. - */ - public static - OperationCallable longRunningOperation( - UnaryCallable initialCallable, - OperationCallSettings operationCallSettings, - ClientContext clientContext, - LongRunningClient longRunningClient) { - return longRunningOperationImpl( - initialCallable, operationCallSettings, clientContext, longRunningClient); - } - - static - OperationCallableImpl longRunningOperationImpl( - UnaryCallable initialCallable, - OperationCallSettings operationCallSettings, - ClientContext clientContext, - LongRunningClient longRunningClient) { - RetryAlgorithm pollingAlgorithm = - new RetryAlgorithm<>( - new OperationResponsePollAlgorithm(), operationCallSettings.getPollingAlgorithm()); - ScheduledRetryingExecutor scheduler = - new ScheduledRetryingExecutor<>(pollingAlgorithm, clientContext.getExecutor()); - - return new OperationCallableImpl<>( - initialCallable, scheduler, longRunningClient, operationCallSettings); - } - - private static boolean areRetriesDisabled( - Collection retryableCodes, RetrySettings retrySettings) { - return retrySettings.getMaxAttempts() == 1 - || retryableCodes.isEmpty() - || (retrySettings.getMaxAttempts() == 0 && retrySettings.getTotalTimeout().isZero()); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/CancelledException.java b/gax/src/main/java/com/google/api/gax/rpc/CancelledException.java deleted file mode 100644 index 7bc15f04c..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/CancelledException.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -/** The exception thrown when the operation was cancelled (typically by the caller). */ -public class CancelledException extends ApiException { - public CancelledException(Throwable cause, StatusCode statusCode, boolean retryable) { - super(cause, statusCode, retryable); - } - - public CancelledException( - String message, Throwable cause, StatusCode statusCode, boolean retryable) { - super(message, cause, statusCode, retryable); - } - - public CancelledException( - Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { - super(cause, statusCode, retryable, errorDetails); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/CheckingAttemptCallable.java b/gax/src/main/java/com/google/api/gax/rpc/CheckingAttemptCallable.java deleted file mode 100644 index 17670a5e7..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/CheckingAttemptCallable.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.api.gax.retrying.NonCancellableFuture; -import com.google.api.gax.retrying.RetryingFuture; -import com.google.common.base.Preconditions; -import java.util.concurrent.Callable; -import org.threeten.bp.Duration; - -/** - * A callable representing an attempt to check the status of something by issuing a call to a - * UnaryCallable. This class is used from {@link RecheckingCallable}. - * - *

Package-private for internal use. - * - * @param request type - * @param response type - */ -class CheckingAttemptCallable implements Callable { - private final UnaryCallable callable; - private final ApiCallContext originalCallContext; - - private volatile RetryingFuture externalFuture; - - CheckingAttemptCallable(UnaryCallable callable, ApiCallContext callContext) { - this.callable = Preconditions.checkNotNull(callable); - this.originalCallContext = Preconditions.checkNotNull(callContext); - } - - public void setExternalFuture(RetryingFuture externalFuture) { - this.externalFuture = Preconditions.checkNotNull(externalFuture); - } - - @Override - public ResponseT call() { - ApiCallContext callContext = originalCallContext; - - try { - Duration rpcTimeout = externalFuture.getAttemptSettings().getRpcTimeout(); - if (!rpcTimeout.isZero()) { - callContext = callContext.withTimeout(rpcTimeout); - } - - externalFuture.setAttemptFuture(new NonCancellableFuture()); - if (externalFuture.isDone()) { - return null; - } - - callContext - .getTracer() - .attemptStarted(externalFuture.getAttemptSettings().getOverallAttemptCount()); - - // NOTE: The callable here is an OperationCheckingCallable, which will compose its own - // request using a resolved operation name and ignore anything that we pass here for the - // request. - ApiFuture internalFuture = callable.futureCall(null, callContext); - externalFuture.setAttemptFuture(internalFuture); - } catch (Throwable e) { - externalFuture.setAttemptFuture(ApiFutures.immediateFailedFuture(e)); - } - - return null; - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/ClientContext.java b/gax/src/main/java/com/google/api/gax/rpc/ClientContext.java deleted file mode 100644 index 45a54e549..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/ClientContext.java +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.ApiClock; -import com.google.api.core.BetaApi; -import com.google.api.core.NanoClock; -import com.google.api.gax.core.BackgroundResource; -import com.google.api.gax.core.ExecutorAsBackgroundResource; -import com.google.api.gax.core.ExecutorProvider; -import com.google.api.gax.rpc.internal.QuotaProjectIdHidingCredentials; -import com.google.api.gax.rpc.mtls.MtlsProvider; -import com.google.api.gax.tracing.ApiTracerFactory; -import com.google.api.gax.tracing.BaseApiTracerFactory; -import com.google.auth.Credentials; -import com.google.auto.value.AutoValue; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Sets; -import java.io.IOException; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import org.threeten.bp.Duration; - -/** - * Encapsulates client state, including executor, credentials, and transport channel. - * - *

Unlike {@link ClientSettings} which allows users to configure the client, {@code - * ClientContext} is intended to be used in generated code. Most users will not need to use it. - */ -@AutoValue -public abstract class ClientContext { - private static final String QUOTA_PROJECT_ID_HEADER_KEY = "x-goog-user-project"; - - /** - * The objects that need to be closed in order to clean up the resources created in the process of - * creating this ClientContext. This will include the closeables from the transport context. - */ - public abstract List getBackgroundResources(); - - /** - * Gets the executor to use for running scheduled API call logic (such as retries and long-running - * operations). - */ - public abstract ScheduledExecutorService getExecutor(); - - @Nullable - public abstract Credentials getCredentials(); - - @Nullable - public abstract TransportChannel getTransportChannel(); - - public abstract Map getHeaders(); - - protected abstract Map getInternalHeaders(); - - public abstract ApiClock getClock(); - - public abstract ApiCallContext getDefaultCallContext(); - - @Nullable - public abstract Watchdog getStreamWatchdog(); - - @Nonnull - public abstract Duration getStreamWatchdogCheckInterval(); - - @Nullable - public abstract String getEndpoint(); - - @Nullable - public abstract String getQuotaProjectId(); - - /** Gets the {@link ApiTracerFactory} that will be used to generate traces for operations. */ - @BetaApi("The surface for tracing is not stable yet and may change in the future.") - @Nonnull - public abstract ApiTracerFactory getTracerFactory(); - - public static Builder newBuilder() { - return new AutoValue_ClientContext.Builder() - .setBackgroundResources(Collections.emptyList()) - .setExecutor(Executors.newScheduledThreadPool(0)) - .setHeaders(Collections.emptyMap()) - .setInternalHeaders(Collections.emptyMap()) - .setClock(NanoClock.getDefaultClock()) - .setStreamWatchdog(null) - .setStreamWatchdogCheckInterval(Duration.ZERO) - .setTracerFactory(BaseApiTracerFactory.getInstance()) - .setQuotaProjectId(null); - } - - public abstract Builder toBuilder(); - - /** - * Instantiates the executor, credentials, and transport context based on the given client - * settings. - */ - public static ClientContext create(ClientSettings settings) throws IOException { - return create(settings.getStubSettings()); - } - - /** Returns the endpoint that should be used. See https://google.aip.dev/auth/4114. */ - static String getEndpoint( - String endpoint, - String mtlsEndpoint, - boolean switchToMtlsEndpointAllowed, - MtlsProvider mtlsProvider) - throws IOException { - if (switchToMtlsEndpointAllowed) { - switch (mtlsProvider.getMtlsEndpointUsagePolicy()) { - case ALWAYS: - return mtlsEndpoint; - case NEVER: - return endpoint; - default: - if (mtlsProvider.useMtlsClientCertificate() && mtlsProvider.getKeyStore() != null) { - return mtlsEndpoint; - } - return endpoint; - } - } - return endpoint; - } - - /** - * Instantiates the executor, credentials, and transport context based on the given client - * settings. - */ - public static ClientContext create(StubSettings settings) throws IOException { - ApiClock clock = settings.getClock(); - - ExecutorProvider backgroundExecutorProvider = settings.getBackgroundExecutorProvider(); - final ScheduledExecutorService backgroundExecutor = backgroundExecutorProvider.getExecutor(); - - Credentials credentials = settings.getCredentialsProvider().getCredentials(); - - if (settings.getQuotaProjectId() != null) { - // If the quotaProjectId is set, wrap original credentials with correct quotaProjectId as - // QuotaProjectIdHidingCredentials. - // Ensure that a custom set quota project id takes priority over one detected by credentials. - // Avoid the backend receiving possibly conflict values of quotaProjectId - credentials = new QuotaProjectIdHidingCredentials(credentials); - } - - TransportChannelProvider transportChannelProvider = settings.getTransportChannelProvider(); - // After needsExecutor and StubSettings#setExecutorProvider are deprecated, transport channel - // executor can only be set from TransportChannelProvider#withExecutor directly, and a provider - // will have a default executor if it needs one. - if (transportChannelProvider.needsExecutor() && settings.getExecutorProvider() != null) { - transportChannelProvider = transportChannelProvider.withExecutor(backgroundExecutor); - } - Map headers = getHeadersFromSettings(settings); - if (transportChannelProvider.needsHeaders()) { - transportChannelProvider = transportChannelProvider.withHeaders(headers); - } - if (transportChannelProvider.needsCredentials() && credentials != null) { - transportChannelProvider = transportChannelProvider.withCredentials(credentials); - } - String endpoint = - getEndpoint( - settings.getEndpoint(), - settings.getMtlsEndpoint(), - settings.getSwitchToMtlsEndpointAllowed(), - new MtlsProvider()); - if (transportChannelProvider.needsEndpoint()) { - transportChannelProvider = transportChannelProvider.withEndpoint(endpoint); - } - TransportChannel transportChannel = transportChannelProvider.getTransportChannel(); - - ApiCallContext defaultCallContext = - transportChannel.getEmptyCallContext().withTransportChannel(transportChannel); - if (credentials != null) { - defaultCallContext = defaultCallContext.withCredentials(credentials); - } - - WatchdogProvider watchdogProvider = settings.getStreamWatchdogProvider(); - @Nullable Watchdog watchdog = null; - - if (watchdogProvider != null) { - if (watchdogProvider.needsCheckInterval()) { - watchdogProvider = - watchdogProvider.withCheckInterval(settings.getStreamWatchdogCheckInterval()); - } - if (watchdogProvider.needsClock()) { - watchdogProvider = watchdogProvider.withClock(clock); - } - if (watchdogProvider.needsExecutor()) { - watchdogProvider = watchdogProvider.withExecutor(backgroundExecutor); - } - watchdog = watchdogProvider.getWatchdog(); - } - - ImmutableList.Builder backgroundResources = ImmutableList.builder(); - - if (transportChannelProvider.shouldAutoClose()) { - backgroundResources.add(transportChannel); - } - if (backgroundExecutorProvider.shouldAutoClose()) { - backgroundResources.add(new ExecutorAsBackgroundResource(backgroundExecutor)); - } - if (watchdogProvider != null && watchdogProvider.shouldAutoClose()) { - backgroundResources.add(watchdog); - } - - return newBuilder() - .setBackgroundResources(backgroundResources.build()) - .setExecutor(backgroundExecutor) - .setCredentials(credentials) - .setTransportChannel(transportChannel) - .setHeaders(ImmutableMap.copyOf(settings.getHeaderProvider().getHeaders())) - .setInternalHeaders(ImmutableMap.copyOf(settings.getInternalHeaderProvider().getHeaders())) - .setClock(clock) - .setDefaultCallContext(defaultCallContext) - .setEndpoint(settings.getEndpoint()) - .setQuotaProjectId(settings.getQuotaProjectId()) - .setStreamWatchdog(watchdog) - .setStreamWatchdogCheckInterval(settings.getStreamWatchdogCheckInterval()) - .setTracerFactory(settings.getTracerFactory()) - .build(); - } - - /** - * Getting a header map from HeaderProvider and InternalHeaderProvider from settings with Quota - * Project Id. - */ - private static Map getHeadersFromSettings(StubSettings settings) { - // Resolve conflicts when merging headers from multiple sources - Map userHeaders = settings.getHeaderProvider().getHeaders(); - Map internalHeaders = settings.getInternalHeaderProvider().getHeaders(); - Map conflictResolution = new HashMap<>(); - - Set conflicts = Sets.intersection(userHeaders.keySet(), internalHeaders.keySet()); - for (String key : conflicts) { - if ("user-agent".equals(key)) { - conflictResolution.put(key, userHeaders.get(key) + " " + internalHeaders.get(key)); - continue; - } - // Backwards compat: quota project id can conflict if its overriden in settings - if (QUOTA_PROJECT_ID_HEADER_KEY.equals(key) && settings.getQuotaProjectId() != null) { - continue; - } - throw new IllegalArgumentException("Header provider can't override the header: " + key); - } - if (settings.getQuotaProjectId() != null) { - conflictResolution.put(QUOTA_PROJECT_ID_HEADER_KEY, settings.getQuotaProjectId()); - } - - Map effectiveHeaders = new HashMap<>(); - effectiveHeaders.putAll(internalHeaders); - effectiveHeaders.putAll(userHeaders); - effectiveHeaders.putAll(conflictResolution); - - return ImmutableMap.copyOf(effectiveHeaders); - } - - @AutoValue.Builder - public abstract static class Builder { - - public abstract Builder setBackgroundResources(List backgroundResources); - - /** - * Sets the executor to use for running scheduled API call logic (such as retries and - * long-running operations). - */ - public abstract Builder setExecutor(ScheduledExecutorService value); - - public abstract Builder setCredentials(Credentials value); - - public abstract Builder setTransportChannel(TransportChannel transportChannel); - - public abstract Builder setHeaders(Map headers); - - protected abstract Builder setInternalHeaders(Map headers); - - public abstract Builder setClock(ApiClock clock); - - public abstract Builder setDefaultCallContext(ApiCallContext defaultCallContext); - - public abstract Builder setEndpoint(String endpoint); - - public abstract Builder setQuotaProjectId(String QuotaProjectId); - - public abstract Builder setStreamWatchdog(Watchdog watchdog); - - public abstract Builder setStreamWatchdogCheckInterval(Duration duration); - - /** - * Set the {@link ApiTracerFactory} that will be used to generate traces for operations. - * - * @param tracerFactory an instance {@link ApiTracerFactory}. - */ - @BetaApi("The surface for tracing is not stable yet and may change in the future.") - public abstract Builder setTracerFactory(ApiTracerFactory tracerFactory); - - public abstract ClientContext build(); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/ClientSettings.java b/gax/src/main/java/com/google/api/gax/rpc/ClientSettings.java deleted file mode 100644 index a1097a410..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/ClientSettings.java +++ /dev/null @@ -1,350 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.ApiClock; -import com.google.api.core.ApiFunction; -import com.google.api.gax.core.CredentialsProvider; -import com.google.api.gax.core.ExecutorProvider; -import com.google.common.base.MoreObjects; -import java.io.IOException; -import java.util.concurrent.Executor; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import org.threeten.bp.Duration; - -/** - * A base settings class to configure a client class. - * - *

This base class includes settings that are applicable to all services, which includes things - * like settings for creating an executor, credentials, transport-specific settings, and identifiers - * for http headers. - * - *

If no ExecutorProvider is set, then InstantiatingExecutorProvider will be used, which creates - * a default executor. - */ -public abstract class ClientSettings> { - - private final StubSettings stubSettings; - - /** Constructs an instance of ClientSettings. */ - protected ClientSettings(Builder builder) throws IOException { - this.stubSettings = builder.stubSettings.build(); - } - - public final StubSettings getStubSettings() { - return stubSettings; - } - - /** @deprecated Please use {@link #getBackgroundExecutorProvider()} */ - @Deprecated - public final ExecutorProvider getExecutorProvider() { - return stubSettings.getExecutorProvider(); - } - - public final ExecutorProvider getBackgroundExecutorProvider() { - return stubSettings.getBackgroundExecutorProvider(); - } - - public final TransportChannelProvider getTransportChannelProvider() { - return stubSettings.getTransportChannelProvider(); - } - - public final CredentialsProvider getCredentialsProvider() { - return stubSettings.getCredentialsProvider(); - } - - public final HeaderProvider getHeaderProvider() { - return stubSettings.getHeaderProvider(); - } - - protected final HeaderProvider getInternalHeaderProvider() { - return stubSettings.getInternalHeaderProvider(); - } - - public final ApiClock getClock() { - return stubSettings.getClock(); - } - - public final String getEndpoint() { - return stubSettings.getEndpoint(); - } - - public final String getQuotaProjectId() { - return stubSettings.getQuotaProjectId(); - } - - @Nullable - public final WatchdogProvider getWatchdogProvider() { - return stubSettings.getStreamWatchdogProvider(); - } - - @Nonnull - public final Duration getWatchdogCheckInterval() { - return stubSettings.getStreamWatchdogCheckInterval(); - } - - public String toString() { - return MoreObjects.toStringHelper(this) - .add("executorProvider", getExecutorProvider()) - .add("backgroundExecutorProvider", getBackgroundExecutorProvider()) - .add("transportChannelProvider", getTransportChannelProvider()) - .add("credentialsProvider", getCredentialsProvider()) - .add("headerProvider", getHeaderProvider()) - .add("internalHeaderProvider", getInternalHeaderProvider()) - .add("clock", getClock()) - .add("endpoint", getEndpoint()) - .add("quotaProjectId", getQuotaProjectId()) - .add("watchdogProvider", getWatchdogProvider()) - .add("watchdogCheckInterval", getWatchdogCheckInterval()) - .toString(); - } - - public abstract > B toBuilder(); - - public abstract static class Builder< - SettingsT extends ClientSettings, B extends Builder> { - - private StubSettings.Builder stubSettings; - - /** Create a builder from a ClientSettings object. */ - protected Builder(ClientSettings settings) { - this.stubSettings = settings.stubSettings.toBuilder(); - } - - /** Create a builder from a StubSettings object. */ - protected Builder(StubSettings.Builder stubSettings) { - this.stubSettings = stubSettings; - } - - protected Builder() { - this((StubSettings.Builder) null); - } - - @SuppressWarnings("unchecked") - protected B self() { - return (B) this; - } - - protected StubSettings.Builder getStubSettings() { - return stubSettings; - } - - /** - * Sets the ExecutorProvider to use for getting the executor to use for running asynchronous API - * call logic (such as retries and long-running operations), and also to pass to the transport - * settings if an executor is needed for the transport and it doesn't have its own executor - * provider. - * - * @deprecated Please use {@link #setBackgroundExecutorProvider(ExecutorProvider)} for setting - * executor to use for running scheduled API call logic. To set executor for {@link - * TransportChannelProvider}, please use {@link - * TransportChannelProvider#withExecutor(Executor)} instead. - */ - @Deprecated - public B setExecutorProvider(ExecutorProvider executorProvider) { - stubSettings.setExecutorProvider(executorProvider); - stubSettings.setBackgroundExecutorProvider(executorProvider); - return self(); - } - - /** - * Sets the ExecutorProvider to use for getting the executor to use for running scheduled API - * call logic (such as retries and long-running operations). This will not set the executor in - * {@link TransportChannelProvider}. To set executor for {@link TransportChannelProvider}, - * please use {@link TransportChannelProvider#withExecutor(Executor)}. - */ - public B setBackgroundExecutorProvider(ExecutorProvider executorProvider) { - stubSettings.setBackgroundExecutorProvider(executorProvider); - return self(); - } - - /** Sets the CredentialsProvider to use for getting the credentials to make calls with. */ - public B setCredentialsProvider(CredentialsProvider credentialsProvider) { - stubSettings.setCredentialsProvider(credentialsProvider); - return self(); - } - - /** - * Sets the HeaderProvider for getting custom static headers for http requests. The header - * provider will be called during client construction only once. The headers returned by the - * provider will be cached and supplied as is for each request issued by the constructed client. - * Some reserved headers can be overridden (e.g. Content-Type) or merged with the default value - * (e.g. User-Agent) by the underlying transport layer. - */ - public B setHeaderProvider(HeaderProvider headerProvider) { - stubSettings.setHeaderProvider(headerProvider); - return self(); - } - - /** - * Sets the HeaderProvider for getting internal (library-defined) static headers for http - * requests. The header provider will be called during client construction only once. The - * headers returned by the provider will be cached and supplied as is for each request issued by - * the constructed client. Some reserved headers can be overridden (e.g. Content-Type) or merged - * with the default value (e.g. User-Agent) by the underlying transport layer. - */ - protected B setInternalHeaderProvider(HeaderProvider internalHeaderProvider) { - stubSettings.setInternalHeaderProvider(internalHeaderProvider); - return self(); - } - - /** - * Sets the TransportProvider to use for getting the transport-specific context to make calls - * with. - */ - public B setTransportChannelProvider(TransportChannelProvider transportChannelProvider) { - stubSettings.setTransportChannelProvider(transportChannelProvider); - return self(); - } - - /** - * Sets the clock to use for retry logic. - * - *

This will default to a system clock if it is not set. - */ - public B setClock(ApiClock clock) { - stubSettings.setClock(clock); - return self(); - } - - public B setEndpoint(String endpoint) { - stubSettings.setEndpoint(endpoint); - return self(); - } - - public B setQuotaProjectId(String quotaProjectId) { - stubSettings.setQuotaProjectId(quotaProjectId); - return self(); - } - - public B setWatchdogProvider(@Nullable WatchdogProvider watchdogProvider) { - stubSettings.setStreamWatchdogProvider(watchdogProvider); - return self(); - } - - public B setWatchdogCheckInterval(@Nullable Duration checkInterval) { - stubSettings.setStreamWatchdogCheckInterval(checkInterval); - return self(); - } - - /** - * Gets the ExecutorProvider that was previously set on this Builder. This ExecutorProvider is - * to use for running asynchronous API call logic (such as retries and long-running operations), - * and also to pass to the transport settings if an executor is needed for the transport and it - * doesn't have its own executor provider. - * - * @deprecated Please use {@link #getBackgroundExecutorProvider()} for getting the executor - * provider that's used for running scheduled API call logic. - */ - @Deprecated - public ExecutorProvider getExecutorProvider() { - return stubSettings.getExecutorProvider(); - } - - /** - * Gets the ExecutorProvider that was previously set on this Builder. This ExecutorProvider is - * to use for running asynchronous API call logic (such as retries and long-running operations). - * This ExecutorProvider is not used to set the executor in {@link TransportChannelProvider}. - */ - public ExecutorProvider getBackgroundExecutorProvider() { - return stubSettings.getBackgroundExecutorProvider(); - } - - /** Gets the TransportProvider that was previously set on this Builder. */ - public TransportChannelProvider getTransportChannelProvider() { - return stubSettings.getTransportChannelProvider(); - } - - /** Gets the CredentialsProvider that was previously set on this Builder. */ - public CredentialsProvider getCredentialsProvider() { - return stubSettings.getCredentialsProvider(); - } - - /** Gets the custom HeaderProvider that was previously set on this Builder. */ - public HeaderProvider getHeaderProvider() { - return stubSettings.getHeaderProvider(); - } - - /** Gets the internal HeaderProvider that was previously set on this Builder. */ - protected HeaderProvider getInternalHeaderProvider() { - return stubSettings.getInternalHeaderProvider(); - } - - /** Gets the ApiClock that was previously set on this Builder. */ - public ApiClock getClock() { - return stubSettings.getClock(); - } - - public String getEndpoint() { - return stubSettings.getEndpoint(); - } - - /** Gets the QuotaProjectId that was previously set on this Builder. */ - public String getQuotaProjectId() { - return stubSettings.getQuotaProjectId(); - } - - @Nullable - public WatchdogProvider getWatchdogProvider() { - return stubSettings.getStreamWatchdogProvider(); - } - - @Nullable - public Duration getWatchdogCheckInterval() { - return stubSettings.getStreamWatchdogCheckInterval(); - } - - /** Applies the given settings updater function to the given method settings builders. */ - protected static void applyToAllUnaryMethods( - Iterable> methodSettingsBuilders, - ApiFunction, Void> settingsUpdater) { - StubSettings.Builder.applyToAllUnaryMethods(methodSettingsBuilders, settingsUpdater); - } - - public abstract SettingsT build() throws IOException; - - public String toString() { - return MoreObjects.toStringHelper(this) - .add("executorProvider", getExecutorProvider()) - .add("backgroundExecutorProvider", getBackgroundExecutorProvider()) - .add("transportChannelProvider", getTransportChannelProvider()) - .add("credentialsProvider", getCredentialsProvider()) - .add("headerProvider", getHeaderProvider()) - .add("internalHeaderProvider", getInternalHeaderProvider()) - .add("clock", getClock()) - .add("endpoint", getEndpoint()) - .add("quotaProjectId", getQuotaProjectId()) - .add("watchdogProvider", getWatchdogProvider()) - .add("watchdogCheckInterval", getWatchdogCheckInterval()) - .toString(); - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/ClientStream.java b/gax/src/main/java/com/google/api/gax/rpc/ClientStream.java deleted file mode 100644 index 0a451b68d..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/ClientStream.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -/** - * A wrapper used to send requests to the server. - * - *

After sending requests, users must either call {@link #closeSend()} or {@link - * #closeSendWithError(Throwable)} on the stream. The error, if any, will be propagated to the - * server. - * - *

Example usage: - * - *

{@code
- * ClientStream stream = ...;
- * List lines = getLinesFromFile();
- * for (String line : lines) {
- *   stream.send(line);
- * }
- * stream.closeSend();
- * }
- * - * @param The type of each request. - */ -public interface ClientStream { - /** Sends a request to the server. It is an error to call this if the stream is already closed. */ - void send(RequestT request); - - /** - * Closes the stream with an error. If called, this must be the last call on this {@code - * ClientStream}. - */ - void closeSendWithError(Throwable t); - - /** - * Closes the stream. If called, this must be the last call on this {@code ClientStream}. - * - *

Note that if {@code close()} itself throws, a further call to {@code closeSendWithError} is - * not allowed. - */ - void closeSend(); - - /** - * Reports whether a new request can be sent without excessive buffering. - * - *

This is only an optimization hint to the user. It is correct, if suboptimal, to call {@code - * send} if {@code isSendReady} returns false. - */ - boolean isSendReady(); -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/ClientStreamReadyObserver.java b/gax/src/main/java/com/google/api/gax/rpc/ClientStreamReadyObserver.java deleted file mode 100644 index 034752451..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/ClientStreamReadyObserver.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -/** A callback used to report that the {@link ClientStream} is ready to send more messages. */ -public interface ClientStreamReadyObserver { - void onReady(ClientStream stream); -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/ClientStreamingCallable.java b/gax/src/main/java/com/google/api/gax/rpc/ClientStreamingCallable.java deleted file mode 100644 index 13ef1c645..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/ClientStreamingCallable.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -/** - * A ClientStreamingCallable is an immutable object which is capable of making RPC calls to client - * streaming API methods. Not all transports support streaming. - * - *

It is considered advanced usage for a user to create a ClientStreamingCallable themselves. - * This class is intended to be created by a generated client class, and configured by instances of - * StreamingCallSettings.Builder which are exposed through the client settings class. - */ -public abstract class ClientStreamingCallable { - - protected ClientStreamingCallable() {} - - /** - * Conduct a client streaming call with the given {@link ApiCallContext} - * - * @param responseObserver {@link ApiStreamObserver} to receive the non-streaming response. - * @param context {@link ApiCallContext} to provide context information for the RPC call. - * @return {@link ApiStreamObserver} which is used for making streaming requests. - */ - public abstract ApiStreamObserver clientStreamingCall( - ApiStreamObserver responseObserver, ApiCallContext context); - - /** - * Conduct a client streaming call - * - * @param responseObserver {@link ApiStreamObserver} to receive the non-streaming response. - * @return {@link ApiStreamObserver} which is used for making streaming requests. - */ - public ApiStreamObserver clientStreamingCall( - ApiStreamObserver responseObserver) { - return clientStreamingCall(responseObserver, null); - } - - /** - * Returns a new {@code ClientStreamingCallable} with an {@link ApiCallContext} that is used as a - * default when none is supplied in individual calls. - * - * @param defaultCallContext the default {@link ApiCallContext}. - */ - public ClientStreamingCallable withDefaultCallContext( - final ApiCallContext defaultCallContext) { - return new ClientStreamingCallable() { - @Override - public ApiStreamObserver clientStreamingCall( - ApiStreamObserver responseObserver, ApiCallContext thisCallContext) { - return ClientStreamingCallable.this.clientStreamingCall( - responseObserver, defaultCallContext.merge(thisCallContext)); - } - }; - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/DataLossException.java b/gax/src/main/java/com/google/api/gax/rpc/DataLossException.java deleted file mode 100644 index e3d9a8107..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/DataLossException.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -/** Exception thrown due to unrecoverable data loss or corruption. */ -public class DataLossException extends ApiException { - public DataLossException(Throwable cause, StatusCode statusCode, boolean retryable) { - super(cause, statusCode, retryable); - } - - public DataLossException( - String message, Throwable cause, StatusCode statusCode, boolean retryable) { - super(message, cause, statusCode, retryable); - } - - public DataLossException( - Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { - super(cause, statusCode, retryable, errorDetails); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/DeadlineExceededException.java b/gax/src/main/java/com/google/api/gax/rpc/DeadlineExceededException.java deleted file mode 100644 index 37b5d8db0..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/DeadlineExceededException.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -/** - * Exception thrown when deadline expired before operation could complete. For operations that - * change the state of the system, this error may be returned even if the operation has completed - * successfully. For example, a successful response from a server could have been delayed long - * enough for the deadline to expire. - */ -public class DeadlineExceededException extends ApiException { - public DeadlineExceededException(Throwable cause, StatusCode statusCode, boolean retryable) { - super(cause, statusCode, retryable); - } - - public DeadlineExceededException( - String message, Throwable cause, StatusCode statusCode, boolean retryable) { - super(message, cause, statusCode, retryable); - } - - public DeadlineExceededException( - Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { - super(cause, statusCode, retryable, errorDetails); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/ErrorDetails.java b/gax/src/main/java/com/google/api/gax/rpc/ErrorDetails.java deleted file mode 100644 index 09c924b59..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/ErrorDetails.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.auto.value.AutoValue; -import com.google.common.annotations.VisibleForTesting; -import com.google.protobuf.Any; -import com.google.protobuf.InvalidProtocolBufferException; -import com.google.protobuf.Message; -import com.google.rpc.BadRequest; -import com.google.rpc.DebugInfo; -import com.google.rpc.ErrorInfo; -import com.google.rpc.Help; -import com.google.rpc.LocalizedMessage; -import com.google.rpc.PreconditionFailure; -import com.google.rpc.QuotaFailure; -import com.google.rpc.RequestInfo; -import com.google.rpc.ResourceInfo; -import com.google.rpc.RetryInfo; -import java.util.List; -import javax.annotation.Nullable; - -/** This class contains a list of standard error messages that returns from server. */ -@AutoValue -public abstract class ErrorDetails { - - /** - * This is the most important and special error message. It describes the cause of the error with - * structured details that both humans and applications can depend on. - */ - @Nullable - public ErrorInfo getErrorInfo() { - return unpack(ErrorInfo.class); - } - - /** - * Describes when the clients can retry a failed request. Clients could ignore the recommendation - * here or retry when this information is missing from error responses. - */ - @Nullable - public RetryInfo getRetryInfo() { - return unpack(RetryInfo.class); - } - - /** Describes additional debugging info. */ - @Nullable - public DebugInfo getDebugInfo() { - return unpack(DebugInfo.class); - } - - /** Describes how a quota check failed. */ - @Nullable - public QuotaFailure getQuotaFailure() { - return unpack(QuotaFailure.class); - } - - /** Describes what preconditions have failed. */ - @Nullable - public PreconditionFailure getPreconditionFailure() { - return unpack(PreconditionFailure.class); - } - - /** - * Describes violations in a client request. This error type focuses on the syntactic aspects of - * the request. - */ - @Nullable - public BadRequest getBadRequest() { - return unpack(BadRequest.class); - } - - /** - * Contains metadata about the request that clients can attach when filing a bug or providing - * other forms of feedback. - */ - @Nullable - public RequestInfo getRequestInfo() { - return unpack(RequestInfo.class); - } - - /** Describes the resource that is being accessed. */ - @Nullable - public ResourceInfo getResourceInfo() { - return unpack(ResourceInfo.class); - } - - /** Provides links to documentation or for performing an out-of-band action. */ - @Nullable - public Help getHelp() { - return unpack(Help.class); - } - - /** - * Provides a localized error message that is safe to return to the user which can be attached to - * an RPC error - */ - @Nullable - public LocalizedMessage getLocalizedMessage() { - return unpack(LocalizedMessage.class); - } - - /** This is a list of raw/unparsed error messages that returns from server. */ - @Nullable - abstract List getRawErrorMessages(); - - public static Builder builder() { - return new AutoValue_ErrorDetails.Builder(); - } - - @AutoValue.Builder - public abstract static class Builder { - - public abstract Builder setRawErrorMessages(List rawErrorMessages); - - public abstract ErrorDetails build(); - } - - @VisibleForTesting - T unpack(Class errorTypeClazz) { - List rawErrorMessages = getRawErrorMessages(); - if (rawErrorMessages == null) { - return null; - } - for (Any detail : rawErrorMessages) { - if (!detail.is(errorTypeClazz)) { - continue; - } - try { - return detail.unpack(errorTypeClazz); - } catch (InvalidProtocolBufferException e) { - throw new ProtocolBufferParsingException( - String.format( - "Failed to unpack %s from raw error messages", errorTypeClazz.getSimpleName()), - e); - } - } - return null; - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/FailedPreconditionException.java b/gax/src/main/java/com/google/api/gax/rpc/FailedPreconditionException.java deleted file mode 100644 index e1b3ec75e..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/FailedPreconditionException.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -/** - * Exception thrown when the operation was rejected because the system is not in a state required - * for the operation's execution. For example, directory to be deleted may be non-empty, an rmdir - * operation is applied to a non-directory, etc. - */ -public class FailedPreconditionException extends ApiException { - public FailedPreconditionException(Throwable cause, StatusCode statusCode, boolean retryable) { - super(cause, statusCode, retryable); - } - - public FailedPreconditionException( - String message, Throwable cause, StatusCode statusCode, boolean retryable) { - super(message, cause, statusCode, retryable); - } - - public FailedPreconditionException( - Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { - super(cause, statusCode, retryable, errorDetails); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/FirstElementCallable.java b/gax/src/main/java/com/google/api/gax/rpc/FirstElementCallable.java deleted file mode 100644 index 3446e9ffc..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/FirstElementCallable.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.ApiFuture; - -/** - * Wraps a {@link ServerStreamingCallable} in a {@link UnaryCallable} that returns the first - * element. After returning the first element, the underlying stream will be gracefully cancelled. - * - *

Package-private for internal use. - * - * @param The type of the request. - * @param The type of the item in the stream. - */ -final class FirstElementCallable extends UnaryCallable { - private final ServerStreamingCallable streamingCallable; - - FirstElementCallable(ServerStreamingCallable streamingCallable) { - this.streamingCallable = streamingCallable; - } - - /** - * Starts the RPC and returns a future wrapping the result. If the stream is empty, the result - * will be null. If a request is cancelled, the future will be rejected with a {@link - * java.util.concurrent.CancellationException}. - * - * @param request The request. - * @param context {@link ApiCallContext} to make the call with - * @return A {@link ApiFuture} wrapping a possible first element of the stream. - */ - @Override - public ApiFuture futureCall(RequestT request, ApiCallContext context) { - FirstElementResponseObserver observer = new FirstElementResponseObserver<>(); - - streamingCallable.call(request, observer, context); - // NOTE: Since onStart must be called synchronously on this thread, the observer is now fully - // initialized and the future can be safely returned to the caller. - return observer.getFuture(); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/FirstElementResponseObserver.java b/gax/src/main/java/com/google/api/gax/rpc/FirstElementResponseObserver.java deleted file mode 100644 index d6e250176..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/FirstElementResponseObserver.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.AbstractApiFuture; -import com.google.api.core.ApiFuture; - -/** - * A {@link ResponseObserver} that wraps a future. The future will resolved upon receiving the first - * element or exhausting the streaming. - * - *

Package-private for internal use. - * - * @param The type of the element in the stream. - */ -class FirstElementResponseObserver extends StateCheckingResponseObserver { - private final MyFuture future = new MyFuture(); - private StreamController controller; - - @Override - protected void onStartImpl(StreamController controller) { - // NOTE: the call is started before the future is exposed to the caller - this.controller = controller; - - controller.disableAutoInboundFlowControl(); - controller.request(1); - } - - @Override - protected void onResponseImpl(ResponseT response) { - future.set(response); - controller.cancel(); - } - - @Override - protected void onErrorImpl(Throwable t) { - future.setException(t); - } - - @Override - protected void onCompleteImpl() { - future.set(null); - } - - ApiFuture getFuture() { - return future; - } - - /** Simple implementation of a future that allows the receiver to cancel the underlying stream. */ - private class MyFuture extends AbstractApiFuture { - @Override - protected void interruptTask() { - FirstElementResponseObserver.this.controller.cancel(); - } - - @Override - protected boolean set(ResponseT value) { - return super.set(value); - } - - @Override - protected boolean setException(Throwable throwable) { - return super.setException(throwable); - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/FixedHeaderProvider.java b/gax/src/main/java/com/google/api/gax/rpc/FixedHeaderProvider.java deleted file mode 100644 index 8aa781697..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/FixedHeaderProvider.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.auto.value.AutoValue; -import com.google.common.collect.ImmutableMap; -import java.io.Serializable; -import java.util.Collection; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import javax.annotation.Nullable; - -/** An instance of HeaderProvider that always provides the same headers. */ -@AutoValue -public abstract class FixedHeaderProvider implements HeaderProvider, Serializable { - - private static final long serialVersionUID = -4881534091594970538L; - - @Override - @Nullable - public abstract Map getHeaders(); - - /** Creates a FixedHeaderProvider. */ - public static FixedHeaderProvider create(Map headers) { - checkKeys(headers.keySet()); - return new AutoValue_FixedHeaderProvider(ImmutableMap.copyOf(headers)); - } - - public static FixedHeaderProvider create(String... keyValuePairs) { - if (keyValuePairs.length % 2 != 0) { - throw new IllegalArgumentException( - "The keyValuePairs var-arg parameter must contain an even number of elements"); - } - ImmutableMap.Builder headersBuilder = ImmutableMap.builder(); - for (int i = 0; i < keyValuePairs.length; i += 2) { - headersBuilder.put(keyValuePairs[i], keyValuePairs[i + 1]); - } - Map headers = headersBuilder.build(); - - checkKeys(headers.keySet()); - return new AutoValue_FixedHeaderProvider(headers); - } - - private static void checkKeys(Collection keys) { - Set caseInsensitiveKeys = new HashSet<>(); - for (String key : keys) { - if (!caseInsensitiveKeys.add(key.toLowerCase())) { - throw new IllegalArgumentException( - "The header key '" + key + "' is not case insensitively unique"); - } - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/FixedTransportChannelProvider.java b/gax/src/main/java/com/google/api/gax/rpc/FixedTransportChannelProvider.java deleted file mode 100644 index 0bf6205dd..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/FixedTransportChannelProvider.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.InternalExtensionOnly; -import com.google.auth.Credentials; -import com.google.common.base.Preconditions; -import java.io.IOException; -import java.util.Map; -import java.util.concurrent.Executor; -import java.util.concurrent.ScheduledExecutorService; - -/** An instance of TransportChannelProvider that always provides the same TransportChannel. */ -@InternalExtensionOnly -public class FixedTransportChannelProvider implements TransportChannelProvider { - - private final TransportChannel transportChannel; - - private FixedTransportChannelProvider(TransportChannel transportChannel) { - this.transportChannel = Preconditions.checkNotNull(transportChannel); - } - - @Override - public boolean shouldAutoClose() { - return false; - } - - @Override - public boolean needsExecutor() { - return false; - } - - @Override - public FixedTransportChannelProvider withExecutor(ScheduledExecutorService executor) { - return withExecutor((Executor) executor); - } - - @Override - public FixedTransportChannelProvider withExecutor(Executor executor) { - throw new UnsupportedOperationException( - "FixedTransportChannelProvider doesn't need an executor"); - } - - @Override - public boolean needsHeaders() { - return false; - } - - @Override - public FixedTransportChannelProvider withHeaders(Map headers) { - throw new UnsupportedOperationException("FixedTransportChannelProvider doesn't need headers"); - } - - @Override - public boolean needsEndpoint() { - return false; - } - - @Override - public TransportChannelProvider withEndpoint(String endpoint) { - throw new UnsupportedOperationException( - "FixedTransportChannelProvider doesn't need an endpoint"); - } - - /** @deprecated FixedTransportChannelProvider doesn't support ChannelPool configuration */ - @Deprecated - @Override - public boolean acceptsPoolSize() { - return false; - } - - /** @deprecated FixedTransportChannelProvider doesn't support ChannelPool configuration */ - @Deprecated - @Override - public TransportChannelProvider withPoolSize(int size) { - throw new UnsupportedOperationException( - "FixedTransportChannelProvider doesn't allow pool size customization"); - } - - @Override - public TransportChannel getTransportChannel() throws IOException { - return transportChannel; - } - - @Override - public String getTransportName() { - return transportChannel.getTransportName(); - } - - @Override - public boolean needsCredentials() { - return false; - } - - @Override - public TransportChannelProvider withCredentials(Credentials credentials) { - throw new UnsupportedOperationException( - "FixedTransportChannelProvider doesn't need credentials"); - } - - /** Creates a FixedTransportChannelProvider. */ - public static FixedTransportChannelProvider create(TransportChannel transportChannel) { - return new FixedTransportChannelProvider(transportChannel); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/FixedWatchdogProvider.java b/gax/src/main/java/com/google/api/gax/rpc/FixedWatchdogProvider.java deleted file mode 100644 index a1fd245b5..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/FixedWatchdogProvider.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.ApiClock; -import com.google.api.core.InternalApi; -import java.util.concurrent.ScheduledExecutorService; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import org.threeten.bp.Duration; - -/** - * A watchdog provider which always returns the same watchdog instance provided to the provider - * during construction. - * - *

This is the internal class and is public only for technical reasons. It may change any time - * without notice, please do not depend on it explicitly. - */ -@InternalApi -public final class FixedWatchdogProvider implements WatchdogProvider { - @Nullable private final Watchdog watchdog; - - public static WatchdogProvider create(Watchdog watchdog) { - return new FixedWatchdogProvider(watchdog); - } - - private FixedWatchdogProvider(Watchdog watchdog) { - this.watchdog = watchdog; - } - - @Override - public boolean needsClock() { - return false; - } - - @Override - public WatchdogProvider withClock(@Nonnull ApiClock clock) { - throw new UnsupportedOperationException("FixedWatchdogProvider doesn't need a clock"); - } - - @Override - public boolean needsCheckInterval() { - return false; - } - - @Override - public WatchdogProvider withCheckInterval(Duration checkInterval) { - throw new UnsupportedOperationException("FixedWatchdogProvider doesn't need a checkInterval"); - } - - @Override - public boolean needsExecutor() { - return false; - } - - @Override - public WatchdogProvider withExecutor(ScheduledExecutorService executor) { - throw new UnsupportedOperationException("FixedWatchdogProvider doesn't need an executor"); - } - - @Override - public Watchdog getWatchdog() { - return watchdog; - } - - @Override - public boolean shouldAutoClose() { - return false; - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/HeaderProvider.java b/gax/src/main/java/com/google/api/gax/rpc/HeaderProvider.java deleted file mode 100644 index c20351c0a..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/HeaderProvider.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import java.util.Map; - -/** Provider of headers to put on http requests. */ -public interface HeaderProvider { - - /** Get the headers to put on http requests. */ - Map getHeaders(); -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/InstantiatingWatchdogProvider.java b/gax/src/main/java/com/google/api/gax/rpc/InstantiatingWatchdogProvider.java deleted file mode 100644 index a069c49c8..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/InstantiatingWatchdogProvider.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.ApiClock; -import com.google.api.core.InternalApi; -import com.google.common.base.Preconditions; -import java.util.concurrent.ScheduledExecutorService; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import org.threeten.bp.Duration; - -/** - * A watchdog provider which instantiates a new provider on every request. - * - *

This is the internal class and is public only for technical reasons. It may change any time - * without notice, please do not depend on it explicitly. - */ -@InternalApi -public final class InstantiatingWatchdogProvider implements WatchdogProvider { - @Nullable private final ApiClock clock; - @Nullable private final ScheduledExecutorService executor; - @Nullable private final Duration checkInterval; - - public static WatchdogProvider create() { - return new InstantiatingWatchdogProvider(null, null, null); - } - - private InstantiatingWatchdogProvider( - @Nullable ApiClock clock, - @Nullable ScheduledExecutorService executor, - @Nullable Duration checkInterval) { - this.clock = clock; - this.executor = executor; - this.checkInterval = checkInterval; - } - - @Override - public boolean needsClock() { - return clock == null; - } - - @Override - public WatchdogProvider withClock(@Nonnull ApiClock clock) { - return new InstantiatingWatchdogProvider( - Preconditions.checkNotNull(clock), executor, checkInterval); - } - - @Override - public boolean needsCheckInterval() { - return checkInterval == null; - } - - @Override - public WatchdogProvider withCheckInterval(@Nonnull Duration checkInterval) { - return new InstantiatingWatchdogProvider( - clock, executor, Preconditions.checkNotNull(checkInterval)); - } - - @Override - public boolean needsExecutor() { - return executor == null; - } - - @Override - public WatchdogProvider withExecutor(ScheduledExecutorService executor) { - return new InstantiatingWatchdogProvider( - clock, Preconditions.checkNotNull(executor), checkInterval); - } - - @SuppressWarnings("ConstantConditions") - @Nullable - @Override - public Watchdog getWatchdog() { - Preconditions.checkState(!needsClock(), "A clock is needed"); - Preconditions.checkState(!needsCheckInterval(), "A check interval is needed"); - Preconditions.checkState(!needsExecutor(), "An executor is needed"); - - // Watchdog is disabled - if (checkInterval.isZero()) { - return null; - } - - return Watchdog.create(clock, checkInterval, executor); - } - - @Override - public boolean shouldAutoClose() { - return true; - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/InternalException.java b/gax/src/main/java/com/google/api/gax/rpc/InternalException.java deleted file mode 100644 index 3d5763f06..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/InternalException.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -/** - * Exception thrown due to internal errors. Means some invariants expected by underlying system has - * been broken. If you see one of these errors, something is very broken. - */ -public class InternalException extends ApiException { - public InternalException(Throwable cause, StatusCode statusCode, boolean retryable) { - super(cause, statusCode, retryable); - } - - public InternalException( - String message, Throwable cause, StatusCode statusCode, boolean retryable) { - super(message, cause, statusCode, retryable); - } - - public InternalException( - Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { - super(cause, statusCode, retryable, errorDetails); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/InvalidArgumentException.java b/gax/src/main/java/com/google/api/gax/rpc/InvalidArgumentException.java deleted file mode 100644 index 6b0ccc6f6..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/InvalidArgumentException.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -/** - * Exception thrown when client specified an invalid argument. Note that this differs from {@link - * FailedPreconditionException}. This exception indicates arguments that are problematic regardless - * of the state of the system (e.g., a malformed file name). - */ -public class InvalidArgumentException extends ApiException { - public InvalidArgumentException(Throwable cause, StatusCode statusCode, boolean retryable) { - super(cause, statusCode, retryable); - } - - public InvalidArgumentException( - String message, Throwable cause, StatusCode statusCode, boolean retryable) { - super(message, cause, statusCode, retryable); - } - - public InvalidArgumentException( - Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { - super(cause, statusCode, retryable, errorDetails); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/LongRunningClient.java b/gax/src/main/java/com/google/api/gax/rpc/LongRunningClient.java deleted file mode 100644 index 87ebd2611..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/LongRunningClient.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.gax.longrunning.OperationSnapshot; - -/** Implementation-agnostic interface for managing long-running operations. */ -public interface LongRunningClient { - - /** - * Returns a {@link UnaryCallable} which can issue calls to get the latest state of an operation. - */ - UnaryCallable getOperationCallable(); - - /** Returns a {@link UnaryCallable} which can issue calls to cancel an operation. */ - UnaryCallable cancelOperationCallable(); - - /** Returns a {@link UnaryCallable} which can issue calls to delete an operation. */ - UnaryCallable deleteOperationCallable(); -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/NoHeaderProvider.java b/gax/src/main/java/com/google/api/gax/rpc/NoHeaderProvider.java deleted file mode 100644 index 48b8532ea..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/NoHeaderProvider.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import java.io.Serializable; -import java.util.Collections; -import java.util.Map; - -/** Implementation of HeaderProvider that provides empty headers. */ -public class NoHeaderProvider implements HeaderProvider, Serializable { - private static final long serialVersionUID = 7323717933589691233L; - - @Override - public Map getHeaders() { - return Collections.emptyMap(); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/NotFoundException.java b/gax/src/main/java/com/google/api/gax/rpc/NotFoundException.java deleted file mode 100644 index ce8b0b1d7..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/NotFoundException.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -/** Exception thrown when some requested entity (e.g., file or directory) was not found. */ -public class NotFoundException extends ApiException { - public NotFoundException(Throwable cause, StatusCode statusCode, boolean retryable) { - super(cause, statusCode, retryable); - } - - public NotFoundException( - String message, Throwable cause, StatusCode statusCode, boolean retryable) { - super(message, cause, statusCode, retryable); - } - - public NotFoundException( - Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { - super(cause, statusCode, retryable, errorDetails); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/OperationCallSettings.java b/gax/src/main/java/com/google/api/gax/rpc/OperationCallSettings.java deleted file mode 100644 index 0236f59a5..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/OperationCallSettings.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.api.core.ApiFunction; -import com.google.api.gax.longrunning.OperationSnapshot; -import com.google.api.gax.retrying.TimedRetryAlgorithm; - -/** - * A settings class to configure an {@link OperationCallable} for calls to initiate, resume, and - * cancel a long-running operation. - */ -public final class OperationCallSettings { - private final UnaryCallSettings initialCallSettings; - private final TimedRetryAlgorithm pollingAlgorithm; - private final ApiFunction responseTransformer; - private final ApiFunction metadataTransformer; - - public final UnaryCallSettings getInitialCallSettings() { - return initialCallSettings; - } - - public final TimedRetryAlgorithm getPollingAlgorithm() { - return pollingAlgorithm; - } - - public final ApiFunction getResponseTransformer() { - return responseTransformer; - } - - public final ApiFunction getMetadataTransformer() { - return metadataTransformer; - } - - private OperationCallSettings( - UnaryCallSettings initialCallSettings, - TimedRetryAlgorithm pollingAlgorithm, - ApiFunction responseTransformer, - ApiFunction metadataTransformer) { - this.initialCallSettings = checkNotNull(initialCallSettings); - this.pollingAlgorithm = checkNotNull(pollingAlgorithm); - this.responseTransformer = checkNotNull(responseTransformer); - this.metadataTransformer = metadataTransformer; - } - - /** Create a new builder which can construct an instance of OperationCallSettings. */ - public static - Builder newBuilder() { - return new Builder<>(); - } - - public final Builder toBuilder() { - return new Builder<>(this); - } - - public static class Builder { - private UnaryCallSettings initialCallSettings; - private TimedRetryAlgorithm pollingAlgorithm; - private ApiFunction responseTransformer; - private ApiFunction metadataTransformer; - - public Builder() {} - - public Builder(OperationCallSettings settings) { - this.initialCallSettings = settings.initialCallSettings.toBuilder().build(); - this.pollingAlgorithm = settings.pollingAlgorithm; - this.responseTransformer = settings.responseTransformer; - this.metadataTransformer = settings.metadataTransformer; - } - - /** Set the polling algorithm of the operation. */ - public Builder setPollingAlgorithm( - TimedRetryAlgorithm pollingAlgorithm) { - this.pollingAlgorithm = pollingAlgorithm; - return this; - } - - /** Get the polling algorithm of the operation. */ - public TimedRetryAlgorithm getPollingAlgorithm() { - return pollingAlgorithm; - } - - /** Set the call settings which are used on the call to initiate the operation. */ - public Builder setInitialCallSettings( - UnaryCallSettings initialCallSettings) { - this.initialCallSettings = initialCallSettings; - return this; - } - - /** Get the call settings which are used on the call to initiate the operation. */ - public UnaryCallSettings getInitialCallSettings() { - return initialCallSettings; - } - - public final ApiFunction getResponseTransformer() { - return responseTransformer; - } - - public Builder setResponseTransformer( - ApiFunction responseTransformer) { - this.responseTransformer = responseTransformer; - return this; - } - - public final ApiFunction getMetadataTransformer() { - return metadataTransformer; - } - - public Builder setMetadataTransformer( - ApiFunction metadataTransformer) { - this.metadataTransformer = metadataTransformer; - return this; - } - - public OperationCallSettings build() { - return new OperationCallSettings<>( - initialCallSettings, pollingAlgorithm, responseTransformer, metadataTransformer); - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/OperationCallable.java b/gax/src/main/java/com/google/api/gax/rpc/OperationCallable.java deleted file mode 100644 index 75eac0e92..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/OperationCallable.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.ApiFuture; -import com.google.api.gax.longrunning.OperationFuture; - -/** - * An OperationCallable is an immutable object which is capable of initiating RPC calls to - * long-running API methods and returning an {@link OperationFuture} to manage the polling of the - * Operation and getting the response. - * - *

It is considered advanced usage for a user to create an OperationCallable themselves. This - * class is intended to be created by a generated client class, and configured by instances of - * OperationCallSettings.Builder which are exposed through the client settings class. - */ -public abstract class OperationCallable { - - protected OperationCallable() {} - - /** - * Initiates an operation asynchronously. - * - * @param request The request to initiate the operation. - * @param context {@link ApiCallContext} to make the call with - * @return {@link OperationFuture} for the call result - */ - public abstract OperationFuture futureCall( - RequestT request, ApiCallContext context); - - /** - * Same as {@link #futureCall(Object, ApiCallContext)}, with a null context. - * - * @param request request - * @return {@link ApiFuture} for the call result - */ - public OperationFuture futureCall(RequestT request) { - return futureCall(request, null); - } - - /** - * Perform a call synchronously. - * - * @param request The request to initiate the operation. - * @param context {@link ApiCallContext} to make the call with - * @return the call result - * @throws ApiException if there is any bad status in the response. - * @throws RuntimeException if there is any other exception unrelated to bad status. - */ - public ResponseT call(RequestT request, ApiCallContext context) { - return ApiExceptions.callAndTranslateApiException(futureCall(request, context)); - } - - /** - * Same as {@link #call(Object, ApiCallContext)}, with a null context. - * - * @param request The request to initiate the operation. - * @return the call result - * @throws ApiException if there is any bad status in the response. - * @throws RuntimeException if there is any other exception unrelated to bad status. - */ - public ResponseT call(RequestT request) { - return ApiExceptions.callAndTranslateApiException(futureCall(request)); - } - - /** - * Creates a new {@link OperationFuture} to watch an operation that has been initiated previously. - * Note: This is not type-safe at static time; the result type can only be checked once the - * operation finishes. - * - * @param operationName The name of the operation to resume. - * @param context {@link ApiCallContext} to make the call with - * @return {@link OperationFuture} for the call result. - */ - public abstract OperationFuture resumeFutureCall( - String operationName, ApiCallContext context); - - /** - * Creates a new {@link OperationFuture} to watch an operation that has been initiated previously. - * Note: This is not type-safe at static time; the result type can only be checked once the - * operation finishes. - * - * @param operationName The name of the operation to resume. - * @return {@link OperationFuture} for the call result. - */ - public OperationFuture resumeFutureCall(String operationName) { - return resumeFutureCall(operationName, null); - } - - /** - * Sends a cancellation request to the server for the operation with name {@code operationName}. - * - * @param operationName The name of the operation to cancel. - * @param context {@link ApiCallContext} to make the call with - * @return the future which completes once the operation is canceled on the server side. - */ - public abstract ApiFuture cancel(String operationName, ApiCallContext context); - - /** - * Sends a cancellation request to the server for the operation with name {@code operationName}. - * - * @param operationName The name of the operation to cancel. - * @return the future which completes once the operation is canceled on the server side. - */ - public ApiFuture cancel(String operationName) { - return cancel(operationName, null); - } - - /** - * Returns a new {@code OperationCallable} with an {@link ApiCallContext} that is used as a - * default when none is supplied in individual calls. - * - * @param defaultCallContext the default {@link ApiCallContext}. - */ - public OperationCallable withDefaultCallContext( - final ApiCallContext defaultCallContext) { - return new OperationCallable() { - @Override - public OperationFuture futureCall( - RequestT request, ApiCallContext thisCallContext) { - return OperationCallable.this.futureCall( - request, defaultCallContext.merge(thisCallContext)); - } - - @Override - public OperationFuture resumeFutureCall( - String operationName, ApiCallContext thisCallContext) { - return OperationCallable.this.resumeFutureCall( - operationName, defaultCallContext.merge(thisCallContext)); - } - - @Override - public ApiFuture cancel(String operationName, ApiCallContext thisCallContext) { - return OperationCallable.this.cancel( - operationName, defaultCallContext.merge(thisCallContext)); - } - }; - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/OperationCallableImpl.java b/gax/src/main/java/com/google/api/gax/rpc/OperationCallableImpl.java deleted file mode 100644 index f1161851b..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/OperationCallableImpl.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.api.core.ApiFunction; -import com.google.api.core.ApiFuture; -import com.google.api.gax.longrunning.OperationFuture; -import com.google.api.gax.longrunning.OperationFutureImpl; -import com.google.api.gax.longrunning.OperationSnapshot; -import com.google.api.gax.retrying.RetryingExecutorWithContext; -import com.google.api.gax.retrying.RetryingFuture; - -/** - * An OperationCallableImpl is an immutable object which is capable of initiating RPC calls to - * long-running API methods and returning a {@link OperationFuture} to manage the polling of the - * Operation and getting the response. - * - *

Package-private for internal use. - */ -class OperationCallableImpl - extends OperationCallable { - - private final UnaryCallable initialCallable; - private final RetryingExecutorWithContext executor; - private final LongRunningClient longRunningClient; - private final ApiFunction responseTransformer; - private final ApiFunction metadataTransformer; - - OperationCallableImpl( - UnaryCallable initialCallable, - RetryingExecutorWithContext executor, - LongRunningClient longRunningClient, - OperationCallSettings operationCallSettings) { - this.initialCallable = checkNotNull(initialCallable); - this.executor = checkNotNull(executor); - this.longRunningClient = checkNotNull(longRunningClient); - this.responseTransformer = operationCallSettings.getResponseTransformer(); - this.metadataTransformer = operationCallSettings.getMetadataTransformer(); - } - - /** - * Initiates an operation asynchronously. If the {@link TransportChannel} encapsulated in the - * given {@link ApiCallContext} is null, a channel must have already been bound at construction - * time. - * - * @param request The request to initiate the operation. - * @param callContext {@link ApiCallContext} to make the call with - * @return {@link OperationFuture} for the call result - */ - @Override - public OperationFuture futureCall( - RequestT request, ApiCallContext callContext) { - ApiFuture initialFuture = initialCallable.futureCall(request, callContext); - return futureCall(initialFuture, callContext); - } - - /** Waits for the initialFuture to resolve and then starts to poll the return operation. */ - OperationFutureImpl futureCall( - ApiFuture initialFuture, ApiCallContext callContext) { - - RecheckingCallable callable = - new RecheckingCallable<>( - new OperationCheckingCallable(longRunningClient, initialFuture), executor); - - // NOTE: OperationCheckingCallable will compose its own request using the resolved - // initialFuture. So the request parameter to futureCall is ignored - RetryingFuture pollingFuture = callable.futureCall(null, callContext); - return new OperationFutureImpl<>( - pollingFuture, initialFuture, responseTransformer, metadataTransformer); - } - - /** - * Creates a new {@link OperationFuture} to watch an operation that has been initiated previously. - * Note: This is not type-safe at static time; the result type can only be checked once the - * operation finishes. - * - * @param operationName The name of the operation to resume. - * @param callContext {@link ApiCallContext} to make the call with - * @return {@link OperationFuture} for the call result. - */ - @Override - public OperationFuture resumeFutureCall( - String operationName, ApiCallContext callContext) { - ApiFuture firstAttempt = - longRunningClient.getOperationCallable().futureCall(operationName, callContext); - return futureCall(firstAttempt, callContext); - } - - /** - * Sends a cancellation request to the server for the operation with name {@code operationName}. - * - * @param operationName The name of the operation to cancel. - * @param callContext {@link ApiCallContext} to make the call with - * @return the future which completes once the operation is canceled on the server side. - */ - @Override - public ApiFuture cancel(String operationName, ApiCallContext callContext) { - return longRunningClient.cancelOperationCallable().futureCall(operationName, callContext); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/OperationCheckingCallable.java b/gax/src/main/java/com/google/api/gax/rpc/OperationCheckingCallable.java deleted file mode 100644 index 302e0fbae..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/OperationCheckingCallable.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.api.gax.longrunning.OperationSnapshot; -import java.util.concurrent.ExecutionException; - -/** - * A future callable which relies on callback chaining to execute server polling (asking for a - * status of a specific operation: in progress, completed, canceled etc.). This implementation is - * called from {@link AttemptCallable}, essentially using for polling the same logic which is used - * for retrying. - * - *

Package-private for internal use. - * - * @param type of the request - */ -class OperationCheckingCallable extends UnaryCallable { - private final LongRunningClient longRunningClient; - private final ApiFuture initialFuture; - - OperationCheckingCallable( - LongRunningClient longRunningClient, ApiFuture initialFuture) { - this.longRunningClient = checkNotNull(longRunningClient); - this.initialFuture = checkNotNull(initialFuture); - } - - /** - * This method is supposed to be called from {@link AttemptCallable#call()} - * - * @param ignored The ignored request; the actual request will be composed based on the result of - * the {@code initialFuture}. - * @param callContext call context - */ - @Override - public ApiFuture futureCall(RequestT ignored, ApiCallContext callContext) { - try { - if (!initialFuture.isDone() || initialFuture.isCancelled()) { - return initialFuture; - } - // Since initialFuture is done at this point, the following call should be non-blocking - OperationSnapshot initialOperation = initialFuture.get(); - - if (initialOperation.isDone()) { - return initialFuture; - } - - return longRunningClient - .getOperationCallable() - .futureCall(initialOperation.getName(), callContext); - } catch (ExecutionException e) { - return ApiFutures.immediateFailedFuture(e.getCause()); - } catch (InterruptedException e) { - return ApiFutures.immediateFailedFuture(e); - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/OutOfRangeException.java b/gax/src/main/java/com/google/api/gax/rpc/OutOfRangeException.java deleted file mode 100644 index 33ecb38ca..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/OutOfRangeException.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -/** - * Exception thrown when the operation was attempted past the valid range. E.g., seeking or reading - * past end of file. - */ -public class OutOfRangeException extends ApiException { - public OutOfRangeException(Throwable cause, StatusCode statusCode, boolean retryable) { - super(cause, statusCode, retryable); - } - - public OutOfRangeException( - String message, Throwable cause, StatusCode statusCode, boolean retryable) { - super(message, cause, statusCode, retryable); - } - - public OutOfRangeException( - Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { - super(cause, statusCode, retryable, errorDetails); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/PageContext.java b/gax/src/main/java/com/google/api/gax/rpc/PageContext.java deleted file mode 100644 index a58238881..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/PageContext.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.auto.value.AutoValue; - -/** The context for a page call. */ -@AutoValue -public abstract class PageContext { - - public abstract UnaryCallable getCallable(); - - public abstract PagedListDescriptor getPageDescriptor(); - - public abstract RequestT getRequest(); - - public abstract ApiCallContext getCallContext(); - - public PageContext withRequest(RequestT newRequest) { - return new AutoValue_PageContext<>( - getCallable(), getPageDescriptor(), newRequest, getCallContext()); - } - - public static PageContext create( - UnaryCallable callable, - PagedListDescriptor pageDescriptor, - RequestT request, - ApiCallContext callContext) { - return new AutoValue_PageContext<>(callable, pageDescriptor, request, callContext); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/PagedCallSettings.java b/gax/src/main/java/com/google/api/gax/rpc/PagedCallSettings.java deleted file mode 100644 index cff1ed0b7..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/PagedCallSettings.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.InternalExtensionOnly; -import com.google.api.gax.retrying.RetrySettings; -import java.util.Set; - -/** - * A settings class to configure a {@link UnaryCallable} for calls to an API method that supports - * page streaming. - */ -@InternalExtensionOnly -public final class PagedCallSettings - extends UnaryCallSettings { - private final PagedListResponseFactory - pagedListResponseFactory; - - public PagedListResponseFactory - getPagedListResponseFactory() { - return pagedListResponseFactory; - } - - public static - Builder newBuilder( - PagedListResponseFactory - pagedListResponseFactory) { - return new Builder<>(pagedListResponseFactory); - } - - @Override - public final Builder toBuilder() { - return new Builder<>(this); - } - - private PagedCallSettings(Builder builder) { - super(builder); - this.pagedListResponseFactory = builder.pagedListResponseFactory; - } - - public static class Builder - extends UnaryCallSettings.Builder { - private PagedListResponseFactory - pagedListResponseFactory; - - public Builder( - PagedListResponseFactory - pagedListResponseFactory) { - this.pagedListResponseFactory = pagedListResponseFactory; - } - - public Builder(PagedCallSettings settings) { - super(settings); - this.pagedListResponseFactory = settings.pagedListResponseFactory; - } - - @Override - public Builder setRetryableCodes( - Set retryableCodes) { - super.setRetryableCodes(retryableCodes); - return this; - } - - @Override - public Builder setRetryableCodes( - StatusCode.Code... codes) { - super.setRetryableCodes(codes); - return this; - } - - @Override - public Builder setRetrySettings( - RetrySettings retrySettings) { - super.setRetrySettings(retrySettings); - return this; - } - - public PagedListResponseFactory - getPagedListResponseFactory() { - return pagedListResponseFactory; - } - - @Override - public PagedCallSettings build() { - return new PagedCallSettings<>(this); - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/PagedCallable.java b/gax/src/main/java/com/google/api/gax/rpc/PagedCallable.java deleted file mode 100644 index 5a2f47815..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/PagedCallable.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.ApiFuture; -import com.google.api.core.InternalApi; -import com.google.common.base.Preconditions; - -/** - * A UnaryCallable which provides page streaming functionality for unary calls. - * - *

Public for technical reasons - for advanced usage. - */ -@InternalApi("For use by transport-specific implementations") -public class PagedCallable - extends UnaryCallable { - private final UnaryCallable callable; - private final PagedListResponseFactory - pagedListResponseFactory; - - public PagedCallable( - UnaryCallable callable, - PagedListResponseFactory pagedListResponseFactory) { - this.callable = Preconditions.checkNotNull(callable); - this.pagedListResponseFactory = pagedListResponseFactory; - } - - @Override - public String toString() { - return String.format("paged(%s)", callable); - } - - @Override - public ApiFuture futureCall(RequestT request, ApiCallContext context) { - ApiFuture futureResponse = callable.futureCall(request, context); - return pagedListResponseFactory.getFuturePagedResponse( - callable.withDefaultCallContext(context), request, context, futureResponse); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/PagedListDescriptor.java b/gax/src/main/java/com/google/api/gax/rpc/PagedListDescriptor.java deleted file mode 100644 index ee272bb91..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/PagedListDescriptor.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -/** - * An interface which provides the functionality to extract data from requests and inject data into - * requests for the purposes of page streaming. - * - *

This class is designed to be used by generated code. - */ -public interface PagedListDescriptor { - - /** Delivers the empty page token. */ - String emptyToken(); - - /** Injects a page token into the request. */ - RequestT injectToken(RequestT payload, String token); - - /** Injects page size setting into the request. */ - RequestT injectPageSize(RequestT payload, int pageSize); - - /** Extracts the page size setting from the request. */ - Integer extractPageSize(RequestT payload); - - /** - * Extracts the next token from the response. Returns the empty token if there are no more pages. - */ - String extractNextToken(ResponseT payload); - - /** Extracts an iterable of resources from the response. */ - Iterable extractResources(ResponseT payload); -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/PagedListResponseFactory.java b/gax/src/main/java/com/google/api/gax/rpc/PagedListResponseFactory.java deleted file mode 100644 index ed8d5551d..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/PagedListResponseFactory.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.ApiFuture; - -/** - * Interface for constructing futures which return PagedListResponse objects. - * - *

This class is designed to be used by generated code. - */ -public interface PagedListResponseFactory { - - ApiFuture getFuturePagedResponse( - UnaryCallable callable, - RequestT request, - ApiCallContext context, - ApiFuture futureResponse); -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/PermissionDeniedException.java b/gax/src/main/java/com/google/api/gax/rpc/PermissionDeniedException.java deleted file mode 100644 index c9e751597..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/PermissionDeniedException.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -/** Exception thrown when the caller does not have permission to execute the specified operation. */ -public class PermissionDeniedException extends ApiException { - public PermissionDeniedException(Throwable cause, StatusCode statusCode, boolean retryable) { - super(cause, statusCode, retryable); - } - - public PermissionDeniedException( - String message, Throwable cause, StatusCode statusCode, boolean retryable) { - super(message, cause, statusCode, retryable); - } - - public PermissionDeniedException( - Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { - super(cause, statusCode, retryable, errorDetails); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/ProtocolBufferParsingException.java b/gax/src/main/java/com/google/api/gax/rpc/ProtocolBufferParsingException.java deleted file mode 100644 index ce8f306a2..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/ProtocolBufferParsingException.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -/** Exception thrown when parsing protocol buffer message failed */ -public class ProtocolBufferParsingException extends RuntimeException { - - public ProtocolBufferParsingException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/QueuingResponseObserver.java b/gax/src/main/java/com/google/api/gax/rpc/QueuingResponseObserver.java deleted file mode 100644 index 36e5384bf..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/QueuingResponseObserver.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.common.collect.Queues; -import java.util.concurrent.BlockingQueue; - -/** - * A back pressure aware bridge from a {@link ResponseObserver} to a {@link BlockingQueue}. The - * queue size is fixed to 1 item and a close signal. The observer will manage its own flow control, - * keeping the queue in one of 3 states: - * - *

    - *
  • empty: a item has been requested and we are awaiting the next item - *
  • 1 item: an in progress stream with 1 item buffered - *
  • 1 control signal: either a Throwable, or an EOF_MARKER which means that the stream is - * closed - *
  • 1 item & 1 control signal: this is the last item of the stream - *
- * - *

The observer can also be abruptly cancelled, which cancels the underlying call and always - * returns an EOF_MARKER. - * - *

Package-private for internal use. - * - * @param The item type. - */ -final class QueuingResponseObserver extends StateCheckingResponseObserver { - static final Object EOF_MARKER = new Object(); - - private final BlockingQueue buffer = Queues.newArrayBlockingQueue(2); - private StreamController controller; - private boolean isCancelled; - - void request() { - controller.request(1); - } - - Object getNext() throws InterruptedException { - if (isCancelled) { - return EOF_MARKER; - } - return buffer.take(); - } - - boolean isReady() { - return isCancelled || !buffer.isEmpty(); - } - - /** - * Cancels the underlying RPC and causes getNext to always return EOF_MARKER. This can only be - * called after starting the underlying call. - */ - void cancel() { - isCancelled = true; - controller.cancel(); - } - - /** - * Before starting the RPC, disable automatic flow control and retain a reference to the - * controller. - * - * @param controller The controller for the stream. - */ - @Override - protected void onStartImpl(StreamController controller) { - this.controller = controller; - controller.disableAutoInboundFlowControl(); - controller.request(1); - } - - /** - * Buffer the response. There should be at most 1 response in the buffer. - * - * @param response The received response. - */ - @Override - protected void onResponseImpl(V response) { - buffer.add(response); - } - - /** - * Enqueue the error to be thrown later on. The error might occur without a request so the queue - * might grow to 2 elements, and in that case the previous response will be consumed first. - * - * @param t The error occurred on the stream - */ - @Override - protected void onErrorImpl(Throwable t) { - buffer.add(t); - } - - /** - * Enqueue a marker to notify the consumer that the stream is finished. In most situations this - * will cause the queue to grow to 2 elements: the requested response and an unsolicited - * completion marker. - */ - @Override - protected void onCompleteImpl() { - buffer.add(EOF_MARKER); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/RecheckingCallable.java b/gax/src/main/java/com/google/api/gax/rpc/RecheckingCallable.java deleted file mode 100644 index 9441223e4..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/RecheckingCallable.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.gax.retrying.RetryingExecutorWithContext; -import com.google.api.gax.retrying.RetryingFuture; -import com.google.common.base.Preconditions; - -/** - * A UnaryCallable that will keep issuing calls to an inner callable until a terminal condition is - * met. - * - *

Note: Any request passed to this class is ignored. - * - *

Package-private for internal use. - */ -class RecheckingCallable extends UnaryCallable { - private final UnaryCallable callable; - private final RetryingExecutorWithContext executor; - - RecheckingCallable( - UnaryCallable callable, - RetryingExecutorWithContext executor) { - this.callable = Preconditions.checkNotNull(callable); - this.executor = Preconditions.checkNotNull(executor); - } - - @Override - public RetryingFuture futureCall(RequestT ignored, ApiCallContext inputContext) { - CheckingAttemptCallable checkingAttemptCallable = - new CheckingAttemptCallable<>(callable, inputContext); - - RetryingFuture retryingFuture = - executor.createFuture(checkingAttemptCallable, inputContext); - checkingAttemptCallable.setExternalFuture(retryingFuture); - checkingAttemptCallable.call(); - - return retryingFuture; - } - - @Override - public String toString() { - return String.format("rechecking(%s)", callable); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/RequestParamsBuilder.java b/gax/src/main/java/com/google/api/gax/rpc/RequestParamsBuilder.java deleted file mode 100644 index 4f234f0ce..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/RequestParamsBuilder.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.BetaApi; -import com.google.api.pathtemplate.PathTemplate; -import com.google.common.collect.ImmutableMap; -import java.util.Map; - -/** - * This builder class builds a request params map that will be used by autogenerated implementation - * of {@link RequestParamsExtractor}. - */ -@BetaApi -public class RequestParamsBuilder { - - private final ImmutableMap.Builder paramsBuilder; - - private RequestParamsBuilder() { - this.paramsBuilder = ImmutableMap.builder(); - } - - public static RequestParamsBuilder create() { - return new RequestParamsBuilder(); - } - - /** - * Add an entry to paramsBuilder by match-and-extract field values from requests based on - * pre-configured path templates. This method is called repeatedly for each configured routing - * rule parameter, it's possible that the incoming field value from request is null or there is no - * matches found, we'll continue the match-and-extract process for the next routing rule parameter - * in such case. - * - * @param fieldValue the field value from a request - * @param headerKey the header key for the routing header param - * @param pathTemplate {@link PathTemplate} the path template used for match-and-extract - */ - public void add(String fieldValue, String headerKey, PathTemplate pathTemplate) { - if (fieldValue == null) { - return; - } - Map matchedValues = pathTemplate.match(fieldValue); - if (matchedValues != null && matchedValues.containsKey(headerKey)) { - paramsBuilder.put(headerKey, matchedValues.get(headerKey)); - } - } - - public Map build() { - return paramsBuilder.buildKeepingLast(); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/RequestParamsEncoder.java b/gax/src/main/java/com/google/api/gax/rpc/RequestParamsEncoder.java deleted file mode 100644 index 19f4742eb..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/RequestParamsEncoder.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.InternalApi; - -/** - * A request params encoder takes a {@code request} object and encodes some (or all) of its - * parameters in a string form following specific parameter extraction and string encoding rules, - * defined by concrete implementations of this interface. - * - * @param request message type - */ -@InternalApi("For use by transport-specific implementations") -public interface RequestParamsEncoder { - - /** - * Encodes {@code request} message in a string. - * - * @param request request message - */ - String encode(RequestT request); -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/RequestParamsExtractor.java b/gax/src/main/java/com/google/api/gax/rpc/RequestParamsExtractor.java deleted file mode 100644 index eb52c6e92..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/RequestParamsExtractor.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.InternalApi; -import java.util.Map; - -/** - * A request params extractor takes a {@code request} message, extracts specific field values from - * it, converts them in strings and returns them as key-value pairs, where a key is a request field - * name and a value is a string representation of a field value. Nested fields should also be - * extractable, in such case the "dot notation" can be used to represent a nested field name, for - * example {@code "field_name.nested_field_name"}. - * - *

Implementations of this interface are expected to be autogenerated. - * - * @param request message type - */ -@InternalApi("For use by transport-specific implementations") -public interface RequestParamsExtractor { - /** - * Extracts specific fields from the {@code request} and returns them in a form of key-value - * pairs, where a key is a field name and a value is a field's string representation. To represent - * nested field names the "dot notation" can be used. - * - * @param request request message - */ - Map extract(RequestT request); -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/RequestUrlParamsEncoder.java b/gax/src/main/java/com/google/api/gax/rpc/RequestUrlParamsEncoder.java deleted file mode 100644 index 6bb1da250..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/RequestUrlParamsEncoder.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.api.core.InternalApi; -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import java.net.URLEncoder; -import java.util.Map; - -/** - * The request params encoder, which encodes URL-encoded parameters in one URL parameters string. - * This class expects that name-value pairs, returned from parameters extractor are already - * URL-encoded and can perform optional validation of that, but does not encode the name-value pairs - * themselves. - * - * @param request message type - */ -@InternalApi("For use by transport-specific implementations") -public class RequestUrlParamsEncoder implements RequestParamsEncoder { - private static final String STR_ENCODING = "UTF-8"; - - private final RequestParamsExtractor paramsExtractor; - private final boolean validateExtractedParameters; - - /** - * Creates the encoder. - * - * @param paramsExtractor parameters extractor which returns already URL-encoded key-value pairs - * @param validateExtractedParameters {@code true} if this class should validate that the - * extracted parameters are URL-encoded, {@code false} otherwise - */ - public RequestUrlParamsEncoder( - RequestParamsExtractor paramsExtractor, boolean validateExtractedParameters) { - this.paramsExtractor = checkNotNull(paramsExtractor); - this.validateExtractedParameters = validateExtractedParameters; - } - - /** - * Encodes the {@code request} in a form of a URL parameters string, for example {@code - * "param1=value+1¶m2=value2%26"}. This method may optionally validate that the name-value - * paris are URL-encoded, but it will not perform the actual encoding of them (it will only - * concatenate the valid individual name-value pairs in a valid URL parameters string). This is - * so, because in most practical cases the name-value paris are already URL-encoded. - * - * @param request request message - * @throws IllegalArgumentException if is not - */ - @Override - public String encode(RequestT request) { - Map params = paramsExtractor.extract(request); - if (params.isEmpty()) { - return ""; - } - StringBuilder sb = new StringBuilder(); - for (Map.Entry entry : params.entrySet()) { - if (sb.length() > 0) { - sb.append("&"); - } - String name = entry.getKey(); - String value = entry.getValue(); - if (name == null) { - throw new IllegalArgumentException("Request parameter name cannot be null"); - } - - // Let the server decide if the value is required. - // Empty value is allowed. - if (value != null) { - if (!isValid(name, value)) { - throw new IllegalArgumentException( - "Invalid url-encoded request parameter name-value pair: " + name + "=" + value); - } - sb.append(name).append("=").append(value); - } - } - - return sb.toString(); - } - - // Not sure if we need this at all. - private boolean isValid(String name, String value) { - try { - // hoping that encode/decode do not lose information in the middle - // (at least for practical use cases) - return !validateExtractedParameters - || name.equals(URLEncoder.encode(URLDecoder.decode(name, STR_ENCODING), STR_ENCODING)) - && value.equals( - URLEncoder.encode(URLDecoder.decode(value, STR_ENCODING), STR_ENCODING)); - } catch (UnsupportedEncodingException e) { - return false; - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/ResourceExhaustedException.java b/gax/src/main/java/com/google/api/gax/rpc/ResourceExhaustedException.java deleted file mode 100644 index 2561c54ce..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/ResourceExhaustedException.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -/** - * Exception thrown when some resource has been exhausted, perhaps a per-user quota, or perhaps the - * entire file system is out of space. - */ -public class ResourceExhaustedException extends ApiException { - public ResourceExhaustedException(Throwable cause, StatusCode statusCode, boolean retryable) { - super(cause, statusCode, retryable); - } - - public ResourceExhaustedException( - String message, Throwable cause, StatusCode statusCode, boolean retryable) { - super(message, cause, statusCode, retryable); - } - - public ResourceExhaustedException( - Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { - super(cause, statusCode, retryable, errorDetails); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/ResponseObserver.java b/gax/src/main/java/com/google/api/gax/rpc/ResponseObserver.java deleted file mode 100644 index 77c7a82d3..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/ResponseObserver.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -/** - * Receives notifications from server-streaming calls. - * - *

The application is responsible for implementing the {@code ResponseObserver} and passing it to - * GAX, which then calls the observer with the messages for the application to receive them. The - * methods might be called by different threads, but are guaranteed to happen sequentially. The - * order of callbacks is guaranteed to be: - * - *

    - *
  • exactly 1 onStart - *
  • 0 or more on Response - *
  • exactly 1 onError or onComplete - *
- * - *

By default, the stream uses automatic flow control, where the next response will be delivered - * as soon as the current one is processed by onResponse. A consumer can disable automatic flow - * control by calling {@code disableAutoInboundFlowControl()} in {@code onStart}. After this, the - * consumer must request responses by calling {@code request()}. - */ -public interface ResponseObserver { - - /** - * Called before the stream is started. This must be invoked synchronously on the same thread that - * called {@link ServerStreamingCallable#call(Object, ResponseObserver, ApiCallContext)} - * - *

Allows for disabling flow control and early stream termination via {@code StreamController}. - * - * @param controller The controller for the stream. - */ - void onStart(StreamController controller); - - /** - * Receives a value from the stream. - * - *

Can be called many times but is never called after {@link #onError(Throwable)} or {@link - * #onComplete()} are called. - * - *

Clients may may receive 0 or more onResponse callbacks. - * - *

If an exception is thrown by an implementation the caller will terminate the stream by - * calling {@link #onError(Throwable)} with the caught exception as the cause. - * - * @param response the value passed to the stream - */ - void onResponse(V response); - - /** - * Receives a terminating error from the stream. - * - *

May only be called once, and if called, it must be the last method called. In particular, if - * an exception is thrown by an implementation of {@code onError}, no further calls to any method - * are allowed. - * - * @param t the error occurred on the stream - */ - void onError(Throwable t); - - /** - * Receives a notification of successful stream completion. - * - *

May only be called once, and if called, it must be the last method called. In particular, if - * an exception is thrown by an implementation of {@code onComplete}, no further calls to any - * method are allowed. - */ - void onComplete(); -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/RetryingCallable.java b/gax/src/main/java/com/google/api/gax/rpc/RetryingCallable.java deleted file mode 100644 index 0a92794a2..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/RetryingCallable.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.gax.retrying.RetryingExecutorWithContext; -import com.google.api.gax.retrying.RetryingFuture; -import com.google.common.base.Preconditions; - -/** - * A UnaryCallable that will keep issuing calls to an inner callable until it succeeds or times out. - * - *

Package-private for internal use. - */ -class RetryingCallable extends UnaryCallable { - private final ApiCallContext callContextPrototype; - private final UnaryCallable callable; - private final RetryingExecutorWithContext executor; - - RetryingCallable( - ApiCallContext callContextPrototype, - UnaryCallable callable, - RetryingExecutorWithContext executor) { - this.callContextPrototype = Preconditions.checkNotNull(callContextPrototype); - this.callable = Preconditions.checkNotNull(callable); - this.executor = Preconditions.checkNotNull(executor); - } - - @Override - public RetryingFuture futureCall(RequestT request, ApiCallContext inputContext) { - ApiCallContext context = callContextPrototype.nullToSelf(inputContext); - AttemptCallable retryCallable = - new AttemptCallable<>(callable, request, context); - - RetryingFuture retryingFuture = executor.createFuture(retryCallable, inputContext); - retryCallable.setExternalFuture(retryingFuture); - retryCallable.call(); - - return retryingFuture; - } - - @Override - public String toString() { - return String.format("retrying(%s)", callable); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/RetryingServerStreamingCallable.java b/gax/src/main/java/com/google/api/gax/rpc/RetryingServerStreamingCallable.java deleted file mode 100644 index cb7e3bb78..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/RetryingServerStreamingCallable.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static com.google.common.util.concurrent.MoreExecutors.directExecutor; - -import com.google.api.core.ApiFutureCallback; -import com.google.api.core.ApiFutures; -import com.google.api.gax.retrying.RetryingFuture; -import com.google.api.gax.retrying.ScheduledRetryingExecutor; -import com.google.api.gax.retrying.ServerStreamingAttemptException; -import com.google.api.gax.retrying.StreamResumptionStrategy; - -/** - * A ServerStreamingCallable that implements resumable retries. - * - *

Wraps a request, a {@link ResponseObserver} and an inner {@link ServerStreamingCallable} and - * coordinates retries between them. When the inner callable throws an error, this class will - * schedule retries using the configured {@link ScheduledRetryingExecutor}. - * - *

Streams can be resumed using a {@link StreamResumptionStrategy}. The {@link - * StreamResumptionStrategy} is notified of incoming responses and is expected to track the progress - * of the stream. Upon receiving an error, the {@link StreamResumptionStrategy} is asked to modify - * the original request to resume the stream. - * - *

Package-private for internal use. - */ -final class RetryingServerStreamingCallable - extends ServerStreamingCallable { - - private final ServerStreamingCallable innerCallable; - private final ScheduledRetryingExecutor executor; - private final StreamResumptionStrategy resumptionStrategyPrototype; - - RetryingServerStreamingCallable( - ServerStreamingCallable innerCallable, - ScheduledRetryingExecutor executor, - StreamResumptionStrategy resumptionStrategyPrototype) { - this.innerCallable = innerCallable; - this.executor = executor; - this.resumptionStrategyPrototype = resumptionStrategyPrototype; - } - - @Override - public void call( - RequestT request, - final ResponseObserver responseObserver, - ApiCallContext context) { - - ServerStreamingAttemptCallable attemptCallable = - new ServerStreamingAttemptCallable<>( - innerCallable, - resumptionStrategyPrototype.createNew(), - request, - context, - responseObserver); - - RetryingFuture retryingFuture = executor.createFuture(attemptCallable, context); - attemptCallable.setExternalFuture(retryingFuture); - attemptCallable.start(); - - // Bridge the future result back to the external responseObserver - ApiFutures.addCallback( - retryingFuture, - new ApiFutureCallback() { - @Override - public void onFailure(Throwable throwable) { - // Make sure to unwrap the underlying ApiException - if (throwable instanceof ServerStreamingAttemptException) { - throwable = throwable.getCause(); - } - responseObserver.onError(throwable); - } - - @Override - public void onSuccess(Void ignored) { - responseObserver.onComplete(); - } - }, - directExecutor()); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/ServerStream.java b/gax/src/main/java/com/google/api/gax/rpc/ServerStream.java deleted file mode 100644 index 518c68523..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/ServerStream.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.InternalApi; -import java.util.Iterator; -import javax.annotation.Nonnull; - -/** - * A blocking Iterable-style wrapper around server stream responses. - * - *

This class asynchronously pulls responses from upstream via {@link - * StreamController#request(int)} and exposes them via its Iterator. The implementation is back - * pressure aware and uses a constant buffer of 1 item. - * - *

Please note that the stream can only be consumed once and must either be fully consumed or be - * canceled. - * - *

Neither this class nor the iterator it returns is thread-safe. - * - *

Example usage: - * - *

{@code
- * ServerStream stream = ...;
- *
- * for (Item item : stream) {
- *   System.out.println(item.id());
- *
- *   // Allow for early termination
- *   if (item.id().equals("needle")) {
- *     // Cancelling the stream will cause `hasNext()` to return false on the next iteration,
- *     // naturally breaking the loop.
- *     stream.cancel();
- *   }
- * }
- * }
- * - * @param The type of each response. - */ -public class ServerStream implements Iterable { - private final QueuingResponseObserver observer = new QueuingResponseObserver<>(); - private final ServerStreamIterator iterator = new ServerStreamIterator<>(observer); - private boolean consumed; - - @InternalApi("For use by ServerStreamingCallable only.") - ServerStream() {} - - @InternalApi("For use by ServerStreamingCallable only.") - ResponseObserver observer() { - return observer; - } - - /** {@inheritDoc} */ - @Override - @Nonnull - public Iterator iterator() { - if (consumed) { - throw new IllegalStateException("Iterator already consumed"); - } - consumed = true; - - return iterator; - } - - /** - * Returns true if the next call to the iterator's hasNext() or next() is guaranteed to be - * nonblocking. - * - * @return If the call on any of the iterator's methods is guaranteed to be nonblocking. - */ - public boolean isReceiveReady() { - return iterator.isReady(); - } - - /** - * Cleanly cancels a partially consumed stream. The associated iterator will return false for the - * hasNext() in the next iteration. This maintains the contract that an observed true from - * hasNext() will yield an item in next(), but afterwards will return false. - */ - public void cancel() { - observer.cancel(); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/ServerStreamIterator.java b/gax/src/main/java/com/google/api/gax/rpc/ServerStreamIterator.java deleted file mode 100644 index 17a912de8..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/ServerStreamIterator.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.common.util.concurrent.UncheckedExecutionException; -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * Internal implementation of a blocking Iterator, which will coordinate with the - * QueuingResponseObserver to fetch new items from upstream. The Iterator expects the observer to - * request the first item, and afterwards, new items will be requested when the current ones are - * consumed by next(). - * - *

Package-private for internal use. - * - * @param The type of items to be Iterated over. - */ -final class ServerStreamIterator implements Iterator { - private final QueuingResponseObserver observer; - private Object last; - - ServerStreamIterator(QueuingResponseObserver observer) { - this.observer = observer; - } - - /** - * Checks if the next call to {@code hasNext()} (and {@code next()}) will block. - * - * @return true if the next call is guaranteed to be nonblocking. - */ - boolean isReady() { - return last != null || observer.isReady(); - } - - /** - * Consumes the next response and asynchronously request the next response from the observer. - * - * @return The next response. - * @throws NoSuchElementException If the stream has been consumed or cancelled. - */ - @Override - public V next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - try { - observer.request(); - @SuppressWarnings("unchecked") - V tmp = (V) last; - return tmp; - } finally { - last = null; - } - } - - /** - * Checks if the stream has been fully consumed or cancelled. This method will block until the - * observer enqueues another event (response or completion event). If the observer encountered an - * error, this method will propagate the error and put itself into an error where it will always - * return the same error. - * - * @return true If iterator has more responses. - */ - @Override - public boolean hasNext() { - if (last == null) { - try { - last = observer.getNext(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new RuntimeException(e); - } - } - // Preserve async error while keeping the caller's stacktrace as a suppressed exception - if (last instanceof RuntimeException) { - RuntimeException runtimeException = (RuntimeException) last; - runtimeException.addSuppressed(new RuntimeException("Asynchronous task failed")); - throw runtimeException; - } - - // This should never really happen because currently gax doesn't throw checked exceptions. - // Wrap checked exceptions. This will preserve both the caller's stacktrace and the async error. - if (last instanceof Throwable) { - Throwable throwable = (Throwable) last; - throw new UncheckedExecutionException(throwable); - } - - return last != QueuingResponseObserver.EOF_MARKER; - } - - /** Unsupported. */ - @Override - public void remove() { - throw new UnsupportedOperationException(); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/ServerStreamingAttemptCallable.java b/gax/src/main/java/com/google/api/gax/rpc/ServerStreamingAttemptCallable.java deleted file mode 100644 index 0c71d1242..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/ServerStreamingAttemptCallable.java +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.SettableApiFuture; -import com.google.api.gax.retrying.RetryingFuture; -import com.google.api.gax.retrying.ServerStreamingAttemptException; -import com.google.api.gax.retrying.StreamResumptionStrategy; -import com.google.common.base.Preconditions; -import java.util.concurrent.Callable; -import java.util.concurrent.CancellationException; -import javax.annotation.concurrent.GuardedBy; -import org.threeten.bp.Duration; - -/** - * A callable that generates Server Streaming attempts. At any one time, it is responsible for at - * most a single outstanding attempt. During an attempt, it proxies all incoming message to the - * outer {@link ResponseObserver} and the {@link StreamResumptionStrategy}. Once the attempt - * completes, the external {@link RetryingFuture} future is notified. If the {@link RetryingFuture} - * decides to retry the attempt, it will invoke {@link #call()}. - * - *

The lifecycle of this class is: - * - *

    - *
  1. The caller instantiates this class. - *
  2. The caller sets the {@link RetryingFuture} via {@link #setExternalFuture(RetryingFuture)}. - * The {@link RetryingFuture} will be responsible for scheduling future attempts. - *
  3. The caller calls {@link #start()}. This notifies the outer {@link ResponseObserver} that - * call is about to start. - *
  4. The outer {@link ResponseObserver} configures inbound flow control via the {@link - * StreamController} that it received in {@link ResponseObserver#onStart(StreamController)}. - *
  5. The attempt call is sent via the inner/upstream {@link ServerStreamingCallable}. - *
  6. A future representing the end state of the inner attempt is passed to the outer {@link - * RetryingFuture}. - *
  7. All messages received from the inner {@link ServerStreamingCallable} are recorded by the - * {@link StreamResumptionStrategy}. - *
  8. All messages received from the inner {@link ServerStreamingCallable} are forwarded to the - * outer {@link ResponseObserver}. - *
  9. Upon attempt completion (either success or failure) are communicated to the outer {@link - * RetryingFuture}. - *
  10. If the {@link RetryingFuture} decides to resume the RPC, it will invoke {@link #call()}, - * which will consult the {@link StreamResumptionStrategy} for the resuming request and - * restart the process at step 5. - *
  11. Once the {@link RetryingFuture} decides to stop the retry loop, it will notify the outer - * {@link ResponseObserver}. - *
- * - *

This class is meant to be used as middleware between an outer {@link ResponseObserver} and an - * inner {@link ServerStreamingCallable}. As such it follows the general threading model of {@link - * ServerStreamingCallable}s: - * - *

    - *
  • {@code onStart} must be called in the same thread that invoked {@code call()} - *
  • The outer {@link ResponseObserver} can call {@code request()} and {@code cancel()} on this - * class' {@link StreamController} from any thread - *
  • The inner callable will serialize calls to {@code onResponse()}, {@code onError()} and - * {@code onComplete} - *
- * - *

With this model in mind, this class only needs to synchronize access data that is shared - * between: the outer {@link ResponseObserver} (via this class' {@link StreamController}) and the - * inner {@link ServerStreamingCallable}: pendingRequests, cancellationCause and the current - * innerController. - * - *

Package-private for internal use. - * - * @param request type - * @param response type - */ -final class ServerStreamingAttemptCallable implements Callable { - private final Object lock = new Object(); - - private final ServerStreamingCallable innerCallable; - private final StreamResumptionStrategy resumptionStrategy; - private final RequestT initialRequest; - private ApiCallContext context; - private final ResponseObserver outerObserver; - - // Start state - private boolean autoFlowControl = true; - private boolean isStarted; - - // Outer state - @GuardedBy("lock") - private Throwable cancellationCause; - - @GuardedBy("lock") - private int pendingRequests; - - private RetryingFuture outerRetryingFuture; - - // Internal retry state - private int numAttempts; - - @GuardedBy("lock") - private StreamController innerController; - - private boolean seenSuccessSinceLastError; - private SettableApiFuture innerAttemptFuture; - - ServerStreamingAttemptCallable( - ServerStreamingCallable innerCallable, - StreamResumptionStrategy resumptionStrategy, - RequestT initialRequest, - ApiCallContext context, - ResponseObserver outerObserver) { - this.innerCallable = innerCallable; - this.resumptionStrategy = resumptionStrategy; - this.initialRequest = initialRequest; - this.context = context; - this.outerObserver = outerObserver; - } - - /** Sets controlling {@link RetryingFuture}. Must be called be before {@link #start()}. */ - void setExternalFuture(RetryingFuture retryingFuture) { - Preconditions.checkState(!isStarted, "Can't change the RetryingFuture once the call has start"); - Preconditions.checkNotNull(retryingFuture, "RetryingFuture can't be null"); - - this.outerRetryingFuture = retryingFuture; - } - - /** - * Starts the initial call. The call is attempted on the caller's thread. Further call attempts - * will be scheduled by the {@link RetryingFuture}. - */ - public void start() { - Preconditions.checkState(!isStarted, "Already started"); - - // Initialize the outer observer - outerObserver.onStart( - new StreamController() { - @Override - public void disableAutoInboundFlowControl() { - Preconditions.checkState( - !isStarted, "Can't disable auto flow control once the stream is started"); - autoFlowControl = false; - } - - @Override - public void request(int count) { - onRequest(count); - } - - @Override - public void cancel() { - onCancel(); - } - }); - - if (autoFlowControl) { - synchronized (lock) { - pendingRequests = Integer.MAX_VALUE; - } - } - isStarted = true; - - // Propagate the totalTimeout as the overall stream deadline, so long as the user - // has not provided a timeout via the ApiCallContext. If they have, retain it. - Duration totalTimeout = - outerRetryingFuture.getAttemptSettings().getGlobalSettings().getTotalTimeout(); - - if (totalTimeout != null && context != null && context.getTimeout() == null) { - context = context.withTimeout(totalTimeout); - } - - // Call the inner callable - call(); - } - - /** - * Sends the actual RPC. The request being sent will first be transformed by the {@link - * StreamResumptionStrategy}. - * - *

This method expects to be called by one thread at a time. Furthermore, it expects that the - * current RPC finished before the next time it's called. - */ - @Override - public Void call() { - Preconditions.checkState(isStarted, "Must be started first"); - - RequestT request = - (++numAttempts == 1) ? initialRequest : resumptionStrategy.getResumeRequest(initialRequest); - - // Should never happen. onAttemptError will check if ResumptionStrategy can create a resume - // request, - // which the RetryingFuture/StreamResumptionStrategy should respect. - Preconditions.checkState(request != null, "ResumptionStrategy returned a null request."); - - innerAttemptFuture = SettableApiFuture.create(); - seenSuccessSinceLastError = false; - - ApiCallContext attemptContext = context; - - // Set the streamWaitTimeout to the attempt RPC Timeout, only if the context - // does not already have a timeout set by a user via withStreamWaitTimeout. - if (!outerRetryingFuture.getAttemptSettings().getRpcTimeout().isZero() - && attemptContext.getStreamWaitTimeout() == null) { - attemptContext = - attemptContext.withStreamWaitTimeout( - outerRetryingFuture.getAttemptSettings().getRpcTimeout()); - } - - attemptContext - .getTracer() - .attemptStarted(request, outerRetryingFuture.getAttemptSettings().getOverallAttemptCount()); - - innerCallable.call( - request, - new StateCheckingResponseObserver() { - @Override - public void onStartImpl(StreamController controller) { - onAttemptStart(controller); - } - - @Override - public void onResponseImpl(ResponseT response) { - onAttemptResponse(response); - } - - @Override - public void onErrorImpl(Throwable t) { - onAttemptError(t); - } - - @Override - public void onCompleteImpl() { - onAttemptComplete(); - } - }, - attemptContext); - - outerRetryingFuture.setAttemptFuture(innerAttemptFuture); - - return null; - } - - /** - * Called by the inner {@link ServerStreamingCallable} when the call is about to start. This will - * transfer unfinished state from the previous attempt. - * - * @see ResponseObserver#onStart(StreamController) - */ - private void onAttemptStart(StreamController controller) { - if (!autoFlowControl) { - controller.disableAutoInboundFlowControl(); - } - - Throwable localCancellationCause; - int numToRequest = 0; - - synchronized (lock) { - innerController = controller; - - localCancellationCause = this.cancellationCause; - - if (!autoFlowControl) { - numToRequest = pendingRequests; - } - } - - if (localCancellationCause != null) { - controller.cancel(); - } else if (numToRequest > 0) { - controller.request(numToRequest); - } - } - - /** - * Called when the outer {@link ResponseObserver} wants to prematurely cancel the stream. - * - * @see StreamController#cancel() - */ - private void onCancel() { - StreamController localInnerController; - - synchronized (lock) { - if (cancellationCause != null) { - return; - } - // NOTE: BasicRetryingFuture will replace j.u.c.CancellationExceptions with it's own, - // which will not have the current stacktrace, so a special wrapper has be used here. - cancellationCause = - new ServerStreamingAttemptException( - new CancellationException("User cancelled stream"), - resumptionStrategy.canResume(), - seenSuccessSinceLastError); - localInnerController = innerController; - } - - if (localInnerController != null) { - localInnerController.cancel(); - } - } - - /** - * Called when the outer {@link ResponseObserver} is ready for more data. - * - * @see StreamController#request(int) - */ - private void onRequest(int count) { - Preconditions.checkState(!autoFlowControl, "Automatic flow control is enabled"); - Preconditions.checkArgument(count > 0, "Count must be > 0"); - - final StreamController localInnerController; - - synchronized (lock) { - int maxInc = Integer.MAX_VALUE - pendingRequests; - count = Math.min(maxInc, count); - - pendingRequests += count; - localInnerController = this.innerController; - } - - // Note: there is a race condition here where the count might go to the previous attempt's - // StreamController after it failed. But it doesn't matter, because the controller will just - // ignore it and the current controller will pick it up onStart. - if (localInnerController != null) { - localInnerController.request(count); - } - } - - /** Called when the inner callable has responses to deliver. */ - private void onAttemptResponse(ResponseT message) { - if (!autoFlowControl) { - synchronized (lock) { - pendingRequests--; - } - } - // Update local state to allow for future resume. - seenSuccessSinceLastError = true; - message = resumptionStrategy.processResponse(message); - // Notify the outer observer. - outerObserver.onResponse(message); - } - - /** - * Called when the current RPC fails. The error will be bubbled up to the outer {@link - * RetryingFuture} via the {@link #innerAttemptFuture}. - */ - private void onAttemptError(Throwable throwable) { - Throwable localCancellationCause; - synchronized (lock) { - localCancellationCause = cancellationCause; - } - - if (localCancellationCause != null) { - // Take special care to preserve the cancellation's stack trace. - innerAttemptFuture.setException(localCancellationCause); - } else { - // Wrap the original exception and provide more context for StreamingRetryAlgorithm. - innerAttemptFuture.setException( - new ServerStreamingAttemptException( - throwable, resumptionStrategy.canResume(), seenSuccessSinceLastError)); - } - } - - /** - * Called when the current RPC successfully completes. Notifies the outer {@link RetryingFuture} - * via {@link #innerAttemptFuture}. - */ - private void onAttemptComplete() { - innerAttemptFuture.set(null); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/ServerStreamingCallSettings.java b/gax/src/main/java/com/google/api/gax/rpc/ServerStreamingCallSettings.java deleted file mode 100644 index eb9373e0c..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/ServerStreamingCallSettings.java +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.retrying.SimpleStreamResumptionStrategy; -import com.google.api.gax.retrying.StreamResumptionStrategy; -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.common.base.MoreObjects; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Sets; -import java.util.Set; -import javax.annotation.Nonnull; -import org.threeten.bp.Duration; - -/** - * A settings class to configure a {@link ServerStreamingCallable}. - * - *

This class includes settings that are applicable to all server streaming calls, which - * currently just includes retries and watchdog timers. - * - *

The watchdog timer is configured via {@code idleTimeout}. The watchdog will terminate any - * stream that has not has seen any demand (via {@link StreamController#request(int)}) in the - * configured interval. To turn off idle checks, set the interval to {@link Duration#ZERO}. - * - *

Retry configuration allows for the stream to be restarted and resumed. It is composed of 3 - * parts: the retryable codes, the retry settings and the stream resumption strategy. The retryable - * codes indicate which codes cause a retry to occur, the retry settings configure the retry logic - * when the retry needs to happen, and the stream resumption strategy composes the request to resume - * the stream. To turn off retries, set the retryable codes to the empty set. - * - *

The retry settings have slightly different semantics when compared to unary RPCs: - * - *

    - *
  • retry delays are reset to the initial value as soon as a response is received. - *
  • RPC timeouts are reset to the initial value as soon as a response is received. - *
  • RPC timeouts apply to the time interval between caller demanding more responses via {@link - * StreamController#request(int)} and the {@link ResponseObserver} receiving the message. - *
  • RPC timeouts are best effort and are checked once every {@link - * StubSettings#getStreamWatchdogCheckInterval()}. - *
  • Attempt counts are reset as soon as a response is received. This means that max attempts is - * the maximum number of failures in a row. - *
  • totalTimeout still applies to the entire stream. - *
- */ -public final class ServerStreamingCallSettings - extends StreamingCallSettings { - - @Nonnull private final Set retryableCodes; - @Nonnull private final RetrySettings retrySettings; - @Nonnull private final StreamResumptionStrategy resumptionStrategy; - - @Nonnull private final Duration idleTimeout; - - private ServerStreamingCallSettings(Builder builder) { - this.retryableCodes = ImmutableSet.copyOf(builder.retryableCodes); - this.retrySettings = builder.retrySettingsBuilder.build(); - this.resumptionStrategy = builder.resumptionStrategy; - this.idleTimeout = builder.idleTimeout; - } - - /** - * See the class documentation of {@link ServerStreamingCallSettings} for a description of what - * retryableCodes do. - */ - @Nonnull - public Set getRetryableCodes() { - return retryableCodes; - } - - /** - * See the class documentation of {@link ServerStreamingCallSettings} for a description of what - * retrySettings do. - */ - @Nonnull - public RetrySettings getRetrySettings() { - return retrySettings; - } - - /** - * See the class documentation of {@link ServerStreamingCallSettings} and {@link - * StreamResumptionStrategy} for a description of what the StreamResumptionStrategy does. - */ - @Nonnull - public StreamResumptionStrategy getResumptionStrategy() { - return resumptionStrategy; - } - - /** - * See the class documentation of {@link ServerStreamingCallSettings} for a description of what - * the {@link #idleTimeout} does. - */ - @Nonnull - public Duration getIdleTimeout() { - return idleTimeout; - } - - public Builder toBuilder() { - return new Builder<>(this); - } - - public static Builder newBuilder() { - return new Builder<>(); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("idleTimeout", idleTimeout) - .add("retryableCodes", retryableCodes) - .add("retrySettings", retrySettings) - .toString(); - } - - public static class Builder - extends StreamingCallSettings.Builder { - @Nonnull private Set retryableCodes; - @Nonnull private RetrySettings.Builder retrySettingsBuilder; - @Nonnull private StreamResumptionStrategy resumptionStrategy; - - @Nonnull private Duration idleTimeout; - - /** Initialize the builder with default settings */ - private Builder() { - this.retryableCodes = ImmutableSet.of(); - this.retrySettingsBuilder = RetrySettings.newBuilder(); - this.resumptionStrategy = new SimpleStreamResumptionStrategy<>(); - - this.idleTimeout = Duration.ZERO; - } - - private Builder(ServerStreamingCallSettings settings) { - super(settings); - this.retryableCodes = settings.retryableCodes; - this.retrySettingsBuilder = settings.retrySettings.toBuilder(); - this.resumptionStrategy = settings.resumptionStrategy; - - this.idleTimeout = settings.idleTimeout; - } - - /** - * See the class documentation of {@link ServerStreamingCallSettings} for a description of what - * retryableCodes do. - */ - public Builder setRetryableCodes(StatusCode.Code... codes) { - this.setRetryableCodes(Sets.newHashSet(codes)); - return this; - } - - /** - * See the class documentation of {@link ServerStreamingCallSettings} for a description of what - * retryableCodes do. - */ - public Builder setRetryableCodes(Set retryableCodes) { - Preconditions.checkNotNull(retryableCodes); - this.retryableCodes = Sets.newHashSet(retryableCodes); - return this; - } - - @Nonnull - public Set getRetryableCodes() { - return retryableCodes; - } - - /** - * Returns the underlying {@link RetrySettings.Builder}, which allows callers to augment the - * existing {@link RetrySettings}. - */ - public RetrySettings.Builder retrySettings() { - return this.retrySettingsBuilder; - } - - /** - * Replaces the {@link RetrySettings} for the associated {@link ServerStreamingCallable}. - * - *

When using the method, make sure that the {@link RetrySettings} are complete. For example, - * the following code will disable retries because the retry delay is not set: - * - *

{@code
-     * stubSettings.setRetrySettings(
-     *   RetrySettings.newBuilder()
-     *     .setTotalTimeout(Duration.ofSeconds(10)
-     * );
-     * }
- * - * @see #retrySettings() - */ - public Builder setRetrySettings(@Nonnull RetrySettings retrySettings) { - Preconditions.checkNotNull(retrySettings); - this.retrySettingsBuilder = retrySettings.toBuilder(); - return this; - } - - @Nonnull - public RetrySettings getRetrySettings() { - return retrySettingsBuilder.build(); - } - - /** Disables retries and sets the overall timeout. */ - public Builder setSimpleTimeoutNoRetries(@Nonnull Duration timeout) { - setRetryableCodes(); - setRetrySettings( - RetrySettings.newBuilder() - .setTotalTimeout(timeout) - .setInitialRetryDelay(Duration.ZERO) - .setRetryDelayMultiplier(1) - .setMaxRetryDelay(Duration.ZERO) - .setInitialRpcTimeout(Duration.ZERO) - .setRpcTimeoutMultiplier(1) - .setMaxRpcTimeout(Duration.ZERO) - .setMaxAttempts(1) - .build()); - - return this; - } - - /** - * See the class documentation of {@link ServerStreamingCallSettings} for a description of what - * StreamResumptionStrategy does. - */ - public Builder setResumptionStrategy( - @Nonnull StreamResumptionStrategy resumptionStrategy) { - Preconditions.checkNotNull(resumptionStrategy); - this.resumptionStrategy = Preconditions.checkNotNull(resumptionStrategy); - return this; - } - - @Nonnull - public StreamResumptionStrategy getResumptionStrategy() { - return resumptionStrategy; - } - - @Nonnull - public Duration getIdleTimeout() { - return idleTimeout; - } - - /** - * See the class documentation of {@link ServerStreamingCallSettings} for a description of what - * the {@link #idleTimeout} does. {@link Duration#ZERO} disables the watchdog. - */ - public Builder setIdleTimeout(@Nonnull Duration idleTimeout) { - this.idleTimeout = Preconditions.checkNotNull(idleTimeout); - return this; - } - - @Override - public ServerStreamingCallSettings build() { - return new ServerStreamingCallSettings<>(this); - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/ServerStreamingCallable.java b/gax/src/main/java/com/google/api/gax/rpc/ServerStreamingCallable.java deleted file mode 100644 index 51eed9388..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/ServerStreamingCallable.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import java.util.Iterator; -import java.util.List; - -/** - * A ServerStreamingCallable is an immutable object which is capable of making RPC calls to server - * streaming API methods. Not all transports support streaming. - * - *

It is considered advanced usage for a user to create a ServerStreamingCallable themselves. - * This class is intended to be created by a generated client class, and configured by instances of - * StreamingCallSettings.Builder which are exposed through the client settings class. - */ -public abstract class ServerStreamingCallable { - private final FirstElementCallable firstCallable; - private final SpoolingCallable spoolingCallable; - - protected ServerStreamingCallable() { - firstCallable = new FirstElementCallable<>(this); - spoolingCallable = new SpoolingCallable<>(this); - } - - /** - * Construct a {@link UnaryCallable} that will yield the first item in the stream and cancel it. - * If the stream is empty, the item will be null. - * - *

Example usage: - * - *

{@code
-   * StreamingCallable streamingCallable = // ..
-   * String theResult = streamingCallable.first().call(request);
-   * ApiFuture theResult = streamingCallable.first().futureCall(request);
-   * }
- * - * @return The {@link UnaryCallable}. - */ - public UnaryCallable first() { - return firstCallable; - } - - /** - * Construct a {@link UnaryCallable} that will buffer the entire stream into memory before - * completing. If the stream is empty, then the list will be empty. - * - *

Example usage: - * - *

{@code
-   * StreamingCallable streamingCallable = // ..
-   * List theResult = streamingCallable.all().call(request);
-   * ApiFuture> theResult = streamingCallable.all().futureCall(request);
-   * }
- * - * @return The {@link UnaryCallable}. - */ - public UnaryCallable> all() { - return spoolingCallable; - } - - /** - * Conduct a iteration server streaming call. - * - *

This returns a live stream that must either be fully consumed or cancelled. Example usage: - * - *

{@code
-   * StreamingCallable streamingCallable = // ..
-   * ServerStream stream = streamingCallable.call(request)
-   * for (String s : stream) {
-   *   if ("needle".equals(s)) {
-   *     // Cancelling the stream will cause `hasNext()` to return false on the next iteration,
-   *     // naturally breaking the loop.
-   *     stream.cancel();
-   *   }
-   * }
-   * List theResult = streamingCallable.all().call(request);
-   * ApiFuture> theResult = streamingCallable.all().futureCall(request);
-   * }
- * - * @param request request - * @return {@link ServerStream} which is used for iterating the responses. - */ - public ServerStream call(RequestT request) { - return call(request, (ApiCallContext) null); - } - - /** - * Conduct a server streaming call with the given {@link ApiCallContext}. - * - *

This returns a live stream that must either be fully consumed or cancelled. - * - * @param request request - * @param context the context - * @return {@link ServerStream} which is used for iterating the responses. - */ - public ServerStream call(RequestT request, ApiCallContext context) { - ServerStream stream = new ServerStream<>(); - call(request, stream.observer(), context); - - return stream; - } - - /** - * Conduct a server streaming call with the given {@link ApiCallContext}. - * - * @param request request - * @param responseObserver {@link ResponseObserver} to observe the streaming responses - * @param context {@link ApiCallContext} to provide context information for the RPC call. - */ - public abstract void call( - RequestT request, ResponseObserver responseObserver, ApiCallContext context); - - /** - * Conduct a server streaming call - * - * @param request request - * @param responseObserver {@link ResponseObserver} to observe the streaming responses - */ - public void call(RequestT request, ResponseObserver responseObserver) { - call(request, responseObserver, null); - } - - /** - * Conduct a server streaming call with the given {@link ApiCallContext}. - * - * @param request request - * @param responseObserver {@link ApiStreamObserver} to observe the streaming responses - * @param context {@link ApiCallContext} to provide context information for the RPC call. - * @deprecated Please use the {@link ResponseObserver} variant instead. - */ - @Deprecated - public void serverStreamingCall( - RequestT request, - final ApiStreamObserver responseObserver, - ApiCallContext context) { - - call(request, new ApiStreamObserverAdapter<>(responseObserver), context); - } - - /** - * Conduct a server streaming call - * - * @param request request - * @param responseObserver {@link ApiStreamObserver} to observe the streaming responses - * @deprecated Please use the {@link ResponseObserver} variant instead. - */ - @Deprecated - public void serverStreamingCall(RequestT request, ApiStreamObserver responseObserver) { - serverStreamingCall(request, responseObserver, null); - } - - /** - * Conduct an iteration server streaming call - * - * @param request request - * @param context context - * @return {@link Iterator} which is used for iterating the responses. - * @deprecated Please use call() instead. - */ - @Deprecated - public Iterator blockingServerStreamingCall(RequestT request, ApiCallContext context) { - return call(request, context).iterator(); - } - - /** - * Conduct a iteration server streaming call - * - * @param request request - * @return {@link Iterator} which is used for iterating the responses. - * @deprecated Please use call() instead. - */ - @Deprecated - public Iterator blockingServerStreamingCall(RequestT request) { - return blockingServerStreamingCall(request, null); - } - - /** - * Returns a new {@code ServerStreamingCallable} with an {@link ApiCallContext} that is used as a - * default when none is supplied in individual calls. - * - * @param defaultCallContext the default {@link ApiCallContext}. - */ - public ServerStreamingCallable withDefaultCallContext( - final ApiCallContext defaultCallContext) { - return new ServerStreamingCallable() { - // In case the next callable overrides the default behavior of first(), make sure to route - // the call directly to the next callable's first() implementation. - // The default implementation of first() instantiates a new FirstElementCallable which - // calls this instance's call method, bypassing the next callable's first implementation. - // Instead we will bypass the anonymous implementation of call() and invoke the next - // link's first() implementation. - @Override - public UnaryCallable first() { - return ServerStreamingCallable.this.first().withDefaultCallContext(defaultCallContext); - } - - // Like, first(), make sure to respect the next callable's all() impl. - @Override - public UnaryCallable> all() { - return ServerStreamingCallable.this.all().withDefaultCallContext(defaultCallContext); - } - - @Override - public void call( - RequestT request, - ResponseObserver responseObserver, - ApiCallContext thisCallContext) { - ServerStreamingCallable.this.call( - request, responseObserver, defaultCallContext.merge(thisCallContext)); - } - }; - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/SpoolingCallable.java b/gax/src/main/java/com/google/api/gax/rpc/SpoolingCallable.java deleted file mode 100644 index fbccc520c..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/SpoolingCallable.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.ApiFuture; -import java.util.List; - -/** - * Wraps a {@link ServerStreamingCallable} in a buffering {@link UnaryCallable}. The {@link - * UnaryCallable} will buffer the entire stream in memory. This is meant to be used for short - * streams and provides interoperability with {@link UnaryCallable} middleware like {@link - * BatchingCallable}. - * - *

Package-private for internal use. - * - * @param The type of the request. - * @param The type of an item in the stream. - */ -class SpoolingCallable extends UnaryCallable> { - private final ServerStreamingCallable streamingCallable; - - SpoolingCallable(ServerStreamingCallable streamingCallable) { - this.streamingCallable = streamingCallable; - } - - /** - * Starts the RPC and returns a future wrapping a list of results. If the stream is empty, the - * result will be an empty list. If a request is cancelled, the future will be rejected with a - * {@link java.util.concurrent.CancellationException}. - * - * @param request The request. - * @param context {@link ApiCallContext} to make the call with. - * @return A {@link ApiFuture} wrapping a possible first element of the stream. - */ - @Override - public ApiFuture> futureCall(RequestT request, ApiCallContext context) { - SpoolingResponseObserver observer = new SpoolingResponseObserver<>(); - streamingCallable.call(request, observer, context); - // NOTE: Since onStart must be called synchronously on this thread, the observer is now fully - // initialized and the future can be safely returned to the caller. - return observer.getFuture(); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/SpoolingResponseObserver.java b/gax/src/main/java/com/google/api/gax/rpc/SpoolingResponseObserver.java deleted file mode 100644 index dd1827f0b..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/SpoolingResponseObserver.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.AbstractApiFuture; -import com.google.api.core.ApiFuture; -import com.google.common.collect.Lists; -import java.util.List; - -/** - * A {@link ResponseObserver} that buffers the results from a {@link ServerStreamingCallable} in an - * {@link ApiFuture}. - * - *

Package-private for internal use. - * - * @param The type of the element in the stream. - */ -class SpoolingResponseObserver extends StateCheckingResponseObserver { - private final MyFuture future = new MyFuture(); - private StreamController controller; - private final List buffer = Lists.newArrayList(); - - ApiFuture> getFuture() { - return future; - } - - @Override - protected void onStartImpl(StreamController controller) { - // NOTE: the call is started before the future is exposed to the caller - this.controller = controller; - } - - @Override - protected void onResponseImpl(ResponseT response) { - buffer.add(response); - } - - @Override - protected void onErrorImpl(Throwable t) { - future.setException(t); - } - - @Override - protected void onCompleteImpl() { - future.set(buffer); - } - - /** Simple implementation of a future that allows the receiver to cancel the underlying stream. */ - class MyFuture extends AbstractApiFuture> { - @Override - protected void interruptTask() { - SpoolingResponseObserver.this.controller.cancel(); - } - - @Override - protected boolean set(List value) { - return super.set(value); - } - - @Override - protected boolean setException(Throwable throwable) { - return super.setException(throwable); - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/StateCheckingResponseObserver.java b/gax/src/main/java/com/google/api/gax/rpc/StateCheckingResponseObserver.java deleted file mode 100644 index d787f434d..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/StateCheckingResponseObserver.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.common.base.Preconditions; - -/** Base implementation of {@link ResponseObserver} that performs state sanity checks. */ -public abstract class StateCheckingResponseObserver implements ResponseObserver { - private boolean isStarted; - private boolean isClosed; - - /** - * {@inheritDoc} - * - *

This implementation simply delegates to {@link #onStartImpl(StreamController)} after - * ensuring consistent state. - */ - public final void onStart(StreamController controller) { - Preconditions.checkState(!isStarted, getClass() + " is already started."); - isStarted = true; - - onStartImpl(controller); - } - - /** - * {@inheritDoc} - * - *

This implementation simply delegates to {@link #onResponseImpl(Object)} after ensuring - * consistent state. - */ - public final void onResponse(V response) { - Preconditions.checkState(!isClosed, getClass() + " received a response after being closed."); - onResponseImpl(response); - } - - /** - * {@inheritDoc} - * - *

This implementation simply delegates to {@link #onCompleteImpl()} after ensuring consistent - * state. - */ - public final void onComplete() { - Preconditions.checkState(!isClosed, getClass() + " tried to double close."); - isClosed = true; - onCompleteImpl(); - } - - /** - * {@inheritDoc} - * - *

This implementation simply delegates to {@link #onErrorImpl(Throwable)} after ensuring - * consistent state. - */ - public final void onError(Throwable t) { - Preconditions.checkState(!isClosed, getClass() + " received error after being closed", t); - isClosed = true; - onErrorImpl(t); - } - - /** @see #onStart(StreamController) */ - protected abstract void onStartImpl(StreamController controller); - - /** @see #onResponse(Object) */ - protected abstract void onResponseImpl(V response); - - /** @see #onErrorImpl(Throwable) */ - protected abstract void onErrorImpl(Throwable t); - - /** @see #onComplete() */ - protected abstract void onCompleteImpl(); -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/StatusCode.java b/gax/src/main/java/com/google/api/gax/rpc/StatusCode.java deleted file mode 100644 index 14163c3a8..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/StatusCode.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.InternalExtensionOnly; - -/** - * Transport-specific status code. - * - *

The status codes are modeled after the status codes in grpc. For more information about grpc - * status codes, see - * https://github.com/grpc/grpc-java/blob/master/api/src/main/java/io/grpc/Status.java - */ -@InternalExtensionOnly -public interface StatusCode { - - enum Code { - OK(200), - CANCELLED(499), - UNKNOWN(500), - INVALID_ARGUMENT(400), - DEADLINE_EXCEEDED(504), - NOT_FOUND(404), - ALREADY_EXISTS(409), - PERMISSION_DENIED(403), - RESOURCE_EXHAUSTED(429), - FAILED_PRECONDITION(400), - ABORTED(409), - OUT_OF_RANGE(400), - UNIMPLEMENTED(501), - INTERNAL(500), - UNAVAILABLE(503), - DATA_LOSS(500), - UNAUTHENTICATED(401); - - Code(int httpStatusCode) { - this.httpStatusCode = httpStatusCode; - } - - private int httpStatusCode; - - public int getHttpStatusCode() { - return httpStatusCode; - } - } - - /** Return the code enum value. */ - Code getCode(); - - /** Return the transport-specific status code value. */ - Object getTransportCode(); -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/StreamController.java b/gax/src/main/java/com/google/api/gax/rpc/StreamController.java deleted file mode 100644 index 42a09efdc..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/StreamController.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import java.util.concurrent.CancellationException; - -/** - * Allows the implementer of {@link ResponseObserver} to control the flow of responses. - * - *

An instance of this class will be passed to {@link - * ResponseObserver#onStart(StreamController)}, at which point the receiver can disable automatic - * flow control. The receiver can also save a reference to the instance and terminate the stream - * early using {@code cancel()}. - */ -public interface StreamController { - /** - * Cancel the stream early. - * - *

This will manifest as an onError on the {@link ResponseObserver} with the cause being a - * {@link CancellationException}. - */ - void cancel(); - - /** - * Disables automatic flow control. - * - *

The next response is requested immediately after the current response is processed by {@link - * ResponseObserver#onResponse(Object)}. If disabled, an application must make explicit calls to - * {@link #request} to receive messages. - */ - void disableAutoInboundFlowControl(); - - /** - * Requests up to the given number of responses from the call to be delivered to {@link - * ResponseObserver#onResponse(Object)}. No additional messages will be delivered. - * - *

This method can only be called after disabling automatic flow control. - * - *

Message delivery is guaranteed to be sequential in the order received. In addition, the - * listener methods will not be accessed concurrently. While it is not guaranteed that the same - * thread will always be used, it is guaranteed that only a single thread will access the listener - * at a time. - * - *

If called multiple times, the number of messages able to delivered will be the sum of the - * calls. - * - *

This method is safe to call from multiple threads without external synchronizaton. - * - * @param count the requested number of messages to be delivered to the listener. Must be - * non-negative. - */ - void request(int count); -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/StreamingCallSettings.java b/gax/src/main/java/com/google/api/gax/rpc/StreamingCallSettings.java deleted file mode 100644 index 7f8895436..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/StreamingCallSettings.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.InternalExtensionOnly; - -/** - * A settings class to configure a streaming callable object for calls to a streaming API method. - */ -@InternalExtensionOnly -public class StreamingCallSettings { - - public static Builder newBuilder() { - return new Builder<>(); - } - - protected StreamingCallSettings() {} - - public Builder toBuilder() { - return new Builder<>(this); - } - - public static class Builder { - public Builder() {} - - public Builder(StreamingCallSettings settings) {} - - public StreamingCallSettings build() { - return new StreamingCallSettings<>(); - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/StubSettings.java b/gax/src/main/java/com/google/api/gax/rpc/StubSettings.java deleted file mode 100644 index 877b03e29..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/StubSettings.java +++ /dev/null @@ -1,546 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.ApiClock; -import com.google.api.core.ApiFunction; -import com.google.api.core.BetaApi; -import com.google.api.core.NanoClock; -import com.google.api.gax.core.CredentialsProvider; -import com.google.api.gax.core.ExecutorProvider; -import com.google.api.gax.core.FixedCredentialsProvider; -import com.google.api.gax.core.FixedExecutorProvider; -import com.google.api.gax.core.InstantiatingExecutorProvider; -import com.google.api.gax.core.NoCredentialsProvider; -import com.google.api.gax.tracing.ApiTracerFactory; -import com.google.api.gax.tracing.BaseApiTracerFactory; -import com.google.auth.oauth2.QuotaProjectIdProvider; -import com.google.common.base.MoreObjects; -import com.google.common.base.Preconditions; -import java.io.IOException; -import java.util.concurrent.Executor; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import org.threeten.bp.Duration; - -/** - * A base settings class to configure a client stub class. - * - *

This base class includes settings that are applicable to all services, which includes things - * like settings for creating an executor, credentials, transport-specific settings, and identifiers - * for http headers. - * - *

If no ExecutorProvider is set, then InstantiatingExecutorProvider will be used, which creates - * a default executor. - */ -public abstract class StubSettings> { - - static final String QUOTA_PROJECT_ID_HEADER_KEY = "x-goog-user-project"; - - private final ExecutorProvider backgroundExecutorProvider; - private final CredentialsProvider credentialsProvider; - private final HeaderProvider headerProvider; - private final HeaderProvider internalHeaderProvider; - private final TransportChannelProvider transportChannelProvider; - private final ApiClock clock; - private final String endpoint; - private final String mtlsEndpoint; - private final String quotaProjectId; - @Nullable private final WatchdogProvider streamWatchdogProvider; - @Nonnull private final Duration streamWatchdogCheckInterval; - @Nonnull private final ApiTracerFactory tracerFactory; - // Track if deprecated setExecutorProvider is called - private boolean deprecatedExecutorProviderSet; - - /** - * Indicate when creating transport whether it is allowed to use mTLS endpoint instead of the - * default endpoint. Only the endpoint set by client libraries is allowed. User provided endpoint - * should always be used as it is. Client libraries can set it via the {@link - * Builder#setSwitchToMtlsEndpointAllowed} method. - */ - private final boolean switchToMtlsEndpointAllowed; - - /** Constructs an instance of StubSettings. */ - protected StubSettings(Builder builder) { - this.backgroundExecutorProvider = builder.backgroundExecutorProvider; - this.transportChannelProvider = builder.transportChannelProvider; - this.credentialsProvider = builder.credentialsProvider; - this.headerProvider = builder.headerProvider; - this.internalHeaderProvider = builder.internalHeaderProvider; - this.clock = builder.clock; - this.endpoint = builder.endpoint; - this.mtlsEndpoint = builder.mtlsEndpoint; - this.switchToMtlsEndpointAllowed = builder.switchToMtlsEndpointAllowed; - this.quotaProjectId = builder.quotaProjectId; - this.streamWatchdogProvider = builder.streamWatchdogProvider; - this.streamWatchdogCheckInterval = builder.streamWatchdogCheckInterval; - this.tracerFactory = builder.tracerFactory; - this.deprecatedExecutorProviderSet = builder.deprecatedExecutorProviderSet; - } - - /** @deprecated Please use {@link #getBackgroundExecutorProvider()}. */ - @Deprecated - public final ExecutorProvider getExecutorProvider() { - return deprecatedExecutorProviderSet ? backgroundExecutorProvider : null; - } - - public final ExecutorProvider getBackgroundExecutorProvider() { - return backgroundExecutorProvider; - } - - public final TransportChannelProvider getTransportChannelProvider() { - return transportChannelProvider; - } - - public final CredentialsProvider getCredentialsProvider() { - return credentialsProvider; - } - - public final HeaderProvider getHeaderProvider() { - return headerProvider; - } - - protected final HeaderProvider getInternalHeaderProvider() { - return internalHeaderProvider; - } - - public final ApiClock getClock() { - return clock; - } - - public final String getEndpoint() { - return endpoint; - } - - public final String getMtlsEndpoint() { - return mtlsEndpoint; - } - - /** Limit the visibility to this package only since only this package needs it. */ - final boolean getSwitchToMtlsEndpointAllowed() { - return switchToMtlsEndpointAllowed; - } - - public final String getQuotaProjectId() { - return quotaProjectId; - } - - @Nullable - public final WatchdogProvider getStreamWatchdogProvider() { - return streamWatchdogProvider; - } - - @Nonnull - public final Duration getStreamWatchdogCheckInterval() { - return streamWatchdogCheckInterval; - } - - /** - * Gets the configured {@link ApiTracerFactory} that will be used to generate traces for - * operations. - */ - @BetaApi("The surface for tracing is not stable yet and may change in the future.") - @Nonnull - public ApiTracerFactory getTracerFactory() { - return tracerFactory; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("backgroundExecutorProvider", backgroundExecutorProvider) - .add("transportChannelProvider", transportChannelProvider) - .add("credentialsProvider", credentialsProvider) - .add("headerProvider", headerProvider) - .add("internalHeaderProvider", internalHeaderProvider) - .add("clock", clock) - .add("endpoint", endpoint) - .add("mtlsEndpoint", mtlsEndpoint) - .add("switchToMtlsEndpointAllowed", switchToMtlsEndpointAllowed) - .add("quotaProjectId", quotaProjectId) - .add("streamWatchdogProvider", streamWatchdogProvider) - .add("streamWatchdogCheckInterval", streamWatchdogCheckInterval) - .add("tracerFactory", tracerFactory) - .toString(); - } - - public abstract StubSettings.Builder toBuilder(); - - public abstract static class Builder< - SettingsT extends StubSettings, B extends Builder> { - - private ExecutorProvider backgroundExecutorProvider; - private CredentialsProvider credentialsProvider; - private HeaderProvider headerProvider; - private HeaderProvider internalHeaderProvider; - private TransportChannelProvider transportChannelProvider; - private ApiClock clock; - private String endpoint; - private String mtlsEndpoint; - private String quotaProjectId; - @Nullable private WatchdogProvider streamWatchdogProvider; - @Nonnull private Duration streamWatchdogCheckInterval; - @Nonnull private ApiTracerFactory tracerFactory; - private boolean deprecatedExecutorProviderSet; - - /** - * Indicate when creating transport whether it is allowed to use mTLS endpoint instead of the - * default endpoint. Only the endpoint set by client libraries is allowed. User provided - * endpoint should always be used as it is. Client libraries can set it via the {@link - * Builder#setSwitchToMtlsEndpointAllowed} method. - */ - private boolean switchToMtlsEndpointAllowed = false; - - /** Create a builder from a StubSettings object. */ - protected Builder(StubSettings settings) { - this.backgroundExecutorProvider = settings.backgroundExecutorProvider; - this.transportChannelProvider = settings.transportChannelProvider; - this.credentialsProvider = settings.credentialsProvider; - this.headerProvider = settings.headerProvider; - this.internalHeaderProvider = settings.internalHeaderProvider; - this.clock = settings.clock; - this.endpoint = settings.endpoint; - this.mtlsEndpoint = settings.mtlsEndpoint; - this.switchToMtlsEndpointAllowed = settings.switchToMtlsEndpointAllowed; - this.quotaProjectId = settings.quotaProjectId; - this.streamWatchdogProvider = settings.streamWatchdogProvider; - this.streamWatchdogCheckInterval = settings.streamWatchdogCheckInterval; - this.tracerFactory = settings.tracerFactory; - this.deprecatedExecutorProviderSet = settings.deprecatedExecutorProviderSet; - } - - /** Get Quota Project ID from Client Context * */ - private static String getQuotaProjectIdFromClientContext(ClientContext clientContext) { - if (clientContext.getQuotaProjectId() != null) { - return clientContext.getQuotaProjectId(); - } - if (clientContext.getCredentials() instanceof QuotaProjectIdProvider) { - return ((QuotaProjectIdProvider) clientContext.getCredentials()).getQuotaProjectId(); - } - if (clientContext.getHeaders().containsKey(QUOTA_PROJECT_ID_HEADER_KEY)) { - return clientContext.getHeaders().get(QUOTA_PROJECT_ID_HEADER_KEY); - } - if (clientContext.getInternalHeaders().containsKey(QUOTA_PROJECT_ID_HEADER_KEY)) { - return clientContext.getInternalHeaders().get(QUOTA_PROJECT_ID_HEADER_KEY); - } - return null; - } - - protected Builder(ClientContext clientContext) { - if (clientContext == null) { - this.backgroundExecutorProvider = InstantiatingExecutorProvider.newBuilder().build(); - this.transportChannelProvider = null; - this.credentialsProvider = NoCredentialsProvider.create(); - this.headerProvider = new NoHeaderProvider(); - this.internalHeaderProvider = new NoHeaderProvider(); - this.clock = NanoClock.getDefaultClock(); - this.endpoint = null; - this.mtlsEndpoint = null; - this.quotaProjectId = null; - this.streamWatchdogProvider = InstantiatingWatchdogProvider.create(); - this.streamWatchdogCheckInterval = Duration.ofSeconds(10); - this.tracerFactory = BaseApiTracerFactory.getInstance(); - this.deprecatedExecutorProviderSet = false; - } else { - ExecutorProvider fixedExecutorProvider = - FixedExecutorProvider.create(clientContext.getExecutor()); - this.deprecatedExecutorProviderSet = true; - this.backgroundExecutorProvider = fixedExecutorProvider; - this.transportChannelProvider = - FixedTransportChannelProvider.create(clientContext.getTransportChannel()); - this.credentialsProvider = FixedCredentialsProvider.create(clientContext.getCredentials()); - this.headerProvider = FixedHeaderProvider.create(clientContext.getHeaders()); - this.internalHeaderProvider = - FixedHeaderProvider.create(clientContext.getInternalHeaders()); - this.clock = clientContext.getClock(); - this.endpoint = clientContext.getEndpoint(); - if (this.endpoint != null) { - this.mtlsEndpoint = this.endpoint.replace("googleapis.com", "mtls.googleapis.com"); - } - this.streamWatchdogProvider = - FixedWatchdogProvider.create(clientContext.getStreamWatchdog()); - this.streamWatchdogCheckInterval = clientContext.getStreamWatchdogCheckInterval(); - this.tracerFactory = clientContext.getTracerFactory(); - this.quotaProjectId = getQuotaProjectIdFromClientContext(clientContext); - } - } - - protected Builder() { - this((ClientContext) null); - } - - @SuppressWarnings("unchecked") - protected B self() { - return (B) this; - } - - /** - * Sets the ExecutorProvider to use for getting the executor to use for running asynchronous API - * call logic (such as retries and long-running operations), and also to pass to the transport - * settings if an executor is needed for the transport and it doesn't have its own executor - * provider. - * - * @deprecated Please use {@link #setBackgroundExecutorProvider(ExecutorProvider)} for setting - * executor to use for running scheduled API call logic. To set executor for {@link - * TransportChannelProvider}, please use {@link - * TransportChannelProvider#withExecutor(Executor)} instead. - */ - @Deprecated - public B setExecutorProvider(ExecutorProvider executorProvider) { - // For backward compatibility, this will set backgroundExecutorProvider and mark - // deprecatedExecutorProviderSet to true. In ClientContext#create(), if - // TransportChannelProvider doesn't have an executor, and deprecatedExecutorProviderSet is - // true, backgroundExecutorProvider will be used as TransportChannelProvider's executor. - // After this method is deprecated, TransportChannelProvider's executor can only be set with - // TransportChannelProvider#withExecutor. - this.deprecatedExecutorProviderSet = true; - this.backgroundExecutorProvider = executorProvider; - return self(); - } - - /** - * Sets the executor to use for running scheduled API call logic (such as retries and - * long-running operations). - */ - public B setBackgroundExecutorProvider(ExecutorProvider backgroundExecutorProvider) { - this.backgroundExecutorProvider = backgroundExecutorProvider; - return self(); - } - - /** Sets the CredentialsProvider to use for getting the credentials to make calls with. */ - public B setCredentialsProvider(CredentialsProvider credentialsProvider) { - this.credentialsProvider = Preconditions.checkNotNull(credentialsProvider); - return self(); - } - - /** - * Sets the HeaderProvider for getting custom static headers for http requests. The header - * provider will be called during client construction only once. The headers returned by the - * provider will be cached and supplied as is for each request issued by the constructed client. - * Some reserved headers can be overridden (e.g. Content-Type) or merged with the default value - * (e.g. User-Agent) by the underlying transport layer. - */ - public B setHeaderProvider(HeaderProvider headerProvider) { - this.headerProvider = headerProvider; - if (this.quotaProjectId == null - && headerProvider.getHeaders().containsKey(QUOTA_PROJECT_ID_HEADER_KEY)) { - this.quotaProjectId = headerProvider.getHeaders().get(QUOTA_PROJECT_ID_HEADER_KEY); - } - return self(); - } - - /** - * Sets the HeaderProvider for getting internal (library-defined) static headers for http - * requests. The header provider will be called during client construction only once. The - * headers returned by the provider will be cached and supplied as is for each request issued by - * the constructed client. Some reserved headers can be overridden (e.g. Content-Type) or merged - * with the default value (e.g. User-Agent) by the underlying transport layer. - */ - protected B setInternalHeaderProvider(HeaderProvider internalHeaderProvider) { - this.internalHeaderProvider = internalHeaderProvider; - if (this.quotaProjectId == null - && internalHeaderProvider.getHeaders().containsKey(QUOTA_PROJECT_ID_HEADER_KEY)) { - this.quotaProjectId = internalHeaderProvider.getHeaders().get(QUOTA_PROJECT_ID_HEADER_KEY); - } - return self(); - } - - /** - * Sets the TransportProvider to use for getting the transport-specific context to make calls - * with. - */ - public B setTransportChannelProvider(TransportChannelProvider transportChannelProvider) { - this.transportChannelProvider = transportChannelProvider; - return self(); - } - - /** - * Sets the {@link WatchdogProvider} to use for streaming RPC. - * - *

This will default to a {@link InstantiatingWatchdogProvider} if it is not set. - */ - public B setStreamWatchdogProvider(@Nullable WatchdogProvider streamWatchdogProvider) { - this.streamWatchdogProvider = streamWatchdogProvider; - return self(); - } - - /** - * Sets the clock to use for retry logic. - * - *

This will default to a system clock if it is not set. - */ - public B setClock(ApiClock clock) { - this.clock = clock; - return self(); - } - - public B setEndpoint(String endpoint) { - this.endpoint = endpoint; - this.switchToMtlsEndpointAllowed = false; - if (this.endpoint != null && this.mtlsEndpoint == null) { - this.mtlsEndpoint = this.endpoint.replace("googleapis.com", "mtls.googleapis.com"); - } - return self(); - } - - protected B setSwitchToMtlsEndpointAllowed(boolean switchToMtlsEndpointAllowed) { - this.switchToMtlsEndpointAllowed = switchToMtlsEndpointAllowed; - return self(); - } - - public B setMtlsEndpoint(String mtlsEndpoint) { - this.mtlsEndpoint = mtlsEndpoint; - return self(); - } - - public B setQuotaProjectId(String quotaProjectId) { - this.quotaProjectId = quotaProjectId; - return self(); - } - - /** - * Sets how often the {@link Watchdog} will check ongoing streaming RPCs. Defaults to 10 secs. - * Use {@link Duration#ZERO} to disable. - */ - public B setStreamWatchdogCheckInterval(@Nonnull Duration checkInterval) { - Preconditions.checkNotNull(checkInterval); - this.streamWatchdogCheckInterval = checkInterval; - return self(); - } - - /** - * Configures the {@link ApiTracerFactory} that will be used to generate traces. - * - * @param tracerFactory an instance of {@link ApiTracerFactory} to set. - */ - @BetaApi("The surface for tracing is not stable yet and may change in the future.") - public B setTracerFactory(@Nonnull ApiTracerFactory tracerFactory) { - Preconditions.checkNotNull(tracerFactory); - this.tracerFactory = tracerFactory; - return self(); - } - - /** @deprecated Please use {@link #getBackgroundExecutorProvider()}. */ - @Deprecated - public ExecutorProvider getExecutorProvider() { - return deprecatedExecutorProviderSet ? backgroundExecutorProvider : null; - } - - /** Gets the ExecutorProvider that was previously set on this Builder. */ - public ExecutorProvider getBackgroundExecutorProvider() { - return backgroundExecutorProvider; - } - - /** Gets the TransportProvider that was previously set on this Builder. */ - public TransportChannelProvider getTransportChannelProvider() { - return transportChannelProvider; - } - - /** Gets the CredentialsProvider that was previously set on this Builder. */ - public CredentialsProvider getCredentialsProvider() { - return credentialsProvider; - } - - /** Gets the custom HeaderProvider that was previously set on this Builder. */ - public HeaderProvider getHeaderProvider() { - return headerProvider; - } - - /** Gets the internal HeaderProvider that was previously set on this Builder. */ - protected HeaderProvider getInternalHeaderProvider() { - return internalHeaderProvider; - } - - /** Gets the {@link WatchdogProvider }that was previously set on this Builder. */ - @Nullable - public WatchdogProvider getStreamWatchdogProvider() { - return streamWatchdogProvider; - } - - /** Gets the ApiClock that was previously set on this Builder. */ - public ApiClock getClock() { - return clock; - } - - public String getEndpoint() { - return endpoint; - } - - public String getMtlsEndpoint() { - return mtlsEndpoint; - } - - /** Gets the QuotaProjectId that was previously set on this Builder. */ - public String getQuotaProjectId() { - return quotaProjectId; - } - - @Nonnull - public Duration getStreamWatchdogCheckInterval() { - return streamWatchdogCheckInterval; - } - - @BetaApi("The surface for tracing is not stable yet and may change in the future.") - @Nonnull - public ApiTracerFactory getTracerFactory() { - return tracerFactory; - } - - /** Applies the given settings updater function to the given method settings builders. */ - protected static void applyToAllUnaryMethods( - Iterable> methodSettingsBuilders, - ApiFunction, Void> settingsUpdater) { - for (UnaryCallSettings.Builder settingsBuilder : methodSettingsBuilders) { - settingsUpdater.apply(settingsBuilder); - } - } - - public abstract > StubSettings build() throws IOException; - - @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("backgroundExecutorProvider", backgroundExecutorProvider) - .add("transportChannelProvider", transportChannelProvider) - .add("credentialsProvider", credentialsProvider) - .add("headerProvider", headerProvider) - .add("internalHeaderProvider", internalHeaderProvider) - .add("clock", clock) - .add("endpoint", endpoint) - .add("mtlsEndpoint", mtlsEndpoint) - .add("switchToMtlsEndpointAllowed", switchToMtlsEndpointAllowed) - .add("quotaProjectId", quotaProjectId) - .add("streamWatchdogProvider", streamWatchdogProvider) - .add("streamWatchdogCheckInterval", streamWatchdogCheckInterval) - .add("tracerFactory", tracerFactory) - .toString(); - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/TranslatingUnaryCallable.java b/gax/src/main/java/com/google/api/gax/rpc/TranslatingUnaryCallable.java deleted file mode 100644 index 8cc151238..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/TranslatingUnaryCallable.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static com.google.common.util.concurrent.MoreExecutors.directExecutor; - -import com.google.api.core.ApiFunction; -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; - -/** - * A UnaryCallable that translates request types and response types using the given transformers. - */ -public class TranslatingUnaryCallable - extends UnaryCallable { - private final UnaryCallable innerUnaryCallable; - private final ApiFunction requestTransformer; - private final ApiFunction responseTransformer; - - private TranslatingUnaryCallable( - UnaryCallable innerUnaryCallable, - ApiFunction requestTransformer, - ApiFunction responseTransformer) { - this.innerUnaryCallable = innerUnaryCallable; - this.requestTransformer = requestTransformer; - this.responseTransformer = responseTransformer; - } - - @Override - public ApiFuture futureCall(OuterRequestT request, ApiCallContext context) { - InnerRequestT innerRequest = requestTransformer.apply(request); - return ApiFutures.transform( - innerUnaryCallable.futureCall(innerRequest, context), - responseTransformer, - directExecutor()); - } - - public static - TranslatingUnaryCallable create( - UnaryCallable innerUnaryCallable, - ApiFunction requestTransformer, - ApiFunction responseTransformer) { - return new TranslatingUnaryCallable<>( - innerUnaryCallable, requestTransformer, responseTransformer); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/TransportChannel.java b/gax/src/main/java/com/google/api/gax/rpc/TransportChannel.java deleted file mode 100644 index d54352e9b..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/TransportChannel.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.InternalExtensionOnly; -import com.google.api.gax.core.BackgroundResource; - -/** Class whose instances can issue RPCs on a particular transport. */ -@InternalExtensionOnly -public interface TransportChannel extends BackgroundResource { - - /** - * The name of the transport. - * - *

This string can be used for identifying transports for switching logic. - */ - String getTransportName(); - - /** - * Returns an empty {@link ApiCallContext} that is compatible with this {@code TransportChannel}. - */ - ApiCallContext getEmptyCallContext(); -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/TransportChannelProvider.java b/gax/src/main/java/com/google/api/gax/rpc/TransportChannelProvider.java deleted file mode 100644 index b2acd458f..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/TransportChannelProvider.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.BetaApi; -import com.google.api.core.InternalExtensionOnly; -import com.google.auth.Credentials; -import java.io.IOException; -import java.util.Map; -import java.util.concurrent.Executor; -import java.util.concurrent.ScheduledExecutorService; - -/** - * Provides an interface to either build a TransportChannel or provide a fixed TransportChannel that - * will be used to make calls to a service. - * - *

Implementations of {@link TransportChannelProvider} may choose to create a new {@link - * TransportChannel} for each call to {@link #getTransportChannel}, or may return a fixed {@link - * TransportChannel} instance. - * - *

Callers should use the following pattern to get a channel: - * - *


- * TransportChannelProvider transportChannelProvider = ...;
- * if (transportChannelProvider.needsHeaders()) {
- *   transportChannelProvider = transportChannelProvider.withHeaders(headers);
- * }
- * // optional: set executor for TransportChannel
- * transportChannelProvider.withExecutor(executor);
- * TransportChannel transportChannel = transportChannelProvider.getTransportChannel();
- * 
- */ -@InternalExtensionOnly -public interface TransportChannelProvider { - /** Indicates whether the TransportChannel should be closed by the containing client class. */ - boolean shouldAutoClose(); - - /** - * True if the TransportProvider needs an executor. - * - * @deprecated Channel providers will have default executors if they need one. - */ - @Deprecated - boolean needsExecutor(); - - /** Sets the executor to use when constructing a new {@link TransportChannel}. */ - TransportChannelProvider withExecutor(Executor executor); - - /** @deprecated Please use {@link #withExecutor(Executor)}. */ - @Deprecated - TransportChannelProvider withExecutor(ScheduledExecutorService executor); - - /** True if the TransportProvider has no headers provided. */ - boolean needsHeaders(); - - /** - * Sets the headers to use when constructing a new {@link TransportChannel}. - * - *

This method should only be called if {@link #needsHeaders()} returns true. - */ - TransportChannelProvider withHeaders(Map headers); - - /** True if the TransportProvider has no endpoint set. */ - boolean needsEndpoint(); - - /** - * Sets the endpoint to use when constructing a new {@link TransportChannel}. - * - *

This method should only be called if {@link #needsEndpoint()} returns true. - */ - TransportChannelProvider withEndpoint(String endpoint); - - /** - * Reports whether this provider allows pool size customization. - * - * @deprecated Pool settings should be configured on the builder of the specific implementation. - */ - @Deprecated - boolean acceptsPoolSize(); - - /** - * Number of underlying transport channels to open. Calls will be load balanced across them. - * - * @deprecated Pool settings should be configured on the builder of the specific implementation. - */ - @Deprecated - TransportChannelProvider withPoolSize(int size); - - /** True if credentials are needed before channel creation. */ - @BetaApi("The surface to customize credentials is not stable yet and may change in the future.") - boolean needsCredentials(); - - /** Sets the credentials that will be applied before channel creation. */ - @BetaApi("The surface to customize credentials is not stable yet and may change in the future.") - TransportChannelProvider withCredentials(Credentials credentials); - - /** - * Provides a Transport, which could either be a new instance for every call, or the same - * instance, depending on the implementation. - * - *

If {@link #needsExecutor()} is true, then {@link #withExecutor(Executor)} needs to be called - * first to provide an executor. - * - *

If {@link #needsHeaders()} is true, then {@link #withHeaders(Map)} needs to be called first - * to provide headers. - * - *

if {@link #needsEndpoint()} is true, then {@link #withEndpoint(String)} needs to be called - * first to provide an endpoint. - */ - TransportChannel getTransportChannel() throws IOException; - - /** - * The name of the transport. - * - *

This string can be used for identifying transports for switching logic. - */ - String getTransportName(); -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/UnaryCallSettings.java b/gax/src/main/java/com/google/api/gax/rpc/UnaryCallSettings.java deleted file mode 100644 index c8f281144..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/UnaryCallSettings.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.InternalExtensionOnly; -import com.google.api.gax.retrying.RetrySettings; -import com.google.common.base.MoreObjects; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Sets; -import java.util.Set; -import org.threeten.bp.Duration; - -/** - * A base settings class to configure a UnaryCallable. An instance of UnaryCallSettings is not - * sufficient on its own to construct a UnaryCallable; a concrete derived type is necessary. - * - *

This base class includes settings that are applicable to all calls, which currently is just - * retry settings. - * - *

Retry configuration is composed of two parts: the retryable codes, and the retry settings. The - * retryable codes indicate which codes cause a retry to occur, and the retry settings configure the - * retry logic when the retry needs to happen. To turn off retries, set the retryable codes to the - * empty set. - * - *

UnaryCallSettings contains a concrete builder class, {@link UnaryCallSettings.Builder}. This - * builder class cannot be used to create an instance of UnaryCallSettings, because - * UnaryCallSettings is an abstract class. - */ -@InternalExtensionOnly -public class UnaryCallSettings { - - private final ImmutableSet retryableCodes; - private final RetrySettings retrySettings; - - /** - * See the class documentation of {@link UnaryCallSettings} for a description of what retryable - * codes do. - */ - public final Set getRetryableCodes() { - return retryableCodes; - } - - /** - * See the class documentation of {@link UnaryCallSettings} for a description of what retry - * settings do. - */ - public final RetrySettings getRetrySettings() { - return retrySettings; - } - - public static Builder newUnaryCallSettingsBuilder() { - return new Builder<>(); - } - - public Builder toBuilder() { - return new Builder<>(this); - } - - protected UnaryCallSettings(Builder builder) { - this.retryableCodes = ImmutableSet.copyOf(builder.retryableCodes); - this.retrySettings = builder.retrySettingsBuilder.build(); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("retryableCodes", retryableCodes) - .add("retrySettings", retrySettings) - .toString(); - } - - @Override - public int hashCode() { - int prime = 43; - int result = prime + ((retrySettings == null) ? 0 : retrySettings.hashCode()); - result = prime * result + ((retryableCodes == null) ? 0 : retryableCodes.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } else if (obj == null) { - return false; - } else if (getClass() != obj.getClass()) { - return false; - } - - UnaryCallSettings other = (UnaryCallSettings) obj; - if (!retrySettings.equals(other.retrySettings)) { - return false; - } else if (!retryableCodes.equals(other.retryableCodes)) { - return false; - } - return true; - } - - /** - * A base builder class for {@link UnaryCallSettings}. This class should not be used to create an - * instance of the base class UnaryCallSettings. See the class documentation of {@link - * UnaryCallSettings} for a description of the different values that can be set, and for a - * description of when this builder may be used. Builders for concrete derived classes can be used - * to create instances of those classes. - */ - public static class Builder { - - private Set retryableCodes; - private RetrySettings.Builder retrySettingsBuilder; - - protected Builder() { - retryableCodes = Sets.newHashSet(); - retrySettingsBuilder = RetrySettings.newBuilder(); - } - - protected Builder(UnaryCallSettings unaryCallSettings) { - setRetryableCodes(unaryCallSettings.retryableCodes); - setRetrySettings(unaryCallSettings.getRetrySettings()); - } - - /** - * See the class documentation of {@link UnaryCallSettings} for a description of what retryable - * codes do. - */ - public UnaryCallSettings.Builder setRetryableCodes( - Set retryableCodes) { - this.retryableCodes = Sets.newHashSet(retryableCodes); - return this; - } - - /** - * See the class documentation of {@link UnaryCallSettings} for a description of what retryable - * codes do. - */ - public UnaryCallSettings.Builder setRetryableCodes( - StatusCode.Code... codes) { - this.setRetryableCodes(Sets.newHashSet(codes)); - return this; - } - - /** - * Returns the underlying {@link RetrySettings.Builder}, which allows callers to augment the - * existing {@link RetrySettings}. - */ - public RetrySettings.Builder retrySettings() { - return this.retrySettingsBuilder; - } - - /** - * Replaces the {@link RetrySettings} for the associated {@link UnaryCallable}. - * - *

When using the method, make sure that the {@link RetrySettings} are complete. For example, - * the following code will disable retries because the retry delay is not set: - * - *

{@code
-     * stubSettings.setRetrySettings(
-     *   RetrySettings.newBuilder()
-     *     .setTotalTimeout(Duration.ofSeconds(10)
-     * );
-     * }
- * - * @see #retrySettings() - */ - public UnaryCallSettings.Builder setRetrySettings( - RetrySettings retrySettings) { - this.retrySettingsBuilder = retrySettings.toBuilder(); - return this; - } - - /** Disables retries and sets the RPC timeout. */ - public UnaryCallSettings.Builder setSimpleTimeoutNoRetries( - Duration timeout) { - setRetryableCodes(); - setRetrySettings( - RetrySettings.newBuilder() - .setTotalTimeout(timeout) - .setInitialRetryDelay(Duration.ZERO) - .setRetryDelayMultiplier(1) - .setMaxRetryDelay(Duration.ZERO) - .setInitialRpcTimeout(timeout) - .setRpcTimeoutMultiplier(1) - .setMaxRpcTimeout(timeout) - .setMaxAttempts(1) - .build()); - return this; - } - - /** - * See the class documentation of {@link UnaryCallSettings} for a description of what retryable - * codes do. - */ - public Set getRetryableCodes() { - return this.retryableCodes; - } - - /** - * Returns an immutable {@link RetrySettings} currently set in this Builder. - * - *

Unlike {@link #retrySettings()}, objects returned by this method are frozen in time. - */ - public RetrySettings getRetrySettings() { - return this.retrySettingsBuilder.build(); - } - - /** - * Builds an instance of the containing class. This operation is unsupported on the abstract - * base class UnaryCallSettings, but is valid on concrete derived classes. - */ - public UnaryCallSettings build() { - return new UnaryCallSettings<>(this); - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/UnaryCallable.java b/gax/src/main/java/com/google/api/gax/rpc/UnaryCallable.java deleted file mode 100644 index 4a53ec8dc..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/UnaryCallable.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.ApiFuture; - -/** - * A UnaryCallable is an immutable object which is capable of making RPC calls to non-streaming API - * methods. - * - *

In typical usage, the request to send to the remote service will not be bound to the - * UnaryCallable, but instead is provided at call time, which allows for a UnaryCallable to be saved - * and used indefinitely. - * - *

There are two styles of calls that can be made through a UnaryCallable: synchronous and - * asynchronous. - * - *

Synchronous example: - * - *

{@code
- * RequestType request = RequestType.newBuilder().build();
- * UnaryCallable unaryCallable = api.doSomethingCallable();
- * ResponseType response = unaryCallable.call();
- * }
- * - *

Asynchronous example: - * - *

{@code
- * RequestType request = RequestType.newBuilder().build();
- * UnaryCallable unaryCallable = api.doSomethingCallable();
- * ApiFuture resultFuture = unaryCallable.futureCall();
- * // do other work
- * // ...
- * ResponseType response = resultFuture.get();
- * }
- * - *

It is considered advanced usage for a user to create a UnaryCallable themselves. This class is - * intended to be created by a generated client class, and configured by instances of - * UnaryCallSettings.Builder which are exposed through the client settings class. - */ -public abstract class UnaryCallable { - - protected UnaryCallable() {} - - /** - * Perform a call asynchronously. - * - * @param context {@link ApiCallContext} to make the call with - * @return {@link ApiFuture} for the call result - */ - public abstract ApiFuture futureCall(RequestT request, ApiCallContext context); - - /** - * Same as {@link #futureCall(Object, ApiCallContext)}, with a null context. - * - * @param request request - * @return {@link ApiFuture} for the call result - */ - public ApiFuture futureCall(RequestT request) { - return futureCall(request, null); - } - - /** - * Perform a call synchronously. - * - * @param request The request to send to the service. - * @param context {@link ApiCallContext} to make the call with - * @return the call result - * @throws ApiException if there is any bad status in the response. - * @throws RuntimeException if there is any other exception unrelated to bad status. - */ - public ResponseT call(RequestT request, ApiCallContext context) { - return ApiExceptions.callAndTranslateApiException(futureCall(request, context)); - } - - /** - * Same as {@link #call(Object, ApiCallContext)}, with a null context. - * - * @param request The request to send to the service. - * @return the call result - * @throws ApiException if there is any bad status in the response. - * @throws RuntimeException if there is any other exception unrelated to bad status. - */ - public ResponseT call(RequestT request) { - return ApiExceptions.callAndTranslateApiException(futureCall(request)); - } - - /** - * Returns a new {@code UnaryCallable} with an {@link ApiCallContext} that is used as a default - * when none is supplied in individual calls. - * - * @param defaultCallContext the default {@link ApiCallContext}. - */ - public UnaryCallable withDefaultCallContext( - final ApiCallContext defaultCallContext) { - return new UnaryCallable() { - @Override - public ApiFuture futureCall(RequestT request, ApiCallContext thisCallContext) { - return UnaryCallable.this.futureCall(request, defaultCallContext.merge(thisCallContext)); - } - }; - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/UnauthenticatedException.java b/gax/src/main/java/com/google/api/gax/rpc/UnauthenticatedException.java deleted file mode 100644 index 6daeece5a..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/UnauthenticatedException.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -/** - * Exception thrown when the request does not have valid authentication credentials for the - * operation. - */ -public class UnauthenticatedException extends ApiException { - public UnauthenticatedException(Throwable cause, StatusCode statusCode, boolean retryable) { - super(cause, statusCode, retryable); - } - - public UnauthenticatedException( - String message, Throwable cause, StatusCode statusCode, boolean retryable) { - super(message, cause, statusCode, retryable); - } - - public UnauthenticatedException( - Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { - super(cause, statusCode, retryable, errorDetails); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/UnavailableException.java b/gax/src/main/java/com/google/api/gax/rpc/UnavailableException.java deleted file mode 100644 index 96fbc8d28..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/UnavailableException.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -/** - * Exception thrown when the service is currently unavailable. This is a most likely a transient - * condition and may be corrected by retrying with a backoff. - */ -public class UnavailableException extends ApiException { - public UnavailableException(Throwable cause, StatusCode statusCode, boolean retryable) { - super(cause, statusCode, retryable); - } - - public UnavailableException( - String message, Throwable cause, StatusCode statusCode, boolean retryable) { - super(message, cause, statusCode, retryable); - } - - public UnavailableException( - Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { - super(cause, statusCode, retryable, errorDetails); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/UnimplementedException.java b/gax/src/main/java/com/google/api/gax/rpc/UnimplementedException.java deleted file mode 100644 index 8e042f441..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/UnimplementedException.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -/** - * Exception thrown when the operation is not implemented or not supported/enabled in this service. - */ -public class UnimplementedException extends ApiException { - public UnimplementedException(Throwable cause, StatusCode statusCode, boolean retryable) { - super(cause, statusCode, retryable); - } - - public UnimplementedException( - String message, Throwable cause, StatusCode statusCode, boolean retryable) { - super(message, cause, statusCode, retryable); - } - - public UnimplementedException( - Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { - super(cause, statusCode, retryable, errorDetails); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/UnknownException.java b/gax/src/main/java/com/google/api/gax/rpc/UnknownException.java deleted file mode 100644 index a3ebe3599..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/UnknownException.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -/** - * Exception thrown due to an unknown error. An example of where this error may be returned is if a - * Status value received from another address space belongs to an error-space that is not known in - * this address space. Also errors raised by APIs that do not return enough error information may be - * converted to this error. - */ -public class UnknownException extends ApiException { - public UnknownException(Throwable cause, StatusCode statusCode, boolean retryable) { - super(cause, statusCode, retryable); - } - - public UnknownException( - String message, Throwable cause, StatusCode statusCode, boolean retryable) { - super(message, cause, statusCode, retryable); - } - - public UnknownException( - Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { - super(cause, statusCode, retryable, errorDetails); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/Watchdog.java b/gax/src/main/java/com/google/api/gax/rpc/Watchdog.java deleted file mode 100644 index 8ca97876c..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/Watchdog.java +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.ApiClock; -import com.google.api.gax.core.BackgroundResource; -import com.google.common.base.Preconditions; -import java.util.Iterator; -import java.util.Map.Entry; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.annotation.Nonnull; -import javax.annotation.concurrent.GuardedBy; -import org.threeten.bp.Duration; - -/** - * Prevents the streams from hanging indefinitely. This middleware garbage collects idle streams in - * case the user forgot to close a ServerStream or if a connection is reset and GRPC does not get - * notified. - * - *

For every {@code checkInterval}, this class checks two thresholds: - * - *

    - *
  • waitingTimeout: the amount of time to wait for a response (after the caller signaled - * demand) before forcefully closing the stream. Duration.ZERO disables the timeout. - *
  • idleTimeout: the amount of time to wait before assuming that the caller forgot to close the - * stream and forcefully closing the stream. This is measured from the last time the caller - * had no outstanding demand. Duration.ZERO disables the timeout. - *
- */ -public final class Watchdog implements Runnable, BackgroundResource { - - private static final Logger LOG = Logger.getLogger(Watchdog.class.getName()); - - // Dummy value to convert the ConcurrentHashMap into a Set - private static Object PRESENT = new Object(); - private final ConcurrentHashMap openStreams = new ConcurrentHashMap<>(); - - private final ApiClock clock; - private final Duration scheduleInterval; - private final ScheduledExecutorService executor; - private ScheduledFuture future; - - /** returns a Watchdog which is scheduled at the provided interval. */ - public static Watchdog create( - ApiClock clock, Duration scheduleInterval, ScheduledExecutorService executor) { - Watchdog watchdog = new Watchdog(clock, scheduleInterval, executor); - watchdog.start(); - return watchdog; - } - - private Watchdog(ApiClock clock, Duration scheduleInterval, ScheduledExecutorService executor) { - this.clock = Preconditions.checkNotNull(clock, "clock can't be null"); - this.scheduleInterval = scheduleInterval; - this.executor = executor; - } - - private void start() { - future = - executor.scheduleAtFixedRate( - this, scheduleInterval.toMillis(), scheduleInterval.toMillis(), TimeUnit.MILLISECONDS); - } - - /** Wraps the target observer with timing constraints. */ - public ResponseObserver watch( - ResponseObserver innerObserver, - @Nonnull Duration waitTimeout, - @Nonnull Duration idleTimeout) { - Preconditions.checkNotNull(innerObserver, "innerObserver can't be null"); - Preconditions.checkNotNull(waitTimeout, "waitTimeout can't be null"); - Preconditions.checkNotNull(idleTimeout, "idleTimeout can't be null"); - - if (waitTimeout.isZero() && idleTimeout.isZero()) { - return innerObserver; - } - - WatchdogStream stream = - new WatchdogStream<>(innerObserver, waitTimeout, idleTimeout); - openStreams.put(stream, PRESENT); - return stream; - } - - @Override - public void run() { - try { - runUnsafe(); - } catch (Throwable t) { - LOG.log(Level.SEVERE, "Caught throwable in periodic Watchdog run. Continuing.", t); - } - } - - private void runUnsafe() { - Iterator> it = openStreams.entrySet().iterator(); - - while (it.hasNext()) { - WatchdogStream stream = it.next().getKey(); - if (stream.cancelIfStale()) { - it.remove(); - } - } - } - - @Override - public void shutdown() { - future.cancel(false); - } - - @Override - public boolean isShutdown() { - return future.isCancelled(); - } - - @Override - public boolean isTerminated() { - return future.isDone(); - } - - @Override - public void shutdownNow() { - future.cancel(true); - } - - @Override - public boolean awaitTermination(long duration, TimeUnit unit) throws InterruptedException { - try { - future.get(duration, unit); - return true; - } catch (ExecutionException | CancellationException e) { - return true; - } catch (TimeoutException e) { - return false; - } - } - - @Override - public void close() { - shutdown(); - } - - enum State { - /** Stream has been started, but doesn't have any outstanding requests. */ - IDLE, - /** Stream is awaiting a response from upstream. */ - WAITING, - /** - * Stream received a response from upstream, and is awaiting outerResponseObserver processing. - */ - DELIVERING - } - - class WatchdogStream extends StateCheckingResponseObserver { - private final Object lock = new Object(); - - private final Duration waitTimeout; - private final Duration idleTimeout; - private boolean hasStarted; - private boolean autoAutoFlowControl = true; - - private final ResponseObserver outerResponseObserver; - private volatile StreamController innerController; - - @GuardedBy("lock") - private State state = State.IDLE; - - @GuardedBy("lock") - private int pendingCount = 0; - - @GuardedBy("lock") - private long lastActivityAt = clock.millisTime(); - - private volatile Throwable error; - - WatchdogStream( - ResponseObserver responseObserver, Duration waitTimeout, Duration idleTimeout) { - this.waitTimeout = waitTimeout; - this.idleTimeout = idleTimeout; - this.outerResponseObserver = responseObserver; - } - - @Override - public void onStartImpl(StreamController controller) { - this.innerController = controller; - outerResponseObserver.onStart( - new StreamController() { - @Override - public void disableAutoInboundFlowControl() { - Preconditions.checkState( - !hasStarted, "Can't disable automatic flow control after the stream has started"); - autoAutoFlowControl = false; - innerController.disableAutoInboundFlowControl(); - } - - @Override - public void request(int count) { - WatchdogStream.this.onRequest(count); - } - - @Override - public void cancel() { - WatchdogStream.this.onCancel(); - } - }); - - hasStarted = true; - } - - private void onRequest(int count) { - Preconditions.checkArgument(count > 0, "count must be > 0"); - Preconditions.checkState(!autoAutoFlowControl, "Auto flow control is enabled"); - - // Only reset the request water mark if there are no outstanding requests. - synchronized (lock) { - if (state == State.IDLE) { - state = State.WAITING; - lastActivityAt = clock.millisTime(); - } - - // Increment the request count without overflow - int maxIncrement = Integer.MAX_VALUE - pendingCount; - count = Math.min(maxIncrement, count); - pendingCount += count; - } - innerController.request(count); - } - - private void onCancel() { - error = new CancellationException("User cancelled stream"); - innerController.cancel(); - } - - @Override - public void onResponseImpl(ResponseT response) { - synchronized (lock) { - state = State.DELIVERING; - } - - outerResponseObserver.onResponse(response); - - synchronized (lock) { - pendingCount--; - lastActivityAt = clock.millisTime(); - - if (autoAutoFlowControl || pendingCount > 0) { - state = State.WAITING; - } else { - state = State.IDLE; - } - } - } - - @Override - public void onErrorImpl(Throwable t) { - // Overlay the cancellation errors (either user or idle) - if (this.error != null) { - t = this.error; - } - openStreams.remove(this); - outerResponseObserver.onError(t); - } - - @Override - public void onCompleteImpl() { - openStreams.remove(this); - outerResponseObserver.onComplete(); - } - - /** - * Checks if this stream has overrun any of its timeouts and cancels it if it does. - * - * @return True if the stream was canceled. - */ - boolean cancelIfStale() { - // If the stream hasn't started yet, innerController will be null. Skip the check this time - // and return false so the stream is still watched. - if (innerController == null) { - return false; - } - - Throwable myError = null; - - synchronized (lock) { - long waitTime = clock.millisTime() - lastActivityAt; - - switch (this.state) { - case IDLE: - if (!idleTimeout.isZero() && waitTime >= idleTimeout.toMillis()) { - myError = new WatchdogTimeoutException("Canceled due to idle connection", false); - } - break; - case WAITING: - if (!waitTimeout.isZero() && waitTime >= waitTimeout.toMillis()) { - myError = - new WatchdogTimeoutException( - "Canceled due to timeout waiting for next response", true); - } - break; - } - } - - if (myError != null) { - this.error = myError; - innerController.cancel(); - return true; - } - return false; - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/WatchdogProvider.java b/gax/src/main/java/com/google/api/gax/rpc/WatchdogProvider.java deleted file mode 100644 index db3fb20bb..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/WatchdogProvider.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.ApiClock; -import java.util.concurrent.ScheduledExecutorService; -import javax.annotation.Nonnull; -import org.threeten.bp.Duration; - -public interface WatchdogProvider { - boolean needsClock(); - - WatchdogProvider withClock(@Nonnull ApiClock clock); - - boolean needsCheckInterval(); - - WatchdogProvider withCheckInterval(Duration checkInterval); - - boolean needsExecutor(); - - WatchdogProvider withExecutor(ScheduledExecutorService executor); - - Watchdog getWatchdog(); - - /** Return true if the watchdog should be automatically unscheduled. */ - boolean shouldAutoClose(); -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/WatchdogServerStreamingCallable.java b/gax/src/main/java/com/google/api/gax/rpc/WatchdogServerStreamingCallable.java deleted file mode 100644 index cc3dfec82..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/WatchdogServerStreamingCallable.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.common.base.MoreObjects; -import com.google.common.base.Preconditions; -import org.threeten.bp.Duration; - -/** - * A callable that uses a {@link Watchdog} to monitor streams. - * - *

It extracts the {@code StreamWaitTimeout} and the {@code StreamIdleTimeout} from the {@link - * ApiCallContext} and applies then to the stream using the {@link Watchdog}. - * - *

Package-private for internal use. - * - * @see Watchdog for more details - */ -class WatchdogServerStreamingCallable - extends ServerStreamingCallable { - private final ServerStreamingCallable inner; - private final Watchdog watchdog; - - WatchdogServerStreamingCallable( - ServerStreamingCallable inner, Watchdog watchdog) { - Preconditions.checkNotNull(inner); - Preconditions.checkNotNull(watchdog); - - this.inner = inner; - this.watchdog = watchdog; - } - - @Override - public void call( - RequestT request, ResponseObserver responseObserver, ApiCallContext context) { - - // If the caller never configured the timeouts, disable them - Duration waitTimeout = MoreObjects.firstNonNull(context.getStreamWaitTimeout(), Duration.ZERO); - Duration idleTimeout = MoreObjects.firstNonNull(context.getStreamIdleTimeout(), Duration.ZERO); - - responseObserver = watchdog.watch(responseObserver, waitTimeout, idleTimeout); - inner.call(request, responseObserver, context); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/WatchdogTimeoutException.java b/gax/src/main/java/com/google/api/gax/rpc/WatchdogTimeoutException.java deleted file mode 100644 index 15b0cc388..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/WatchdogTimeoutException.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -/** - * The marker exception thrown when a timeout is exceeded. - * - *

This error can be thrown under 2 circumstances: - * - *

    - *
  • A wait timeout has exceeded, which means that the client timed out waiting for the next - * message from the server. In this case, {@link #isRetryable()} will be true. - *
  • An idle timeout has exceeded, which means that the stream is using manual flow control and - * the caller has not called {@link StreamController#request(int)} (in case of callback api) - * or next on {@link ServerStream#iterator()} (in case of blocking api). - *
- */ -public class WatchdogTimeoutException extends ApiException { - private static final long serialVersionUID = -777463630112442086L; - - public static final StatusCode LOCAL_ABORTED_STATUS_CODE = - new StatusCode() { - @Override - public Code getCode() { - return Code.ABORTED; - } - - @Override - public Object getTransportCode() { - return null; - } - }; - - /** Package private for internal use. */ - WatchdogTimeoutException(String message, boolean retry) { - super(message, null, LOCAL_ABORTED_STATUS_CODE, retry); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/internal/ApiCallContextOptions.java b/gax/src/main/java/com/google/api/gax/rpc/internal/ApiCallContextOptions.java deleted file mode 100644 index a0873f309..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/internal/ApiCallContextOptions.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc.internal; - -import com.google.api.core.InternalApi; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.ApiCallContext.Key; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableMap; - -/** - * ApiCallContextOptions encapsulates additional call options to pass in a {@link ApiCallContext} - */ -@InternalApi -public final class ApiCallContextOptions { - - private final ImmutableMap options; - private static final ApiCallContextOptions DEFAULT_OPTIONS = - new ApiCallContextOptions(ImmutableMap.of()); - - private ApiCallContextOptions(ImmutableMap options) { - this.options = Preconditions.checkNotNull(options); - } - - public static ApiCallContextOptions getDefaultOptions() { - return DEFAULT_OPTIONS; - } - - /** Add an option. Any existing value of the key is overwritten. */ - public ApiCallContextOptions withOption(Key key, T value) { - Preconditions.checkNotNull(key); - Preconditions.checkNotNull(value); - ImmutableMap.Builder builder = ImmutableMap.builder(); - if (!options.containsKey(key)) { - builder.putAll(options).put(key, value); - } else { - builder.put(key, value); - for (Key oldKey : options.keySet()) { - if (!oldKey.equals(key)) { - builder.put(oldKey, options.get(oldKey)); - } - } - } - return new ApiCallContextOptions(builder.build()); - } - - /** Get an option. */ - public T getOption(Key key) { - Preconditions.checkNotNull(key); - return (T) options.get(key); - } - - /** Merge new options into existing ones. Any existing values of the keys are overwritten. */ - public ApiCallContextOptions merge(ApiCallContextOptions newOptions) { - Preconditions.checkNotNull(newOptions); - ImmutableMap.Builder builder = - ImmutableMap.builder().putAll(newOptions.options); - for (Key key : options.keySet()) { - if (!newOptions.options.containsKey(key)) { - builder.put(key, options.get(key)); - } - } - return new ApiCallContextOptions(builder.build()); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/internal/EnvironmentProvider.java b/gax/src/main/java/com/google/api/gax/rpc/internal/EnvironmentProvider.java deleted file mode 100644 index af623f4b0..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/internal/EnvironmentProvider.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc.internal; - -import com.google.api.core.InternalExtensionOnly; - -/** Provides an interface to provide the environment variable values. */ -@InternalExtensionOnly -public interface EnvironmentProvider { - /** Returns the environment variable value. */ - String getenv(String name); -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/internal/Headers.java b/gax/src/main/java/com/google/api/gax/rpc/internal/Headers.java deleted file mode 100644 index ddd660036..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/internal/Headers.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.gax.rpc.internal; - -import com.google.api.core.InternalApi; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import java.util.List; -import java.util.Map; - -@InternalApi -public class Headers { - public static ImmutableMap> mergeHeaders( - Map> oldHeaders, Map> newHeaders) { - ImmutableMap.Builder> headersBuilder = ImmutableMap.builder(); - for (Map.Entry> entry : oldHeaders.entrySet()) { - String key = entry.getKey(); - List oldValue = entry.getValue(); - List newValue = newHeaders.get(key); - ImmutableList.Builder mergedValueBuilder = ImmutableList.builder(); - mergedValueBuilder.addAll(oldValue); - if (newValue != null) { - mergedValueBuilder.addAll(newValue); - } - headersBuilder.put(key, mergedValueBuilder.build()); - } - for (Map.Entry> entry : newHeaders.entrySet()) { - String key = entry.getKey(); - if (!oldHeaders.containsKey(key)) { - headersBuilder.put(key, ImmutableList.copyOf(entry.getValue())); - } - } - return headersBuilder.build(); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/internal/QuotaProjectIdHidingCredentials.java b/gax/src/main/java/com/google/api/gax/rpc/internal/QuotaProjectIdHidingCredentials.java deleted file mode 100644 index 51bbade9a..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/internal/QuotaProjectIdHidingCredentials.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc.internal; - -import com.google.api.client.util.Beta; -import com.google.auth.Credentials; -import com.google.common.collect.ImmutableMap; -import java.io.IOException; -import java.net.URI; -import java.util.List; -import java.util.Map; - -/** - * {@code QuotaProjectIdHidingCredentials} is intended to be used to wrap a {@link Credentials} to - * hide quota project id - * - *

Ensure that a custom set quota project id takes priority over one detected by credentials. - */ -@Beta -public class QuotaProjectIdHidingCredentials extends Credentials { - private static final String QUOTA_PROJECT_ID_HEADER_KEY = "x-goog-user-project"; - private final Credentials wrappedCredentials; - - public QuotaProjectIdHidingCredentials(Credentials credentials) { - this.wrappedCredentials = credentials; - } - - @Override - public String getAuthenticationType() { - return this.wrappedCredentials.getAuthenticationType(); - } - - @Override - public Map> getRequestMetadata(URI uri) throws IOException { - ImmutableMap.Builder> metaBuilder = ImmutableMap.builder(); - for (Map.Entry> entry : - this.wrappedCredentials.getRequestMetadata(uri).entrySet()) { - if (entry.getKey().equals(QUOTA_PROJECT_ID_HEADER_KEY)) { - continue; - } - metaBuilder.put(entry); - } - return metaBuilder.build(); - } - - @Override - public Map> getRequestMetadata() throws IOException { - return this.getRequestMetadata(null); - } - - @Override - public boolean hasRequestMetadata() { - return this.wrappedCredentials.hasRequestMetadata(); - } - - @Override - public boolean hasRequestMetadataOnly() { - return this.wrappedCredentials.hasRequestMetadataOnly(); - } - - @Override - public void refresh() throws IOException { - this.wrappedCredentials.refresh(); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/mtls/ContextAwareMetadataJson.java b/gax/src/main/java/com/google/api/gax/rpc/mtls/ContextAwareMetadataJson.java deleted file mode 100644 index 25d7d27de..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/mtls/ContextAwareMetadataJson.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.gax.rpc.mtls; - -import com.google.api.client.json.GenericJson; -import com.google.api.client.util.Key; -import com.google.api.core.BetaApi; -import com.google.common.collect.ImmutableList; -import java.util.List; - -/** Data class representing context_aware_metadata.json file. */ -@BetaApi -public class ContextAwareMetadataJson extends GenericJson { - /** Cert provider command */ - @Key("cert_provider_command") - private List commands; - - /** Returns the cert provider command. */ - public final ImmutableList getCommands() { - return ImmutableList.copyOf(commands); - } -} diff --git a/gax/src/main/java/com/google/api/gax/rpc/mtls/MtlsProvider.java b/gax/src/main/java/com/google/api/gax/rpc/mtls/MtlsProvider.java deleted file mode 100644 index c24fc80d6..000000000 --- a/gax/src/main/java/com/google/api/gax/rpc/mtls/MtlsProvider.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.gax.rpc.mtls; - -import com.google.api.client.json.JsonParser; -import com.google.api.client.json.gson.GsonFactory; -import com.google.api.client.util.SecurityUtils; -import com.google.api.core.BetaApi; -import com.google.api.gax.rpc.internal.EnvironmentProvider; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.ImmutableList; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.security.GeneralSecurityException; -import java.security.KeyStore; -import java.util.List; - -/** - * Provider class for mutual TLS. It is used to configure the mutual TLS in the transport with the - * default client certificate on device. - */ -@BetaApi -public class MtlsProvider { - interface ProcessProvider { - public Process createProcess(InputStream metadata) throws IOException; - } - - static class DefaultProcessProvider implements ProcessProvider { - @Override - public Process createProcess(InputStream metadata) throws IOException { - if (metadata == null) { - return null; - } - List command = extractCertificateProviderCommand(metadata); - return new ProcessBuilder(command).start(); - } - } - - private static final String DEFAULT_CONTEXT_AWARE_METADATA_PATH = - System.getProperty("user.home") + "/.secureConnect/context_aware_metadata.json"; - - private String metadataPath; - private EnvironmentProvider envProvider; - private ProcessProvider processProvider; - - /** - * The policy for mutual TLS endpoint usage. NEVER means always use regular endpoint; ALWAYS means - * always use mTLS endpoint; AUTO means auto switch to mTLS endpoint if client certificate exists - * and should be used. - */ - public enum MtlsEndpointUsagePolicy { - NEVER, - AUTO, - ALWAYS; - } - - @VisibleForTesting - MtlsProvider( - EnvironmentProvider envProvider, ProcessProvider processProvider, String metadataPath) { - this.envProvider = envProvider; - this.processProvider = processProvider; - this.metadataPath = metadataPath; - } - - public MtlsProvider() { - this(System::getenv, new DefaultProcessProvider(), DEFAULT_CONTEXT_AWARE_METADATA_PATH); - } - - /** - * Returns if mutual TLS client certificate should be used. If the value is true, the key store - * from {@link #getKeyStore()} will be used to configure mutual TLS transport. - */ - public boolean useMtlsClientCertificate() { - String useClientCertificate = envProvider.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE"); - return "true".equals(useClientCertificate); - } - - /** Returns the current mutual TLS endpoint usage policy. */ - public MtlsEndpointUsagePolicy getMtlsEndpointUsagePolicy() { - String mtlsEndpointUsagePolicy = envProvider.getenv("GOOGLE_API_USE_MTLS_ENDPOINT"); - if ("never".equals(mtlsEndpointUsagePolicy)) { - return MtlsEndpointUsagePolicy.NEVER; - } else if ("always".equals(mtlsEndpointUsagePolicy)) { - return MtlsEndpointUsagePolicy.ALWAYS; - } - return MtlsEndpointUsagePolicy.AUTO; - } - - /** The mutual TLS key store created with the default client certificate on device. */ - public KeyStore getKeyStore() throws IOException { - try (InputStream stream = new FileInputStream(metadataPath)) { - return getKeyStore(stream, processProvider); - } catch (InterruptedException e) { - throw new IOException("Interrupted executing certificate provider command", e); - } catch (GeneralSecurityException e) { - // Return null as if the file doesn't exist. - return null; - } catch (FileNotFoundException exception) { - // If the metadata file doesn't exist, then there is no key store, just return null. - return null; - } - } - - @VisibleForTesting - static KeyStore getKeyStore(InputStream metadata, ProcessProvider processProvider) - throws IOException, InterruptedException, GeneralSecurityException { - Process process = processProvider.createProcess(metadata); - - // Run the command and timeout after 1000 milliseconds. - int exitCode = runCertificateProviderCommand(process, 1000); - if (exitCode != 0) { - throw new IOException("Cert provider command failed with exit code: " + exitCode); - } - - // Create mTLS key store with the input certificates from shell command. - return SecurityUtils.createMtlsKeyStore(process.getInputStream()); - } - - @VisibleForTesting - static ImmutableList extractCertificateProviderCommand(InputStream contextAwareMetadata) - throws IOException { - JsonParser parser = new GsonFactory().createJsonParser(contextAwareMetadata); - ContextAwareMetadataJson json = parser.parse(ContextAwareMetadataJson.class); - return json.getCommands(); - } - - @VisibleForTesting - static int runCertificateProviderCommand(Process commandProcess, long timeoutMilliseconds) - throws IOException, InterruptedException { - long startTime = System.currentTimeMillis(); - long remainTime = timeoutMilliseconds; - - // In the while loop, keep checking if the process is terminated every 100 milliseconds - // until timeout is reached or process is terminated. In getKeyStore we set timeout to - // 1000 milliseconds, so 100 millisecond is a good number for the sleep. - while (remainTime > 0) { - Thread.sleep(Math.min(remainTime + 1, 100)); - remainTime -= System.currentTimeMillis() - startTime; - - try { - return commandProcess.exitValue(); - } catch (IllegalThreadStateException ignored) { - // exitValue throws IllegalThreadStateException if process has not yet terminated. - // Once the process is terminated, exitValue no longer throws exception. Therefore - // in the while loop, we use exitValue to check if process is terminated. See - // https://docs.oracle.com/javase/7/docs/api/java/lang/Process.html#exitValue() - // for more details. - } - } - - commandProcess.destroy(); - throw new IOException("cert provider command timed out"); - } -} diff --git a/gax/src/main/java/com/google/api/gax/tracing/ApiTracer.java b/gax/src/main/java/com/google/api/gax/tracing/ApiTracer.java deleted file mode 100644 index 3176be4b9..000000000 --- a/gax/src/main/java/com/google/api/gax/tracing/ApiTracer.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.tracing; - -import com.google.api.core.InternalApi; -import org.threeten.bp.Duration; - -/** - * Implementations of this class trace the logical flow of a google cloud client. - * - *

A single instance of a tracer represents a logical operation that can be annotated throughout - * its lifecycle. Constructing an instance of a subclass will implicitly signal the start of a new - * operation. - * - *

For internal use only. google-cloud-java libraries should extend {@link BaseApiTracer}. - */ -@InternalApi -public interface ApiTracer { - - /** - * Asks the underlying implementation to install itself as a thread local. This allows for interop - * between clients using gax and external resources to share the same implementation of the - * tracing. For example OpenCensus will install a thread local that can read by the GRPC. - */ - Scope inScope(); - - /** - * Signals that the overall operation has finished successfully. The tracer is now considered - * closed and should no longer be used. - */ - void operationSucceeded(); - - /** - * Signals that the operation was cancelled by the user. The tracer is now considered closed and - * should no longer be used. - */ - void operationCancelled(); - - /** - * Signals that the overall operation has failed and no further attempts will be made. The tracer - * is now considered closed and should no longer be used. - * - * @param error the final error that caused the operation to fail. - */ - void operationFailed(Throwable error); - - /** - * Annotates the operation with selected connection id from the {@code ChannelPool}. - * - * @param id the local connection identifier of the selected connection. - */ - void connectionSelected(String id); - - /** - * Adds an annotation that an attempt is about to start. In general this should occur at the very - * start of the operation. The attemptNumber is zero based. So the initial attempt will be 0. - * - * @param attemptNumber the zero based sequential attempt number. - * @deprecated Please use {@link #attemptStarted(Object, int)} instead. - */ - @Deprecated - void attemptStarted(int attemptNumber); - - /** - * Adds an annotation that an attempt is about to start with additional information from the - * request. In general this should occur at the very start of the operation. The attemptNumber is - * zero based. So the initial attempt will be 0. - * - * @param attemptNumber the zero based sequential attempt number. - * @param request request of this attempt. - */ - void attemptStarted(Object request, int attemptNumber); - - /** Adds an annotation that the attempt succeeded. */ - void attemptSucceeded(); - - /** Add an annotation that the attempt was cancelled by the user. */ - void attemptCancelled(); - - /** - * Adds an annotation that the attempt failed, but another attempt will be made after the delay. - * - * @param error the transient error that caused the attempt to fail. - * @param delay the amount of time to wait before the next attempt will start. - */ - void attemptFailed(Throwable error, Duration delay); - - /** - * Adds an annotation that the attempt failed and that no further attempts will be made because - * retry limits have been reached. - * - * @param error the last error received before retries were exhausted. - */ - void attemptFailedRetriesExhausted(Throwable error); - - /** - * Adds an annotation that the attempt failed and that no further attempts will be made because - * the last error was not retryable. - * - * @param error the error that caused the final attempt to fail. - */ - void attemptPermanentFailure(Throwable error); - - /** - * Signals that the initial RPC for the long running operation failed. - * - * @param error the error that caused the long running operation fail. - */ - void lroStartFailed(Throwable error); - - /** - * Signals that the initial RPC successfully started the long running operation. The long running - * operation will now be polled for completion. - */ - void lroStartSucceeded(); - - /** Adds an annotation that a streaming response has been received. */ - void responseReceived(); - - /** Adds an annotation that a streaming request has been sent. */ - void requestSent(); - - /** - * Adds an annotation that a batch of writes has been flushed. - * - * @param elementCount the number of elements in the batch. - * @param requestSize the size of the batch in bytes. - */ - void batchRequestSent(long elementCount, long requestSize); - - /** - * A context class to be used with {@link #inScope()} and a try-with-resources block. Closing a - * {@link Scope} removes any context that the underlying implementation might've set in {@link - * #inScope()}. - */ - interface Scope extends AutoCloseable { - @Override - void close(); - } -} diff --git a/gax/src/main/java/com/google/api/gax/tracing/ApiTracerFactory.java b/gax/src/main/java/com/google/api/gax/tracing/ApiTracerFactory.java deleted file mode 100644 index bb8345b88..000000000 --- a/gax/src/main/java/com/google/api/gax/tracing/ApiTracerFactory.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.tracing; - -import com.google.api.core.InternalApi; -import com.google.api.core.InternalExtensionOnly; - -/** - * A factory to create new instances of {@link ApiTracer}s. - * - *

In general a single instance of an {@link ApiTracer} will correspond to a single logical - * operation. - * - *

For internal use only. google-cloud-java libraries should extend {@link BaseApiTracerFactory}. - */ -@InternalApi -@InternalExtensionOnly -public interface ApiTracerFactory { - /** The type of operation the {@link ApiTracer} is tracing. */ - enum OperationType { - Unary, - Batching, - LongRunning, - ServerStreaming, - ClientStreaming, - BidiStreaming - } - - /** - * Create a new {@link ApiTracer} that will be a child of the current context. - * - * @param parent the parent of this tracer - * @param spanName the name of the new span - * @param operationType the type of operation that the tracer will trace - */ - ApiTracer newTracer(ApiTracer parent, SpanName spanName, OperationType operationType); -} diff --git a/gax/src/main/java/com/google/api/gax/tracing/BaseApiTracer.java b/gax/src/main/java/com/google/api/gax/tracing/BaseApiTracer.java deleted file mode 100644 index 538708b87..000000000 --- a/gax/src/main/java/com/google/api/gax/tracing/BaseApiTracer.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.tracing; - -import com.google.api.core.InternalApi; -import org.threeten.bp.Duration; - -/** - * A base implementation of {@link ApiTracer} that does nothing. - * - *

For internal use only. - */ -@InternalApi("For internal use by google-cloud-java clients only") -public class BaseApiTracer implements ApiTracer { - private static final ApiTracer INSTANCE = new BaseApiTracer(); - - private static final Scope NOOP_SCOPE = - new Scope() { - @Override - public void close() { - // noop - } - }; - - protected BaseApiTracer() {} - - public static ApiTracer getInstance() { - return INSTANCE; - } - - @Override - public Scope inScope() { - return NOOP_SCOPE; - } - - @Override - public void operationSucceeded() { - // noop - } - - @Override - public void operationCancelled() { - // noop - } - - @Override - public void operationFailed(Throwable error) { - // noop - } - - @Override - public void connectionSelected(String id) { - // noop - } - - @Override - public void attemptStarted(int attemptNumber) { - // noop - } - - @Override - public void attemptStarted(Object request, int attemptNumber) { - attemptStarted(attemptNumber); - } - - @Override - public void attemptSucceeded() { - // noop - } - - @Override - public void attemptCancelled() { - // noop - } - - @Override - public void attemptFailed(Throwable error, Duration delay) { - // noop - } - - @Override - public void attemptFailedRetriesExhausted(Throwable error) { - // noop - } - - @Override - public void attemptPermanentFailure(Throwable error) { - // noop - - } - - @Override - public void lroStartFailed(Throwable error) { - // noop - } - - @Override - public void lroStartSucceeded() { - // noop - } - - @Override - public void responseReceived() { - // noop - } - - @Override - public void requestSent() { - // noop - } - - @Override - public void batchRequestSent(long elementCount, long requestSize) { - // noop - } -} diff --git a/gax/src/main/java/com/google/api/gax/tracing/BaseApiTracerFactory.java b/gax/src/main/java/com/google/api/gax/tracing/BaseApiTracerFactory.java deleted file mode 100644 index 0b04bf872..000000000 --- a/gax/src/main/java/com/google/api/gax/tracing/BaseApiTracerFactory.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.tracing; - -import com.google.api.core.InternalApi; - -/** - * Base factory that will build {@link ApiTracer}s that do nothing. - * - *

For internal use only. - */ -@InternalApi("For internal use by google-cloud-java clients only") -public class BaseApiTracerFactory implements ApiTracerFactory { - private static final BaseApiTracerFactory INSTANCE = new BaseApiTracerFactory(); - - public static BaseApiTracerFactory getInstance() { - return INSTANCE; - } - - protected BaseApiTracerFactory() {} - - /** {@inheritDoc} */ - @Override - public ApiTracer newTracer(ApiTracer parent, SpanName spanName, OperationType operationType) { - return BaseApiTracer.getInstance(); - } -} diff --git a/gax/src/main/java/com/google/api/gax/tracing/OpencensusTracer.java b/gax/src/main/java/com/google/api/gax/tracing/OpencensusTracer.java deleted file mode 100644 index ea4c5f903..000000000 --- a/gax/src/main/java/com/google/api/gax/tracing/OpencensusTracer.java +++ /dev/null @@ -1,492 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.tracing; - -import com.google.api.core.BetaApi; -import com.google.api.core.InternalApi; -import com.google.api.gax.rpc.ApiException; -import com.google.api.gax.rpc.StatusCode; -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.api.gax.tracing.ApiTracerFactory.OperationType; -import com.google.common.base.Preconditions; -import com.google.common.base.Strings; -import io.opencensus.trace.AttributeValue; -import io.opencensus.trace.EndSpanOptions; -import io.opencensus.trace.Span; -import io.opencensus.trace.Status; -import io.opencensus.trace.Status.CanonicalCode; -import io.opencensus.trace.Tracer; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.atomic.AtomicLong; -import javax.annotation.Nonnull; -import org.threeten.bp.Duration; - -/** - * Implementation of {@link ApiTracer} that uses OpenCensus. - * - *

This implementation wraps an OpenCensus {@link Span} for every tracer and annotates that - * {@link Span} with various events throughout the lifecycle of the logical operation. - * - *

Each span will be named {@code ClientName.MethodName} and will have the following attributes: - * - *

- *
{@code attempt count} - *
The Number of attempts sent before the logical operation completed - *
{@code status} - *
The status code of the last attempt - *
{@code total response count} - *
The number of messages received across all of the attempts. This will only be set for - * server streaming and bidi RPCs. - *
{@code total request count} - *
The number of messages sent across all of the attempts. This will only be set for client - * streaming and bidi RPCs. - *
{@code batch count} - *
For batch requests, the number of elements in the request. - *
{@code batch size} - *
For batch requests, the byte size of the request. - *
- * - *

The spans will contain the following annotations: - * - *

    - *
  • {@code Attempt cancelled} with the following attributes: - *
    - *
    {@code attempt} - *
    Zero based sequential attempt number - *
    {@code attempt request count} - *
    The number of requests sent in this attempt. This will only be set for client - * streaming and bidi RPCs. - *
    {@code attempt response count} - *
    The number of responses received in this attempt. This will only be set for server - * streaming and bidi RPCs. - *
    {@code connection} - *
    The UUID of the connection which the attempt was sent. - *
    - *
  • {@code Attempt failed, scheduling next attempt} with the following attributes: - *
    - *
    {@code attempt} - *
    Zero based sequential attempt number - *
    {@code status} - *
    The status code of the failed attempt - *
    {@code delay} - *
    The number of milliseconds to wait before trying again - *
    {@code attempt request count} - *
    The number of requests sent in this attempt. This will only be set for client - * streaming and bidi RPCs. - *
    {@code attempt response count} - *
    The number of responses received in this attempt. This will only be set for server - * streaming and bidi RPCs. - *
    {@code connection} - *
    The UUID of the connection which the attempt was sent. - *
    - *
  • {@code Attempts exhausted} with the following attributes: - *
    - *
    {@code attempt} - *
    Zero based sequential attempt number - *
    {@code status} - *
    The status code of the failed attempt - *
    {@code attempt request count} - *
    The number of requests sent in this attempt. This will only be set for client - * streaming and bidi RPCs. - *
    {@code attempt response count} - *
    The number of responses received in this attempt. This will only be set for server - * streaming and bidi RPCs. - *
    {@code connection} - *
    The UUID of the connection which the attempt was sent. - *
    - *
  • {@code Attempt failed, error not retryable} with the following attributes: - *
    - *
    {@code attempt} - *
    Zero based sequential attempt number - *
    {@code status} - *
    The status code of the failed attempt - *
    {@code attempt request count} - *
    The number of requests sent in this attempt. This will only be set for client - * streaming and bidi RPCs. - *
    {@code attempt response count} - *
    The number of responses received in this attempt. This will only be set for server - * streaming and bidi RPCs. - *
    {@code connection} - *
    The UUID of the connection which the attempt was sent. - *
    - *
  • {@code Attempt succeeded} with the following attributes: - *
    - *
    {@code attempt} - *
    Zero based sequential attempt number - *
    {@code attempt request count} - *
    The number of requests sent in this attempt. This will only be set for client - * streaming and bidi RPCs. - *
    {@code attempt response count} - *
    The number of responses received in this attempt. This will only be set for server - * streaming and bidi RPCs. - *
    {@code connection} - *
    The UUID of the connection which the attempt was sent. - *
    - *
- * - *

Long running operations, which are composed of an initial RPC to start the operation and a - * number of polling RPCs will be represented as a tree of spans. The top level span will be named - * after the initial RPC name suffixed with "Operation" and will have the following annotations: - * - *

    - *
  • {@code Operation started} - *
  • {@code Operation failed to start} with the following attributes: - *
    - *
    {@code status} - *
    The status code of why the operation failed to start - *
    - *
  • {@code Polling was cancelled} with the following attributes: - *
    - *
    {@code attempt} - *
    Zero based sequential poll number. - *
    {@code attempt request count} - *
    - *
  • {@code Scheduling next poll} with the following attributes: - *
    - *
    {@code attempt} - *
    Zero based sequential poll number - *
    {@code status} - *
    OK if the poll succeeded, but the operation is still running. - *
    {@code delay} - *
    The number of milliseconds to wait before polling again - *
    - *
  • {@code Polling attempts exhausted} with the following attributes: - *
    - *
    {@code attempt} - *
    Zero based sequential poll number - *
    {@code status} - *
    OK if the poll succeeded, but the operation is still running. - *
    - *
  • {@code Polling failed} with the following attributes: - *
    - *
    {@code attempt} - *
    Zero based sequential poll number - *
    {@code status} - *
    OK if the poll succeeded, but the operation is still running. - *
    - *
  • {@code Polling completed} with the following attributes: - *
    - *
    {@code attempt} - *
    Zero based sequential poll number - *
    - *
- * - *

The toplevel long running operation span will also contain child spans to describe the retry - * attempts for the initial RPC and each poll as described in the general span section above. - * - *

This class is thread compatible. It expects callers to follow grpc's threading model: there is - * only one thread that invokes the operation* and attempt* methods. Please see {@link - * com.google.api.gax.rpc.ApiStreamObserver} for more information. - */ -@BetaApi("Surface for tracing is not yet stable") -public class OpencensusTracer extends BaseApiTracer { - private final Tracer tracer; - private final Span span; - private final OperationType operationType; - - private volatile String lastConnectionId; - private volatile long currentAttemptId; - private AtomicLong attemptSentMessages = new AtomicLong(0); - private long attemptReceivedMessages = 0; - private AtomicLong totalSentMessages = new AtomicLong(0); - private long totalReceivedMessages = 0; - - OpencensusTracer( - @Nonnull Tracer tracer, @Nonnull Span span, @Nonnull OperationType operationType) { - this.tracer = Preconditions.checkNotNull(tracer, "tracer can't be null"); - this.span = Preconditions.checkNotNull(span, "span can't be null"); - this.operationType = Preconditions.checkNotNull(operationType, "operationType can't be null"); - } - - Span getSpan() { - return span; - } - - /** {@inheritDoc} */ - @Override - public Scope inScope() { - // Suppressing to make MustBeClosedChecker happy. The scope will be closed but indirectly - // (inside new Scope()), and the checker cannot recognize it. - @SuppressWarnings("MustBeClosedChecker") - final io.opencensus.common.Scope scope = tracer.withSpan(span); - - return new Scope() { - @Override - public void close() { - scope.close(); - } - }; - } - - /** {@inheritDoc} */ - @Override - public void operationSucceeded() { - Map attributes = baseOperationAttributes(); - - span.putAttributes(attributes); - span.end(); - } - - /** {@inheritDoc} */ - @Override - public void operationCancelled() { - Map attributes = baseOperationAttributes(); - span.putAttributes(attributes); - span.end( - EndSpanOptions.builder() - .setStatus(Status.CANCELLED.withDescription("Cancelled by caller")) - .build()); - } - - /** {@inheritDoc} */ - @Override - public void operationFailed(Throwable error) { - Map attributes = baseOperationAttributes(); - - span.putAttributes(attributes); - span.end(EndSpanOptions.builder().setStatus(convertErrorToStatus(error)).build()); - } - - /** {@inheritDoc} */ - @Override - public void lroStartFailed(Throwable error) { - Map attributes = new HashMap<>(); - populateError(attributes, error); - - span.addAnnotation("Operation failed to start", attributes); - } - - /** {@inheritDoc} */ - @Override - public void lroStartSucceeded() { - span.addAnnotation("Operation started"); - } - - /** {@inheritDoc} */ - @Override - public void connectionSelected(String id) { - lastConnectionId = id; - } - - /** {@inheritDoc} */ - @Override - public void attemptStarted(int attemptNumber) { - currentAttemptId = attemptNumber; - attemptSentMessages.set(0); - attemptReceivedMessages = 0; - - // NOTE: no annotations are added because they don't provide any semantic value. - // This simply is used for state management. - } - - /** {@inheritDoc} */ - @Override - public void attemptStarted(Object request, int attemptNumber) { - attemptStarted(attemptNumber); - } - - /** {@inheritDoc} */ - @Override - public void attemptSucceeded() { - Map attributes = baseAttemptAttributes(); - - // Same infrastructure is used for both polling and retries, so need to disambiguate it here. - if (operationType == OperationType.LongRunning) { - span.addAnnotation("Polling completed", attributes); - } else { - span.addAnnotation("Attempt succeeded", attributes); - } - } - - /** {@inheritDoc} */ - @Override - public void attemptCancelled() { - Map attributes = baseAttemptAttributes(); - - // Same infrastructure is used for both polling and retries, so need to disambiguate it here. - if (operationType == OperationType.LongRunning) { - span.addAnnotation("Polling was cancelled", attributes); - } else { - span.addAnnotation("Attempt cancelled", attributes); - } - lastConnectionId = null; - } - - /** {@inheritDoc} */ - @Override - public void attemptFailed(Throwable error, Duration delay) { - Map attributes = baseAttemptAttributes(); - attributes.put("delay ms", AttributeValue.longAttributeValue(delay.toMillis())); - populateError(attributes, error); - - // Same infrastructure is used for both polling and retries, so need to disambiguate it here. - if (operationType == OperationType.LongRunning) { - // The poll RPC was successful, but it indicated that the operation is still running. - span.addAnnotation("Scheduling next poll", attributes); - } else { - span.addAnnotation("Attempt failed, scheduling next attempt", attributes); - } - lastConnectionId = null; - } - - /** {@inheritDoc} */ - @Override - public void attemptFailedRetriesExhausted(Throwable error) { - Map attributes = baseAttemptAttributes(); - populateError(attributes, error); - - // Same infrastructure is used for both polling and retries, so need to disambiguate it here. - if (operationType == OperationType.LongRunning) { - span.addAnnotation("Polling attempts exhausted", attributes); - } else { - span.addAnnotation("Attempts exhausted", attributes); - } - lastConnectionId = null; - } - - /** {@inheritDoc} */ - @Override - public void attemptPermanentFailure(Throwable error) { - Map attributes = baseAttemptAttributes(); - populateError(attributes, error); - - // Same infrastructure is used for both polling and retries, so need to disambiguate it here. - if (operationType == OperationType.LongRunning) { - span.addAnnotation("Polling failed", attributes); - } else { - span.addAnnotation("Attempt failed, error not retryable", attributes); - } - lastConnectionId = null; - } - - /** {@inheritDoc} */ - @Override - public void responseReceived() { - attemptReceivedMessages++; - totalReceivedMessages++; - } - - /** {@inheritDoc} */ - @Override - public void requestSent() { - attemptSentMessages.incrementAndGet(); - totalSentMessages.incrementAndGet(); - } - - /** {@inheritDoc} */ - @Override - public void batchRequestSent(long elementCount, long requestSize) { - span.putAttribute("batch count", AttributeValue.longAttributeValue(elementCount)); - span.putAttribute("batch size", AttributeValue.longAttributeValue(requestSize)); - } - - private Map baseOperationAttributes() { - HashMap attributes = new HashMap<>(); - - attributes.put("attempt count", AttributeValue.longAttributeValue(currentAttemptId + 1)); - - long localTotalSentMessages = totalSentMessages.get(); - if (localTotalSentMessages > 0) { - attributes.put( - "total request count", AttributeValue.longAttributeValue(localTotalSentMessages)); - } - if (totalReceivedMessages > 0) { - attributes.put( - "total response count", AttributeValue.longAttributeValue(totalReceivedMessages)); - } - - return attributes; - } - - private Map baseAttemptAttributes() { - HashMap attributes = new HashMap<>(); - - populateAttemptNumber(attributes); - - long localAttemptSentMessages = attemptSentMessages.get(); - if (localAttemptSentMessages > 0) { - attributes.put( - "attempt request count", AttributeValue.longAttributeValue(localAttemptSentMessages)); - } - if (attemptReceivedMessages > 0) { - attributes.put( - "attempt response count", AttributeValue.longAttributeValue(attemptReceivedMessages)); - } - - String localLastConnectionId = lastConnectionId; - if (localLastConnectionId != null) { - attributes.put("connection", AttributeValue.stringAttributeValue(localLastConnectionId)); - } - - return attributes; - } - - private void populateAttemptNumber(Map attributes) { - attributes.put("attempt", AttributeValue.longAttributeValue(currentAttemptId)); - } - - private void populateError(Map attributes, Throwable error) { - if (error == null) { - attributes.put("status", AttributeValue.stringAttributeValue("OK")); - return; - } - - Status status = convertErrorToStatus(error); - - attributes.put( - "status", AttributeValue.stringAttributeValue(status.getCanonicalCode().toString())); - - if (!Strings.isNullOrEmpty(status.getDescription())) { - attributes.put( - "status message", AttributeValue.stringAttributeValue(status.getDescription())); - } - } - - @InternalApi("Visible for testing") - static Status convertErrorToStatus(Throwable error) { - StatusCode.Code gaxCode = Code.UNKNOWN; - - if (error instanceof ApiException) { - gaxCode = ((ApiException) error).getStatusCode().getCode(); - } else if (error.getCause() instanceof ApiException) { - gaxCode = ((ApiException) error.getCause()).getStatusCode().getCode(); - } - - Status.CanonicalCode code; - try { - code = Status.CanonicalCode.valueOf(gaxCode.name()); - } catch (IllegalArgumentException e) { - code = CanonicalCode.UNKNOWN; - } - - return code.toStatus().withDescription(error.getMessage()); - } -} diff --git a/gax/src/main/java/com/google/api/gax/tracing/OpencensusTracerFactory.java b/gax/src/main/java/com/google/api/gax/tracing/OpencensusTracerFactory.java deleted file mode 100644 index b9966b1f5..000000000 --- a/gax/src/main/java/com/google/api/gax/tracing/OpencensusTracerFactory.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.tracing; - -import com.google.api.core.InternalApi; -import com.google.common.base.Objects; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableMap; -import io.opencensus.trace.AttributeValue; -import io.opencensus.trace.Span; -import io.opencensus.trace.Tracer; -import io.opencensus.trace.Tracing; -import java.util.Map; -import javax.annotation.Nonnull; - -/** - * A {@link ApiTracerFactory} to build instances of {@link OpencensusTracer}. - * - *

This class wraps the {@link Tracer} provided by Opencensus in {@code Tracing.getTracer()}. It - * will be used to create new spans and wrap them in {@link OpencensusTracer} defined in gax. - * - *

This class is thread safe. - */ -@InternalApi("For google-cloud-java client use only") -public final class OpencensusTracerFactory extends BaseApiTracerFactory { - @Nonnull private final Tracer internalTracer; - @Nonnull private final Map spanAttributes; - - /** - * Instantiates a new instance capturing the {@link io.opencensus.trace.Tracer} in {@code - * Tracing.getTracer}. - */ - public OpencensusTracerFactory() { - this(ImmutableMap.of()); - } - - /** - * Instantiates a new instance capturing the {@link io.opencensus.trace.Tracer} in {@code - * Tracing.getTracer}. It will also override the service name of the grpc stub with a custom - * client name. This is useful disambiguate spans created outer manual written wrappers and around - * generated gapic spans. - * - * @param spanAttributes the attributes to stamp on every span. Should include things like library - * version. - */ - public OpencensusTracerFactory(Map spanAttributes) { - this(Tracing.getTracer(), spanAttributes); - } - - /** - * Instantiates a new instance with an explicit {@link io.opencensus.trace.Tracer}. It will also - * override the service name of the grpc stub with a custom client name. This is useful - * disambiguate spans created outer manual written wrappers and around generated gapic spans. - * - * @param internalTracer the Opencensus tracer to wrap. - */ - @InternalApi("Visible for testing") - OpencensusTracerFactory(Tracer internalTracer, @Nonnull Map spanAttributes) { - this.internalTracer = - Preconditions.checkNotNull(internalTracer, "internalTracer can't be null"); - ImmutableMap.Builder formattedSpanAttributes = ImmutableMap.builder(); - for (Map.Entry entry : spanAttributes.entrySet()) { - formattedSpanAttributes.put( - entry.getKey(), AttributeValue.stringAttributeValue(entry.getValue())); - } - this.spanAttributes = formattedSpanAttributes.build(); - } - - /** {@inheritDoc } */ - @Override - public ApiTracer newTracer(ApiTracer parent, SpanName spanName, OperationType operationType) { - // Default to the current in context span. This is used for outermost tracers that inherit - // the caller's parent span. - Span parentSpan = internalTracer.getCurrentSpan(); - - // If an outer callable started a span, use it as the parent. - if (parent instanceof OpencensusTracer) { - parentSpan = ((OpencensusTracer) parent).getSpan(); - } - - Span span = - internalTracer - .spanBuilderWithExplicitParent(spanName.toString(), parentSpan) - .setRecordEvents(true) - .startSpan(); - span.putAttributes(spanAttributes); - - return new OpencensusTracer(internalTracer, span, operationType); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - OpencensusTracerFactory that = (OpencensusTracerFactory) o; - return Objects.equal(internalTracer, that.internalTracer) - && Objects.equal(spanAttributes, that.spanAttributes); - } - - @Override - public int hashCode() { - return Objects.hashCode(internalTracer, spanAttributes); - } -} diff --git a/gax/src/main/java/com/google/api/gax/tracing/SpanName.java b/gax/src/main/java/com/google/api/gax/tracing/SpanName.java deleted file mode 100644 index da62d7c5a..000000000 --- a/gax/src/main/java/com/google/api/gax/tracing/SpanName.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.tracing; - -import com.google.api.core.BetaApi; -import com.google.api.core.InternalApi; -import com.google.auto.value.AutoValue; - -/** A value class to represent the name of the operation in an {@link ApiTracer}. */ -@BetaApi("Surface for tracing is not yet stable") -@InternalApi("For google-cloud-java client use only") -@AutoValue -public abstract class SpanName { - /** - * Creates a new instance of the name. - * - * @param clientName The name of the client. In general this will be GAPIC generated client name. - * However, in some cases, when the GAPIC generated client is wrapped, this will be overridden - * to specify the manually written wrapper's name. - * @param methodName The name of the logical operation being traced. - */ - public static SpanName of(String clientName, String methodName) { - return new AutoValue_SpanName(clientName, methodName); - } - - /** The name of the client. ie BigtableData */ - public abstract String getClientName(); - - /** The name of the logical operation being traced. ie. ReadRows. */ - public abstract String getMethodName(); - - @Override - public String toString() { - return getClientName() + "." + getMethodName(); - } -} diff --git a/gax/src/main/java/com/google/api/gax/tracing/TraceFinisher.java b/gax/src/main/java/com/google/api/gax/tracing/TraceFinisher.java deleted file mode 100644 index 292a82775..000000000 --- a/gax/src/main/java/com/google/api/gax/tracing/TraceFinisher.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.tracing; - -import com.google.api.core.ApiFutureCallback; -import com.google.common.base.Preconditions; -import java.util.concurrent.CancellationException; -import javax.annotation.Nonnull; - -/** An {@link ApiFutureCallback} to mark a started operation trace as finished. */ -class TraceFinisher implements ApiFutureCallback { - private final ApiTracer tracer; - - TraceFinisher(@Nonnull ApiTracer tracer) { - this.tracer = Preconditions.checkNotNull(tracer, "tracer can't be null"); - } - - @Override - public void onFailure(Throwable throwable) { - if (throwable instanceof CancellationException) { - tracer.operationCancelled(); - } else { - tracer.operationFailed(throwable); - } - } - - @Override - public void onSuccess(T responseT) { - tracer.operationSucceeded(); - } -} diff --git a/gax/src/main/java/com/google/api/gax/tracing/TracedBatchingCallable.java b/gax/src/main/java/com/google/api/gax/tracing/TracedBatchingCallable.java deleted file mode 100644 index 0cfb7df08..000000000 --- a/gax/src/main/java/com/google/api/gax/tracing/TracedBatchingCallable.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.tracing; - -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.api.core.BetaApi; -import com.google.api.core.InternalApi; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.BatchingDescriptor; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.api.gax.tracing.ApiTracerFactory.OperationType; -import com.google.common.util.concurrent.MoreExecutors; - -/** - * This callable wraps a batching callable chain in a {@link ApiTracer}. - * - *

For internal use only. - */ -@BetaApi("The surface for tracing is not stable and might change in the future") -@InternalApi("For internal use by google-cloud-java clients only") -public class TracedBatchingCallable - extends UnaryCallable { - private final ApiTracerFactory tracerFactory; - private final SpanName spanName; - private final BatchingDescriptor batchingDescriptor; - private final UnaryCallable innerCallable; - - public TracedBatchingCallable( - UnaryCallable innerCallable, - ApiTracerFactory tracerFactory, - SpanName spanName, - BatchingDescriptor batchingDescriptor) { - this.tracerFactory = tracerFactory; - this.spanName = spanName; - this.batchingDescriptor = batchingDescriptor; - this.innerCallable = innerCallable; - } - - @Override - public ApiFuture futureCall(RequestT request, ApiCallContext context) { - // NOTE: This will be invoked asynchronously outside of the original caller's thread. - // So this start a top level tracer. - ApiTracer tracer = - tracerFactory.newTracer(context.getTracer(), spanName, OperationType.Batching); - TraceFinisher finisher = new TraceFinisher<>(tracer); - - try { - long elementCount = batchingDescriptor.countElements(request); - long requestSize = batchingDescriptor.countBytes(request); - - tracer.batchRequestSent(elementCount, requestSize); - - context = context.withTracer(tracer); - ApiFuture future = innerCallable.futureCall(request, context); - ApiFutures.addCallback(future, finisher, MoreExecutors.directExecutor()); - - return future; - } catch (RuntimeException e) { - finisher.onFailure(e); - throw e; - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/tracing/TracedBidiCallable.java b/gax/src/main/java/com/google/api/gax/tracing/TracedBidiCallable.java deleted file mode 100644 index fd2172752..000000000 --- a/gax/src/main/java/com/google/api/gax/tracing/TracedBidiCallable.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.tracing; - -import com.google.api.core.BetaApi; -import com.google.api.core.InternalApi; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.BidiStreamingCallable; -import com.google.api.gax.rpc.ClientStream; -import com.google.api.gax.rpc.ClientStreamReadyObserver; -import com.google.api.gax.rpc.ResponseObserver; -import com.google.api.gax.tracing.ApiTracerFactory.OperationType; -import com.google.common.base.Preconditions; -import java.util.concurrent.CancellationException; -import java.util.concurrent.atomic.AtomicBoolean; -import javax.annotation.Nonnull; - -/** - * A wrapper callable that will wrap a callable chain in a trace. - * - *

For internal use only. - */ -@BetaApi("The surface for tracing is not stable and might change in the future") -@InternalApi("For internal use by google-cloud-java clients only") -public class TracedBidiCallable - extends BidiStreamingCallable { - - @Nonnull private final ApiTracerFactory tracerFactory; - @Nonnull private final SpanName spanName; - @Nonnull private final BidiStreamingCallable innerCallable; - - public TracedBidiCallable( - @Nonnull BidiStreamingCallable innerCallable, - @Nonnull ApiTracerFactory tracerFactory, - @Nonnull SpanName spanName) { - this.tracerFactory = Preconditions.checkNotNull(tracerFactory, "tracerFactory can't be null"); - this.spanName = Preconditions.checkNotNull(spanName, "spanName can't be null"); - this.innerCallable = Preconditions.checkNotNull(innerCallable, "innerCallable can't be null"); - } - - @Override - public ClientStream internalCall( - ResponseObserver responseObserver, - ClientStreamReadyObserver onReady, - ApiCallContext context) { - - ApiTracer tracer = - tracerFactory.newTracer(context.getTracer(), spanName, OperationType.BidiStreaming); - context = context.withTracer(tracer); - - AtomicBoolean wasCancelled = new AtomicBoolean(); - - ResponseObserver tracedObserver = - new TracedResponseObserver<>(tracer, responseObserver, wasCancelled); - ClientStreamReadyObserver tracedReadyObserver = - new TracedClientStreamReadyObserver<>(tracer, onReady, wasCancelled); - - try { - ClientStream clientStream = - innerCallable.internalCall(tracedObserver, tracedReadyObserver, context); - return new TracingClientStream<>(tracer, clientStream, wasCancelled); - } catch (RuntimeException e) { - tracer.operationFailed(e); - throw e; - } - } - - private static class TracedClientStreamReadyObserver - implements ClientStreamReadyObserver { - private final ApiTracer tracer; - private final ClientStreamReadyObserver innerObserver; - private final AtomicBoolean wasCancelled; - - TracedClientStreamReadyObserver( - ApiTracer tracer, - ClientStreamReadyObserver innerObserver, - AtomicBoolean wasCancelled) { - this.tracer = tracer; - this.innerObserver = innerObserver; - this.wasCancelled = wasCancelled; - } - - @Override - public void onReady(ClientStream stream) { - innerObserver.onReady(new TracingClientStream<>(tracer, stream, wasCancelled)); - } - } - - /** {@link ClientStream} wrapper that annotates traces with sent messages. */ - private static class TracingClientStream implements ClientStream { - private final ApiTracer tracer; - private final ClientStream innerStream; - private final AtomicBoolean wasCancelled; - - private TracingClientStream( - ApiTracer tracer, ClientStream innerStream, AtomicBoolean wasCancelled) { - this.tracer = tracer; - this.innerStream = innerStream; - this.wasCancelled = wasCancelled; - } - - @Override - public void send(RequestT request) { - tracer.requestSent(); - innerStream.send(request); - } - - @Override - public void closeSendWithError(Throwable t) { - if (t == null) { - t = new CancellationException(); - } - wasCancelled.set(true); - innerStream.closeSendWithError(t); - } - - @Override - public void closeSend() { - innerStream.closeSend(); - } - - @Override - public boolean isSendReady() { - return innerStream.isSendReady(); - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/tracing/TracedClientStreamingCallable.java b/gax/src/main/java/com/google/api/gax/tracing/TracedClientStreamingCallable.java deleted file mode 100644 index 773efe2de..000000000 --- a/gax/src/main/java/com/google/api/gax/tracing/TracedClientStreamingCallable.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.tracing; - -import com.google.api.core.BetaApi; -import com.google.api.core.InternalApi; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.ApiStreamObserver; -import com.google.api.gax.rpc.ClientStreamingCallable; -import com.google.api.gax.tracing.ApiTracerFactory.OperationType; -import com.google.common.base.Preconditions; -import java.util.concurrent.CancellationException; -import java.util.concurrent.atomic.AtomicReference; -import javax.annotation.Nonnull; - -/** - * A wrapper callable that will wrap a callable chain in a trace. - * - *

This can be safely called from multiple threads. However the request {@link ApiStreamObserver} - * can only be used from a single thread. - * - *

For internal use only. - */ -@BetaApi("The surface for tracing is not stable and might change in the future") -@InternalApi -public class TracedClientStreamingCallable - extends ClientStreamingCallable { - private final ClientStreamingCallable innerCallable; - private final ApiTracerFactory tracerFactory; - private final SpanName spanName; - - public TracedClientStreamingCallable( - @Nonnull ClientStreamingCallable innerCallable, - @Nonnull ApiTracerFactory tracerFactory, - @Nonnull SpanName spanName) { - this.tracerFactory = Preconditions.checkNotNull(tracerFactory, "tracerFactory can't be null"); - this.spanName = Preconditions.checkNotNull(spanName, "spanName can't be null"); - this.innerCallable = Preconditions.checkNotNull(innerCallable, "innerCallable can't be null"); - } - - @Override - public ApiStreamObserver clientStreamingCall( - ApiStreamObserver responseObserver, ApiCallContext context) { - - ApiTracer tracer = - tracerFactory.newTracer(context.getTracer(), spanName, OperationType.ClientStreaming); - context = context.withTracer(tracer); - - // Shared state that allows the response observer to know that the error it received was - // triggered by a caller initiated cancellation. - AtomicReference cancellationCauseHolder = new AtomicReference<>(null); - - try { - ApiStreamObserver innerResponseObserver = - new TracedResponseObserver<>(tracer, responseObserver, cancellationCauseHolder); - - ApiStreamObserver innerRequestObserver = - innerCallable.clientStreamingCall(innerResponseObserver, context); - - return new TracedRequestObserver<>(tracer, innerRequestObserver, cancellationCauseHolder); - } catch (RuntimeException e) { - tracer.operationFailed(e); - throw e; - } - } - - /** {@link ApiStreamObserver} wrapper to annotate the current trace with sent message. */ - private static class TracedRequestObserver implements ApiStreamObserver { - private final ApiTracer tracer; - private final ApiStreamObserver innerObserver; - private final AtomicReference cancellationCauseHolder; - - TracedRequestObserver( - @Nonnull ApiTracer tracer, - @Nonnull ApiStreamObserver innerObserver, - @Nonnull AtomicReference cancellationCauseHolder) { - this.tracer = Preconditions.checkNotNull(tracer, "tracer can't be null"); - this.innerObserver = Preconditions.checkNotNull(innerObserver, "innerObserver can't be null"); - this.cancellationCauseHolder = - Preconditions.checkNotNull( - cancellationCauseHolder, "cancellationCauseHolder can't be null"); - } - - @Override - public void onNext(RequestT value) { - tracer.requestSent(); - innerObserver.onNext(value); - } - - @Override - public void onError(Throwable throwable) { - if (throwable == null) { - throwable = new CancellationException("Cancelled without a cause"); - } - // NOTE: Calling onError will eventually cancel the entire stream. So we just set a flag now - // and trace later in the TracedResponseObserver. - cancellationCauseHolder.compareAndSet(null, throwable); - innerObserver.onError(throwable); - } - - @Override - public void onCompleted() { - // TODO(igorbernstein2): consider tracing request stream completion. - innerObserver.onCompleted(); - } - } - - /** - * {@link ApiStreamObserver} wrapper to annotate the current trace with received messages and to - * close the current trace upon completion of the RPC. - */ - private static class TracedResponseObserver implements ApiStreamObserver { - @Nonnull private final ApiTracer tracer; - @Nonnull private final ApiStreamObserver innerObserver; - @Nonnull private final AtomicReference cancellationCauseHolder; - - TracedResponseObserver( - @Nonnull ApiTracer tracer, - @Nonnull ApiStreamObserver innerObserver, - @Nonnull AtomicReference cancellationCauseHolder) { - this.tracer = Preconditions.checkNotNull(tracer, "tracer can't be null"); - this.innerObserver = Preconditions.checkNotNull(innerObserver, "innerObserver can't be null"); - this.cancellationCauseHolder = cancellationCauseHolder; - } - - @Override - public void onNext(RequestT value) { - tracer.responseReceived(); - innerObserver.onNext(value); - } - - @Override - public void onError(Throwable t) { - Throwable cancellationCause = cancellationCauseHolder.get(); - if (cancellationCause != null) { - tracer.operationCancelled(); - } else { - tracer.operationFailed(t); - } - innerObserver.onError(t); - } - - @Override - public void onCompleted() { - tracer.operationSucceeded(); - innerObserver.onCompleted(); - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/tracing/TracedOperationCallable.java b/gax/src/main/java/com/google/api/gax/tracing/TracedOperationCallable.java deleted file mode 100644 index 3b83d7fd7..000000000 --- a/gax/src/main/java/com/google/api/gax/tracing/TracedOperationCallable.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.tracing; - -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.api.core.InternalApi; -import com.google.api.gax.longrunning.OperationFuture; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.OperationCallable; -import com.google.api.gax.tracing.ApiTracerFactory.OperationType; -import com.google.common.util.concurrent.MoreExecutors; -import javax.annotation.Nonnull; - -/** - * This callable wraps a {@link OperationCallable} in a {@link ApiTracer}. - * - *

For internal use only. - */ -@InternalApi("For internal use by google-cloud-java clients only") -public class TracedOperationCallable - extends OperationCallable { - - private @Nonnull OperationCallable innerCallable; - private @Nonnull ApiTracerFactory tracerFactory; - private @Nonnull SpanName spanName; - - public TracedOperationCallable( - @Nonnull OperationCallable innerCallable, - @Nonnull ApiTracerFactory tracerFactory, - @Nonnull SpanName spanName) { - this.innerCallable = innerCallable; - this.tracerFactory = tracerFactory; - this.spanName = spanName; - } - - /** - * Wrap the initial start polling logical operations in a single parent trace using a {@link - * OperationType#LongRunning} {@link ApiTracer}. - */ - @Override - public OperationFuture futureCall( - RequestT request, ApiCallContext context) { - - ApiTracer tracer = - tracerFactory.newTracer(context.getTracer(), spanName, OperationType.LongRunning); - TraceFinisher finisher = new TraceFinisher<>(tracer); - - try { - context = context.withTracer(tracer); - OperationFuture future = innerCallable.futureCall(request, context); - ApiFutures.addCallback(future, finisher, MoreExecutors.directExecutor()); - - return future; - } catch (RuntimeException e) { - finisher.onFailure(e); - throw e; - } - } - - /** - * Wrap the polling logical operations in a single parent trace using a {@link - * OperationType#LongRunning} {@link ApiTracer}. - */ - @Override - public OperationFuture resumeFutureCall( - String operationName, ApiCallContext context) { - ApiTracer tracer = - tracerFactory.newTracer(context.getTracer(), spanName, OperationType.LongRunning); - TraceFinisher finisher = new TraceFinisher<>(tracer); - - try { - context = context.withTracer(tracer); - OperationFuture future = - innerCallable.resumeFutureCall(operationName, context); - - ApiFutures.addCallback(future, finisher, MoreExecutors.directExecutor()); - return future; - } catch (RuntimeException e) { - finisher.onFailure(e); - throw e; - } - } - - /** Wrap operation cancellation in a {@link OperationType#Unary} trace. */ - @Override - public ApiFuture cancel(String operationName, ApiCallContext context) { - SpanName cancelSpanName = - SpanName.of(spanName.getClientName(), spanName.getMethodName() + ".Cancel"); - - ApiTracer tracer = - tracerFactory.newTracer(context.getTracer(), cancelSpanName, OperationType.Unary); - TraceFinisher finisher = new TraceFinisher<>(tracer); - - try { - context = context.withTracer(tracer); - ApiFuture future = innerCallable.cancel(operationName, context); - ApiFutures.addCallback(future, finisher, MoreExecutors.directExecutor()); - return future; - } catch (RuntimeException e) { - finisher.onFailure(e); - throw e; - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/tracing/TracedOperationInitialCallable.java b/gax/src/main/java/com/google/api/gax/tracing/TracedOperationInitialCallable.java deleted file mode 100644 index 224b8e0f1..000000000 --- a/gax/src/main/java/com/google/api/gax/tracing/TracedOperationInitialCallable.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.tracing; - -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutureCallback; -import com.google.api.core.ApiFutures; -import com.google.api.gax.longrunning.OperationSnapshot; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.common.util.concurrent.MoreExecutors; - -/** - * Traces the initial RPC of a long running operation. - * - *

It will trace it like a child unary RPC and will also contribute to the parent tracer (created - * by {@link TracedOperationCallable}) the result of the call. - */ -public class TracedOperationInitialCallable - extends TracedUnaryCallable { - - public TracedOperationInitialCallable( - UnaryCallable innerCallable, - ApiTracerFactory tracedFactory, - SpanName spanName) { - super(innerCallable, tracedFactory, spanName); - } - - @Override - public ApiFuture futureCall(RequestT request, ApiCallContext context) { - InitialCallableFinisher finisher = new InitialCallableFinisher(context.getTracer()); - - try { - ApiFuture future = super.futureCall(request, context); - ApiFutures.addCallback(future, finisher, MoreExecutors.directExecutor()); - - return future; - } catch (RuntimeException e) { - finisher.onFailure(e); - throw e; - } - } - - private static class InitialCallableFinisher implements ApiFutureCallback { - private final ApiTracer operationTracer; - - private InitialCallableFinisher(ApiTracer operationTracer) { - this.operationTracer = operationTracer; - } - - @Override - public void onSuccess(OperationSnapshot result) { - operationTracer.lroStartSucceeded(); - } - - @Override - public void onFailure(Throwable t) { - operationTracer.lroStartFailed(t); - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/tracing/TracedResponseObserver.java b/gax/src/main/java/com/google/api/gax/tracing/TracedResponseObserver.java deleted file mode 100644 index ba72d2f5b..000000000 --- a/gax/src/main/java/com/google/api/gax/tracing/TracedResponseObserver.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.tracing; - -import com.google.api.core.InternalApi; -import com.google.api.gax.rpc.ResponseObserver; -import com.google.api.gax.rpc.StreamController; -import com.google.common.base.Preconditions; -import java.util.concurrent.atomic.AtomicBoolean; -import javax.annotation.Nonnull; - -/** - * A {@link ResponseObserver} to mark a started operation trace as finished. - * - *

The operation will be marked as complete before notifying the wrapped observer. Which means - * that the span of the instrumentation will not include processing of the innerObserver's - * onComplete. - */ -@InternalApi -class TracedResponseObserver implements ResponseObserver { - private final ApiTracer tracer; - private final ResponseObserver innerObserver; - private AtomicBoolean wasCancelled; - - TracedResponseObserver( - @Nonnull ApiTracer tracer, @Nonnull ResponseObserver innerObserver) { - this(tracer, innerObserver, new AtomicBoolean()); - } - - TracedResponseObserver( - @Nonnull ApiTracer tracer, - @Nonnull ResponseObserver innerObserver, - @Nonnull AtomicBoolean wasCancelled) { - this.tracer = Preconditions.checkNotNull(tracer, "tracer"); - this.innerObserver = Preconditions.checkNotNull(innerObserver, "innerObserver"); - this.wasCancelled = Preconditions.checkNotNull(wasCancelled, "wasCancelled"); - } - - @Override - public void onStart(final StreamController controller) { - innerObserver.onStart( - new StreamController() { - @Override - public void cancel() { - wasCancelled.set(true); - controller.cancel(); - } - - @Override - public void disableAutoInboundFlowControl() { - controller.disableAutoInboundFlowControl(); - } - - @Override - public void request(int count) { - controller.request(count); - } - }); - } - - @Override - public void onResponse(ResponseT response) { - tracer.responseReceived(); - innerObserver.onResponse(response); - } - - @Override - public void onError(Throwable t) { - // Only mark explicit user cancellations. Since the retry logic can also throw - // CancellationException, we can't simply check that t is an instance of a - // CancellationException. - if (wasCancelled.get()) { - tracer.operationCancelled(); - } else { - tracer.operationFailed(t); - } - innerObserver.onError(t); - } - - @Override - public void onComplete() { - tracer.operationSucceeded(); - innerObserver.onComplete(); - } -} diff --git a/gax/src/main/java/com/google/api/gax/tracing/TracedServerStreamingCallable.java b/gax/src/main/java/com/google/api/gax/tracing/TracedServerStreamingCallable.java deleted file mode 100644 index e46520e61..000000000 --- a/gax/src/main/java/com/google/api/gax/tracing/TracedServerStreamingCallable.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.tracing; - -import com.google.api.core.BetaApi; -import com.google.api.core.InternalApi; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.ResponseObserver; -import com.google.api.gax.rpc.ServerStreamingCallable; -import com.google.api.gax.tracing.ApiTracerFactory.OperationType; -import com.google.common.base.Preconditions; -import javax.annotation.Nonnull; - -/** - * A wrapper callable that will wrap a callable chain in a trace. - * - *

For internal use only. - */ -@BetaApi("The surface for tracing is not stable and might change in the future") -@InternalApi("For internal use by google-cloud-java clients only") -public final class TracedServerStreamingCallable - extends ServerStreamingCallable { - - @Nonnull private final ApiTracerFactory tracerFactory; - @Nonnull private final SpanName spanName; - @Nonnull private final ServerStreamingCallable innerCallable; - - public TracedServerStreamingCallable( - @Nonnull ServerStreamingCallable innerCallable, - @Nonnull ApiTracerFactory tracerFactory, - @Nonnull SpanName spanName) { - this.tracerFactory = Preconditions.checkNotNull(tracerFactory, "tracerFactory can't be null"); - this.spanName = Preconditions.checkNotNull(spanName, "spanName can't be null"); - this.innerCallable = Preconditions.checkNotNull(innerCallable, "innerCallable can't be null"); - } - - @Override - public void call( - RequestT request, ResponseObserver responseObserver, ApiCallContext context) { - - ApiTracer tracer = - tracerFactory.newTracer(context.getTracer(), spanName, OperationType.ServerStreaming); - TracedResponseObserver tracedObserver = - new TracedResponseObserver<>(tracer, responseObserver); - - context = context.withTracer(tracer); - - try { - innerCallable.call(request, tracedObserver, context); - } catch (RuntimeException e) { - tracedObserver.onError(e); - throw e; - } - } -} diff --git a/gax/src/main/java/com/google/api/gax/tracing/TracedUnaryCallable.java b/gax/src/main/java/com/google/api/gax/tracing/TracedUnaryCallable.java deleted file mode 100644 index b7d628dcf..000000000 --- a/gax/src/main/java/com/google/api/gax/tracing/TracedUnaryCallable.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.tracing; - -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.api.core.BetaApi; -import com.google.api.core.InternalApi; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.api.gax.tracing.ApiTracerFactory.OperationType; -import com.google.common.util.concurrent.MoreExecutors; - -/** - * This callable wraps a callable chain in a {@link ApiTracer}. - * - *

For internal use only. - */ -@BetaApi("The surface for tracing is not stable and might change in the future") -@InternalApi("For internal use by google-cloud-java clients only") -public class TracedUnaryCallable extends UnaryCallable { - private final UnaryCallable innerCallable; - private final ApiTracerFactory tracerFactory; - private final SpanName spanName; - - public TracedUnaryCallable( - UnaryCallable innerCallable, - ApiTracerFactory tracerFactory, - SpanName spanName) { - this.innerCallable = innerCallable; - this.tracerFactory = tracerFactory; - this.spanName = spanName; - } - - /** - * Calls the wrapped {@link UnaryCallable} within the context of a new trace. - * - * @param request the request to send. - * @param context {@link ApiCallContext} to make the call with. - */ - @Override - public ApiFuture futureCall(RequestT request, ApiCallContext context) { - ApiTracer tracer = tracerFactory.newTracer(context.getTracer(), spanName, OperationType.Unary); - TraceFinisher finisher = new TraceFinisher<>(tracer); - - try { - context = context.withTracer(tracer); - ApiFuture future = innerCallable.futureCall(request, context); - ApiFutures.addCallback(future, finisher, MoreExecutors.directExecutor()); - - return future; - } catch (RuntimeException e) { - finisher.onFailure(e); - throw e; - } - } -} diff --git a/gax/src/main/resources/META-INF/native-image/com.google.api/gax/native-image.properties b/gax/src/main/resources/META-INF/native-image/com.google.api/gax/native-image.properties deleted file mode 100644 index d411aa2e5..000000000 --- a/gax/src/main/resources/META-INF/native-image/com.google.api/gax/native-image.properties +++ /dev/null @@ -1,8 +0,0 @@ -Args = --enable-url-protocols=https,http \ ---initialize-at-build-time=org.conscrypt,\ - org.slf4j.LoggerFactory,\ - org.junit.platform.engine.TestTag \ ---initialize-at-run-time=com.google.api.client.googleapis.services.AbstractGoogleClientRequest$ApiClientVersion \ - --features=com.google.api.gax.nativeimage.OpenCensusFeature,\ - com.google.api.gax.nativeimage.GoogleJsonClientFeature \ - --add-modules=jdk.httpserver diff --git a/gax/src/main/resources/META-INF/native-image/com.google.api/gax/resource-config.json b/gax/src/main/resources/META-INF/native-image/com.google.api/gax/resource-config.json deleted file mode 100644 index bc40a95d5..000000000 --- a/gax/src/main/resources/META-INF/native-image/com.google.api/gax/resource-config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "resources":[ - {"pattern":"\\QMETA-INF/services/jdk.vm.ci.services.JVMCIServiceLocator\\E"}, - {"pattern":"\\Qdependencies.properties\\E"}, - {"pattern":"\\Qcom/google/api/client/googleapis/google-api-client.properties\\E"}, - {"pattern":"\\Qcom/google/api/client/googleapis/google.p12\\E"}, - {"pattern":"\\Qcom/google/api/client/http/google-http-client.properties\\E"}], - "bundles":[] -} diff --git a/gax/src/main/resources/dependencies.properties b/gax/src/main/resources/dependencies.properties deleted file mode 100644 index 60e15975f..000000000 --- a/gax/src/main/resources/dependencies.properties +++ /dev/null @@ -1,2 +0,0 @@ -# Used in GaxProperties to determine the version of the project -version.gax=${project.version} \ No newline at end of file diff --git a/gax/src/test/java/com/google/api/gax/batching/BatcherImplTest.java b/gax/src/test/java/com/google/api/gax/batching/BatcherImplTest.java deleted file mode 100644 index b503e28da..000000000 --- a/gax/src/test/java/com/google/api/gax/batching/BatcherImplTest.java +++ /dev/null @@ -1,956 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -import static com.google.api.gax.rpc.testing.FakeBatchableApi.SQUARER_BATCHING_DESC_V2; -import static com.google.api.gax.rpc.testing.FakeBatchableApi.callLabeledIntSquarer; -import static com.google.common.truth.Truth.assertThat; -import static com.google.common.truth.Truth.assertWithMessage; -import static org.mockito.Mockito.when; - -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.api.core.SettableApiFuture; -import com.google.api.gax.batching.BatcherImpl.BatcherReference; -import com.google.api.gax.batching.FlowController.FlowControlRuntimeException; -import com.google.api.gax.batching.FlowController.LimitExceededBehavior; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.api.gax.rpc.testing.FakeBatchableApi.LabeledIntList; -import com.google.api.gax.rpc.testing.FakeBatchableApi.LabeledIntSquarerCallable; -import com.google.api.gax.rpc.testing.FakeBatchableApi.SquarerBatchingDescriptorV2; -import com.google.common.base.Stopwatch; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Queues; -import java.util.ArrayList; -import java.util.List; -import java.util.Queue; -import java.util.concurrent.Callable; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.logging.Filter; -import java.util.logging.Level; -import java.util.logging.LogRecord; -import java.util.logging.Logger; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Test; -import org.junit.function.ThrowingRunnable; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class BatcherImplTest { - - private static final ScheduledExecutorService EXECUTOR = - Executors.newSingleThreadScheduledExecutor(); - - private Batcher underTest; - private final LabeledIntList labeledIntList = new LabeledIntList("Default"); - private final BatchingSettings batchingSettings = - BatchingSettings.newBuilder() - .setElementCountThreshold(1000L) - .setRequestByteThreshold(1000L) - .setDelayThreshold(Duration.ofSeconds(1)) - .build(); - - @After - public void tearDown() throws InterruptedException { - if (underTest != null) { - try { - // Close the batcher to avoid warnings of orphaned batchers - underTest.close(); - } catch (BatchingException ignored) { - // Some tests intentionally inject failures into mutations - } - } - } - - @AfterClass - public static void tearDownExecutor() throws InterruptedException { - EXECUTOR.shutdown(); - EXECUTOR.awaitTermination(100, TimeUnit.MILLISECONDS); - } - /** The accumulated results in the test are resolved when {@link Batcher#flush()} is called. */ - @Test - public void testResultsAreResolvedAfterFlush() throws Exception { - underTest = createDefaultBatcherImpl(batchingSettings, null); - Future result = underTest.add(4); - assertThat(result.isDone()).isFalse(); - underTest.flush(); - assertThat(result.isDone()).isTrue(); - assertThat(result.get()).isEqualTo(16); - - Future anotherResult = underTest.add(5); - assertThat(anotherResult.isDone()).isFalse(); - } - - @Test - public void testSendOutstanding() { - final AtomicInteger callableCounter = new AtomicInteger(); - - underTest = - new BatcherImpl<>( - SQUARER_BATCHING_DESC_V2, - new LabeledIntSquarerCallable() { - @Override - public ApiFuture> futureCall( - LabeledIntList request, ApiCallContext context) { - callableCounter.incrementAndGet(); - return super.futureCall(request, context); - } - }, - labeledIntList, - batchingSettings, - EXECUTOR); - - // Empty Batcher - underTest.sendOutstanding(); - assertThat(callableCounter.get()).isEqualTo(0); - - underTest.add(2); - underTest.add(3); - underTest.add(4); - underTest.sendOutstanding(); - assertThat(callableCounter.get()).isEqualTo(1); - } - - /** Element results are resolved after batch is closed. */ - @Test - public void testWhenBatcherIsClose() throws Exception { - Future result; - try (Batcher batcher = createDefaultBatcherImpl(batchingSettings, null)) { - result = batcher.add(5); - } - assertThat(result.isDone()).isTrue(); - assertThat(result.get()).isEqualTo(25); - } - - /** Validates exception when batch is called after {@link Batcher#close()}. */ - @Test - public void testNoElementAdditionAfterClose() throws Exception { - underTest = createDefaultBatcherImpl(batchingSettings, null); - underTest.close(); - Throwable addOnClosedError = null; - try { - underTest.add(1); - } catch (Exception ex) { - addOnClosedError = ex; - } - assertThat(addOnClosedError).isInstanceOf(IllegalStateException.class); - assertThat(addOnClosedError) - .hasMessageThat() - .matches("Cannot add elements on a closed batcher"); - } - - /** Validates exception when batch is called after {@link Batcher#close()}. */ - @Test - public void testNoElementAdditionAfterCloseAsync() throws Exception { - underTest = createDefaultBatcherImpl(batchingSettings, null); - underTest.add(1); - underTest.closeAsync(); - - IllegalStateException e = - Assert.assertThrows( - IllegalStateException.class, - new ThrowingRunnable() { - @Override - public void run() throws Throwable { - underTest.add(1); - } - }); - - assertThat(e).hasMessageThat().matches("Cannot add elements on a closed batcher"); - } - - @Test - public void testCloseAsyncNonblocking() throws ExecutionException, InterruptedException { - final SettableApiFuture> innerFuture = SettableApiFuture.create(); - - UnaryCallable> unaryCallable = - new UnaryCallable>() { - @Override - public ApiFuture> futureCall( - LabeledIntList request, ApiCallContext context) { - return innerFuture; - } - }; - underTest = - new BatcherImpl<>( - SQUARER_BATCHING_DESC_V2, unaryCallable, labeledIntList, batchingSettings, EXECUTOR); - - ApiFuture elementFuture = underTest.add(1); - - Stopwatch stopwatch = Stopwatch.createStarted(); - ApiFuture closeFuture = underTest.closeAsync(); - assertThat(stopwatch.elapsed(TimeUnit.MILLISECONDS)).isAtMost(100); - - assertThat(closeFuture.isDone()).isFalse(); - assertThat(elementFuture.isDone()).isFalse(); - - innerFuture.set(ImmutableList.of(1)); - closeFuture.get(); - } - - /** Verifies exception occurred at RPC is propagated to element results */ - @Test - public void testResultFailureAfterRPCFailure() throws Exception { - final Exception fakeError = new RuntimeException(); - UnaryCallable> unaryCallable = - new UnaryCallable>() { - @Override - public ApiFuture> futureCall( - LabeledIntList request, ApiCallContext context) { - return ApiFutures.immediateFailedFuture(fakeError); - } - }; - underTest = - new BatcherImpl<>( - SQUARER_BATCHING_DESC_V2, unaryCallable, labeledIntList, batchingSettings, EXECUTOR); - Future failedResult = underTest.add(5); - underTest.add(6); - underTest.add(7); - underTest.flush(); - assertThat(failedResult.isDone()).isTrue(); - Throwable actualError = null; - try { - failedResult.get(); - } catch (InterruptedException | ExecutionException ex) { - actualError = ex; - } - assertThat(actualError).hasCauseThat().isSameInstanceAs(fakeError); - - try { - underTest.close(); - } catch (RuntimeException e) { - actualError = e; - } - - assertThat(actualError).isNotNull(); - assertThat(actualError).isInstanceOf(BatchingException.class); - assertThat(actualError) - .hasMessageThat() - .contains("1 batches failed to apply due to: 1 RuntimeException"); - } - - /** Resolves future results when {@link BatchingDescriptor#splitResponse} throws exception. */ - @Test - public void testExceptionInDescriptor() throws InterruptedException { - final RuntimeException fakeError = new RuntimeException("internal exception"); - BatchingDescriptor> descriptor = - new SquarerBatchingDescriptorV2() { - @Override - public void splitResponse( - List batchResponse, List> batch) { - throw fakeError; - } - }; - underTest = - new BatcherImpl<>( - descriptor, callLabeledIntSquarer, labeledIntList, batchingSettings, EXECUTOR); - - Future result = underTest.add(2); - underTest.flush(); - Throwable actualError = null; - try { - result.get(); - } catch (ExecutionException ex) { - actualError = ex; - } - - assertThat(actualError).hasCauseThat().isSameInstanceAs(fakeError); - try { - underTest.close(); - } catch (Exception batchingEx) { - actualError = batchingEx; - } - assertThat(actualError).isInstanceOf(BatchingException.class); - assertThat(actualError) - .hasMessageThat() - .contains( - "Batching finished with 1 batches failed to apply due to: 1 RuntimeException and 0 " - + "partial failures."); - } - - /** Resolves future results when {@link BatchingDescriptor#splitException} throws exception */ - @Test - public void testExceptionInDescriptorErrorHandling() throws InterruptedException { - final RuntimeException fakeError = new RuntimeException("internal exception"); - BatchingDescriptor> descriptor = - new SquarerBatchingDescriptorV2() { - @Override - public void splitResponse( - List batchResponse, List> batch) { - throw fakeError; - } - - @Override - public void splitException( - Throwable throwable, List> batch) { - throw fakeError; - } - }; - underTest = - new BatcherImpl<>( - descriptor, callLabeledIntSquarer, labeledIntList, batchingSettings, EXECUTOR); - - Future result = underTest.add(2); - underTest.flush(); - Throwable actualError = null; - try { - result.get(); - } catch (ExecutionException ex) { - actualError = ex; - } - - assertThat(actualError).hasCauseThat().isSameInstanceAs(fakeError); - try { - underTest.close(); - } catch (Exception ex) { - actualError = ex; - } - assertThat(actualError).isInstanceOf(BatchingException.class); - } - - @Test - public void testWhenElementCountExceeds() throws Exception { - BatchingSettings settings = batchingSettings.toBuilder().setElementCountThreshold(2L).build(); - testElementTriggers(settings); - } - - @Test - public void testWhenElementBytesExceeds() throws Exception { - BatchingSettings settings = batchingSettings.toBuilder().setRequestByteThreshold(2L).build(); - testElementTriggers(settings); - } - - @Test - public void testWhenThresholdIsDisabled() throws Exception { - BatchingSettings settings = - BatchingSettings.newBuilder() - .setElementCountThreshold(null) - .setRequestByteThreshold(null) - .setDelayThreshold(null) - .build(); - underTest = createDefaultBatcherImpl(settings, null); - Future result = underTest.add(2); - assertThat(result.isDone()).isTrue(); - assertThat(result.get()).isEqualTo(4); - } - - @Test - public void testWhenDelayThresholdExceeds() throws Exception { - BatchingSettings settings = - batchingSettings.toBuilder().setDelayThreshold(Duration.ofMillis(100)).build(); - underTest = createDefaultBatcherImpl(settings, null); - Future result = underTest.add(6); - assertThat(result.isDone()).isFalse(); - assertThat(result.get()).isEqualTo(36); - } - - /** Validates that the elements are not leaking to multiple batches */ - @Test(timeout = 500) - public void testElementsNotLeaking() throws Exception { - ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); - ScheduledExecutorService multiThreadExecutor = Executors.newScheduledThreadPool(20); - - final AtomicBoolean isDuplicateElement = new AtomicBoolean(false); - final ConcurrentMap map = new ConcurrentHashMap<>(); - final UnaryCallable> callable = - new UnaryCallable>() { - @Override - public ApiFuture> futureCall( - LabeledIntList request, ApiCallContext context) { - for (int val : request.ints) { - Boolean isPresent = map.putIfAbsent(val, Boolean.TRUE); - if (isPresent != null && isPresent) { - isDuplicateElement.set(true); - throw new AssertionError("Duplicate Element found"); - } - } - return ApiFutures.immediateFuture(request.ints); - } - }; - BatchingSettings settings = - batchingSettings.toBuilder().setDelayThreshold(Duration.ofMillis(50)).build(); - - try (final BatcherImpl> batcherTest = - new BatcherImpl<>(SQUARER_BATCHING_DESC_V2, callable, labeledIntList, settings, EXECUTOR)) { - - final Callable addElement = - new Callable() { - @Override - public Void call() throws Exception { - int counter = 0; - while (!isDuplicateElement.get() && counter < 10_000) { - batcherTest.add(counter++); - } - return null; - } - }; - final Callable sendBatch = - new Callable() { - @Override - public Void call() throws InterruptedException { - batcherTest.flush(); - return null; - } - }; - - // Started sequential element addition - Future future = singleThreadExecutor.submit(addElement); - for (int i = 0; !isDuplicateElement.get() && i < 3_000; i++) { - multiThreadExecutor.submit(sendBatch); - } - - // Closing the resources - future.get(); - assertThat(isDuplicateElement.get()).isFalse(); - singleThreadExecutor.shutdown(); - multiThreadExecutor.shutdown(); - } - } - - /** Validates ongoing runnable is cancelled once Batcher is GCed. */ - @Test - public void testPushCurrentBatchRunnable() throws Exception { - long DELAY_TIME = 50L; - BatchingSettings settings = - batchingSettings.toBuilder().setDelayThreshold(Duration.ofMillis(DELAY_TIME)).build(); - BatcherImpl> batcher = - createDefaultBatcherImpl(settings, null); - - BatcherImpl.PushCurrentBatchRunnable> - pushBatchRunnable = new BatcherImpl.PushCurrentBatchRunnable<>(batcher); - ScheduledFuture onGoingRunnable = - EXECUTOR.scheduleWithFixedDelay( - pushBatchRunnable, DELAY_TIME, DELAY_TIME, TimeUnit.MILLISECONDS); - pushBatchRunnable.setScheduledFuture(onGoingRunnable); - - boolean isExecutorCancelled = pushBatchRunnable.isCancelled(); - - // ScheduledFuture should be not isCancelled yet. - assertThat(isExecutorCancelled).isFalse(); - - // Batcher present inside runnable should be GCed after following loop. - batcher.close(); - batcher = null; - for (int retry = 0; retry < 3; retry++) { - System.gc(); - System.runFinalization(); - isExecutorCancelled = pushBatchRunnable.isCancelled(); - if (isExecutorCancelled) { - break; - } - Thread.sleep(DELAY_TIME * (1L << retry)); - } - // ScheduledFuture should be isCancelled now. - assertThat(pushBatchRunnable.isCancelled()).isTrue(); - } - - @Test - public void testEmptyBatchesAreNeverSent() throws Exception { - UnaryCallable> callable = - new UnaryCallable>() { - @Override - public ApiFuture> futureCall( - LabeledIntList request, ApiCallContext context) { - throw new AssertionError("Should not call"); - } - }; - underTest = - new BatcherImpl<>( - SQUARER_BATCHING_DESC_V2, callable, labeledIntList, batchingSettings, EXECUTOR); - underTest.flush(); - } - - /** To confirm the partial failures in Batching does not mark whole batch failed */ - @Test - public void testPartialFailureWithSplitResponse() throws Exception { - SquarerBatchingDescriptorV2 descriptor = - new SquarerBatchingDescriptorV2() { - @Override - public void splitResponse( - List batchResponse, List> batch) { - for (int i = 0; i < batchResponse.size(); i++) { - if (batchResponse.get(i) > 10_000) { - batch.get(i).getResultFuture().setException(new ArithmeticException()); - } else { - batch.get(i).getResultFuture().set(batchResponse.get(i)); - } - } - } - }; - - underTest = - new BatcherImpl<>( - descriptor, callLabeledIntSquarer, labeledIntList, batchingSettings, EXECUTOR); - underTest.add(10); - // This will cause partial failure - underTest.add(200); - underTest.flush(); - - underTest.add(40); - underTest.add(50); - underTest.flush(); - - // These will cause partial failure - underTest.add(500); - underTest.add(600); - Exception actualError = null; - try { - underTest.close(); - } catch (Exception e) { - actualError = e; - } - assertThat(actualError).isInstanceOf(BatchingException.class); - assertThat(actualError) - .hasMessageThat() - .contains( - "Batching finished with 2 partial failures. The 2 partial failures contained " - + "3 entries that failed with: 3 ArithmeticException."); - } - - @Test - public void testPartialFailureInResultProcessing() throws Exception { - final Queue queue = Queues.newArrayBlockingQueue(3); - queue.add(new NullPointerException()); - queue.add(new RuntimeException()); - queue.add(new ArithmeticException()); - - SquarerBatchingDescriptorV2 descriptor = - new SquarerBatchingDescriptorV2() { - - @Override - public void splitResponse( - List batchResponse, List> batch) { - throw queue.poll(); - } - }; - - underTest = - new BatcherImpl<>( - descriptor, callLabeledIntSquarer, labeledIntList, batchingSettings, EXECUTOR); - // This batch should fail with NullPointerException - underTest.add(10); - underTest.flush(); - - // This batch should fail with RuntimeException - underTest.add(20); - underTest.add(30); - underTest.flush(); - - // This batch should fail with ArithmeticException - underTest.add(40); - underTest.add(50); - underTest.add(60); - - Exception actualError = null; - try { - underTest.close(); - } catch (Exception e) { - actualError = e; - } - assertThat(actualError).isInstanceOf(BatchingException.class); - assertThat(actualError) - .hasMessageThat() - .contains("Batching finished with 3 batches failed to apply due to:"); - assertThat(actualError).hasMessageThat().contains("1 NullPointerException"); - assertThat(actualError).hasMessageThat().contains("1 RuntimeException"); - assertThat(actualError).hasMessageThat().contains("1 ArithmeticException"); - assertThat(actualError).hasMessageThat().contains(" and 0 partial failures."); - } - - /** - * Validates the presence of warning in case {@link BatcherImpl} is garbage collected without - * being closed first. - * - *

Note:This test cannot run concurrently with other tests that use Batchers. - */ - @Test - public void testUnclosedBatchersAreLogged() throws Exception { - final long DELAY_TIME = 30L; - int actualRemaining = 0; - for (int retry = 0; retry < 3; retry++) { - System.gc(); - System.runFinalization(); - actualRemaining = BatcherReference.cleanQueue(); - if (actualRemaining == 0) { - break; - } - Thread.sleep(DELAY_TIME * (1L << retry)); - } - assertThat(actualRemaining).isAtMost(0); - underTest = createDefaultBatcherImpl(batchingSettings, null); - Batcher extraBatcher = createDefaultBatcherImpl(batchingSettings, null); - - // Try to capture the log output but without causing terminal noise. Adding the filter must - // be done before clearing the ref or else it might be missed. - final List records = new ArrayList<>(1); - Logger batcherLogger = Logger.getLogger(BatcherImpl.class.getName()); - Filter oldFilter = batcherLogger.getFilter(); - batcherLogger.setFilter( - new Filter() { - @Override - public boolean isLoggable(LogRecord record) { - synchronized (records) { - records.add(record); - } - return false; - } - }); - - try { - // extraBatcher should not create any noise in the console as we called close() on it. - extraBatcher.close(); - extraBatcher = null; - - underTest = null; - // That *should* have been the last reference. Try to reclaim it. - boolean success = false; - for (int retry = 0; retry < 3; retry++) { - System.gc(); - System.runFinalization(); - int orphans = BatcherReference.cleanQueue(); - if (orphans == 1) { - success = true; - break; - } - // Validates that there are no other batcher instance present while GC cleanup. - assertWithMessage("unexpected extra orphans").that(orphans).isEqualTo(0); - Thread.sleep(DELAY_TIME * (1L << retry)); - } - assertWithMessage("Batcher was not garbage collected").that(success).isTrue(); - - LogRecord lr; - synchronized (records) { - assertThat(records.size()).isEqualTo(1); - lr = records.get(0); - } - assertThat(lr.getMessage()).contains("not closed properly"); - assertThat(lr.getLevel()).isEqualTo(Level.SEVERE); - } finally { - batcherLogger.setFilter(oldFilter); - } - } - - /** - * Validates the absence of warning in case {@link BatcherImpl} is garbage collected after being - * closed. - * - *

Note:This test cannot run concurrently with other tests that use Batchers. - */ - @Test - public void testClosedBatchersAreNotLogged() throws Exception { - // Clean out the existing instances - final long DELAY_TIME = 30L; - int actualRemaining = 0; - for (int retry = 0; retry < 3; retry++) { - System.gc(); - System.runFinalization(); - actualRemaining = BatcherReference.cleanQueue(); - if (actualRemaining == 0) { - break; - } - Thread.sleep(DELAY_TIME * (1L << retry)); - } - assertThat(actualRemaining).isAtMost(0); - - // Capture logs - final List records = new ArrayList<>(1); - Logger batcherLogger = Logger.getLogger(BatcherImpl.class.getName()); - Filter oldFilter = batcherLogger.getFilter(); - batcherLogger.setFilter( - new Filter() { - @Override - public boolean isLoggable(LogRecord record) { - synchronized (records) { - records.add(record); - } - return false; - } - }); - - try { - // Create a bunch of batchers that will garbage collected after being closed - for (int i = 0; i < 1_000; i++) { - BatcherImpl> batcher = - createDefaultBatcherImpl(batchingSettings, null); - batcher.add(1); - - if (i % 2 == 0) { - batcher.close(); - } else { - batcher.closeAsync(); - } - } - // Run GC a few times to give the batchers a chance to be collected - for (int retry = 0; retry < 100; retry++) { - System.gc(); - System.runFinalization(); - BatcherReference.cleanQueue(); - Thread.sleep(10); - } - - synchronized (records) { - assertThat(records).isEmpty(); - } - } finally { - // reset logging - batcherLogger.setFilter(oldFilter); - } - } - - @Test - public void testCloseRace() throws ExecutionException, InterruptedException, TimeoutException { - int iterations = 1_000_000; - ExecutorService executor = Executors.newFixedThreadPool(100); - - try { - List> closeFutures = new ArrayList<>(); - - for (int i = 0; i < iterations; i++) { - final SettableApiFuture> result = SettableApiFuture.create(); - - UnaryCallable> callable = - new UnaryCallable>() { - @Override - public ApiFuture> futureCall( - LabeledIntList request, ApiCallContext context) { - return result; - } - }; - final Batcher batcher = - new BatcherImpl<>( - SQUARER_BATCHING_DESC_V2, callable, labeledIntList, batchingSettings, EXECUTOR); - - batcher.add(1); - - executor.execute( - new Runnable() { - @Override - public void run() { - result.set(ImmutableList.of(1)); - } - }); - Future f = - executor.submit( - new Runnable() { - @Override - public void run() { - try { - batcher.close(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new RuntimeException(e); - } - } - }); - - closeFutures.add(f); - } - - // Make sure that none hang - for (Future f : closeFutures) { - try { - // Should never take this long, but padded just in case this runs on a limited machine - f.get(1, TimeUnit.MINUTES); - } catch (TimeoutException e) { - assertWithMessage("BatcherImpl.close() is deadlocked").fail(); - } - } - } finally { - executor.shutdownNow(); - } - } - - @Test - public void testConstructors() throws InterruptedException { - try (BatcherImpl batcher1 = createDefaultBatcherImpl(batchingSettings, null)) { - assertThat(batcher1.getFlowController()).isNotNull(); - assertThat(batcher1.getFlowController().getLimitExceededBehavior()) - .isEqualTo(batchingSettings.getFlowControlSettings().getLimitExceededBehavior()); - assertThat(batcher1.getFlowController().getMaxElementCountLimit()) - .isEqualTo(batchingSettings.getFlowControlSettings().getMaxOutstandingElementCount()); - assertThat(batcher1.getFlowController().getMaxRequestBytesLimit()) - .isEqualTo(batchingSettings.getFlowControlSettings().getMaxOutstandingRequestBytes()); - } - - FlowController flowController = - new FlowController( - FlowControlSettings.newBuilder() - .setLimitExceededBehavior(LimitExceededBehavior.ThrowException) - .setMaxOutstandingRequestBytes(6000L) - .build()); - try (BatcherImpl batcher2 = createDefaultBatcherImpl(batchingSettings, flowController)) { - assertThat(batcher2.getFlowController()).isSameInstanceAs(flowController); - } - } - - @Test - public void testThrottlingBlocking() throws Exception { - BatchingSettings settings = - BatchingSettings.newBuilder() - .setElementCountThreshold(1L) - .setRequestByteThreshold(1L) - .build(); - FlowController flowController = - new FlowController( - FlowControlSettings.newBuilder() - .setLimitExceededBehavior(LimitExceededBehavior.Block) - .setMaxOutstandingElementCount(1L) - .build()); - ExecutorService executor = Executors.newFixedThreadPool(2); - - ApiCallContext callContext = Mockito.mock(ApiCallContext.class); - ArgumentCaptor> key = - ArgumentCaptor.forClass(ApiCallContext.Key.class); - ArgumentCaptor value = ArgumentCaptor.forClass(Long.class); - when(callContext.withOption(key.capture(), value.capture())).thenReturn(callContext); - long throttledTime = 50; - - try (final Batcher batcher = - new BatcherImpl<>( - SQUARER_BATCHING_DESC_V2, - callLabeledIntSquarer, - labeledIntList, - settings, - EXECUTOR, - flowController, - callContext)) { - flowController.reserve(1, 1); - Future future = - executor.submit( - new Runnable() { - @Override - public void run() { - batcher.add(1); - } - }); - // Add a little delay ensuring that the next step starts after batcher.add(1) - Thread.sleep(10); - executor.submit( - () -> { - try { - Thread.sleep(throttledTime); - flowController.release(1, 1); - } catch (InterruptedException e) { - } - }); - - try { - future.get(10, TimeUnit.MILLISECONDS); - assertWithMessage("adding elements to batcher should be blocked by FlowControlled").fail(); - } catch (TimeoutException e) { - // expected - } - - try { - future.get(3, TimeUnit.SECONDS); - } catch (TimeoutException e) { - assertWithMessage("adding elements to batcher should not be blocked").fail(); - } - - // Mockito recommends using verify() as the ONLY way to interact with Argument - // captors - otherwise it may incur in unexpected behaviour - Mockito.verify(callContext).withOption(key.capture(), value.capture()); - - // Verify that throttled time is recorded in ApiCallContext - assertThat(key.getValue()).isSameInstanceAs(Batcher.THROTTLED_TIME_KEY); - assertThat(value.getValue()).isAtLeast(throttledTime); - } finally { - executor.shutdownNow(); - } - } - - @Test - public void testThrottlingNonBlocking() throws Exception { - BatchingSettings settings = - BatchingSettings.newBuilder() - .setElementCountThreshold(1L) - .setRequestByteThreshold(1L) - .build(); - FlowController flowController = - new FlowController( - FlowControlSettings.newBuilder() - .setLimitExceededBehavior(LimitExceededBehavior.ThrowException) - .setMaxOutstandingElementCount(1L) - .build()); - try (final Batcher batcher = - createDefaultBatcherImpl(settings, flowController)) { - flowController.reserve(1, 1); - try { - batcher.add(1); - assertWithMessage("Should throw exception because it exceeded FlowController limit").fail(); - } catch (FlowControlRuntimeException e) { - assertThat(e.getMessage()).contains("The maximum number of batch elements"); - } - flowController.release(1, 1); - batcher.add(1); - } - } - - private void testElementTriggers(BatchingSettings settings) throws Exception { - underTest = createDefaultBatcherImpl(settings, null); - Future result = underTest.add(4); - assertThat(result.isDone()).isFalse(); - // After this element is added, the batch triggers sendOutstanding(). - Future anotherResult = underTest.add(5); - // Both the elements should be resolved now. - assertThat(result.isDone()).isTrue(); - assertThat(result.get()).isEqualTo(16); - assertThat(anotherResult.isDone()).isTrue(); - } - - private BatcherImpl> createDefaultBatcherImpl( - BatchingSettings settings, FlowController flowController) { - return new BatcherImpl<>( - SQUARER_BATCHING_DESC_V2, - callLabeledIntSquarer, - labeledIntList, - settings, - EXECUTOR, - flowController); - } -} diff --git a/gax/src/test/java/com/google/api/gax/batching/BatcherStatsTest.java b/gax/src/test/java/com/google/api/gax/batching/BatcherStatsTest.java deleted file mode 100644 index 1a95e4d3c..000000000 --- a/gax/src/test/java/com/google/api/gax/batching/BatcherStatsTest.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.api.core.SettableApiFuture; -import com.google.api.gax.rpc.ApiExceptionFactory; -import com.google.api.gax.rpc.StatusCode; -import com.google.api.gax.rpc.testing.FakeStatusCode; -import com.google.common.collect.ImmutableList; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class BatcherStatsTest { - - @Test - public void testWhenNoException() { - BatcherStats batcherStats = new BatcherStats(); - assertThat(batcherStats.asException()).isNull(); - } - - @Test - public void testRequestFailuresOnly() { - BatcherStats batcherStats = new BatcherStats(); - - batcherStats.recordBatchFailure( - ApiExceptionFactory.createException( - new RuntimeException(), FakeStatusCode.of(StatusCode.Code.INVALID_ARGUMENT), false)); - - batcherStats.recordBatchFailure(new RuntimeException("Request failed")); - - BatchingException exception = batcherStats.asException(); - assertThat(exception).isNotNull(); - assertThat(exception).hasMessageThat().contains("2 batches failed to apply"); - assertThat(exception).hasMessageThat().contains("1 RuntimeException"); - assertThat(exception).hasMessageThat().contains("1 ApiException(1 INVALID_ARGUMENT)"); - assertThat(exception).hasMessageThat().contains("and 0 partial failures."); - } - - @Test - public void testEntryFailureOnly() { - BatcherStats batcherStats = new BatcherStats(); - - SettableApiFuture batchOneResult = SettableApiFuture.create(); - batchOneResult.setException(new IllegalStateException("local element failure")); - batcherStats.recordBatchElementsCompletion( - ImmutableList.of(BatchEntry.create(1, batchOneResult))); - - SettableApiFuture batchTwoResult = SettableApiFuture.create(); - batchTwoResult.setException( - ApiExceptionFactory.createException( - new RuntimeException(), FakeStatusCode.of(StatusCode.Code.UNAVAILABLE), false)); - batcherStats.recordBatchElementsCompletion( - ImmutableList.of(BatchEntry.create(2, batchTwoResult))); - - BatchingException ex = batcherStats.asException(); - assertThat(ex) - .hasMessageThat() - .contains("The 2 partial failures contained 2 entries that failed with:"); - assertThat(ex).hasMessageThat().contains("1 ApiException(1 UNAVAILABLE)"); - assertThat(ex).hasMessageThat().contains("1 IllegalStateException"); - } - - @Test - public void testRequestAndEntryFailures() { - BatcherStats batcherStats = new BatcherStats(); - - batcherStats.recordBatchFailure(new RuntimeException("Batch failure")); - - SettableApiFuture future = SettableApiFuture.create(); - future.setException( - ApiExceptionFactory.createException( - new RuntimeException(), FakeStatusCode.of(StatusCode.Code.ALREADY_EXISTS), false)); - - batcherStats.recordBatchElementsCompletion(ImmutableList.of(BatchEntry.create(1, future))); - - BatchingException ex = batcherStats.asException(); - assertThat(ex) - .hasMessageThat() - .contains( - "Batching finished with 1 batches failed to apply due to: 1 RuntimeException and 1 " - + "partial failures. The 1 partial failures contained 1 entries that failed with:" - + " 1 ApiException(1 ALREADY_EXISTS)."); - } -} diff --git a/gax/src/test/java/com/google/api/gax/batching/BatchingCallSettingsTest.java b/gax/src/test/java/com/google/api/gax/batching/BatchingCallSettingsTest.java deleted file mode 100644 index 51339dfa1..000000000 --- a/gax/src/test/java/com/google/api/gax/batching/BatchingCallSettingsTest.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -import static com.google.api.gax.rpc.testing.FakeBatchableApi.SQUARER_BATCHING_DESC_V2; -import static com.google.common.truth.Truth.assertThat; - -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.rpc.StatusCode; -import com.google.api.gax.rpc.testing.FakeBatchableApi.LabeledIntList; -import com.google.common.collect.ImmutableSet; -import java.util.List; -import java.util.Set; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class BatchingCallSettingsTest { - - private static final BatchingSettings BATCHING_SETTINGS = - BatchingSettings.newBuilder() - .setElementCountThreshold(10L) - .setRequestByteThreshold(20L) - .setDelayThreshold(Duration.ofMillis(5)) - .setFlowControlSettings( - FlowControlSettings.newBuilder() - .setMaxOutstandingElementCount(100L) - .setMaxOutstandingRequestBytes(100L) - .setLimitExceededBehavior(FlowController.LimitExceededBehavior.Block) - .build()) - .build(); - - @Test - public void testEmptyBuilder() { - BatchingCallSettings.Builder> builder = - BatchingCallSettings.newBuilder(SQUARER_BATCHING_DESC_V2); - assertThat(builder.getBatchingSettings()).isNull(); - assertThat(builder.getRetryableCodes()).isEmpty(); - assertThat(builder.getRetrySettings()).isNotNull(); - } - - @Test - public void testBuilder() { - BatchingCallSettings.Builder> builder = - BatchingCallSettings.newBuilder(SQUARER_BATCHING_DESC_V2); - - Set retryCodes = ImmutableSet.of(StatusCode.Code.UNAVAILABLE); - RetrySettings retrySettings = RetrySettings.newBuilder().build(); - builder - .setBatchingSettings(BATCHING_SETTINGS) - .setRetryableCodes(retryCodes) - .setRetrySettings(retrySettings); - - BatchingCallSettings settings = builder.build(); - assertThat(settings.getBatchingSettings()).isEqualTo(BATCHING_SETTINGS); - assertThat(settings.getRetryableCodes()).isEqualTo(retryCodes); - assertThat(settings.getRetrySettings()).isEqualTo(retrySettings); - } - - @Test - public void testBuilderFromSettings() { - BatchingCallSettings.Builder> builder = - BatchingCallSettings.newBuilder(SQUARER_BATCHING_DESC_V2); - RetrySettings retrySettings = - RetrySettings.newBuilder().setTotalTimeout(Duration.ofMinutes(1)).build(); - builder - .setBatchingSettings(BATCHING_SETTINGS) - .setRetryableCodes(StatusCode.Code.UNAVAILABLE, StatusCode.Code.UNAUTHENTICATED) - .setRetrySettings(retrySettings); - - BatchingCallSettings settings = builder.build(); - BatchingCallSettings.Builder newBuilder = settings.toBuilder(); - - assertThat(newBuilder.getBatchingSettings()).isEqualTo(BATCHING_SETTINGS); - assertThat(newBuilder.getRetryableCodes()) - .containsExactly(StatusCode.Code.UNAVAILABLE, StatusCode.Code.UNAUTHENTICATED); - assertThat(newBuilder.getRetrySettings()).isEqualTo(retrySettings); - } - - @Test - public void testMandatorySettings() { - Exception actualEx = null; - try { - BatchingCallSettings.newBuilder(null); - } catch (Exception ex) { - actualEx = ex; - } - assertThat(actualEx).isInstanceOf(NullPointerException.class); - actualEx = null; - try { - BatchingCallSettings.newBuilder(SQUARER_BATCHING_DESC_V2).build(); - } catch (Exception ex) { - actualEx = ex; - } - assertThat(actualEx).isInstanceOf(IllegalStateException.class); - } - - @Test - public void testToString() { - RetrySettings retrySettings = RetrySettings.newBuilder().build(); - Set retryCodes = ImmutableSet.of(StatusCode.Code.UNAUTHENTICATED); - BatchingCallSettings> batchingCallSettings = - BatchingCallSettings.newBuilder(SQUARER_BATCHING_DESC_V2) - .setRetryableCodes(retryCodes) - .setRetrySettings(retrySettings) - .setBatchingSettings(BATCHING_SETTINGS) - .build(); - - assertThat(batchingCallSettings.toString()).contains("retryableCodes=" + retryCodes); - assertThat(batchingCallSettings.toString()).contains("retrySettings=" + retrySettings); - assertThat(batchingCallSettings.toString()).contains("batchingSettings=" + BATCHING_SETTINGS); - } -} diff --git a/gax/src/test/java/com/google/api/gax/batching/DynamicFlowControlSettingsTest.java b/gax/src/test/java/com/google/api/gax/batching/DynamicFlowControlSettingsTest.java deleted file mode 100644 index afbf8ce1e..000000000 --- a/gax/src/test/java/com/google/api/gax/batching/DynamicFlowControlSettingsTest.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.fail; - -import com.google.api.gax.batching.FlowController.LimitExceededBehavior; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class DynamicFlowControlSettingsTest { - - @Test - public void testEmptyBuilder() { - DynamicFlowControlSettings.Builder builder = DynamicFlowControlSettings.newBuilder(); - DynamicFlowControlSettings settings = builder.build(); - assertNull(settings.getInitialOutstandingElementCount()); - assertNull(settings.getInitialOutstandingRequestBytes()); - assertNull(settings.getMaxOutstandingElementCount()); - assertNull(settings.getMaxOutstandingRequestBytes()); - assertNull(settings.getMinOutstandingElementCount()); - assertNull(settings.getMinOutstandingRequestBytes()); - assertEquals(LimitExceededBehavior.Block, settings.getLimitExceededBehavior()); - } - - @Test - public void testPartialSettingsIgnored() { - // If behavior is ignore, build shouldn't throw exceptions even when only one of the bytes or - // element limits is set - DynamicFlowControlSettings.Builder builder = - DynamicFlowControlSettings.newBuilder() - .setLimitExceededBehavior(LimitExceededBehavior.Ignore) - .setMaxOutstandingElementCount(1L); - builder.build(); - builder = - DynamicFlowControlSettings.newBuilder() - .setLimitExceededBehavior(LimitExceededBehavior.Ignore) - .setMinOutstandingRequestBytes(1L); - builder.build(); - } - - @Test - public void testBuilder() { - DynamicFlowControlSettings.Builder builder = - DynamicFlowControlSettings.newBuilder() - .setInitialOutstandingElementCount(5L) - .setMaxOutstandingElementCount(10L) - .setMinOutstandingElementCount(1L) - .setInitialOutstandingRequestBytes(500L) - .setMaxOutstandingRequestBytes(1000L) - .setMinOutstandingRequestBytes(100L); - DynamicFlowControlSettings settings = builder.build(); - assertThat(settings.getInitialOutstandingElementCount()).isEqualTo(5L); - assertThat(settings.getMaxOutstandingElementCount()).isEqualTo(10L); - assertThat(settings.getMinOutstandingElementCount()).isEqualTo(1L); - assertThat(settings.getInitialOutstandingRequestBytes()).isEqualTo(500L); - assertThat(settings.getMaxOutstandingRequestBytes()).isEqualTo(1000L); - assertThat(settings.getMinOutstandingRequestBytes()).isEqualTo(100L); - } - - @Test - public void testValidElementCountSettings() { - DynamicFlowControlSettings.Builder builder = - DynamicFlowControlSettings.newBuilder() - .setInitialOutstandingElementCount(5L) - .setMaxOutstandingElementCount(10L) - .setMinOutstandingElementCount(1L); - DynamicFlowControlSettings settings = builder.build(); - assertThat(settings.getInitialOutstandingElementCount()).isEqualTo(5L); - assertThat(settings.getMaxOutstandingElementCount()).isEqualTo(10L); - assertThat(settings.getMinOutstandingElementCount()).isEqualTo(1L); - } - - @Test - public void testValidRequestByteSettings() { - DynamicFlowControlSettings.Builder builder = - DynamicFlowControlSettings.newBuilder() - .setInitialOutstandingRequestBytes(500L) - .setMaxOutstandingRequestBytes(1000L) - .setMinOutstandingRequestBytes(100L); - DynamicFlowControlSettings settings = builder.build(); - assertThat(settings.getInitialOutstandingRequestBytes()).isEqualTo(500L); - assertThat(settings.getMaxOutstandingRequestBytes()).isEqualTo(1000L); - assertThat(settings.getMinOutstandingRequestBytes()).isEqualTo(100L); - } - - @Test - public void testInvalidPartialSettings() { - DynamicFlowControlSettings.Builder builder = - DynamicFlowControlSettings.newBuilder().setInitialOutstandingElementCount(1L); - try { - builder.build(); - fail("Did not throw an illegal state exception"); - } catch (IllegalStateException e) { - // Expected, ignore - } - builder = DynamicFlowControlSettings.newBuilder().setMinOutstandingRequestBytes(1L); - try { - builder.build(); - fail("Did not throw an illegal state exception"); - } catch (IllegalStateException e) { - // Expected, ignore - } - } - - @Test - public void testInvalidArguments() { - testInvalidElementCount(-1, -5, 10); - testInvalidElementCount(5, -1, 10); - testInvalidElementCount(5, 0, 10); - testInvalidElementCount(5, 6, 10); - testInvalidElementCount(5, 2, 2); - - testInvalidNumberOfBytes(-1, -5, 10); - testInvalidNumberOfBytes(5, -1, 10); - testInvalidNumberOfBytes(5, 0, 10); - testInvalidNumberOfBytes(5, 6, 10); - testInvalidNumberOfBytes(5, 2, 2); - } - - private void testInvalidElementCount(long initial, long min, long max) { - DynamicFlowControlSettings.Builder builder = - DynamicFlowControlSettings.newBuilder() - .setInitialOutstandingElementCount(initial) - .setMinOutstandingElementCount(min) - .setMaxOutstandingElementCount(max); - try { - builder.build(); - fail("Did not throw an illegal state exception"); - } catch (IllegalStateException e) { - // Expected, ignore - } - } - - private void testInvalidNumberOfBytes(long initial, long min, long max) { - DynamicFlowControlSettings.Builder builder = - DynamicFlowControlSettings.newBuilder() - .setInitialOutstandingRequestBytes(initial) - .setMinOutstandingRequestBytes(min) - .setMaxOutstandingRequestBytes(max); - try { - builder.build(); - fail("Did not throw an illegal state exception"); - } catch (IllegalStateException e) { - // Expected, ignore - } - } -} diff --git a/gax/src/test/java/com/google/api/gax/batching/FlowControlEventStatsTest.java b/gax/src/test/java/com/google/api/gax/batching/FlowControlEventStatsTest.java deleted file mode 100644 index 4dcb0c4ff..000000000 --- a/gax/src/test/java/com/google/api/gax/batching/FlowControlEventStatsTest.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.fail; - -import com.google.api.gax.batching.FlowControlEventStats.FlowControlEvent; -import com.google.api.gax.batching.FlowController.MaxOutstandingRequestBytesReachedException; -import java.util.concurrent.TimeUnit; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class FlowControlEventStatsTest { - - @Test - public void testCreateEvent() { - long timestamp = 12345, throttledTimeMs = 5000; - FlowControlEvent event = FlowControlEvent.createReserveDelayed(timestamp, throttledTimeMs); - assertEquals(event.getTimestampMs(), event.getTimestampMs()); - assertEquals(throttledTimeMs / 1000, event.getThrottledTime(TimeUnit.SECONDS).longValue()); - assertNull(event.getException()); - - MaxOutstandingRequestBytesReachedException exception = - new MaxOutstandingRequestBytesReachedException(100); - event = FlowControlEvent.createReserveDenied(timestamp, exception); - assertEquals(timestamp, event.getTimestampMs()); - assertNotNull(event.getException()); - assertEquals(exception, event.getException()); - assertNull(event.getThrottledTime(TimeUnit.MILLISECONDS)); - - try { - event = FlowControlEvent.createReserveDenied(null); - fail("FlowControlEvent did not throw exception"); - } catch (NullPointerException e) { - // expected, ignore - } - } - - @Test - public void testGetLastEvent() { - FlowControlEventStats stats = new FlowControlEventStats(); - long currentTime = System.currentTimeMillis(); - - for (int i = 1; i <= 10; i++) { - int timeElapsed = i; - stats.recordFlowControlEvent( - FlowControlEvent.createReserveDelayed(currentTime + timeElapsed, timeElapsed)); - } - - assertEquals(currentTime + 10, stats.getLastFlowControlEvent().getTimestampMs()); - assertEquals( - 10, stats.getLastFlowControlEvent().getThrottledTime(TimeUnit.MILLISECONDS).longValue()); - } -} diff --git a/gax/src/test/java/com/google/api/gax/batching/FlowControllerTest.java b/gax/src/test/java/com/google/api/gax/batching/FlowControllerTest.java deleted file mode 100644 index cb82d28db..000000000 --- a/gax/src/test/java/com/google/api/gax/batching/FlowControllerTest.java +++ /dev/null @@ -1,792 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import com.google.api.gax.batching.FlowController.FlowControlException; -import com.google.api.gax.batching.FlowController.LimitExceededBehavior; -import com.google.common.util.concurrent.SettableFuture; -import java.lang.Thread.State; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicInteger; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Tests for {@link FlowController}. */ -@RunWith(JUnit4.class) -public class FlowControllerTest { - - @Test - public void testReserveRelease_ok() throws Exception { - FlowController flowController = - new FlowController( - FlowControlSettings.newBuilder() - .setMaxOutstandingElementCount(10L) - .setMaxOutstandingRequestBytes(10L) - .setLimitExceededBehavior(LimitExceededBehavior.Block) - .build()); - - flowController.reserve(1, 1); - flowController.release(1, 1); - } - - @Test - public void testInvalidArguments() throws Exception { - FlowController flowController = - new FlowController( - FlowControlSettings.newBuilder() - .setMaxOutstandingElementCount(10L) - .setMaxOutstandingRequestBytes(10L) - .setLimitExceededBehavior(LimitExceededBehavior.Block) - .build()); - - flowController.reserve(0, 0); - try { - flowController.reserve(-1, 1); - fail("Must have thrown an illegal argument error"); - } catch (IllegalArgumentException expected) { - // Expected - } - try { - flowController.reserve(1, -1); - fail("Must have thrown an illegal argument error"); - } catch (IllegalArgumentException expected) { - // Expected - } - flowController.increaseThresholds(0, 0); - flowController.decreaseThresholds(0, 0); - try { - flowController.increaseThresholds(-1, 1); - fail("Must have thrown an illegal argument error"); - } catch (IllegalArgumentException expected) { - // Expected - } - try { - flowController.decreaseThresholds(1, -1); - fail("Must have thrown an illegal argument error"); - } catch (IllegalArgumentException expected) { - // Expected - } - } - - @Test - public void testReserveRelease_noLimits_ok() throws Exception { - FlowController flowController = - new FlowController( - FlowControlSettings.newBuilder() - .setLimitExceededBehavior(LimitExceededBehavior.Block) - .build()); - - flowController.reserve(1, 1); - flowController.release(1, 1); - } - - @Test - public void testReserveRelease_ignore_ok() throws Exception { - FlowController flowController = - new FlowController( - FlowControlSettings.newBuilder() - .setMaxOutstandingElementCount(1L) - .setMaxOutstandingRequestBytes(1L) - .setLimitExceededBehavior(LimitExceededBehavior.Ignore) - .build()); - - flowController.reserve(1, 1); - flowController.release(1, 1); - } - - @Test - public void testReserveRelease_blockedByElementCount() throws Exception { - FlowController flowController = - new FlowController( - FlowControlSettings.newBuilder() - .setMaxOutstandingElementCount(10L) - .setMaxOutstandingRequestBytes(100L) - .setLimitExceededBehavior(LimitExceededBehavior.Block) - .build()); - - testBlockingReserveRelease(flowController, 10, 10); - } - - @Test - public void testReserveRelease_blockedByElementCount_noBytesLimit() throws Exception { - FlowController flowController = - new FlowController( - FlowControlSettings.newBuilder() - .setMaxOutstandingElementCount(10L) - .setLimitExceededBehavior(LimitExceededBehavior.Block) - .build()); - - testBlockingReserveRelease(flowController, 10, 10); - } - - @Test - public void testReserveRelease_blockedByNumberOfBytes() throws Exception { - FlowController flowController = - new FlowController( - FlowControlSettings.newBuilder() - .setMaxOutstandingElementCount(100L) - .setMaxOutstandingRequestBytes(10L) - .setLimitExceededBehavior(LimitExceededBehavior.Block) - .build()); - - testBlockingReserveRelease(flowController, 10, 10); - } - - @Test - public void testReserveRelease_blockedByNumberOfBytes_noElementCountLimit() throws Exception { - FlowController flowController = - new FlowController( - FlowControlSettings.newBuilder() - .setMaxOutstandingRequestBytes(10L) - .setLimitExceededBehavior(LimitExceededBehavior.Block) - .build()); - - testBlockingReserveRelease(flowController, 10, 10); - } - - private static void testBlockingReserveRelease( - final FlowController flowController, final int maxElementCount, final int maxNumBytes) - throws Exception { - - flowController.reserve(1, 1); - - final SettableFuture permitsReserved = SettableFuture.create(); - Future finished = - Executors.newCachedThreadPool() - .submit( - new Runnable() { - @Override - public void run() { - try { - permitsReserved.set(null); - flowController.reserve(maxElementCount, maxNumBytes); - } catch (FlowController.FlowControlException e) { - throw new AssertionError(e); - } - } - }); - - permitsReserved.get(); - assertFalse(finished.isDone()); - flowController.release(1, 1); - - finished.get(50, TimeUnit.MILLISECONDS); - flowController.release(maxElementCount, maxNumBytes); - } - - @Test - public void testReserveRelease_rejectedByElementCount() throws Exception { - FlowController flowController = - new FlowController( - FlowControlSettings.newBuilder() - .setMaxOutstandingElementCount(10L) - .setMaxOutstandingRequestBytes(100L) - .setLimitExceededBehavior(LimitExceededBehavior.ThrowException) - .build()); - - testRejectedReserveRelease( - flowController, 10, 10, FlowController.MaxOutstandingElementCountReachedException.class); - assertNotNull(flowController.getFlowControlEventStats().getLastFlowControlEvent()); - assertThat(flowController.getFlowControlEventStats().getLastFlowControlEvent().getException()) - .isInstanceOf(FlowController.MaxOutstandingElementCountReachedException.class); - } - - @Test - public void testReserveRelease_rejectedByElementCount_noBytesLimit() throws Exception { - FlowController flowController = - new FlowController( - FlowControlSettings.newBuilder() - .setMaxOutstandingElementCount(10L) - .setLimitExceededBehavior(LimitExceededBehavior.ThrowException) - .build()); - - testRejectedReserveRelease( - flowController, 10, 10, FlowController.MaxOutstandingElementCountReachedException.class); - } - - @Test - public void testReserveRelease_rejectedByNumberOfBytes() throws Exception { - FlowController flowController = - new FlowController( - FlowControlSettings.newBuilder() - .setMaxOutstandingElementCount(100L) - .setMaxOutstandingRequestBytes(10L) - .setLimitExceededBehavior(LimitExceededBehavior.ThrowException) - .build()); - - testRejectedReserveRelease( - flowController, 10, 10, FlowController.MaxOutstandingRequestBytesReachedException.class); - assertNotNull(flowController.getFlowControlEventStats().getLastFlowControlEvent()); - assertThat(flowController.getFlowControlEventStats().getLastFlowControlEvent().getException()) - .isInstanceOf(FlowController.MaxOutstandingRequestBytesReachedException.class); - } - - @Test - public void testReserveRelease_rejectedByNumberOfBytes_noElementCountLimit() throws Exception { - FlowController flowController = - new FlowController( - FlowControlSettings.newBuilder() - .setMaxOutstandingRequestBytes(10L) - .setLimitExceededBehavior(LimitExceededBehavior.ThrowException) - .build()); - - testRejectedReserveRelease( - flowController, 10, 10, FlowController.MaxOutstandingRequestBytesReachedException.class); - } - - @Test - public void testRestoreAfterFail() throws FlowController.FlowControlException { - FlowController flowController = - new FlowController( - FlowControlSettings.newBuilder() - .setMaxOutstandingElementCount(2L) - .setMaxOutstandingRequestBytes(1L) - .setLimitExceededBehavior(LimitExceededBehavior.ThrowException) - .build()); - - flowController.reserve(1, 1); - - try { - flowController.reserve(1, 1); - throw new IllegalStateException("flowController should not have any bytes left"); - } catch (FlowController.MaxOutstandingRequestBytesReachedException e) { - // Ignore. - } - flowController.reserve(1, 0); - } - - @Test - public void testConstructedByDynamicFlowControlSetting() { - FlowController flowController = - new FlowController( - DynamicFlowControlSettings.newBuilder() - .setMinOutstandingElementCount(1L) - .setInitialOutstandingElementCount(2L) - .setMaxOutstandingElementCount(3L) - .setMinOutstandingRequestBytes(10L) - .setInitialOutstandingRequestBytes(20L) - .setMaxOutstandingRequestBytes(30L) - .setLimitExceededBehavior(LimitExceededBehavior.Block) - .build()); - assertEquals(1, flowController.getMinElementCountLimit().longValue()); - assertEquals(2, flowController.getCurrentElementCountLimit().longValue()); - assertEquals(3, flowController.getMaxElementCountLimit().longValue()); - assertEquals(10, flowController.getMinRequestBytesLimit().longValue()); - assertEquals(20, flowController.getCurrentRequestBytesLimit().longValue()); - assertEquals(30, flowController.getMaxRequestBytesLimit().longValue()); - - flowController = - new FlowController( - DynamicFlowControlSettings.newBuilder() - .setMinOutstandingElementCount(1L) - .setInitialOutstandingElementCount(2L) - .setMaxOutstandingElementCount(3L) - .setMinOutstandingRequestBytes(10L) - .setInitialOutstandingRequestBytes(20L) - .setMaxOutstandingRequestBytes(30L) - .setLimitExceededBehavior(LimitExceededBehavior.Ignore) - .build()); - assertNull(flowController.getMinElementCountLimit()); - assertNull(flowController.getCurrentElementCountLimit()); - assertNull(flowController.getMaxElementCountLimit()); - assertNull(flowController.getMinRequestBytesLimit()); - assertNull(flowController.getCurrentRequestBytesLimit()); - assertNull(flowController.getMaxRequestBytesLimit()); - assertNotNull(flowController.getFlowControlEventStats()); - } - - @Test - public void testIncreaseThresholds_blocking() throws Exception { - FlowController flowController = - new FlowController( - DynamicFlowControlSettings.newBuilder() - .setInitialOutstandingElementCount(10L) - .setMinOutstandingElementCount(2L) - .setMaxOutstandingElementCount(20L) - .setInitialOutstandingRequestBytes(10L) - .setMinOutstandingRequestBytes(2L) - .setMaxOutstandingRequestBytes(20L) - .setLimitExceededBehavior(LimitExceededBehavior.Block) - .build()); - - assertEquals(10L, flowController.getCurrentElementCountLimit().longValue()); - assertEquals(10L, flowController.getCurrentRequestBytesLimit().longValue()); - testBlockingReserveRelease(flowController, 10, 0); - testBlockingReserveRelease(flowController, 0, 10); - - flowController.increaseThresholds(5, 5); - assertEquals(15L, flowController.getCurrentElementCountLimit().longValue()); - assertEquals(15L, flowController.getCurrentRequestBytesLimit().longValue()); - testBlockingReserveRelease(flowController, 15, 0); - testBlockingReserveRelease(flowController, 0, 15); - - // Thresholds can't go over max values. FlowController will set the values to max. - flowController.increaseThresholds(10, 10); - assertEquals(20L, flowController.getCurrentElementCountLimit().longValue()); - assertEquals(20L, flowController.getCurrentRequestBytesLimit().longValue()); - testBlockingReserveRelease(flowController, 20, 0); - testBlockingReserveRelease(flowController, 0, 20); - } - - @Test - public void testDecreaseThresholds_blocking() throws Exception { - FlowController flowController = - new FlowController( - DynamicFlowControlSettings.newBuilder() - .setInitialOutstandingElementCount(10L) - .setMinOutstandingElementCount(2L) - .setMaxOutstandingElementCount(20L) - .setInitialOutstandingRequestBytes(10L) - .setMinOutstandingRequestBytes(2L) - .setMaxOutstandingRequestBytes(20L) - .setLimitExceededBehavior(LimitExceededBehavior.Block) - .build()); - - assertEquals(10L, flowController.getCurrentElementCountLimit().longValue()); - assertEquals(10L, flowController.getCurrentRequestBytesLimit().longValue()); - testBlockingReserveRelease(flowController, 10, 0); - testBlockingReserveRelease(flowController, 0, 10); - - flowController.decreaseThresholds(5, 5); - assertEquals(5L, flowController.getCurrentElementCountLimit().longValue()); - assertEquals(5L, flowController.getCurrentRequestBytesLimit().longValue()); - testBlockingReserveRelease(flowController, 5, 0); - testBlockingReserveRelease(flowController, 0, 5); - - // Thresholds can't go below min values. FlowController will set them to min svalues. - flowController.decreaseThresholds(5, 5); - assertEquals(2L, flowController.getCurrentElementCountLimit().longValue()); - assertEquals(2L, flowController.getCurrentRequestBytesLimit().longValue()); - testBlockingReserveRelease(flowController, 2, 0); - testBlockingReserveRelease(flowController, 0, 2); - } - - @Test - public void testIncreaseThresholds_nonBlocking() throws Exception { - FlowController flowController = - new FlowController( - DynamicFlowControlSettings.newBuilder() - .setInitialOutstandingElementCount(10L) - .setMinOutstandingElementCount(2L) - .setMaxOutstandingElementCount(20L) - .setInitialOutstandingRequestBytes(10L) - .setMinOutstandingRequestBytes(2L) - .setMaxOutstandingRequestBytes(20L) - .setLimitExceededBehavior(LimitExceededBehavior.ThrowException) - .build()); - - assertEquals(10L, flowController.getCurrentElementCountLimit().longValue()); - assertEquals(10L, flowController.getCurrentRequestBytesLimit().longValue()); - testRejectedReserveRelease( - flowController, 10, 0, FlowController.MaxOutstandingElementCountReachedException.class); - testRejectedReserveRelease( - flowController, 0, 10, FlowController.MaxOutstandingRequestBytesReachedException.class); - - flowController.increaseThresholds(5, 5); - assertEquals(15L, flowController.getCurrentElementCountLimit().longValue()); - assertEquals(15L, flowController.getCurrentRequestBytesLimit().longValue()); - testRejectedReserveRelease( - flowController, 15, 0, FlowController.MaxOutstandingElementCountReachedException.class); - testRejectedReserveRelease( - flowController, 0, 15, FlowController.MaxOutstandingRequestBytesReachedException.class); - - // Thresholds can't go over max values. FlowController will set the values to max. - flowController.increaseThresholds(10, 10); - assertEquals(20L, flowController.getCurrentElementCountLimit().longValue()); - assertEquals(20L, flowController.getCurrentRequestBytesLimit().longValue()); - testRejectedReserveRelease( - flowController, 20, 0, FlowController.MaxOutstandingElementCountReachedException.class); - testRejectedReserveRelease( - flowController, 0, 20, FlowController.MaxOutstandingRequestBytesReachedException.class); - } - - @Test - public void testDecreaseThresholds_nonBlocking() throws Exception { - FlowController flowController = - new FlowController( - DynamicFlowControlSettings.newBuilder() - .setInitialOutstandingElementCount(10L) - .setMinOutstandingElementCount(2L) - .setMaxOutstandingElementCount(20L) - .setInitialOutstandingRequestBytes(10L) - .setMinOutstandingRequestBytes(2L) - .setMaxOutstandingRequestBytes(20L) - .setLimitExceededBehavior(LimitExceededBehavior.ThrowException) - .build()); - - assertEquals(10L, flowController.getCurrentElementCountLimit().longValue()); - assertEquals(10L, flowController.getCurrentRequestBytesLimit().longValue()); - testRejectedReserveRelease( - flowController, 10, 0, FlowController.MaxOutstandingElementCountReachedException.class); - testRejectedReserveRelease( - flowController, 0, 10, FlowController.MaxOutstandingRequestBytesReachedException.class); - - flowController.decreaseThresholds(5, 5); - assertEquals(5L, flowController.getCurrentElementCountLimit().longValue()); - assertEquals(5L, flowController.getCurrentRequestBytesLimit().longValue()); - testRejectedReserveRelease( - flowController, 5, 0, FlowController.MaxOutstandingElementCountReachedException.class); - testRejectedReserveRelease( - flowController, 0, 5, FlowController.MaxOutstandingRequestBytesReachedException.class); - - // Thresholds can't go below min values. FlowController will set them to min svalues. - flowController.decreaseThresholds(5, 5); - assertEquals(2L, flowController.getCurrentElementCountLimit().longValue()); - assertEquals(2L, flowController.getCurrentRequestBytesLimit().longValue()); - testRejectedReserveRelease( - flowController, 2, 0, FlowController.MaxOutstandingElementCountReachedException.class); - testRejectedReserveRelease( - flowController, 0, 2, FlowController.MaxOutstandingRequestBytesReachedException.class); - } - - private void testRejectedReserveRelease( - FlowController flowController, - int maxElementCount, - int maxNumBytes, - Class expectedException) - throws FlowController.FlowControlException { - - flowController.reserve(1, 1); - - try { - flowController.reserve(maxElementCount, maxNumBytes); - fail("Should thrown a FlowController.FlowControlException"); - } catch (FlowController.FlowControlException e) { - assertTrue(expectedException.isInstance(e)); - } - - flowController.release(1, 1); - flowController.reserve(maxElementCount, maxNumBytes); - flowController.release(maxElementCount, maxNumBytes); - } - - @Test - public void testConcurrentUpdateThresholds_blocking() throws Exception { - int initialValue = 5000; - FlowController flowController = - new FlowController( - DynamicFlowControlSettings.newBuilder() - .setInitialOutstandingElementCount((long) initialValue) - .setMinOutstandingElementCount(1L) - .setMaxOutstandingElementCount(10000L) - .setInitialOutstandingRequestBytes((long) initialValue) - .setMinOutstandingRequestBytes(1L) - .setMaxOutstandingRequestBytes(50000L) - .setLimitExceededBehavior(LimitExceededBehavior.Block) - .build()); - final AtomicInteger totalIncreased = new AtomicInteger(0); - final AtomicInteger totalDecreased = new AtomicInteger(0); - final AtomicInteger releasedCounter = new AtomicInteger(0); - - List reserveThreads = - testConcurrentUpdates( - flowController, 100, 100, 10, totalIncreased, totalDecreased, releasedCounter); - for (Future t : reserveThreads) { - t.get(200, TimeUnit.MILLISECONDS); - } - assertEquals(reserveThreads.size(), releasedCounter.get()); - assertTrue(totalIncreased.get() > 0); - assertTrue(totalDecreased.get() > 0); - int expectedValue = initialValue + totalIncreased.get() - totalDecreased.get(); - assertEquals(expectedValue, flowController.getCurrentRequestBytesLimit().longValue()); - assertEquals(expectedValue, flowController.getCurrentElementCountLimit().longValue()); - testBlockingReserveRelease(flowController, expectedValue, 0); - testBlockingReserveRelease(flowController, 0, expectedValue); - } - - @Test - public void testConcurrentUpdateThresholds_nonBlocking() throws Exception { - int initialValue = 5000; - FlowController flowController = - new FlowController( - DynamicFlowControlSettings.newBuilder() - .setInitialOutstandingElementCount((long) initialValue) - .setMinOutstandingElementCount(1L) - .setMaxOutstandingElementCount(10000L) - .setInitialOutstandingRequestBytes((long) initialValue) - .setMinOutstandingRequestBytes(1L) - .setMaxOutstandingRequestBytes(50000L) - .setLimitExceededBehavior(LimitExceededBehavior.ThrowException) - .build()); - AtomicInteger totalIncreased = new AtomicInteger(0); - AtomicInteger totalDecreased = new AtomicInteger(0); - AtomicInteger releasedCounter = new AtomicInteger(0); - List reserveThreads = - testConcurrentUpdates( - flowController, 100, 100, 100, totalIncreased, totalDecreased, releasedCounter); - for (Future t : reserveThreads) { - t.get(200, TimeUnit.MILLISECONDS); - } - assertEquals(reserveThreads.size(), releasedCounter.get()); - assertTrue(totalIncreased.get() > 0); - assertTrue(totalDecreased.get() > 0); - int expectedValue = initialValue + totalIncreased.get() - totalDecreased.get(); - assertEquals(expectedValue, flowController.getCurrentRequestBytesLimit().longValue()); - assertEquals(expectedValue, flowController.getCurrentElementCountLimit().longValue()); - testRejectedReserveRelease( - flowController, - expectedValue, - 0, - FlowController.MaxOutstandingElementCountReachedException.class); - testRejectedReserveRelease( - flowController, - 0, - expectedValue, - FlowController.MaxOutstandingRequestBytesReachedException.class); - } - - @Test - public void testNumberOfBytesOutOfBoundaryWontDeadlock() throws Exception { - // Test the special case where in FlowController#reserve, to avoid deadlocks, it allows - // reserving byte size greater than current request bytes limit. - int initial = 50; - final FlowController flowController = - new FlowController( - DynamicFlowControlSettings.newBuilder() - .setInitialOutstandingRequestBytes((long) initial) - .setMinOutstandingRequestBytes(1L) - .setMaxOutstandingRequestBytes(100L) - .setLimitExceededBehavior(LimitExceededBehavior.Block) - .build()); - flowController.reserve(0, 10); - // will be blocked by reserve 10 - Thread t = - new Thread( - new Runnable() { - @Override - public void run() { - try { - flowController.reserve(0, 100); - } catch (FlowControlException e) { - } - } - }); - t.start(); - // wait for thread to start, and check it should be blocked - Thread.sleep(50); - assertEquals(State.WAITING, t.getState()); - // increase and decrease should not be blocked - int increase = 5, decrease = 20; - flowController.decreaseThresholds(0, decrease); - flowController.increaseThresholds(0, increase); - // releasing 10 permits should unblock t - flowController.release(0, 10); - t.join(); - int expectedNewThreshold = initial - decrease + increase; - assertEquals(expectedNewThreshold, flowController.getCurrentRequestBytesLimit().longValue()); - flowController.release(0, 100); - // Verify no extra permits are released to the semaphore - testBlockingReserveRelease(flowController, 0, expectedNewThreshold); - } - - @Test(timeout = 500) - public void testElementCountsOutOfBoundaryWontDeadlock() throws Exception { - // Test the special case where in FlowController#reserve, to avoid deadlocks, it allows - // reserving byte size greater than current request bytes limit. - final int initial = 50; - final FlowController flowController = - new FlowController( - DynamicFlowControlSettings.newBuilder() - .setInitialOutstandingElementCount((long) initial) - .setMinOutstandingElementCount(1L) - .setMaxOutstandingElementCount(100L) - .setInitialOutstandingRequestBytes((long) initial) - .setMinOutstandingRequestBytes(1L) - .setMaxOutstandingRequestBytes(100L) - .setLimitExceededBehavior(LimitExceededBehavior.Block) - .build()); - Thread t = - new Thread( - new Runnable() { - @Override - public void run() { - try { - flowController.reserve(initial + 10, 10); - } catch (FlowControlException e) { - } - } - }); - t.start(); - // wait for thread to start, and check it should be blocked - Thread.sleep(50); - assertEquals(State.WAITING, t.getState()); - // increase and decrease should not be blocked - int increase = 5, decrease = 20; - flowController.decreaseThresholds(decrease, 0); - flowController.increaseThresholds(increase, 0); - // reserve 1 permit should also not be blocked - flowController.reserve(1, 1); - flowController.release(1, 1); - // increasing permits to unblock - flowController.increaseThresholds(50, 0); - t.join(); - } - - @Test - public void testFlowControlBlockEventIsRecorded() throws Exception { - // Test when reserve is blocked for at least FlowController#RESERVE_FLOW_CONTROL_THRESHOLD_MS, - // FlowController will record the FlowControlEvent in FlowControlEventStats - final FlowController flowController = - new FlowController( - DynamicFlowControlSettings.newBuilder() - .setInitialOutstandingElementCount(5L) - .setMinOutstandingElementCount(1L) - .setMaxOutstandingElementCount(10L) - .setInitialOutstandingRequestBytes(5L) - .setMinOutstandingRequestBytes(1L) - .setMaxOutstandingRequestBytes(10L) - .setLimitExceededBehavior(LimitExceededBehavior.Block) - .build()); - Runnable runnable = - new Runnable() { - @Override - public void run() { - try { - flowController.reserve(1, 1); - } catch (FlowController.FlowControlException e) { - throw new AssertionError(e); - } - } - }; - // blocked by element. Reserve all 5 elements first, reserve in the runnable will be blocked - flowController.reserve(5, 1); - Future finished1 = Executors.newSingleThreadExecutor().submit(runnable); - try { - finished1.get(50, TimeUnit.MILLISECONDS); - fail("reserve should block"); - } catch (TimeoutException e) { - // expected - } - assertFalse(finished1.isDone()); - flowController.release(5, 1); - // After other elements are released, reserve in the runnable should go through. Since reserve - // was blocked for longer than 1 millisecond, FlowController should record this event in - // FlowControlEventStats. - finished1.get(50, TimeUnit.MILLISECONDS); - assertNotNull(flowController.getFlowControlEventStats().getLastFlowControlEvent()); - assertNotNull( - flowController - .getFlowControlEventStats() - .getLastFlowControlEvent() - .getThrottledTime(TimeUnit.MILLISECONDS)); - flowController.release(1, 1); - - // Similar to blocked by element, test blocking by bytes. - flowController.reserve(1, 5); - Future finished2 = Executors.newSingleThreadExecutor().submit(runnable); - try { - finished2.get(50, TimeUnit.MILLISECONDS); - fail("reserve should block"); - } catch (TimeoutException e) { - // expected - } - assertFalse(finished2.isDone()); - long currentTime = System.currentTimeMillis(); - flowController.release(1, 5); - finished2.get(50, TimeUnit.MILLISECONDS); - assertNotNull(flowController.getFlowControlEventStats().getLastFlowControlEvent()); - // Make sure this newer event is recorded - assertThat(flowController.getFlowControlEventStats().getLastFlowControlEvent().getTimestampMs()) - .isAtLeast(currentTime); - } - - private List testConcurrentUpdates( - final FlowController flowController, - final int increaseStepRange, - final int decreaseStepRange, - final int reserve, - final AtomicInteger totalIncreased, - final AtomicInteger totalDecreased, - final AtomicInteger releasedCounter) - throws InterruptedException, TimeoutException, ExecutionException { - final Random random = new Random(); - Runnable increaseRunnable = - new Runnable() { - @Override - public void run() { - int increase = random.nextInt(increaseStepRange) + 1; - flowController.increaseThresholds(increase, increase); - totalIncreased.addAndGet(increase); - } - }; - Runnable decreaseRunnable = - new Runnable() { - @Override - public void run() { - int decrease = random.nextInt(decreaseStepRange) + 1; - flowController.decreaseThresholds(decrease, decrease); - totalDecreased.addAndGet(decrease); - } - }; - Runnable reserveReleaseRunnable = - new Runnable() { - @Override - public void run() { - try { - flowController.reserve(reserve, reserve); - flowController.release(reserve, reserve); - releasedCounter.incrementAndGet(); - } catch (Exception e) { - } - } - }; - List updateFuture = new ArrayList<>(); - List reserveReleaseFuture = new ArrayList<>(); - ExecutorService executors = Executors.newFixedThreadPool(10); - ExecutorService reserveExecutor = Executors.newFixedThreadPool(10); - for (int i = 0; i < 5; i++) { - updateFuture.add(executors.submit(increaseRunnable)); - updateFuture.add(executors.submit(decreaseRunnable)); - reserveReleaseFuture.add(reserveExecutor.submit(reserveReleaseRunnable)); - } - for (Future t : updateFuture) { - t.get(50, TimeUnit.MILLISECONDS); - } - executors.shutdown(); - return reserveReleaseFuture; - } -} diff --git a/gax/src/test/java/com/google/api/gax/batching/Semaphore64Test.java b/gax/src/test/java/com/google/api/gax/batching/Semaphore64Test.java deleted file mode 100644 index a0a8a89aa..000000000 --- a/gax/src/test/java/com/google/api/gax/batching/Semaphore64Test.java +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.LinkedList; -import java.util.List; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class Semaphore64Test { - @Test(expected = IllegalArgumentException.class) - public void testNegative() { - Semaphore64 semaphore = new BlockingSemaphore(1); - semaphore.acquire(-1); - } - - @Test - public void testReturning() { - Semaphore64 semaphore = new NonBlockingSemaphore(1); - assertTrue(semaphore.acquire(1)); - assertFalse(semaphore.acquire(1)); - semaphore.release(1); - assertTrue(semaphore.acquire(1)); - } - - @Test(timeout = 500) - public void testBlocking() throws InterruptedException { - final Semaphore64 semaphore = new BlockingSemaphore(1); - semaphore.acquire(1); - - Thread t = - new Thread( - new Runnable() { - @Override - public void run() { - semaphore.acquire(1); - } - }); - t.start(); - - Thread.sleep(50); - assertTrue(t.isAlive()); - - semaphore.release(1); - t.join(); - } - - @Test - public void testReducePermitLimitNonBlocking() { - final Semaphore64 semaphore = new NonBlockingSemaphore(5); - semaphore.reducePermitLimit(3); - assertFalse(semaphore.acquire(3)); - assertTrue(semaphore.acquire(2)); - assertEquals(2, semaphore.getPermitLimit()); - } - - @Test(timeout = 500) - public void testReducePermitLimitBlocking() throws InterruptedException { - final Semaphore64 semaphore = new BlockingSemaphore(2); - - semaphore.reducePermitLimit(1); - semaphore.acquire(1); - - Thread t = - new Thread( - new Runnable() { - @Override - public void run() { - semaphore.acquire(1); - } - }); - t.start(); - - Thread.sleep(50); - assertTrue(t.isAlive()); - - semaphore.release(1); - t.join(); - - assertEquals(1, semaphore.getPermitLimit()); - } - - @Test - public void testAcquirePartialNonBlocking() { - Semaphore64 semaphore = new NonBlockingSemaphore(5); - assertTrue(semaphore.acquirePartial(6)); - assertFalse(semaphore.acquire(1)); - semaphore.release(6); - assertTrue(semaphore.acquire(1)); - assertFalse(semaphore.acquirePartial(6)); - // limit should still be 5 - assertEquals(5, semaphore.getPermitLimit()); - } - - @Test(timeout = 500) - public void testAcquirePartialBlocking() throws Exception { - final Semaphore64 semaphore = new BlockingSemaphore(5); - semaphore.acquirePartial(6); - Thread t1 = - new Thread( - new Runnable() { - @Override - public void run() { - semaphore.acquire(1); - } - }); - t1.start(); - // wait for thread to start - Thread.sleep(100); - assertTrue(t1.isAlive()); - semaphore.release(6); - t1.join(); - - // now there should be 4 permits available, acquiring 6 should block - Thread t2 = - new Thread( - new Runnable() { - @Override - public void run() { - semaphore.acquirePartial(6); - } - }); - t2.start(); - // wait fo thread to start - Thread.sleep(100); - assertTrue(t2.isAlive()); - // limit should still be 5 and get limit should not block - assertEquals(5, semaphore.getPermitLimit()); - } - - @Test - public void testIncreasePermitLimitNonBlocking() { - Semaphore64 semaphore = new NonBlockingSemaphore(1); - assertFalse(semaphore.acquire(2)); - semaphore.increasePermitLimit(1); - assertTrue(semaphore.acquire(2)); - semaphore.release(2); - assertFalse(semaphore.acquire(3)); - assertEquals(2, semaphore.getPermitLimit()); - } - - @Test(timeout = 500) - public void testIncreasePermitLimitBlocking() throws Exception { - final Semaphore64 semaphore = new BlockingSemaphore(1); - semaphore.acquire(1); - Thread t = - new Thread( - new Runnable() { - @Override - public void run() { - semaphore.acquire(1); - } - }); - t.start(); - - Thread.sleep(50); - assertTrue(t.isAlive()); - - semaphore.increasePermitLimit(1); - t.join(); - semaphore.release(2); - - semaphore.acquire(2); - assertEquals(2, semaphore.getPermitLimit()); - } - - @Test(timeout = 500) - public void testReleaseWontOverflowNonBlocking() throws Exception { - final Semaphore64 semaphore = new NonBlockingSemaphore(10); - List threads = new LinkedList<>(); - for (int i = 0; i < 20; i++) { - final int id = i; - Thread t = - new Thread( - new Runnable() { - @Override - public void run() { - semaphore.acquire(5); - semaphore.release(6); - } - }); - threads.add(t); - } - for (Thread t : threads) { - t.start(); - } - for (Thread t : threads) { - t.join(); - } - // Limit should still be 10 and only 10 permits should be available - assertEquals(10, semaphore.getPermitLimit()); - assertFalse(semaphore.acquire(11)); - assertTrue(semaphore.acquire(10)); - } - - @Test(timeout = 500) - public void testReleaseWontOverflowBlocking() throws Exception { - final Semaphore64 semaphore = new BlockingSemaphore(10); - semaphore.acquire(5); - semaphore.release(6); - // Limit should still be 10 and only 10 permits should be available - assertEquals(10, semaphore.getPermitLimit()); - semaphore.acquire(10); - semaphore.release(10); - Thread t = - new Thread( - new Runnable() { - @Override - public void run() { - semaphore.acquire(11); - } - }); - t.start(); - Thread.sleep(100); - assertTrue(t.isAlive()); - } - - @Test - public void testPermitLimitUnderflowNonBlocking() { - Semaphore64 semaphore = new NonBlockingSemaphore(10); - try { - semaphore.reducePermitLimit(10); - fail("Did not throw illegal state exception"); - } catch (IllegalStateException e) { - } - assertEquals(10, semaphore.getPermitLimit()); - assertFalse(semaphore.acquire(11)); - assertTrue(semaphore.acquire(10)); - } - - @Test(timeout = 500) - public void testPermitLimitUnderflowBlocking() throws Exception { - final Semaphore64 semaphore = new BlockingSemaphore(10); - try { - semaphore.reducePermitLimit(10); - fail("Did not throw illegal state exception"); - } catch (IllegalStateException e) { - } - assertEquals(10, semaphore.getPermitLimit()); - semaphore.acquire(10); - semaphore.release(10); - Thread t = - new Thread( - new Runnable() { - @Override - public void run() { - semaphore.acquire(11); - } - }); - t.start(); - Thread.sleep(100); - assertTrue(t.isAlive()); - } -} diff --git a/gax/src/test/java/com/google/api/gax/batching/ThresholdBatcherTest.java b/gax/src/test/java/com/google/api/gax/batching/ThresholdBatcherTest.java deleted file mode 100644 index 45eaa84b7..000000000 --- a/gax/src/test/java/com/google/api/gax/batching/ThresholdBatcherTest.java +++ /dev/null @@ -1,360 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.api.core.ApiFutures; -import com.google.api.gax.batching.FlowController.FlowControlException; -import com.google.api.gax.batching.FlowController.LimitExceededBehavior; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import org.junit.Assert; -import org.junit.Test; -import org.threeten.bp.Duration; - -public class ThresholdBatcherTest { - - private static final ScheduledExecutorService EXECUTOR = new ScheduledThreadPoolExecutor(1); - - private static FlowController getDisabledFlowController() { - return new FlowController( - FlowControlSettings.newBuilder() - .setLimitExceededBehavior(LimitExceededBehavior.Ignore) - .build()); - } - - private static BatchingFlowController getDisabledBatchingFlowController() { - return new BatchingFlowController<>( - getDisabledFlowController(), - new ElementCounter() { - @Override - public long count(T t) { - return 1; - } - }, - new ElementCounter() { - @Override - public long count(T t) { - return 1; - } - }); - } - - private static TrackedFlowController trackedFlowController; - - private static BatchingFlowController getTrackedIntegerBatchingFlowController( - Long elementCount, Long byteCount, LimitExceededBehavior limitExceededBehaviour) { - trackedFlowController = - new TrackedFlowController( - FlowControlSettings.newBuilder() - .setMaxOutstandingElementCount(elementCount) - .setMaxOutstandingRequestBytes(byteCount) - .setLimitExceededBehavior(limitExceededBehaviour) - .build()); - return new BatchingFlowController<>( - trackedFlowController, - new ElementCounter() { - @Override - public long count(SimpleBatch t) { - return t.getIntegers().size(); - } - }, - new ElementCounter() { - @Override - public long count(SimpleBatch t) { - long counter = 0; - for (Integer i : t.integers) { - counter += i; - } - return counter; - } - }); - } - - private static class SimpleBatch { - - private final List integers = new ArrayList<>(); - - private static SimpleBatch fromInteger(Integer integer) { - SimpleBatch batch = new SimpleBatch(); - batch.integers.add(integer); - return batch; - } - - public void merge(SimpleBatch t) { - integers.addAll(t.integers); - } - - private List getIntegers() { - return integers; - } - } - - private static class SimpleBatchMerger implements BatchMerger { - @Override - public void merge(SimpleBatch batch, SimpleBatch newBatch) { - batch.merge(newBatch); - } - } - - private static ThresholdBatcher.Builder createSimpleBatcherBuidler( - AccumulatingBatchReceiver receiver) { - return ThresholdBatcher.newBuilder() - .setThresholds(BatchingThresholds.create(100)) - .setExecutor(EXECUTOR) - .setMaxDelay(Duration.ofMillis(10000)) - .setReceiver(receiver) - .setFlowController(ThresholdBatcherTest.getDisabledBatchingFlowController()) - .setBatchMerger(new SimpleBatchMerger()); - } - - @Test - public void testAdd() throws Exception { - AccumulatingBatchReceiver receiver = - new AccumulatingBatchReceiver<>(ApiFutures.immediateFuture(null)); - ThresholdBatcher batcher = createSimpleBatcherBuidler(receiver).build(); - batcher.add(SimpleBatch.fromInteger(14)); - assertThat(batcher.isEmpty()).isFalse(); - assertThat(receiver.getBatches()).hasSize(0); - - batcher.pushCurrentBatch().get(); - assertThat(batcher.isEmpty()).isTrue(); - assertThat(receiver.getBatches()).hasSize(1); - assertThat(receiver.getBatches().get(0).getIntegers()).isEqualTo(Arrays.asList(14)); - } - - @Test - public void testBatching() throws Exception { - AccumulatingBatchReceiver receiver = - new AccumulatingBatchReceiver<>(ApiFutures.immediateFuture(null)); - ThresholdBatcher batcher = - createSimpleBatcherBuidler(receiver) - .setThresholds(BatchingThresholds.create(2)) - .build(); - - batcher.add(SimpleBatch.fromInteger(3)); - batcher.add(SimpleBatch.fromInteger(5)); - // Give time for the executor to push the batch - Thread.sleep(100); - assertThat(receiver.getBatches()).hasSize(1); - - batcher.add(SimpleBatch.fromInteger(7)); - batcher.add(SimpleBatch.fromInteger(9)); - // Give time for the executor to push the batch - Thread.sleep(100); - assertThat(receiver.getBatches()).hasSize(2); - - batcher.add(SimpleBatch.fromInteger(11)); - - batcher.pushCurrentBatch().get(); - - List> expected = - Arrays.asList(Arrays.asList(3, 5), Arrays.asList(7, 9), Arrays.asList(11)); - List> actual = new ArrayList<>(); - for (SimpleBatch batch : receiver.getBatches()) { - actual.add(batch.getIntegers()); - } - assertThat(actual).isEqualTo(expected); - } - - @Test - public void testBatchingWithDelay() throws Exception { - AccumulatingBatchReceiver receiver = - new AccumulatingBatchReceiver<>(ApiFutures.immediateFuture(null)); - ThresholdBatcher batcher = - createSimpleBatcherBuidler(receiver).setMaxDelay(Duration.ofMillis(100)).build(); - - batcher.add(SimpleBatch.fromInteger(3)); - batcher.add(SimpleBatch.fromInteger(5)); - // Give time for the delay to trigger and push the batch - Thread.sleep(500); - assertThat(receiver.getBatches()).hasSize(1); - - batcher.add(SimpleBatch.fromInteger(11)); - - batcher.pushCurrentBatch().get(); - - List> expected = Arrays.asList(Arrays.asList(3, 5), Arrays.asList(11)); - List> actual = new ArrayList<>(); - for (SimpleBatch batch : receiver.getBatches()) { - actual.add(batch.getIntegers()); - } - assertThat(actual).isEqualTo(expected); - } - - @Test - public void testExceptionWithNullFlowController() { - try { - ThresholdBatcher.newBuilder() - .setThresholds(BatchingThresholds.create(100)) - .setExecutor(EXECUTOR) - .setMaxDelay(Duration.ofMillis(10000)) - .setReceiver( - new AccumulatingBatchReceiver(ApiFutures.immediateFuture(null))) - .setBatchMerger(new SimpleBatchMerger()) - .build(); - Assert.fail("ThresholdBatcher should have thrown an exception"); - } catch (NullPointerException expected) { - assertThat(expected).isInstanceOf(NullPointerException.class); - } - } - - @Test - public void testBatchingWithFlowControl() throws Exception { - AccumulatingBatchReceiver receiver = - new AccumulatingBatchReceiver<>(ApiFutures.immediateFuture(null)); - ThresholdBatcher batcher = - createSimpleBatcherBuidler(receiver) - .setThresholds(BatchingThresholds.create(2)) - .setFlowController( - getTrackedIntegerBatchingFlowController(2L, null, LimitExceededBehavior.Block)) - .build(); - - assertThat(trackedFlowController.getElementsReserved()).isEqualTo(0); - assertThat(trackedFlowController.getElementsReleased()).isEqualTo(0); - assertThat(trackedFlowController.getBytesReserved()).isEqualTo(0); - assertThat(trackedFlowController.getBytesReleased()).isEqualTo(0); - - batcher.add(SimpleBatch.fromInteger(3)); - batcher.add(SimpleBatch.fromInteger(5)); - batcher.add( - SimpleBatch.fromInteger(7)); // We expect to block here until the first batch is handled - assertThat(receiver.getBatches()).hasSize(1); - batcher.add(SimpleBatch.fromInteger(9)); - batcher.add( - SimpleBatch.fromInteger(11)); // We expect to block here until the second batch is handled - assertThat(receiver.getBatches()).hasSize(2); - - batcher.pushCurrentBatch().get(); - - List> expected = - Arrays.asList(Arrays.asList(3, 5), Arrays.asList(7, 9), Arrays.asList(11)); - List> actual = new ArrayList<>(); - for (SimpleBatch batch : receiver.getBatches()) { - actual.add(batch.getIntegers()); - } - assertThat(actual).isEqualTo(expected); - - assertThat(trackedFlowController.getElementsReserved()) - .isEqualTo(trackedFlowController.getElementsReleased()); - assertThat(trackedFlowController.getBytesReserved()) - .isEqualTo(trackedFlowController.getBytesReleased()); - } - - @Test - public void testBatchingFlowControlExceptionRecovery() throws Exception { - AccumulatingBatchReceiver receiver = - new AccumulatingBatchReceiver<>(ApiFutures.immediateFuture(null)); - ThresholdBatcher batcher = - createSimpleBatcherBuidler(receiver) - .setThresholds(BatchingThresholds.create(4)) - .setFlowController( - getTrackedIntegerBatchingFlowController( - 3L, null, LimitExceededBehavior.ThrowException)) - .build(); - - assertThat(trackedFlowController.getElementsReserved()).isEqualTo(0); - assertThat(trackedFlowController.getElementsReleased()).isEqualTo(0); - assertThat(trackedFlowController.getBytesReserved()).isEqualTo(0); - assertThat(trackedFlowController.getBytesReleased()).isEqualTo(0); - - batcher.add(SimpleBatch.fromInteger(3)); - batcher.add(SimpleBatch.fromInteger(5)); - batcher.add(SimpleBatch.fromInteger(7)); - try { - batcher.add(SimpleBatch.fromInteger(9)); - Assert.fail("expected exception"); - } catch (FlowControlException e) { - } - batcher.pushCurrentBatch().get(); - assertThat(receiver.getBatches()).hasSize(1); - batcher.add(SimpleBatch.fromInteger(11)); - batcher.add(SimpleBatch.fromInteger(13)); - batcher.pushCurrentBatch().get(); - - List> expected = Arrays.asList(Arrays.asList(3, 5, 7), Arrays.asList(11, 13)); - List> actual = new ArrayList<>(); - for (SimpleBatch batch : receiver.getBatches()) { - actual.add(batch.getIntegers()); - } - assertThat(actual).isEqualTo(expected); - - assertThat(trackedFlowController.getElementsReserved()) - .isEqualTo(trackedFlowController.getElementsReleased()); - assertThat(trackedFlowController.getBytesReserved()) - .isEqualTo(trackedFlowController.getBytesReleased()); - } - - @Test - public void testBatchingFailedRPC() throws Exception { - Exception ex = new IllegalStateException("does nothing, unsuccessfully"); - AccumulatingBatchReceiver receiver = - new AccumulatingBatchReceiver<>(ApiFutures.immediateFailedFuture(ex)); - ThresholdBatcher batcher = - createSimpleBatcherBuidler(receiver) - .setThresholds(BatchingThresholds.create(4)) - .setFlowController( - getTrackedIntegerBatchingFlowController( - 3L, null, LimitExceededBehavior.ThrowException)) - .build(); - - assertThat(trackedFlowController.getElementsReserved()).isEqualTo(0); - assertThat(trackedFlowController.getElementsReleased()).isEqualTo(0); - assertThat(trackedFlowController.getBytesReserved()).isEqualTo(0); - assertThat(trackedFlowController.getBytesReleased()).isEqualTo(0); - - batcher.add(SimpleBatch.fromInteger(3)); - try { - batcher.pushCurrentBatch().get(); - Assert.fail("expected exception"); - } catch (Exception e) { - assertThat(e).isInstanceOf(ExecutionException.class); - assertThat(e).hasCauseThat().isSameInstanceAs(ex); - } - assertThat(receiver.getBatches()).hasSize(1); - - List> expected = Arrays.asList(Arrays.asList(3)); - List> actual = new ArrayList<>(); - for (SimpleBatch batch : receiver.getBatches()) { - actual.add(batch.getIntegers()); - } - assertThat(actual).isEqualTo(expected); - - assertThat(trackedFlowController.getElementsReserved()) - .isEqualTo(trackedFlowController.getElementsReleased()); - assertThat(trackedFlowController.getBytesReserved()) - .isEqualTo(trackedFlowController.getBytesReleased()); - } -} diff --git a/gax/src/test/java/com/google/api/gax/batching/TrackedFlowController.java b/gax/src/test/java/com/google/api/gax/batching/TrackedFlowController.java deleted file mode 100644 index 567e6f29c..000000000 --- a/gax/src/test/java/com/google/api/gax/batching/TrackedFlowController.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.batching; - -/** - * An extension of FlowController that tracks the number of permits and calls to reserve and release - */ -public class TrackedFlowController extends FlowController { - private long elementsReserved = 0; - private long elementsReleased = 0; - private long bytesReserved = 0; - private long bytesReleased = 0; - private int callsToReserve = 0; - private int callsToRelease = 0; - - public TrackedFlowController(FlowControlSettings settings) { - super(settings); - } - - @Override - public void reserve(long elements, long bytes) throws FlowControlException { - super.reserve(elements, bytes); - this.elementsReserved += elements; - this.bytesReserved += bytes; - this.callsToReserve += 1; - } - - @Override - public void release(long elements, long bytes) { - super.release(elements, bytes); - this.elementsReleased += elements; - this.bytesReleased += bytes; - this.callsToRelease += 1; - } - - public long getElementsReserved() { - return elementsReserved; - } - - public long getElementsReleased() { - return elementsReleased; - } - - public long getBytesReserved() { - return bytesReserved; - } - - public long getBytesReleased() { - return bytesReleased; - } - - public int getCallsToReserve() { - return callsToReserve; - } - - public int getCallsToRelease() { - return callsToRelease; - } -} diff --git a/gax/src/test/java/com/google/api/gax/core/DistributionTest.java b/gax/src/test/java/com/google/api/gax/core/DistributionTest.java deleted file mode 100644 index 7e6cb8a6a..000000000 --- a/gax/src/test/java/com/google/api/gax/core/DistributionTest.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.core; - -import static com.google.common.truth.Truth.assertThat; - -import java.util.Arrays; -import java.util.Collections; -import org.junit.Test; - -public class DistributionTest { - @Test - public void testPercentile() { - // These tests come from examples in - // https://en.wikipedia.org/wiki/Percentile#The_nearest-rank_method - Distribution dist; - - dist = of(15, 20, 35, 40, 50); - assertThat(dist.getPercentile(5)).isEqualTo(15); - assertThat(dist.getPercentile(30)).isEqualTo(20); - assertThat(dist.getPercentile(40)).isEqualTo(20); - assertThat(dist.getPercentile(50)).isEqualTo(35); - assertThat(dist.getPercentile(100)).isEqualTo(50); - - dist = of(3, 6, 7, 8, 8, 10, 13, 15, 16, 20); - assertThat(dist.getPercentile(25)).isEqualTo(7); - assertThat(dist.getPercentile(50)).isEqualTo(8); - assertThat(dist.getPercentile(75)).isEqualTo(15); - assertThat(dist.getPercentile(100)).isEqualTo(20); - - dist = of(3, 6, 7, 8, 8, 9, 10, 13, 15, 16, 20); - assertThat(dist.getPercentile(25)).isEqualTo(7); - assertThat(dist.getPercentile(50)).isEqualTo(9); - assertThat(dist.getPercentile(75)).isEqualTo(15); - assertThat(dist.getPercentile(100)).isEqualTo(20); - } - - @Test(expected = IllegalArgumentException.class) - public void testZeroMaxValue() { - new Distribution(0); - } - - @Test(expected = IllegalArgumentException.class) - public void testNegativeMaxValue() { - new Distribution(-1); - } - - @Test - public void testOverflowMaxValue() { - // Record value greater than maxValue-1 is OK. We record maxValue-1 instead. - Distribution dist = new Distribution(10); - dist.record(10); - assertThat(dist.getPercentile(100)).isEqualTo(9); - } - - private Distribution of(Integer... values) { - int max = Collections.max(Arrays.asList(values)); - Distribution dist = new Distribution(max + 1); - for (int value : values) { - dist.record(value); - } - return dist; - } -} diff --git a/gax/src/test/java/com/google/api/gax/core/FakeApiClock.java b/gax/src/test/java/com/google/api/gax/core/FakeApiClock.java deleted file mode 100644 index 087fbf1ec..000000000 --- a/gax/src/test/java/com/google/api/gax/core/FakeApiClock.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.core; - -import com.google.api.core.ApiClock; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; - -public class FakeApiClock implements ApiClock { - private final AtomicLong currentNanoTime; - - public FakeApiClock(long initialNanoTime) { - currentNanoTime = new AtomicLong(initialNanoTime); - } - - @Override - public long nanoTime() { - return currentNanoTime.get(); - } - - @Override - public long millisTime() { - return TimeUnit.MILLISECONDS.convert(nanoTime(), TimeUnit.NANOSECONDS); - } - - public void incrementNanoTime(long delta) { - currentNanoTime.getAndAdd(delta); - } -} diff --git a/gax/src/test/java/com/google/api/gax/core/GaxPropertiesTest.java b/gax/src/test/java/com/google/api/gax/core/GaxPropertiesTest.java deleted file mode 100644 index 27d942e69..000000000 --- a/gax/src/test/java/com/google/api/gax/core/GaxPropertiesTest.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.core; - -import static org.graalvm.nativeimage.ImageInfo.PROPERTY_IMAGE_CODE_KEY; -import static org.graalvm.nativeimage.ImageInfo.PROPERTY_IMAGE_CODE_VALUE_RUNTIME; -import static org.junit.Assert.assertTrue; - -import java.util.regex.Pattern; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class GaxPropertiesTest { - - @Test - public void testGaxVersion() { - String gaxVersion = GaxProperties.getGaxVersion(); - assertTrue(Pattern.compile("^\\d+\\.\\d+\\.\\d+").matcher(gaxVersion).find()); - String[] versionComponents = gaxVersion.split("\\."); - // This test was added in version 1.56.0, so check that the major and minor numbers are greater - // than that. - int major = Integer.parseInt(versionComponents[0]); - int minor = Integer.parseInt(versionComponents[1]); - - assertTrue(major >= 1); - if (major == 1) { - assertTrue(minor >= 56); - } - } - - @Test - public void testGetVersion_nativeImage() { - System.setProperty(PROPERTY_IMAGE_CODE_KEY, PROPERTY_IMAGE_CODE_VALUE_RUNTIME); - String javaVersion = GaxProperties.getJavaVersion(); - assertTrue(javaVersion.endsWith("-graalvm")); - } -} diff --git a/gax/src/test/java/com/google/api/gax/core/GoogleCredentialsProviderTest.java b/gax/src/test/java/com/google/api/gax/core/GoogleCredentialsProviderTest.java deleted file mode 100644 index 9cea58f6a..000000000 --- a/gax/src/test/java/com/google/api/gax/core/GoogleCredentialsProviderTest.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.core; - -import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.assertTrue; - -import com.google.auth.Credentials; -import com.google.auth.oauth2.ServiceAccountCredentials; -import com.google.auth.oauth2.ServiceAccountJwtAccessCredentials; -import com.google.common.collect.ImmutableList; -import java.security.PrivateKey; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; - -@RunWith(JUnit4.class) -public class GoogleCredentialsProviderTest { - ServiceAccountCredentials CreateServiceAccountCredentials() { - return ServiceAccountCredentials.newBuilder() - .setClientId("fake-client-id") - .setClientEmail("fake@example.com") - .setPrivateKeyId("fake-private-key") - .setPrivateKey(Mockito.mock(PrivateKey.class)) - .build(); - } - - @Test - public void serviceAccountReplacedWithJwtTokens() throws Exception { - ServiceAccountCredentials serviceAccountCredentials = CreateServiceAccountCredentials(); - - GoogleCredentialsProvider provider = - GoogleCredentialsProvider.newBuilder() - .setScopesToApply(ImmutableList.of("scope1", "scope2")) - .setJwtEnabledScopes(ImmutableList.of("scope1")) - .setOAuth2Credentials(serviceAccountCredentials) - .build(); - - Credentials credentials = provider.getCredentials(); - assertThat(credentials).isInstanceOf(ServiceAccountJwtAccessCredentials.class); - ServiceAccountJwtAccessCredentials jwtCreds = (ServiceAccountJwtAccessCredentials) credentials; - assertThat(jwtCreds.getClientId()).isEqualTo(serviceAccountCredentials.getClientId()); - assertThat(jwtCreds.getClientEmail()).isEqualTo(serviceAccountCredentials.getClientEmail()); - assertThat(jwtCreds.getPrivateKeyId()).isEqualTo(serviceAccountCredentials.getPrivateKeyId()); - assertThat(jwtCreds.getPrivateKey()).isEqualTo(serviceAccountCredentials.getPrivateKey()); - } - - @Test - public void noJwtWithoutScopeMatch() throws Exception { - ServiceAccountCredentials serviceAccountCredentials = CreateServiceAccountCredentials(); - - GoogleCredentialsProvider provider = - GoogleCredentialsProvider.newBuilder() - .setScopesToApply(ImmutableList.of("scope1", "scope2")) - .setJwtEnabledScopes(ImmutableList.of("other")) - .setOAuth2Credentials(serviceAccountCredentials) - .build(); - - Credentials credentials = provider.getCredentials(); - assertThat(credentials).isInstanceOf(ServiceAccountCredentials.class); - - ServiceAccountCredentials serviceAccountCredentials2 = (ServiceAccountCredentials) credentials; - assertThat(serviceAccountCredentials2.getClientId()) - .isEqualTo(serviceAccountCredentials.getClientId()); - assertThat(serviceAccountCredentials2.getClientEmail()) - .isEqualTo(serviceAccountCredentials.getClientEmail()); - assertThat(serviceAccountCredentials2.getPrivateKeyId()) - .isEqualTo(serviceAccountCredentials.getPrivateKeyId()); - assertThat(serviceAccountCredentials2.getPrivateKey()) - .isEqualTo(serviceAccountCredentials.getPrivateKey()); - assertThat(serviceAccountCredentials2.getScopes()).containsExactly("scope1", "scope2"); - } - - @Test - public void useJwtAccessWithScope() throws Exception { - ServiceAccountCredentials serviceAccountCredentials = CreateServiceAccountCredentials(); - - GoogleCredentialsProvider provider = - GoogleCredentialsProvider.newBuilder() - .setScopesToApply(ImmutableList.of("scope1", "scope2")) - .setOAuth2Credentials(serviceAccountCredentials) - .setUseJwtAccessWithScope(true) - .build(); - - Credentials credentials = provider.getCredentials(); - assertThat(credentials).isInstanceOf(ServiceAccountCredentials.class); - - ServiceAccountCredentials serviceAccountCredentials2 = (ServiceAccountCredentials) credentials; - assertThat(serviceAccountCredentials2.getClientId()) - .isEqualTo(serviceAccountCredentials.getClientId()); - assertThat(serviceAccountCredentials2.getClientEmail()) - .isEqualTo(serviceAccountCredentials.getClientEmail()); - assertThat(serviceAccountCredentials2.getPrivateKeyId()) - .isEqualTo(serviceAccountCredentials.getPrivateKeyId()); - assertThat(serviceAccountCredentials2.getPrivateKey()) - .isEqualTo(serviceAccountCredentials.getPrivateKey()); - assertTrue(serviceAccountCredentials2.getUseJwtAccessWithScope()); - } -} diff --git a/gax/src/test/java/com/google/api/gax/core/RecordingScheduler.java b/gax/src/test/java/com/google/api/gax/core/RecordingScheduler.java deleted file mode 100644 index 6d8cf9119..000000000 --- a/gax/src/test/java/com/google/api/gax/core/RecordingScheduler.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.core; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.when; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import org.mockito.Mockito; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; -import org.threeten.bp.Duration; - -public abstract class RecordingScheduler implements ScheduledExecutorService { - - public abstract List getSleepDurations(); - - public abstract int getIterationsCount(); - - public static RecordingScheduler create(final FakeApiClock clock) { - RecordingScheduler mock = Mockito.mock(RecordingScheduler.class); - - // mock class fields: - final ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(1); - final List sleepDurations = new ArrayList<>(); - final AtomicInteger iterationsCount = new AtomicInteger(0); - - // mock class methods: - // ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit); - when(mock.schedule(any(Runnable.class), anyLong(), any(TimeUnit.class))) - .then( - new Answer>() { - @Override - public ScheduledFuture answer(InvocationOnMock invocation) throws Throwable { - Object[] args = invocation.getArguments(); - Runnable runnable = (Runnable) args[0]; - Long delay = (Long) args[1]; - TimeUnit unit = (TimeUnit) args[2]; - iterationsCount.incrementAndGet(); - sleepDurations.add(Duration.ofMillis(TimeUnit.MILLISECONDS.convert(delay, unit))); - clock.incrementNanoTime(TimeUnit.NANOSECONDS.convert(delay, unit)); - return executor.schedule(runnable, 0, TimeUnit.NANOSECONDS); - } - }); - - // List shutdownNow() - when(mock.shutdownNow()) - .then( - new Answer>() { - @Override - public List answer(InvocationOnMock invocation) throws Throwable { - return executor.shutdownNow(); - } - }); - - // List getSleepDurations() - when(mock.getSleepDurations()).thenReturn(sleepDurations); - - // int getIterationsCount() - when(mock.getIterationsCount()) - .then( - new Answer() { - @Override - public Integer answer(InvocationOnMock invocation) throws Throwable { - return iterationsCount.get(); - } - }); - - return mock; - } -} diff --git a/gax/src/test/java/com/google/api/gax/longrunning/OperationFuturesTest.java b/gax/src/test/java/com/google/api/gax/longrunning/OperationFuturesTest.java deleted file mode 100644 index 9b9ea96a5..000000000 --- a/gax/src/test/java/com/google/api/gax/longrunning/OperationFuturesTest.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.longrunning; - -import static com.google.common.truth.Truth.assertThat; -import static com.google.common.util.concurrent.MoreExecutors.directExecutor; -import static org.junit.Assert.fail; - -import com.google.api.core.AbstractApiFuture; -import com.google.api.core.ApiFunction; -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.api.core.SettableApiFuture; -import com.google.api.gax.retrying.RetryingFuture; -import com.google.api.gax.retrying.TimedAttemptSettings; -import com.google.api.gax.rpc.ApiException; -import com.google.api.gax.rpc.StatusCode; -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.api.gax.rpc.testing.FakeOperationSnapshot; -import com.google.api.gax.rpc.testing.FakeStatusCode; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import org.junit.Test; - -public class OperationFuturesTest { - @Test(expected = IllegalArgumentException.class) - public void testNotDone() { - OperationFutures.immediateOperationFuture( - FakeOperationSnapshot.newBuilder() - .setName("required") - .setDone(false) - .setErrorCode(FakeStatusCode.of(StatusCode.Code.OK)) - .build()); - } - - @Test - public void testCompleted() throws Exception { - OperationFuture future = - OperationFutures.immediateOperationFuture( - FakeOperationSnapshot.newBuilder() - .setName("myName") - .setDone(true) - .setResponse("theResponse") - .setMetadata(42) - .setErrorCode(FakeStatusCode.of(StatusCode.Code.OK)) - .build()); - assertThat(future.getName()).isEqualTo("myName"); - assertThat(future.get()).isEqualTo("theResponse"); - assertThat(future.getMetadata().get()).isEqualTo(42); - } - - @Test - public void testFailed() throws Exception { - OperationFuture future = - OperationFutures.immediateOperationFuture( - FakeOperationSnapshot.newBuilder() - .setName("myName") - .setDone(true) - .setMetadata(42) - .setErrorCode(FakeStatusCode.of(StatusCode.Code.INVALID_ARGUMENT)) - .build()); - assertThat(future.getName()).isEqualTo("myName"); - assertThat(future.getMetadata().get()).isEqualTo(42); - try { - future.get(); - fail(); - } catch (ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ApiException.class); - } - } - - @Test - public void testTransform() throws Exception { - // Test dependencies. - MockRetryingFuture pollingFuture = new MockRetryingFuture<>(); - SettableApiFuture initialFuture = SettableApiFuture.create(); - ApiFunction responseTransform = - new ApiFunction() { - @Override - public String apply(OperationSnapshot operationSnapshot) { - return (String) operationSnapshot.getResponse(); - } - }; - ApiFunction metadataTransform = - new ApiFunction() { - @Override - public Integer apply(OperationSnapshot operationSnapshot) { - return (int) operationSnapshot.getMetadata(); - } - }; - - pollingFuture.set( - FakeOperationSnapshot.newBuilder() - .setName("my-name") - .setDone(true) - .setErrorCode(FakeStatusCode.of(Code.OK)) - .setResponse("response") - .build()); - - // Subject of the test. - OperationFuture future = - new OperationFutureImpl<>( - pollingFuture, initialFuture, responseTransform, metadataTransform); - - // Actual test: make sure that ApiFutures can chain off the result. - ApiFuture transformedFuture = - ApiFutures.transform( - future, - new ApiFunction() { - @Override - public String apply(String s) { - return "transformed: " + s; - } - }, - directExecutor()); - - assertThat(transformedFuture.get(1, TimeUnit.SECONDS)).isEqualTo("transformed: response"); - } - - private static class MockRetryingFuture extends AbstractApiFuture - implements RetryingFuture { - public boolean set(ResponseT value) { - return super.set(value); - } - - @Override - public void setAttemptFuture(ApiFuture attemptFuture) { - throw new UnsupportedOperationException(); - } - - @Override - public Callable getCallable() { - throw new UnsupportedOperationException(); - } - - @Override - public TimedAttemptSettings getAttemptSettings() { - throw new UnsupportedOperationException(); - } - - @Override - public ApiFuture peekAttemptResult() { - throw new UnsupportedOperationException(); - } - - @Override - public ApiFuture getAttemptResult() { - throw new UnsupportedOperationException(); - } - } -} diff --git a/gax/src/test/java/com/google/api/gax/paging/PagesTest.java b/gax/src/test/java/com/google/api/gax/paging/PagesTest.java deleted file mode 100644 index 8bf7d5bfb..000000000 --- a/gax/src/test/java/com/google/api/gax/paging/PagesTest.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.paging; - -import static com.google.common.truth.Truth.assertThat; - -import org.junit.Test; - -public class PagesTest { - @Test - public void testEmpty() { - assertThat(Pages.empty().iterateAll()).isEmpty(); - } -} diff --git a/gax/src/test/java/com/google/api/gax/retrying/AbstractRetryingExecutorTest.java b/gax/src/test/java/com/google/api/gax/retrying/AbstractRetryingExecutorTest.java deleted file mode 100644 index e376a7c7a..000000000 --- a/gax/src/test/java/com/google/api/gax/retrying/AbstractRetryingExecutorTest.java +++ /dev/null @@ -1,478 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -import static com.google.api.gax.retrying.FailingCallable.FAILING_RETRY_SETTINGS; -import static com.google.api.gax.retrying.FailingCallable.FAST_RETRY_SETTINGS; -import static junit.framework.TestCase.assertFalse; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; - -import com.google.api.core.ApiFuture; -import com.google.api.core.NanoClock; -import com.google.api.gax.retrying.FailingCallable.CustomException; -import com.google.api.gax.rpc.testing.FakeCallContext; -import com.google.api.gax.tracing.ApiTracer; -import com.google.common.base.Stopwatch; -import java.util.Arrays; -import java.util.Collection; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicInteger; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameter; -import org.junit.runners.Parameterized.Parameters; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.threeten.bp.Duration; - -@RunWith(Parameterized.class) -public abstract class AbstractRetryingExecutorTest { - - @Parameters(name = "Custom retry settings: {0}") - public static Collection data() { - return Arrays.asList(new Object[][] {{false}, {true}}); - } - - @Parameter public boolean withCustomRetrySettings; - - @Rule public final MockitoRule mockitoRule = MockitoJUnit.rule(); - - @Mock protected ApiTracer tracer; - protected RetryingContext retryingContext; - - protected abstract RetryingExecutorWithContext getExecutor( - RetryAlgorithm retryAlgorithm); - - protected abstract RetryAlgorithm getAlgorithm( - RetrySettings retrySettings, int apocalypseCountDown, RuntimeException apocalypseException); - - protected void busyWaitForInitialResult(RetryingFuture future, Duration timeout) - throws TimeoutException { - Stopwatch watch = Stopwatch.createStarted(); - while (future.peekAttemptResult() == null) { - if (watch.elapsed(TimeUnit.NANOSECONDS) > timeout.toNanos()) { - throw new TimeoutException(); - } - } - } - - @Before - public void setUp() { - if (withCustomRetrySettings) { - retryingContext = - FakeCallContext.createDefault().withTracer(tracer).withRetrySettings(FAST_RETRY_SETTINGS); - } else { - retryingContext = FakeCallContext.createDefault().withTracer(tracer); - } - } - - private RetrySettings getDefaultRetrySettings() { - return withCustomRetrySettings ? FAILING_RETRY_SETTINGS : FAST_RETRY_SETTINGS; - } - - @Test - public void testSuccess() throws Exception { - FailingCallable callable = new FailingCallable(0, "request", "SUCCESS", tracer); - RetryingExecutorWithContext executor = - getExecutor(getAlgorithm(getDefaultRetrySettings(), 0, null)); - RetryingFuture future = executor.createFuture(callable, retryingContext); - future.setAttemptFuture(executor.submit(future)); - - assertFutureSuccess(future); - assertEquals(0, future.getAttemptSettings().getAttemptCount()); - - verify(tracer, times(1)).attemptStarted(eq("request"), eq(0)); - verify(tracer, times(1)).attemptSucceeded(); - verifyNoMoreInteractions(tracer); - } - - @Test - public void testSuccessWithFailures() throws Exception { - FailingCallable callable = new FailingCallable(5, "request", "SUCCESS", tracer); - RetryingExecutorWithContext executor = - getExecutor(getAlgorithm(getDefaultRetrySettings(), 0, null)); - RetryingFuture future = executor.createFuture(callable, retryingContext); - future.setAttemptFuture(executor.submit(future)); - - assertFutureSuccess(future); - assertEquals(5, future.getAttemptSettings().getAttemptCount()); - - verify(tracer, times(6)).attemptStarted(eq("request"), anyInt()); - verify(tracer, times(5)).attemptFailed(any(Throwable.class), any(Duration.class)); - verify(tracer, times(1)).attemptSucceeded(); - verifyNoMoreInteractions(tracer); - } - - @Test - public void testSuccessWithFailuresPeekGetAttempt() throws Exception { - FailingCallable callable = new FailingCallable(5, "request", "SUCCESS", tracer); - RetryingExecutorWithContext executor = - getExecutor(getAlgorithm(getDefaultRetrySettings(), 0, null)); - RetryingFuture future = executor.createFuture(callable, retryingContext); - - assertNull(future.peekAttemptResult()); - assertSame(future.peekAttemptResult(), future.peekAttemptResult()); - assertFalse(future.getAttemptResult().isDone()); - assertFalse(future.getAttemptResult().isCancelled()); - - Exception exception = null; - try { - future.get(1L, TimeUnit.MILLISECONDS); - } catch (TimeoutException e) { - exception = e; - } - assertNotNull(exception); - - future.setAttemptFuture(executor.submit(future)); - - assertFutureSuccess(future); - assertEquals(5, future.getAttemptSettings().getAttemptCount()); - } - - @Test - public void testMaxRetriesExceeded() throws Exception { - FailingCallable callable = new FailingCallable(6, "request", "FAILURE", tracer); - RetryingExecutorWithContext executor = - getExecutor(getAlgorithm(getDefaultRetrySettings(), 0, null)); - RetryingFuture future = executor.createFuture(callable, retryingContext); - future.setAttemptFuture(executor.submit(future)); - - assertFutureFail(future, CustomException.class); - assertEquals(5, future.getAttemptSettings().getAttemptCount()); - - verify(tracer, times(6)).attemptStarted(eq("request"), anyInt()); - verify(tracer, times(5)).attemptFailed(any(Throwable.class), any(Duration.class)); - verify(tracer, times(1)).attemptFailedRetriesExhausted(any(Throwable.class)); - verifyNoMoreInteractions(tracer); - } - - @Test - public void testTotalTimeoutExceeded() throws Exception { - RetrySettings retrySettings = - FAST_RETRY_SETTINGS - .toBuilder() - .setInitialRetryDelay(Duration.ofMillis(Integer.MAX_VALUE)) - .setMaxRetryDelay(Duration.ofMillis(Integer.MAX_VALUE)) - .build(); - boolean useContextRetrySettings = retryingContext.getRetrySettings() != null; - RetryingExecutorWithContext executor = - getExecutor( - getAlgorithm( - useContextRetrySettings ? getDefaultRetrySettings() : retrySettings, 0, null)); - FailingCallable callable = new FailingCallable(6, "request", "FAILURE", tracer); - RetryingContext context; - if (useContextRetrySettings) { - context = FakeCallContext.createDefault().withTracer(tracer).withRetrySettings(retrySettings); - } else { - context = FakeCallContext.createDefault().withTracer(tracer); - } - RetryingFuture future = executor.createFuture(callable, context); - future.setAttemptFuture(executor.submit(future)); - - assertFutureFail(future, CustomException.class); - assertTrue(future.getAttemptSettings().getAttemptCount() < 4); - - verify(tracer, times(1)).attemptStarted(eq("request"), anyInt()); - verify(tracer, times(1)).attemptFailedRetriesExhausted(any(Throwable.class)); - verifyNoMoreInteractions(tracer); - } - - @Test - public void testCancelOuterFutureBeforeStart() throws Exception { - FailingCallable callable = new FailingCallable(4, "request", "SUCCESS", tracer); - - RetrySettings retrySettings = - FAST_RETRY_SETTINGS - .toBuilder() - .setInitialRetryDelay(Duration.ofMillis(1_000L)) - .setMaxRetryDelay(Duration.ofMillis(1_000L)) - .setTotalTimeout(Duration.ofMillis(10_0000L)) - .build(); - RetryingExecutorWithContext executor = - getExecutor(getAlgorithm(retrySettings, 0, null)); - RetryingFuture future = executor.createFuture(callable, retryingContext); - boolean res = future.cancel(false); - - assertTrue(res); - - future.setAttemptFuture(executor.submit(future)); - - assertFutureCancel(future); - assertEquals(0, future.getAttemptSettings().getAttemptCount()); - - verifyNoMoreInteractions(tracer); - } - - @Test - public void testCancelByRetryingAlgorithm() throws Exception { - FailingCallable callable = new FailingCallable(6, "request", "FAILURE", tracer); - RetryingExecutorWithContext executor = - getExecutor(getAlgorithm(getDefaultRetrySettings(), 5, new CancellationException())); - RetryingFuture future = executor.createFuture(callable, retryingContext); - future.setAttemptFuture(executor.submit(future)); - - assertFutureCancel(future); - assertEquals(4, future.getAttemptSettings().getAttemptCount()); - - verify(tracer, times(5)).attemptStarted(eq("request"), anyInt()); - // Pre-apocalypse failures - verify(tracer, times(4)).attemptFailed(any(Throwable.class), any(Duration.class)); - // Apocalypse failure - verify(tracer, times(1)).attemptFailedRetriesExhausted(any(CancellationException.class)); - verifyNoMoreInteractions(tracer); - } - - @Test - public void testUnexpectedExceptionFromRetryAlgorithm() throws Exception { - FailingCallable callable = new FailingCallable(6, "request", "FAILURE", tracer); - RetryingExecutorWithContext executor = - getExecutor(getAlgorithm(getDefaultRetrySettings(), 5, new RuntimeException())); - RetryingFuture future = executor.createFuture(callable, retryingContext); - future.setAttemptFuture(executor.submit(future)); - - assertFutureFail(future, RuntimeException.class); - assertEquals(4, future.getAttemptSettings().getAttemptCount()); - - verify(tracer, times(5)).attemptStarted(eq("request"), anyInt()); - // Pre-apocalypse failures - verify(tracer, times(4)).attemptFailed(any(Throwable.class), any(Duration.class)); - // Apocalypse failure - verify(tracer, times(1)).attemptPermanentFailure(any(RuntimeException.class)); - verifyNoMoreInteractions(tracer); - } - - @Test - public void testPollExceptionByPollAlgorithm() throws Exception { - RetrySettings retrySettings = - FAST_RETRY_SETTINGS - .toBuilder() - .setInitialRetryDelay(Duration.ofMillis(Integer.MAX_VALUE)) - .setMaxRetryDelay(Duration.ofMillis(Integer.MAX_VALUE)) - .build(); - boolean useContextRetrySettings = retryingContext.getRetrySettings() != null; - - RetryAlgorithm retryAlgorithm = - new RetryAlgorithm<>( - new TestResultRetryAlgorithm(0, null), - new ExponentialPollAlgorithm( - useContextRetrySettings ? getDefaultRetrySettings() : retrySettings, - NanoClock.getDefaultClock())); - - RetryingExecutorWithContext executor = getExecutor(retryAlgorithm); - FailingCallable callable = new FailingCallable(6, "request", "FAILURE", tracer); - RetryingContext context; - if (useContextRetrySettings) { - context = FakeCallContext.createDefault().withTracer(tracer).withRetrySettings(retrySettings); - } else { - context = FakeCallContext.createDefault().withTracer(tracer); - } - RetryingFuture future = executor.createFuture(callable, context); - future.setAttemptFuture(executor.submit(future)); - - assertFutureFail(future, PollException.class); - assertTrue(future.getAttemptSettings().getAttemptCount() < 4); - - verify(tracer, times(1)).attemptStarted(eq("request"), anyInt()); - verify(tracer, times(1)).attemptPermanentFailure(any(PollException.class)); - verifyNoMoreInteractions(tracer); - } - - protected static class TestResultRetryAlgorithm - extends BasicResultRetryAlgorithm { - private AtomicInteger apocalypseCountDown; - private RuntimeException apocalypseException; - - TestResultRetryAlgorithm(int apocalypseCountDown, RuntimeException apocalypseException) { - this.apocalypseCountDown = - apocalypseCountDown > 0 - ? new AtomicInteger(apocalypseCountDown * 2) - : new AtomicInteger(Integer.MAX_VALUE); - this.apocalypseException = apocalypseException; - } - - @Override - public boolean shouldRetry(Throwable prevThrowable, ResponseT prevResponse) { - if (apocalypseCountDown.decrementAndGet() == 0) { - throw apocalypseException; - } - return super.shouldRetry(prevThrowable, prevResponse); - } - } - - void assertFutureSuccess(RetryingFuture future) - throws ExecutionException, InterruptedException, TimeoutException { - assertEquals("SUCCESS", future.get(3, TimeUnit.SECONDS)); - assertTrue(future.isDone()); - assertFalse(future.isCancelled()); - - assertEquals("SUCCESS", future.peekAttemptResult().get(3, TimeUnit.SECONDS)); - assertSame(future.peekAttemptResult(), future.peekAttemptResult()); - assertTrue(future.peekAttemptResult().isDone()); - assertFalse(future.peekAttemptResult().isCancelled()); - - assertEquals("SUCCESS", future.getAttemptResult().get(3, TimeUnit.SECONDS)); - assertSame(future.getAttemptResult(), future.getAttemptResult()); - assertTrue(future.getAttemptResult().isDone()); - assertFalse(future.getAttemptResult().isCancelled()); - - String res = future.get(); - ApiFuture gottentAttempt = future.getAttemptResult(); - ApiFuture peekedAttempt = future.peekAttemptResult(); - - // testing completed immutability - assertFalse(future.cancel(true)); - assertFalse(future.cancel(false)); - assertSame(gottentAttempt, future.getAttemptResult()); - assertSame(peekedAttempt, future.peekAttemptResult()); - assertSame(res, future.get()); - assertTrue(future.isDone()); - assertFalse(future.isCancelled()); - } - - void assertFutureFail(RetryingFuture future, Class exceptionClass) - throws TimeoutException, InterruptedException { - Throwable exception = null; - try { - future.get(3, TimeUnit.SECONDS); - } catch (ExecutionException e) { - exception = e.getCause(); - } - assertNotNull(exception); - assertEquals(exception.getClass(), exceptionClass); - assertTrue(future.isDone()); - assertFalse(future.isCancelled()); - - try { - future.peekAttemptResult().get(3, TimeUnit.SECONDS); - } catch (ExecutionException e) { - exception = e.getCause(); - } - assertNotNull(exception); - assertEquals(exception.getClass(), exceptionClass); - assertSame(future.peekAttemptResult(), future.peekAttemptResult()); - assertTrue(future.peekAttemptResult().isDone()); - assertFalse(future.peekAttemptResult().isCancelled()); - - try { - future.getAttemptResult().get(3, TimeUnit.SECONDS); - } catch (ExecutionException e) { - exception = e.getCause(); - } - assertNotNull(exception); - assertEquals(exception.getClass(), exceptionClass); - assertSame(future.getAttemptResult(), future.getAttemptResult()); - assertTrue(future.getAttemptResult().isDone()); - assertFalse(future.getAttemptResult().isCancelled()); - - ApiFuture gottentAttempt = future.getAttemptResult(); - ApiFuture peekedAttempt = future.peekAttemptResult(); - - // testing completed immutability - assertFalse(future.cancel(true)); - assertFalse(future.cancel(false)); - assertSame(gottentAttempt, future.getAttemptResult()); - assertSame(peekedAttempt, future.peekAttemptResult()); - try { - future.get(3, TimeUnit.SECONDS); - } catch (ExecutionException e) { - exception = e.getCause(); - } - assertNotNull(exception); - assertEquals(exception.getClass(), exceptionClass); - assertTrue(future.isDone()); - assertFalse(future.isCancelled()); - } - - void assertFutureCancel(RetryingFuture future) - throws ExecutionException, InterruptedException, TimeoutException { - Exception exception = null; - try { - future.get(3, TimeUnit.SECONDS); - } catch (CancellationException e) { - exception = e; - } - assertNotNull(exception); - assertTrue(future.isDone()); - assertTrue(future.isCancelled()); - - try { - future.getAttemptResult().get(3, TimeUnit.SECONDS); - } catch (CancellationException e) { - exception = e; - } - assertNotNull(exception); - assertSame(future.getAttemptResult(), future.getAttemptResult()); - assertTrue(future.getAttemptResult().isDone()); - assertTrue(future.getAttemptResult().isCancelled()); - try { - future.peekAttemptResult().get(3, TimeUnit.SECONDS); - } catch (CancellationException e) { - exception = e; - } - assertNotNull(exception); - assertSame(future.peekAttemptResult(), future.peekAttemptResult()); - assertTrue(future.peekAttemptResult().isDone()); - assertTrue(future.peekAttemptResult().isCancelled()); - - ApiFuture gottentAttempt = future.getAttemptResult(); - ApiFuture peekedAttempt = future.peekAttemptResult(); - - // testing completed immutability - assertFalse(future.cancel(true)); - assertFalse(future.cancel(false)); - assertSame(gottentAttempt, future.getAttemptResult()); - assertSame(peekedAttempt, future.peekAttemptResult()); - try { - future.get(3, TimeUnit.SECONDS); - } catch (CancellationException e) { - exception = e; - } - assertNotNull(exception); - assertTrue(future.isDone()); - assertTrue(future.isCancelled()); - } -} diff --git a/gax/src/test/java/com/google/api/gax/retrying/BasicRetryingFutureTest.java b/gax/src/test/java/com/google/api/gax/retrying/BasicRetryingFutureTest.java deleted file mode 100644 index c95cda7eb..000000000 --- a/gax/src/test/java/com/google/api/gax/retrying/BasicRetryingFutureTest.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -import static org.mockito.Mockito.mock; - -import com.google.api.gax.tracing.ApiTracer; -import java.lang.reflect.Field; -import java.util.concurrent.Callable; -import java.util.logging.Level; -import java.util.logging.Logger; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.ArgumentMatchers; -import org.mockito.Mockito; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class BasicRetryingFutureTest { - private Level logLevel; - - @Before - public void setUp() throws Exception { - logLevel = getLoggerInstance().getLevel(); - } - - @After - public void tearDown() throws Exception { - getLoggerInstance().setLevel(logLevel); - } - - @Test - public void testHandleAttemptDoesNotThrowNPEWhenLogLevelLowerThanFiner() throws Exception { - @SuppressWarnings("unchecked") - Callable callable = mock(Callable.class); - @SuppressWarnings("unchecked") - RetryAlgorithm retryAlgorithm = mock(RetryAlgorithm.class); - RetryingContext retryingContext = mock(RetryingContext.class); - ApiTracer tracer = mock(ApiTracer.class); - TimedAttemptSettings timedAttemptSettings = mock(TimedAttemptSettings.class); - - Mockito.when(retryingContext.getTracer()).thenReturn(tracer); - - Mockito.when(retryAlgorithm.createFirstAttempt(ArgumentMatchers.any())) - .thenReturn(timedAttemptSettings); - Mockito.when( - retryAlgorithm.createNextAttempt( - ArgumentMatchers.any(), - ArgumentMatchers.any(), - ArgumentMatchers.any(), - ArgumentMatchers.any())) - .thenReturn(timedAttemptSettings); - Mockito.when( - retryAlgorithm.shouldRetry( - ArgumentMatchers.any(), - ArgumentMatchers.any(), - ArgumentMatchers.any(), - ArgumentMatchers.any())) - .thenReturn(true); - - getLoggerInstance().setLevel(Level.FINEST); - - BasicRetryingFuture future = - new BasicRetryingFuture<>(callable, retryAlgorithm, retryingContext); - - future.handleAttempt(null, null); - - Mockito.verify(tracer) - .attemptFailed(ArgumentMatchers.any(), ArgumentMatchers.any()); - Mockito.verifyNoMoreInteractions(tracer); - } - - @Test - public void testUsesRetryingContext() throws Exception { - @SuppressWarnings("unchecked") - Callable callable = mock(Callable.class); - @SuppressWarnings("unchecked") - RetryAlgorithm retryAlgorithm = mock(RetryAlgorithm.class); - RetryingContext retryingContext = mock(RetryingContext.class); - ApiTracer tracer = mock(ApiTracer.class); - TimedAttemptSettings timedAttemptSettings = mock(TimedAttemptSettings.class); - Mockito.when(retryingContext.getTracer()).thenReturn(tracer); - - Mockito.when(retryAlgorithm.createFirstAttempt(retryingContext)) - .thenReturn(timedAttemptSettings); - Mockito.when( - retryAlgorithm.createNextAttempt( - ArgumentMatchers.eq(retryingContext), - ArgumentMatchers.any(), - ArgumentMatchers.any(), - ArgumentMatchers.any())) - .thenReturn(timedAttemptSettings); - Mockito.when( - retryAlgorithm.shouldRetry( - ArgumentMatchers.eq(retryingContext), - ArgumentMatchers.any(), - ArgumentMatchers.any(), - ArgumentMatchers.any())) - .thenReturn(true); - - BasicRetryingFuture future = - new BasicRetryingFuture<>(callable, retryAlgorithm, retryingContext); - - future.handleAttempt(null, null); - - Mockito.verify(retryAlgorithm).createFirstAttempt(retryingContext); - Mockito.verify(retryAlgorithm) - .createNextAttempt( - ArgumentMatchers.eq(retryingContext), - ArgumentMatchers.any(), - ArgumentMatchers.any(), - ArgumentMatchers.any()); - Mockito.verify(retryAlgorithm) - .shouldRetry( - ArgumentMatchers.eq(retryingContext), - ArgumentMatchers.any(), - ArgumentMatchers.any(), - ArgumentMatchers.any()); - Mockito.verifyNoMoreInteractions(retryAlgorithm); - } - - private Logger getLoggerInstance() throws NoSuchFieldException, IllegalAccessException { - Field logger = BasicRetryingFuture.class.getDeclaredField("LOG"); - logger.setAccessible(true); - - return (Logger) logger.get(BasicRetryingFuture.class); - } -} diff --git a/gax/src/test/java/com/google/api/gax/retrying/DirectRetryingExecutorTest.java b/gax/src/test/java/com/google/api/gax/retrying/DirectRetryingExecutorTest.java deleted file mode 100644 index b8a990fbb..000000000 --- a/gax/src/test/java/com/google/api/gax/retrying/DirectRetryingExecutorTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -import com.google.api.core.CurrentMillisClock; -import org.junit.runner.RunWith; -import org.mockito.junit.MockitoJUnitRunner; - -@RunWith(MockitoJUnitRunner.class) -public class DirectRetryingExecutorTest extends AbstractRetryingExecutorTest { - - @Override - protected RetryingExecutorWithContext getExecutor(RetryAlgorithm retryAlgorithm) { - return new DirectRetryingExecutor<>(retryAlgorithm); - } - - @Override - protected RetryAlgorithm getAlgorithm( - RetrySettings retrySettings, int apocalypseCountDown, RuntimeException apocalypseException) { - return new RetryAlgorithm<>( - new TestResultRetryAlgorithm(apocalypseCountDown, apocalypseException), - new ExponentialRetryAlgorithm(retrySettings, CurrentMillisClock.getDefaultClock())); - } -} diff --git a/gax/src/test/java/com/google/api/gax/retrying/ExponentialRetryAlgorithmTest.java b/gax/src/test/java/com/google/api/gax/retrying/ExponentialRetryAlgorithmTest.java deleted file mode 100644 index b81c8c95b..000000000 --- a/gax/src/test/java/com/google/api/gax/retrying/ExponentialRetryAlgorithmTest.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import com.google.api.gax.core.FakeApiClock; -import com.google.api.gax.rpc.testing.FakeCallContext; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class ExponentialRetryAlgorithmTest { - private final FakeApiClock clock = new FakeApiClock(0L); - private final RetrySettings retrySettings = - RetrySettings.newBuilder() - .setMaxAttempts(6) - .setInitialRetryDelay(Duration.ofMillis(1L)) - .setRetryDelayMultiplier(2.0) - .setMaxRetryDelay(Duration.ofMillis(8L)) - .setInitialRpcTimeout(Duration.ofMillis(1L)) - .setRpcTimeoutMultiplier(2.0) - .setMaxRpcTimeout(Duration.ofMillis(8L)) - .setTotalTimeout(Duration.ofMillis(200L)) - .build(); - private final ExponentialRetryAlgorithm algorithm = - new ExponentialRetryAlgorithm(retrySettings, clock); - private final RetrySettings retrySettingsOverride = - RetrySettings.newBuilder() - .setMaxAttempts(3) - .setInitialRetryDelay(Duration.ofMillis(2L)) - .setRetryDelayMultiplier(3.0) - .setMaxRetryDelay(Duration.ofMillis(18L)) - .setInitialRpcTimeout(Duration.ofMillis(2L)) - .setRpcTimeoutMultiplier(3.0) - .setMaxRpcTimeout(Duration.ofMillis(18L)) - .setTotalTimeout(Duration.ofMillis(300L)) - .build(); - private final RetryingContext retryingContext = - FakeCallContext.createDefault().withRetrySettings(retrySettingsOverride); - - @Test - public void testCreateFirstAttempt() { - TimedAttemptSettings attempt = algorithm.createFirstAttempt(); - - // Checking only the most core values, to not make this test too implementation specific. - assertEquals(0, attempt.getAttemptCount()); - assertEquals(0, attempt.getOverallAttemptCount()); - assertEquals(Duration.ZERO, attempt.getRetryDelay()); - assertEquals(Duration.ZERO, attempt.getRandomizedRetryDelay()); - assertEquals(Duration.ofMillis(1L), attempt.getRpcTimeout()); - assertEquals(Duration.ZERO, attempt.getRetryDelay()); - } - - @Test - public void testCreateFirstAttemptOverride() { - TimedAttemptSettings attempt = algorithm.createFirstAttempt(retryingContext); - - // Checking only the most core values, to not make this test too implementation specific. - assertEquals(0, attempt.getAttemptCount()); - assertEquals(0, attempt.getOverallAttemptCount()); - assertEquals(Duration.ZERO, attempt.getRetryDelay()); - assertEquals(Duration.ZERO, attempt.getRandomizedRetryDelay()); - assertEquals(retrySettingsOverride.getInitialRpcTimeout(), attempt.getRpcTimeout()); - assertEquals(Duration.ZERO, attempt.getRetryDelay()); - } - - @Test - public void testCreateNextAttempt() { - TimedAttemptSettings firstAttempt = algorithm.createFirstAttempt(); - TimedAttemptSettings secondAttempt = algorithm.createNextAttempt(firstAttempt); - - // Checking only the most core values, to not make this test too implementation specific. - assertEquals(1, secondAttempt.getAttemptCount()); - assertEquals(1, secondAttempt.getOverallAttemptCount()); - assertEquals(Duration.ofMillis(1L), secondAttempt.getRetryDelay()); - assertEquals(Duration.ofMillis(2L), secondAttempt.getRpcTimeout()); - - TimedAttemptSettings thirdAttempt = algorithm.createNextAttempt(secondAttempt); - assertEquals(2, thirdAttempt.getAttemptCount()); - assertEquals(Duration.ofMillis(2L), thirdAttempt.getRetryDelay()); - assertEquals(Duration.ofMillis(4L), thirdAttempt.getRpcTimeout()); - } - - @Test - public void testCreateNextAttemptOverride() { - TimedAttemptSettings firstAttempt = algorithm.createFirstAttempt(retryingContext); - TimedAttemptSettings secondAttempt = algorithm.createNextAttempt(firstAttempt); - - // Checking only the most core values, to not make this test too implementation specific. - assertEquals(1, secondAttempt.getAttemptCount()); - assertEquals(1, secondAttempt.getOverallAttemptCount()); - assertEquals(Duration.ofMillis(2L), secondAttempt.getRetryDelay()); - assertEquals(Duration.ofMillis(6L), secondAttempt.getRpcTimeout()); - - TimedAttemptSettings thirdAttempt = algorithm.createNextAttempt(secondAttempt); - assertEquals(2, thirdAttempt.getAttemptCount()); - assertEquals(Duration.ofMillis(6L), thirdAttempt.getRetryDelay()); - assertEquals(Duration.ofMillis(18L), thirdAttempt.getRpcTimeout()); - } - - @Test - public void testTruncateToTotalTimeout() { - RetrySettings timeoutSettings = - retrySettings - .toBuilder() - .setInitialRpcTimeout(Duration.ofSeconds(4L)) - .setMaxRpcTimeout(Duration.ofSeconds(4L)) - .setTotalTimeout(Duration.ofSeconds(4L)) - .build(); - ExponentialRetryAlgorithm timeoutAlg = new ExponentialRetryAlgorithm(timeoutSettings, clock); - - TimedAttemptSettings firstAttempt = timeoutAlg.createFirstAttempt(); - TimedAttemptSettings secondAttempt = timeoutAlg.createNextAttempt(firstAttempt); - assertThat(secondAttempt.getRpcTimeout()).isAtLeast(firstAttempt.getRpcTimeout()); - assertThat(secondAttempt.getRpcTimeout()).isAtMost(Duration.ofSeconds(4L)); - - TimedAttemptSettings thirdAttempt = timeoutAlg.createNextAttempt(secondAttempt); - assertThat(thirdAttempt.getRpcTimeout()).isAtMost(Duration.ofSeconds(4L)); - } - - @Test - public void testShouldRetryTrue() { - TimedAttemptSettings attempt = algorithm.createFirstAttempt(); - for (int i = 0; i < 2; i++) { - attempt = algorithm.createNextAttempt(attempt); - } - - assertTrue(algorithm.shouldRetry(attempt)); - } - - @Test - public void testShouldRetryFalseOnMaxAttempts() { - TimedAttemptSettings attempt = algorithm.createFirstAttempt(); - for (int i = 0; i < 6; i++) { - assertTrue(algorithm.shouldRetry(attempt)); - attempt = algorithm.createNextAttempt(attempt); - } - - assertFalse(algorithm.shouldRetry(attempt)); - } - - @Test - public void testShouldRetryFalseOnMaxTimeout() { - TimedAttemptSettings attempt = algorithm.createFirstAttempt(); - for (int i = 0; i < 4; i++) { - assertTrue(algorithm.shouldRetry(attempt)); - attempt = algorithm.createNextAttempt(attempt); - clock.incrementNanoTime(Duration.ofMillis(60L).toNanos()); - } - - assertFalse(algorithm.shouldRetry(attempt)); - } -} diff --git a/gax/src/test/java/com/google/api/gax/retrying/FailingCallable.java b/gax/src/test/java/com/google/api/gax/retrying/FailingCallable.java deleted file mode 100644 index 9b7524ec6..000000000 --- a/gax/src/test/java/com/google/api/gax/retrying/FailingCallable.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -import com.google.api.gax.tracing.ApiTracer; -import java.util.concurrent.Callable; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicInteger; -import org.threeten.bp.Duration; - -class FailingCallable implements Callable { - static final RetrySettings FAST_RETRY_SETTINGS = - RetrySettings.newBuilder() - .setMaxAttempts(6) - .setInitialRetryDelay(Duration.ofMillis(8L)) - .setRetryDelayMultiplier(1) - .setMaxRetryDelay(Duration.ofMillis(8L)) - .setInitialRpcTimeout(Duration.ofMillis(8L)) - .setRpcTimeoutMultiplier(1) - .setMaxRpcTimeout(Duration.ofMillis(8L)) - .setTotalTimeout(Duration.ofMillis(400L)) - .build(); - static final RetrySettings FAILING_RETRY_SETTINGS = - RetrySettings.newBuilder() - .setMaxAttempts(2) - .setInitialRetryDelay(Duration.ofNanos(1L)) - .setRetryDelayMultiplier(1) - .setMaxRetryDelay(Duration.ofNanos(1L)) - .setInitialRpcTimeout(Duration.ofNanos(1L)) - .setRpcTimeoutMultiplier(1) - .setMaxRpcTimeout(Duration.ofNanos(1L)) - .setTotalTimeout(Duration.ofNanos(1L)) - .build(); - - private AtomicInteger attemptsCount = new AtomicInteger(0); - private final ApiTracer tracer; - private final int expectedFailuresCount; - private final String request; - private final String result; - private final CountDownLatch firstAttemptFinished = new CountDownLatch(1); - - FailingCallable(int expectedFailuresCount, String request, String result, ApiTracer tracer) { - this.request = request; - this.tracer = tracer; - this.expectedFailuresCount = expectedFailuresCount; - this.result = result; - } - - CountDownLatch getFirstAttemptFinishedLatch() { - return firstAttemptFinished; - } - - @Override - public String call() throws Exception { - try { - int attemptNumber = attemptsCount.getAndIncrement(); - - tracer.attemptStarted(request, attemptNumber); - - if (attemptNumber < expectedFailuresCount) { - throw new CustomException(); - } - - return result; - } finally { - firstAttemptFinished.countDown(); - } - } - - static class CustomException extends RuntimeException { - - private static final long serialVersionUID = -1543459008653697004L; - } -} diff --git a/gax/src/test/java/com/google/api/gax/retrying/NoopRetryingContextTest.java b/gax/src/test/java/com/google/api/gax/retrying/NoopRetryingContextTest.java deleted file mode 100644 index 23a00470d..000000000 --- a/gax/src/test/java/com/google/api/gax/retrying/NoopRetryingContextTest.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; - -import com.google.api.gax.tracing.BaseApiTracer; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class NoopRetryingContextTest { - - @Test - public void testGetTracer() { - RetryingContext context = NoopRetryingContext.create(); - assertSame(BaseApiTracer.getInstance(), context.getTracer()); - } - - @Test - public void testGetRetrySettings() { - RetryingContext context = NoopRetryingContext.create(); - assertNull(context.getRetrySettings()); - } - - @Test - public void testGetRetryableCodes() { - RetryingContext context = NoopRetryingContext.create(); - assertNull(context.getRetryableCodes()); - } -} diff --git a/gax/src/test/java/com/google/api/gax/retrying/RetryAlgorithmTest.java b/gax/src/test/java/com/google/api/gax/retrying/RetryAlgorithmTest.java deleted file mode 100644 index a08cdee7f..000000000 --- a/gax/src/test/java/com/google/api/gax/retrying/RetryAlgorithmTest.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -import static org.junit.Assert.assertFalse; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@SuppressWarnings({"unchecked", "deprecation"}) -@RunWith(JUnit4.class) -public class RetryAlgorithmTest { - - @Test - public void testCreateFirstAttempt() { - TimedRetryAlgorithm timedAlgorithm = mock(TimedRetryAlgorithm.class); - RetryAlgorithm algorithm = - new RetryAlgorithm<>(mock(ResultRetryAlgorithm.class), timedAlgorithm); - - algorithm.createFirstAttempt(); - verify(timedAlgorithm).createFirstAttempt(); - } - - @Test - public void testCreateFirstAttemptWithUnusedContext() { - TimedRetryAlgorithm timedAlgorithm = mock(TimedRetryAlgorithm.class); - RetryAlgorithm algorithm = - new RetryAlgorithm<>(mock(ResultRetryAlgorithm.class), timedAlgorithm); - - RetryingContext context = mock(RetryingContext.class); - algorithm.createFirstAttempt(context); - verify(timedAlgorithm).createFirstAttempt(); - } - - @Test - public void testCreateFirstAttemptWithContext() { - TimedRetryAlgorithmWithContext timedAlgorithm = mock(TimedRetryAlgorithmWithContext.class); - RetryAlgorithm algorithm = - new RetryAlgorithm<>(mock(ResultRetryAlgorithmWithContext.class), timedAlgorithm); - - RetryingContext context = mock(RetryingContext.class); - algorithm.createFirstAttempt(context); - verify(timedAlgorithm).createFirstAttempt(context); - } - - @Test - public void testCreateFirstAttemptWithNullContext() { - TimedRetryAlgorithmWithContext timedAlgorithm = mock(TimedRetryAlgorithmWithContext.class); - RetryAlgorithm algorithm = - new RetryAlgorithm<>(mock(ResultRetryAlgorithmWithContext.class), timedAlgorithm); - - algorithm.createFirstAttempt(null); - verify(timedAlgorithm).createFirstAttempt(); - } - - @Test - public void testNextAttempt() { - ResultRetryAlgorithm resultAlgorithm = mock(ResultRetryAlgorithm.class); - TimedRetryAlgorithm timedAlgorithm = mock(TimedRetryAlgorithm.class); - RetryAlgorithm algorithm = new RetryAlgorithm<>(resultAlgorithm, timedAlgorithm); - - Throwable previousThrowable = new Throwable(); - Object previousResult = new Object(); - TimedAttemptSettings previousSettings = mock(TimedAttemptSettings.class); - - algorithm.createNextAttempt(previousThrowable, previousResult, previousSettings); - verify(resultAlgorithm).shouldRetry(previousThrowable, previousResult); - } - - @Test - public void testNextAttemptWithContext() { - ResultRetryAlgorithmWithContext resultAlgorithm = - mock(ResultRetryAlgorithmWithContext.class); - TimedRetryAlgorithmWithContext timedAlgorithm = mock(TimedRetryAlgorithmWithContext.class); - RetryAlgorithm algorithm = new RetryAlgorithm<>(resultAlgorithm, timedAlgorithm); - - RetryingContext context = mock(RetryingContext.class); - Throwable previousThrowable = new Throwable(); - Object previousResult = new Object(); - TimedAttemptSettings previousSettings = mock(TimedAttemptSettings.class); - - algorithm.createNextAttempt(context, previousThrowable, previousResult, previousSettings); - verify(resultAlgorithm).shouldRetry(context, previousThrowable, previousResult); - } - - @Test - public void testShouldRetry() { - ResultRetryAlgorithm resultAlgorithm = mock(ResultRetryAlgorithm.class); - TimedRetryAlgorithm timedAlgorithm = mock(TimedRetryAlgorithm.class); - RetryAlgorithm algorithm = new RetryAlgorithm<>(resultAlgorithm, timedAlgorithm); - - Throwable previousThrowable = new Throwable(); - Object previousResult = new Object(); - TimedAttemptSettings previousSettings = mock(TimedAttemptSettings.class); - - algorithm.shouldRetry(previousThrowable, previousResult, previousSettings); - verify(resultAlgorithm).shouldRetry(previousThrowable, previousResult); - } - - @Test - public void testShouldRetry_usesTimedAlgorithm() { - ResultRetryAlgorithm resultAlgorithm = mock(ResultRetryAlgorithm.class); - TimedRetryAlgorithm timedAlgorithm = mock(TimedRetryAlgorithm.class); - RetryAlgorithm algorithm = new RetryAlgorithm<>(resultAlgorithm, timedAlgorithm); - - Throwable previousThrowable = new Throwable(); - Object previousResult = new Object(); - TimedAttemptSettings previousSettings = mock(TimedAttemptSettings.class); - when(resultAlgorithm.shouldRetry(previousThrowable, previousResult)).thenReturn(true); - - algorithm.shouldRetry(previousThrowable, previousResult, previousSettings); - verify(timedAlgorithm).shouldRetry(previousSettings); - } - - @Test - public void testShouldRetryWithContext() { - ResultRetryAlgorithmWithContext resultAlgorithm = - mock(ResultRetryAlgorithmWithContext.class); - TimedRetryAlgorithmWithContext timedAlgorithm = mock(TimedRetryAlgorithmWithContext.class); - RetryAlgorithm algorithm = new RetryAlgorithm<>(resultAlgorithm, timedAlgorithm); - - RetryingContext context = mock(RetryingContext.class); - Throwable previousThrowable = new Throwable(); - Object previousResult = new Object(); - TimedAttemptSettings previousSettings = mock(TimedAttemptSettings.class); - - algorithm.shouldRetry(context, previousThrowable, previousResult, previousSettings); - verify(resultAlgorithm).shouldRetry(context, previousThrowable, previousResult); - } - - @Test - public void testShouldRetryWithContext_usesTimedAlgorithm() { - ResultRetryAlgorithmWithContext resultAlgorithm = - mock(ResultRetryAlgorithmWithContext.class); - TimedRetryAlgorithmWithContext timedAlgorithm = mock(TimedRetryAlgorithmWithContext.class); - RetryAlgorithm algorithm = new RetryAlgorithm<>(resultAlgorithm, timedAlgorithm); - - RetryingContext context = mock(RetryingContext.class); - Throwable previousThrowable = new Throwable(); - Object previousResult = new Object(); - TimedAttemptSettings previousSettings = mock(TimedAttemptSettings.class); - when(resultAlgorithm.shouldRetry(context, previousThrowable, previousResult)).thenReturn(true); - - algorithm.shouldRetry(context, previousThrowable, previousResult, previousSettings); - verify(timedAlgorithm).shouldRetry(context, previousSettings); - } - - @Test - public void testShouldRetry_noPreviousSettings() { - ResultRetryAlgorithm resultAlgorithm = mock(ResultRetryAlgorithm.class); - TimedRetryAlgorithm timedAlgorithm = mock(TimedRetryAlgorithm.class); - RetryAlgorithm algorithm = new RetryAlgorithm<>(resultAlgorithm, timedAlgorithm); - - Throwable previousThrowable = new Throwable(); - Object previousResult = new Object(); - when(resultAlgorithm.shouldRetry(previousThrowable, previousResult)).thenReturn(true); - - assertFalse(algorithm.shouldRetry(previousThrowable, previousResult, null)); - } - - @Test - public void testShouldRetryWithContext_noPreviousSettings() { - ResultRetryAlgorithmWithContext resultAlgorithm = - mock(ResultRetryAlgorithmWithContext.class); - TimedRetryAlgorithmWithContext timedAlgorithm = mock(TimedRetryAlgorithmWithContext.class); - RetryAlgorithm algorithm = new RetryAlgorithm<>(resultAlgorithm, timedAlgorithm); - - RetryingContext context = mock(RetryingContext.class); - Throwable previousThrowable = new Throwable(); - Object previousResult = new Object(); - - assertFalse(algorithm.shouldRetry(context, previousThrowable, previousResult, null)); - } -} diff --git a/gax/src/test/java/com/google/api/gax/retrying/RetrySettingsTest.java b/gax/src/test/java/com/google/api/gax/retrying/RetrySettingsTest.java deleted file mode 100644 index 8bcdea4cc..000000000 --- a/gax/src/test/java/com/google/api/gax/retrying/RetrySettingsTest.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -import com.google.common.truth.Truth; -import org.junit.Test; -import org.threeten.bp.Duration; - -public class RetrySettingsTest { - - @Test - public void retrySettingsSetLogicalTimeout() { - Duration timeout = Duration.ofMillis(60000); - RetrySettings retrySettings = RetrySettings.newBuilder().setLogicalTimeout(timeout).build(); - - Truth.assertThat(retrySettings.getRpcTimeoutMultiplier()).isEqualTo(1); - Truth.assertThat(retrySettings.getInitialRpcTimeout()).isEqualTo(timeout); - Truth.assertThat(retrySettings.getMaxRpcTimeout()).isEqualTo(timeout); - Truth.assertThat(retrySettings.getTotalTimeout()).isEqualTo(timeout); - } - - @Test - public void retrySettingsMerge() { - RetrySettings.Builder builder = - RetrySettings.newBuilder() - .setTotalTimeout(Duration.ofMillis(45000)) - .setInitialRpcTimeout(Duration.ofMillis(2000)) - .setRpcTimeoutMultiplier(1.5) - .setMaxRpcTimeout(Duration.ofMillis(30000)) - .setInitialRetryDelay(Duration.ofMillis(100)) - .setRetryDelayMultiplier(1.2) - .setMaxRetryDelay(Duration.ofMillis(1000)); - RetrySettings.Builder mergedBuilder = RetrySettings.newBuilder(); - mergedBuilder.merge(builder); - - RetrySettings settingsA = builder.build(); - RetrySettings settingsB = mergedBuilder.build(); - - Truth.assertThat(settingsA.getTotalTimeout()).isEqualTo(settingsB.getTotalTimeout()); - Truth.assertThat(settingsA.getInitialRetryDelay()).isEqualTo(settingsB.getInitialRetryDelay()); - Truth.assertThat(settingsA.getRpcTimeoutMultiplier()) - .isWithin(0) - .of(settingsB.getRpcTimeoutMultiplier()); - Truth.assertThat(settingsA.getMaxRpcTimeout()).isEqualTo(settingsB.getMaxRpcTimeout()); - Truth.assertThat(settingsA.getInitialRetryDelay()).isEqualTo(settingsB.getInitialRetryDelay()); - Truth.assertThat(settingsA.getRetryDelayMultiplier()) - .isWithin(0) - .of(settingsB.getRetryDelayMultiplier()); - Truth.assertThat(settingsA.getMaxRetryDelay()).isEqualTo(settingsB.getMaxRetryDelay()); - } -} diff --git a/gax/src/test/java/com/google/api/gax/retrying/ScheduledRetryingExecutorTest.java b/gax/src/test/java/com/google/api/gax/retrying/ScheduledRetryingExecutorTest.java deleted file mode 100644 index 76793ec98..000000000 --- a/gax/src/test/java/com/google/api/gax/retrying/ScheduledRetryingExecutorTest.java +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.retrying; - -import static com.google.api.gax.retrying.FailingCallable.FAST_RETRY_SETTINGS; -import static junit.framework.TestCase.assertFalse; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; - -import com.google.api.core.ApiFuture; -import com.google.api.core.NanoClock; -import com.google.api.gax.retrying.FailingCallable.CustomException; -import com.google.api.gax.rpc.testing.FakeCallContext; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.ScheduledExecutorService; -import org.junit.After; -import org.junit.Test; -import org.mockito.Mockito; -import org.threeten.bp.Duration; - -// @RunWith(MockitoJUnitRunner.class) -public class ScheduledRetryingExecutorTest extends AbstractRetryingExecutorTest { - private ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); - - // Number of test runs, essential for multithreaded tests. - private static final int EXECUTIONS_COUNT = 5; - - @Override - protected RetryingExecutorWithContext getExecutor(RetryAlgorithm retryAlgorithm) { - return getRetryingExecutor(retryAlgorithm, scheduler); - } - - @Override - protected RetryAlgorithm getAlgorithm( - RetrySettings retrySettings, int apocalypseCountDown, RuntimeException apocalypseException) { - return new RetryAlgorithm<>( - new TestResultRetryAlgorithm(apocalypseCountDown, apocalypseException), - new ExponentialRetryAlgorithm(retrySettings, NanoClock.getDefaultClock())); - } - - private RetryingExecutorWithContext getRetryingExecutor( - RetryAlgorithm retryAlgorithm, ScheduledExecutorService scheduler) { - return new ScheduledRetryingExecutor<>(retryAlgorithm, scheduler); - } - - @After - public void after() { - scheduler.shutdownNow(); - } - - @Test - public void testSuccessWithFailuresPeekAttempt() throws Exception { - for (int executionsCount = 0; executionsCount < EXECUTIONS_COUNT; executionsCount++) { - final int maxRetries = 100; - - ScheduledExecutorService localExecutor = Executors.newSingleThreadScheduledExecutor(); - FailingCallable callable = new FailingCallable(15, "request", "SUCCESS", tracer); - - RetrySettings retrySettings = - FAST_RETRY_SETTINGS - .toBuilder() - .setTotalTimeout(Duration.ofMillis(1000L)) - .setMaxAttempts(maxRetries) - .build(); - - RetryingExecutorWithContext executor = - getRetryingExecutor(getAlgorithm(retrySettings, 0, null), localExecutor); - RetryingFuture future = - executor.createFuture(callable, FakeCallContext.createDefault().withTracer(tracer)); - - assertNull(future.peekAttemptResult()); - assertSame(future.peekAttemptResult(), future.peekAttemptResult()); - assertFalse(future.getAttemptResult().isDone()); - assertFalse(future.getAttemptResult().isCancelled()); - - future.setAttemptFuture(executor.submit(future)); - - int failedAttempts = 0; - while (!future.isDone()) { - ApiFuture attemptResult = future.peekAttemptResult(); - if (attemptResult != null) { - assertTrue(attemptResult.isDone()); - assertFalse(attemptResult.isCancelled()); - try { - attemptResult.get(); - } catch (ExecutionException e) { - if (e.getCause() instanceof CustomException) { - failedAttempts++; - } - } - } - Thread.sleep(0L, 100); - } - - assertFutureSuccess(future); - assertEquals(15, future.getAttemptSettings().getAttemptCount()); - assertTrue(failedAttempts > 0); - localExecutor.shutdownNow(); - } - } - - @Test - public void testSuccessWithFailuresGetAttempt() throws Exception { - for (int executionsCount = 0; executionsCount < EXECUTIONS_COUNT; executionsCount++) { - final int maxRetries = 100; - - ScheduledExecutorService localExecutor = Executors.newSingleThreadScheduledExecutor(); - FailingCallable callable = new FailingCallable(15, "request", "SUCCESS", tracer); - RetrySettings retrySettings = - FAST_RETRY_SETTINGS - .toBuilder() - .setTotalTimeout(Duration.ofMillis(1000L)) - .setMaxAttempts(maxRetries) - .build(); - - RetryingExecutorWithContext executor = - getRetryingExecutor(getAlgorithm(retrySettings, 0, null), localExecutor); - RetryingFuture future = - executor.createFuture(callable, FakeCallContext.createDefault().withTracer(tracer)); - - assertNull(future.peekAttemptResult()); - assertSame(future.getAttemptResult(), future.getAttemptResult()); - assertFalse(future.getAttemptResult().isDone()); - assertFalse(future.getAttemptResult().isCancelled()); - - future.setAttemptFuture(executor.submit(future)); - - CustomException exception; - int checks = 0; - do { - exception = null; - checks++; - Future attemptResult = future.getAttemptResult(); - try { - // testing that the gotten attempt result is non-cancelable - assertFalse(attemptResult.cancel(false)); - assertFalse(attemptResult.cancel(true)); - attemptResult.get(); - assertNotNull(future.peekAttemptResult()); - } catch (ExecutionException e) { - exception = (CustomException) e.getCause(); - } - assertTrue(attemptResult.isDone()); - assertFalse(attemptResult.isCancelled()); - } while (exception != null && checks < maxRetries + 1); - - assertTrue(future.isDone()); - assertFutureSuccess(future); - assertEquals(15, future.getAttemptSettings().getAttemptCount()); - assertTrue("checks is equal to " + checks, checks > 1 && checks <= maxRetries); - localExecutor.shutdownNow(); - } - } - - @Test - public void testCancelGetAttempt() throws Exception { - for (int executionsCount = 0; executionsCount < EXECUTIONS_COUNT; executionsCount++) { - ScheduledExecutorService localExecutor = Executors.newSingleThreadScheduledExecutor(); - final int maxRetries = 100; - - FailingCallable callable = new FailingCallable(maxRetries - 1, "request", "SUCCESS", tracer); - RetrySettings retrySettings = - FAST_RETRY_SETTINGS - .toBuilder() - .setTotalTimeout(Duration.ofMillis(1000L)) - .setMaxAttempts(maxRetries) - .build(); - - RetryingExecutorWithContext executor = - getRetryingExecutor(getAlgorithm(retrySettings, 0, null), localExecutor); - RetryingFuture future = executor.createFuture(callable, retryingContext); - - assertNull(future.peekAttemptResult()); - assertSame(future.getAttemptResult(), future.getAttemptResult()); - assertFalse(future.getAttemptResult().isDone()); - assertFalse(future.getAttemptResult().isCancelled()); - - future.setAttemptFuture(executor.submit(future)); - - CustomException exception; - CancellationException cancellationException = null; - int checks = 0; - int failedCancelations = 0; - do { - exception = null; - checks++; - Future attemptResult = future.getAttemptResult(); - try { - attemptResult.get(); - assertNotNull(future.peekAttemptResult()); - } catch (CancellationException e) { - cancellationException = e; - } catch (ExecutionException e) { - exception = (CustomException) e.getCause(); - } - assertTrue(attemptResult.isDone()); - if (!future.cancel(true)) { - failedCancelations++; - } - } while (exception != null && checks < maxRetries); - - assertTrue(future.isDone()); - assertNotNull(cancellationException); - // future.cancel(true) may return false sometimes, which is ok. Also, the every cancellation - // of - // an already cancelled future should return false (this is what -1 means here) - assertEquals(2, checks - (failedCancelations - 1)); - assertTrue(future.getAttemptSettings().getAttemptCount() > 0); - assertFutureCancel(future); - localExecutor.shutdownNow(); - } - } - - @Test - public void testCancelOuterFutureAfterStart() throws Exception { - for (int executionsCount = 0; executionsCount < EXECUTIONS_COUNT; executionsCount++) { - ScheduledExecutorService localExecutor = Executors.newSingleThreadScheduledExecutor(); - FailingCallable callable = new FailingCallable(4, "requset", "SUCCESS", tracer); - RetrySettings retrySettings = - FAST_RETRY_SETTINGS - .toBuilder() - .setInitialRetryDelay(Duration.ofMillis(1_000L)) - .setMaxRetryDelay(Duration.ofMillis(1_000L)) - .setTotalTimeout(Duration.ofMillis(10_0000L)) - .build(); - RetryingExecutorWithContext executor = - getRetryingExecutor(getAlgorithm(retrySettings, 0, null), localExecutor); - RetryingFuture future = - executor.createFuture(callable, FakeCallContext.createDefault().withTracer(tracer)); - future.setAttemptFuture(executor.submit(future)); - - Thread.sleep(30L); - - boolean res = future.cancel(false); - assertTrue(res); - assertFutureCancel(future); - assertTrue(future.getAttemptSettings().getAttemptCount() < 4); - localExecutor.shutdownNow(); - } - } - - @Test - public void testCancelIsTraced() throws Exception { - ScheduledExecutorService localExecutor = Executors.newSingleThreadScheduledExecutor(); - FailingCallable callable = new FailingCallable(4, "request", "SUCCESS", tracer); - RetrySettings retrySettings = - FAST_RETRY_SETTINGS - .toBuilder() - .setInitialRetryDelay(Duration.ofMillis(1_000L)) - .setMaxRetryDelay(Duration.ofMillis(1_000L)) - .setTotalTimeout(Duration.ofMillis(10_0000L)) - .build(); - RetryingExecutorWithContext executor = - getRetryingExecutor(getAlgorithm(retrySettings, 0, null), localExecutor); - RetryingFuture future = - executor.createFuture(callable, FakeCallContext.createDefault().withTracer(tracer)); - future.setAttemptFuture(executor.submit(future)); - - Thread.sleep(30L); - - boolean res = future.cancel(false); - assertTrue(res); - assertFutureCancel(future); - - Mockito.verify(tracer).attemptCancelled(); - localExecutor.shutdownNow(); - } - - @Test - public void testCancelProxiedFutureAfterStart() throws Exception { - // this is a heavy test, which takes a lot of time, so only few executions. - for (int executionsCount = 0; executionsCount < 2; executionsCount++) { - ScheduledExecutorService localExecutor = Executors.newSingleThreadScheduledExecutor(); - FailingCallable callable = new FailingCallable(5, "request", "SUCCESS", tracer); - RetrySettings retrySettings = - FAST_RETRY_SETTINGS - .toBuilder() - .setInitialRetryDelay(Duration.ofMillis(1_000L)) - .setMaxRetryDelay(Duration.ofMillis(1_000L)) - .setTotalTimeout(Duration.ofMillis(10_0000L)) - .build(); - RetryingExecutorWithContext executor = - getRetryingExecutor(getAlgorithm(retrySettings, 0, null), localExecutor); - RetryingFuture future = - executor.createFuture(callable, FakeCallContext.createDefault().withTracer(tracer)); - future.setAttemptFuture(executor.submit(future)); - - Thread.sleep(50L); - - // Note that shutdownNow() will not cancel internal FutureTasks automatically, which - // may potentially cause another thread handing on RetryingFuture#get() call forever. - // Canceling the tasks returned by shutdownNow() also does not help, because of missing - // feature - // in guava's ListenableScheduledFuture, which does not cancel itself, when its delegate is - // canceled. - // So only the graceful shutdown() is supported properly. - localExecutor.shutdown(); - - assertFutureFail(future, RejectedExecutionException.class); - localExecutor.shutdownNow(); - } - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/AccumulatingStreamObserver.java b/gax/src/test/java/com/google/api/gax/rpc/AccumulatingStreamObserver.java deleted file mode 100644 index 65c31f92b..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/AccumulatingStreamObserver.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.api.gax.rpc.testing.FakeStatusCode; -import java.util.ArrayList; -import java.util.List; - -/** Package-private for internal use. */ -class AccumulatingStreamObserver extends StateCheckingResponseObserver { - private List values = new ArrayList<>(); - private StreamController controller; - private Throwable error; - private boolean completed = false; - - @Override - protected void onStartImpl(StreamController controller) { - this.controller = controller; - } - - @Override - protected void onResponseImpl(Integer value) { - values.add(value); - } - - @Override - protected void onErrorImpl(Throwable t) { - error = t; - } - - @Override - protected void onCompleteImpl() { - completed = true; - } - - public List getValues() { - if (!completed) { - throw new IllegalStateException("Stream not completed."); - } - if (error != null) { - throw ApiExceptionFactory.createException(error, FakeStatusCode.of(Code.UNKNOWN), false); - } - return values; - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/ApiClientHeaderProviderTest.java b/gax/src/test/java/com/google/api/gax/rpc/ApiClientHeaderProviderTest.java deleted file mode 100644 index f60c3c076..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/ApiClientHeaderProviderTest.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static com.google.common.truth.Truth.assertThat; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class ApiClientHeaderProviderTest { - - private static final String X_GOOG_API_CLIENT = "x-goog-api-client"; - private static final String CLOUD_RESOURCE_PREFIX = "google-cloud-resource-prefix"; - - @Test - public void testServiceHeaderDefault() { - ApiClientHeaderProvider provider = ApiClientHeaderProvider.newBuilder().build(); - assertThat(provider.getHeaders().size()).isEqualTo(1); - assertThat(provider.getHeaders().get(X_GOOG_API_CLIENT)).matches("^gl-java/.* gax/.*$"); - } - - @Test - public void testServiceHeaderManual() { - ApiClientHeaderProvider provider = - ApiClientHeaderProvider.newBuilder().setClientLibToken("gccl", "1.2.3").build(); - assertThat(provider.getHeaders().size()).isEqualTo(1); - assertThat(provider.getHeaders().get(X_GOOG_API_CLIENT)) - .matches("^gl-java/.* gccl/1\\.2\\.3 gax/.*$"); - } - - @Test - public void testServiceHeaderManualGapic() { - ApiClientHeaderProvider provider = - ApiClientHeaderProvider.newBuilder() - .setTransportToken("grpc", "1.2.3") - .setClientLibToken("gccl", "4.5.6") - .setGeneratedLibToken("gapic", "7.8.9") - .build(); - assertThat(provider.getHeaders().size()).isEqualTo(1); - assertThat(provider.getHeaders().get(X_GOOG_API_CLIENT)) - .matches("^gl-java/.* gccl/4\\.5\\.6 gapic/7\\.8\\.9 gax/.* grpc/1\\.2\\.3$"); - } - - @Test - public void testServiceHeaderManualGrpc() { - ApiClientHeaderProvider provider = - ApiClientHeaderProvider.newBuilder() - .setTransportToken("grpc", "1.2.3") - .setClientLibToken("gccl", "4.5.6") - .build(); - assertThat(provider.getHeaders().size()).isEqualTo(1); - assertThat(provider.getHeaders().get(X_GOOG_API_CLIENT)) - .matches("^gl-java/.* gccl/4\\.5\\.6 gax/.* grpc/1\\.2\\.3$"); - } - - @Test - public void testServiceHeaderGapic() { - ApiClientHeaderProvider provider = - ApiClientHeaderProvider.newBuilder() - .setTransportToken("grpc", "1.2.3") - .setGeneratedLibToken("gapic", "4.5.6") - .build(); - assertThat(provider.getHeaders().size()).isEqualTo(1); - assertThat(provider.getHeaders().get(X_GOOG_API_CLIENT)) - .matches("^gl-java/.* gapic/4\\.5\\.6 gax/.* grpc/1\\.2\\.3$"); - } - - @Test - public void testCloudResourcePrefixHeader() { - ApiClientHeaderProvider provider = - ApiClientHeaderProvider.newBuilder() - .setTransportToken("grpc", "1.2.3") - .setGeneratedLibToken("gapic", "4.5.6") - .setResourceToken("test-prefix") - .build(); - assertThat(provider.getHeaders().size()).isEqualTo(2); - assertThat(provider.getHeaders().get(X_GOOG_API_CLIENT)) - .matches("^gl-java/.* gapic/4\\.5\\.6 gax/.* grpc/1\\.2\\.3$"); - assertThat(provider.getHeaders().get(CLOUD_RESOURCE_PREFIX)).isEqualTo("test-prefix"); - } - - @Test - public void testCustomHeaderKeys() { - ApiClientHeaderProvider provider = - ApiClientHeaderProvider.newBuilder() - .setTransportToken("grpc", "1.2.3") - .setGeneratedLibToken("gapic", "4.5.6") - .setResourceToken("test-prefix") - .setApiClientHeaderKey("custom-header1") - .setResourceHeaderKey("custom-header2") - .build(); - assertThat(provider.getHeaders().size()).isEqualTo(2); - assertThat(provider.getHeaders().get("custom-header1")) - .matches("^gl-java/.* gapic/4\\.5\\.6 gax/.* grpc/1\\.2\\.3$"); - assertThat(provider.getHeaders().get("custom-header2")).isEqualTo("test-prefix"); - } - - @Test - public void testQuotaProjectHeader() { - String quotaProjectHeaderValue = "quota-project-id-value"; - ApiClientHeaderProvider provider = - ApiClientHeaderProvider.newBuilder() - .setClientLibToken("gccl", "1.2.3") - .setQuotaProjectIdToken(quotaProjectHeaderValue) - .build(); - assertThat(provider.getHeaders().size()).isEqualTo(2); - assertThat(provider.getHeaders().get(X_GOOG_API_CLIENT)) - .matches("^gl-java/.* gccl/1\\.2\\.3 gax/.*$"); - assertThat(provider.getHeaders().get(ApiClientHeaderProvider.QUOTA_PROJECT_ID_HEADER_KEY)) - .matches(quotaProjectHeaderValue); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/ApiExceptionFactoryTest.java b/gax/src/test/java/com/google/api/gax/rpc/ApiExceptionFactoryTest.java deleted file mode 100644 index 52e224421..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/ApiExceptionFactoryTest.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.api.gax.rpc.testing.FakeStatusCode; -import com.google.common.truth.Truth; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class ApiExceptionFactoryTest { - - @Test - public void cancelled() { - Truth.assertThat(createException(Code.CANCELLED)).isInstanceOf(CancelledException.class); - Truth.assertThat(createExceptionWithMessage(Code.CANCELLED)) - .isInstanceOf(CancelledException.class); - } - - @Test - public void notFound() { - Truth.assertThat(createException(Code.NOT_FOUND)).isInstanceOf(NotFoundException.class); - Truth.assertThat(createExceptionWithMessage(Code.NOT_FOUND)) - .isInstanceOf(NotFoundException.class); - } - - @Test - public void unknown() { - Truth.assertThat(createException(Code.UNKNOWN)).isInstanceOf(UnknownException.class); - Truth.assertThat(createExceptionWithMessage(Code.UNKNOWN)).isInstanceOf(UnknownException.class); - } - - @Test - public void invalidArgument() { - Truth.assertThat(createException(Code.INVALID_ARGUMENT)) - .isInstanceOf(InvalidArgumentException.class); - Truth.assertThat(createExceptionWithMessage(Code.INVALID_ARGUMENT)) - .isInstanceOf(InvalidArgumentException.class); - } - - @Test - public void deadlineExceeded() { - Truth.assertThat(createException(Code.DEADLINE_EXCEEDED)) - .isInstanceOf(DeadlineExceededException.class); - Truth.assertThat(createExceptionWithMessage(Code.DEADLINE_EXCEEDED)) - .isInstanceOf(DeadlineExceededException.class); - } - - @Test - public void alreadyExists() { - Truth.assertThat(createException(Code.ALREADY_EXISTS)) - .isInstanceOf(AlreadyExistsException.class); - Truth.assertThat(createExceptionWithMessage(Code.ALREADY_EXISTS)) - .isInstanceOf(AlreadyExistsException.class); - } - - @Test - public void permissionDenied() { - Truth.assertThat(createException(Code.PERMISSION_DENIED)) - .isInstanceOf(PermissionDeniedException.class); - Truth.assertThat(createExceptionWithMessage(Code.PERMISSION_DENIED)) - .isInstanceOf(PermissionDeniedException.class); - } - - @Test - public void resourceExhausted() { - Truth.assertThat(createException(Code.RESOURCE_EXHAUSTED)) - .isInstanceOf(ResourceExhaustedException.class); - Truth.assertThat(createExceptionWithMessage(Code.RESOURCE_EXHAUSTED)) - .isInstanceOf(ResourceExhaustedException.class); - } - - @Test - public void failedPrecondition() { - Truth.assertThat(createException(Code.FAILED_PRECONDITION)) - .isInstanceOf(FailedPreconditionException.class); - Truth.assertThat(createExceptionWithMessage(Code.FAILED_PRECONDITION)) - .isInstanceOf(FailedPreconditionException.class); - } - - @Test - public void aborted() { - Truth.assertThat(createException(Code.ABORTED)).isInstanceOf(AbortedException.class); - Truth.assertThat(createExceptionWithMessage(Code.ABORTED)).isInstanceOf(AbortedException.class); - } - - @Test - public void outOfRange() { - Truth.assertThat(createException(Code.OUT_OF_RANGE)).isInstanceOf(OutOfRangeException.class); - Truth.assertThat(createExceptionWithMessage(Code.OUT_OF_RANGE)) - .isInstanceOf(OutOfRangeException.class); - } - - @Test - public void internal() { - Truth.assertThat(createException(Code.INTERNAL)).isInstanceOf(InternalException.class); - Truth.assertThat(createExceptionWithMessage(Code.INTERNAL)) - .isInstanceOf(InternalException.class); - } - - @Test - public void unavailable() { - Truth.assertThat(createException(Code.UNAVAILABLE)).isInstanceOf(UnavailableException.class); - Truth.assertThat(createExceptionWithMessage(Code.UNAVAILABLE)) - .isInstanceOf(UnavailableException.class); - } - - @Test - public void dataLoss() { - Truth.assertThat(createException(Code.DATA_LOSS)).isInstanceOf(DataLossException.class); - Truth.assertThat(createExceptionWithMessage(Code.DATA_LOSS)) - .isInstanceOf(DataLossException.class); - } - - @Test - public void unauthenticated() { - Truth.assertThat(createException(Code.UNAUTHENTICATED)) - .isInstanceOf(UnauthenticatedException.class); - Truth.assertThat(createExceptionWithMessage(Code.UNAUTHENTICATED)) - .isInstanceOf(UnauthenticatedException.class); - } - - @Test - public void unimplemented() { - Truth.assertThat(createException(Code.UNIMPLEMENTED)) - .isInstanceOf(UnimplementedException.class); - Truth.assertThat(createExceptionWithMessage(Code.UNIMPLEMENTED)) - .isInstanceOf(UnimplementedException.class); - } - - @Test - public void unknown_default() { - Truth.assertThat(createException(Code.OK)).isInstanceOf(UnknownException.class); - Truth.assertThat(createExceptionWithMessage(Code.OK)).isInstanceOf(UnknownException.class); - } - - private ApiException createException(StatusCode.Code statusCode) { - return ApiExceptionFactory.createException( - new RuntimeException(), FakeStatusCode.of(statusCode), false); - } - - private ApiException createExceptionWithMessage(StatusCode.Code statusCode) { - return ApiExceptionFactory.createException( - "message", new RuntimeException(), FakeStatusCode.of(statusCode), false); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/ApiExceptionTest.java b/gax/src/test/java/com/google/api/gax/rpc/ApiExceptionTest.java deleted file mode 100644 index 85bf2d9ec..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/ApiExceptionTest.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.api.gax.rpc.testing.FakeStatusCode; -import com.google.common.collect.ImmutableList; -import com.google.common.truth.Truth; -import com.google.protobuf.Any; -import com.google.rpc.ErrorInfo; -import java.util.Collections; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class ApiExceptionTest { - - private static final ErrorDetails ERROR_DETAILS_WITH_NO_ERROR_INFO = - ErrorDetails.builder().setRawErrorMessages(Collections.emptyList()).build(); - private static final String DOMAIN = "googleapis.com"; - private static final String REASON = "SERVICE_DISABLED"; - private static final String METADATA_KEY = "service"; - private static final String METADATA_VALUE = "language.googleapis.com"; - private static final ErrorDetails ERROR_DETAILS_WITH_ERROR_INFO = - ErrorDetails.builder() - .setRawErrorMessages( - ImmutableList.of( - Any.pack( - ErrorInfo.newBuilder() - .setDomain(DOMAIN) - .setReason(REASON) - .putMetadata(METADATA_KEY, METADATA_VALUE) - .build()))) - .build(); - private static final FakeStatusCode STATUS_CODE = FakeStatusCode.of(Code.UNAVAILABLE); - - private ApiException apiException; - - @Test - public void getReason_shouldReturnNullIfErrorDetailsIsNull() { - apiException = new ApiException(null, STATUS_CODE, false, null); - - Truth.assertThat(apiException.getReason()).isNull(); - } - - @Test - public void getReason_shouldReturnNullIfErrorInfoIsNull() { - apiException = new ApiException(null, STATUS_CODE, false, ERROR_DETAILS_WITH_NO_ERROR_INFO); - - Truth.assertThat(apiException.getReason()).isNull(); - } - - @Test - public void getReason_shouldReturnReasonIfAvailable() { - apiException = new ApiException(null, STATUS_CODE, false, ERROR_DETAILS_WITH_ERROR_INFO); - - Truth.assertThat(apiException.getReason()).isEqualTo(REASON); - } - - @Test - public void getDomain_shouldReturnNullIfErrorInfoIsNull() { - apiException = new ApiException(null, STATUS_CODE, false, ERROR_DETAILS_WITH_NO_ERROR_INFO); - - Truth.assertThat(apiException.getDomain()).isNull(); - } - - @Test - public void getDomain_shouldReturnDomainIfAvailable() { - apiException = new ApiException(null, STATUS_CODE, false, ERROR_DETAILS_WITH_ERROR_INFO); - - Truth.assertThat(apiException.getDomain()).isEqualTo(DOMAIN); - } - - @Test - public void getMetadata_shouldReturnNullIfErrorInfoIsNull() { - apiException = new ApiException(null, STATUS_CODE, false, ERROR_DETAILS_WITH_NO_ERROR_INFO); - - Truth.assertThat(apiException.getMetadata()).isNull(); - } - - @Test - public void getMetadata_shouldReturnMetadataIfAvailable() { - apiException = new ApiException(null, STATUS_CODE, false, ERROR_DETAILS_WITH_ERROR_INFO); - - Truth.assertThat(apiException.getMetadata()).containsExactly(METADATA_KEY, METADATA_VALUE); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/ApiExceptionsTest.java b/gax/src/test/java/com/google/api/gax/rpc/ApiExceptionsTest.java deleted file mode 100644 index 411f21b2b..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/ApiExceptionsTest.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.api.core.ApiFutures; -import com.google.api.core.ListenableFutureToApiFuture; -import com.google.api.gax.rpc.testing.FakeStatusCode; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.ListeningExecutorService; -import com.google.common.util.concurrent.MoreExecutors; -import com.google.common.util.concurrent.UncheckedExecutionException; -import java.io.IOException; -import java.util.concurrent.Executors; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class ApiExceptionsTest { - - @Test - public void noException() { - Integer result = ApiExceptions.callAndTranslateApiException(ApiFutures.immediateFuture(2)); - assertThat(result).isEqualTo(2); - } - - @Test - public void throwsApiException() { - Exception throwable = - new UnavailableException(null, FakeStatusCode.of(StatusCode.Code.UNAVAILABLE), false); - try { - ApiExceptions.callAndTranslateApiException(ApiFutures.immediateFailedFuture(throwable)); - Assert.fail("ApiExceptions should have thrown an exception"); - } catch (ApiException expected) { - assertThat(expected).isSameInstanceAs(throwable); - } - } - - @Test - public void throwsIOException() { - try { - ApiExceptions.callAndTranslateApiException( - ApiFutures.immediateFailedFuture(new IOException())); - Assert.fail("ApiExceptions should have thrown an exception"); - } catch (UncheckedExecutionException expected) { - assertThat(expected).hasCauseThat().isInstanceOf(IOException.class); - } - } - - @Test - public void throwsRuntimeException() { - try { - ApiExceptions.callAndTranslateApiException( - ApiFutures.immediateFailedFuture(new IllegalArgumentException())); - Assert.fail("ApiExceptions should have thrown an exception"); - } catch (IllegalArgumentException expected) { - assertThat(expected).isInstanceOf(IllegalArgumentException.class); - } - } - - /** - * Make sure that the caller's stacktrace is preserved when the future is unwrapped. The - * stacktrace will be preserved as a suppressed RuntimeException. - */ - @Test - public void containsCurrentStacktrace() { - final String currentMethod = "containsCurrentStacktrace"; - - // Throw an error in an executor, which will cause it to lose the current stack frame - ListeningExecutorService executor = - MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()); - - ListenableFuture futureError = - executor.submit( - new Runnable() { - @Override - public void run() { - throw new IllegalArgumentException(); - } - }); - ListenableFutureToApiFuture futureErrorWrapper = - new ListenableFutureToApiFuture<>(futureError); - executor.shutdown(); - - // Unwrap the future - Exception actualError = null; - try { - ApiExceptions.callAndTranslateApiException(futureErrorWrapper); - } catch (Exception e) { - actualError = e; - } - - // Sanity check that the current stack trace is not in the exception - assertThat(actualError).isNotNull(); - assertThat(isMethodInStacktrace(currentMethod, actualError)).isFalse(); - - // Verify that it is preserved as a suppressed exception. - assertThat(actualError.getSuppressed()[0]).isInstanceOf(AsyncTaskException.class); - assertThat(isMethodInStacktrace(currentMethod, actualError.getSuppressed()[0])).isTrue(); - } - - private static boolean isMethodInStacktrace(String method, Throwable t) { - for (StackTraceElement e : t.getStackTrace()) { - if (method.equals(e.getMethodName())) { - return true; - } - } - - return false; - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/ApiResultRetryAlgorithmTest.java b/gax/src/test/java/com/google/api/gax/rpc/ApiResultRetryAlgorithmTest.java deleted file mode 100644 index 4e04c1a0b..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/ApiResultRetryAlgorithmTest.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.api.gax.rpc.testing.FakeStatusCode; -import com.google.common.collect.Sets; -import java.util.Collections; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class ApiResultRetryAlgorithmTest { - - @Test - public void testShouldRetryNoContext() { - ApiException nonRetryable = - new ApiException(null, new FakeStatusCode(Code.INTERNAL), /* retryable = */ false); - ApiException retryable = - new ApiException(null, new FakeStatusCode(Code.UNAVAILABLE), /* retryable = */ true); - - ApiResultRetryAlgorithm algorithm = new ApiResultRetryAlgorithm<>(); - assertFalse(algorithm.shouldRetry(nonRetryable, null)); - assertTrue(algorithm.shouldRetry(retryable, null)); - } - - @Test - public void testShouldRetryWithContextWithoutRetryableCodes() { - ApiCallContext context = mock(ApiCallContext.class); - // No retryable codes in the call context, means that the retry algorithm should fall back to - // its default implementation. - when(context.getRetryableCodes()).thenReturn(null); - - ApiException nonRetryable = - new ApiException(null, new FakeStatusCode(Code.UNAVAILABLE), /* retryable = */ false); - ApiException retryable = - new ApiException(null, new FakeStatusCode(Code.UNAVAILABLE), /* retryable = */ true); - - ApiResultRetryAlgorithm algorithm = new ApiResultRetryAlgorithm<>(); - assertFalse(algorithm.shouldRetry(context, nonRetryable, null)); - assertTrue(algorithm.shouldRetry(context, retryable, null)); - } - - @Test - public void testShouldRetryWithContextWithRetryableCodes() { - ApiCallContext context = mock(ApiCallContext.class); - when(context.getRetryableCodes()) - .thenReturn( - Sets.newHashSet(StatusCode.Code.DEADLINE_EXCEEDED, StatusCode.Code.UNAVAILABLE)); - - StatusCode unavailable = mock(StatusCode.class); - when(unavailable.getCode()).thenReturn(Code.UNAVAILABLE); - StatusCode dataLoss = mock(StatusCode.class); - when(dataLoss.getCode()).thenReturn(Code.DATA_LOSS); - - // The return value of isRetryable() will be ignored, as UNAVAILABLE has been added as a - // retryable code to the call context. - ApiException unavailableException = - new ApiException(null, new FakeStatusCode(Code.UNAVAILABLE), /* retryable = */ false); - ApiException dataLossException = - new ApiException(null, new FakeStatusCode(Code.DATA_LOSS), /* retryable = */ true); - - ApiResultRetryAlgorithm algorithm = new ApiResultRetryAlgorithm<>(); - assertTrue(algorithm.shouldRetry(context, unavailableException, null)); - assertFalse(algorithm.shouldRetry(context, dataLossException, null)); - } - - @Test - public void testShouldRetryWithContextWithEmptyRetryableCodes() { - ApiCallContext context = mock(ApiCallContext.class); - // This will effectively make the RPC non-retryable. - when(context.getRetryableCodes()).thenReturn(Collections.emptySet()); - - ApiException unavailableException = - new ApiException(null, new FakeStatusCode(Code.UNAVAILABLE), /* retryable = */ true); - - ApiResultRetryAlgorithm algorithm = new ApiResultRetryAlgorithm<>(); - assertFalse(algorithm.shouldRetry(context, unavailableException, null)); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/AttemptCallableTest.java b/gax/src/test/java/com/google/api/gax/rpc/AttemptCallableTest.java deleted file mode 100644 index 3b16b568d..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/AttemptCallableTest.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.api.core.SettableApiFuture; -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.retrying.RetryingFuture; -import com.google.api.gax.retrying.TimedAttemptSettings; -import com.google.api.gax.rpc.testing.FakeCallContext; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.junit.MockitoJUnitRunner; -import org.mockito.stubbing.Answer; -import org.threeten.bp.Duration; - -@RunWith(MockitoJUnitRunner.class) -public class AttemptCallableTest { - @Mock UnaryCallable mockInnerCallable; - ArgumentCaptor capturedCallContext; - @Mock RetryingFuture mockExternalFuture; - TimedAttemptSettings currentAttemptSettings; - - @Before - public void setUp() { - capturedCallContext = ArgumentCaptor.forClass(ApiCallContext.class); - Mockito.when(mockInnerCallable.futureCall(Mockito.anyString(), capturedCallContext.capture())) - .thenReturn(SettableApiFuture.create()); - - currentAttemptSettings = - TimedAttemptSettings.newBuilder() - .setGlobalSettings(RetrySettings.newBuilder().build()) - .setAttemptCount(0) - .setOverallAttemptCount(0) - .setFirstAttemptStartTimeNanos(0) - .setRetryDelay(Duration.ofSeconds(1)) - .setRandomizedRetryDelay(Duration.ofSeconds(1)) - .setRpcTimeout(Duration.ZERO) - .build(); - - Mockito.when(mockExternalFuture.getAttemptSettings()) - .thenAnswer( - new Answer() { - @Override - public TimedAttemptSettings answer(InvocationOnMock invocation) throws Throwable { - return currentAttemptSettings; - } - }); - } - - @Test - public void testRpcTimeout() { - AttemptCallable callable = - new AttemptCallable<>(mockInnerCallable, "fake-request", FakeCallContext.createDefault()); - callable.setExternalFuture(mockExternalFuture); - - // Make sure that the rpc timeout is set - Duration timeout = Duration.ofSeconds(10); - currentAttemptSettings = currentAttemptSettings.toBuilder().setRpcTimeout(timeout).build(); - - callable.call(); - - assertThat(capturedCallContext.getValue().getTimeout()).isEqualTo(timeout); - - // Make sure that subsequent attempts can extend the time out - Duration longerTimeout = Duration.ofSeconds(20); - currentAttemptSettings = - currentAttemptSettings.toBuilder().setRpcTimeout(longerTimeout).build(); - callable.call(); - assertThat(capturedCallContext.getValue().getTimeout()).isEqualTo(longerTimeout); - } - - @Test - public void testRpcTimeoutIsNotErased() { - Duration callerTimeout = Duration.ofMillis(10); - ApiCallContext callerCallContext = FakeCallContext.createDefault().withTimeout(callerTimeout); - - Duration timeout = Duration.ofMillis(5); - currentAttemptSettings = currentAttemptSettings.toBuilder().setRpcTimeout(timeout).build(); - - AttemptCallable callable = - new AttemptCallable<>(mockInnerCallable, "fake-request", callerCallContext); - callable.setExternalFuture(mockExternalFuture); - - callable.call(); - - assertThat(capturedCallContext.getValue().getTimeout()).isEqualTo(callerTimeout); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/AuthCallableTest.java b/gax/src/test/java/com/google/api/gax/rpc/AuthCallableTest.java deleted file mode 100644 index c0f2f269e..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/AuthCallableTest.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.gax.rpc.testing.FakeCallContext; -import com.google.api.gax.rpc.testing.FakeCallableFactory; -import com.google.api.gax.rpc.testing.FakeChannel; -import com.google.api.gax.rpc.testing.FakeSimpleApi.StashCallable; -import com.google.api.gax.rpc.testing.FakeTransportChannel; -import com.google.auth.Credentials; -import com.google.common.truth.Truth; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; - -@RunWith(JUnit4.class) -public class AuthCallableTest { - private ClientContext clientContext; - - @Before - public void setUp() { - clientContext = - ClientContext.newBuilder() - .setDefaultCallContext(FakeCallContext.createDefault()) - .setTransportChannel(FakeTransportChannel.create(new FakeChannel())) - .build(); - } - - @Test - public void testAuth() throws InterruptedException, ExecutionException, CancellationException { - StashCallable stash = new StashCallable<>(42); - Truth.assertThat(stash.getContext()).isNull(); - - UnaryCallSettings callSettings = - UnaryCallSettings.newUnaryCallSettingsBuilder().build(); - UnaryCallable callable = - FakeCallableFactory.createUnaryCallable( - stash, - callSettings, - clientContext.toBuilder().setCredentials(Mockito.mock(Credentials.class)).build()); - Truth.assertThat(callable.futureCall(0).get()).isEqualTo(42); - Truth.assertThat(stash.getContext()).isNotNull(); - FakeCallContext callContext = (FakeCallContext) stash.getContext(); - Truth.assertThat(callContext.getCredentials()).isNotNull(); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/BatchExecutorTest.java b/gax/src/test/java/com/google/api/gax/rpc/BatchExecutorTest.java deleted file mode 100644 index b55ce9ff2..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/BatchExecutorTest.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.gax.batching.PartitionKey; -import com.google.api.gax.batching.RequestBuilder; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class BatchExecutorTest { - - BatchingDescriptor, Integer> integerDescriptor = - new BatchingDescriptor, Integer>() { - - @Override - public PartitionKey getBatchPartitionKey(List request) { - return new PartitionKey(request.get(0) % 2); - } - - @Override - public RequestBuilder> getRequestBuilder() { - return new RequestBuilder>() { - - List list = new ArrayList<>(); - - @Override - public void appendRequest(List request) { - list.addAll(request); - } - - @Override - public List build() { - return list; - } - }; - } - - @Override - public void splitResponse( - Integer batchResponse, Collection> batch) {} - - @Override - public void splitException( - Throwable throwable, Collection> batch) {} - - @Override - public long countElements(List request) { - return request.size(); - } - - @Override - public long countBytes(List request) { - return request.size(); - } - }; - - @Test - public void testValidate() { - BatchExecutor, Integer> executor = - new BatchExecutor, Integer>(integerDescriptor, new PartitionKey(0)); - List request = new ArrayList(); - request.add(2); - Batch, Integer> batchingContextOk = - new Batch<>(integerDescriptor, request, null, null); - executor.validateBatch(batchingContextOk); - } - - @Test(expected = IllegalArgumentException.class) - public void testValidateFailure() { - BatchExecutor, Integer> executor = - new BatchExecutor, Integer>(integerDescriptor, new PartitionKey(0)); - List request = new ArrayList<>(); - request.add(3); - Batch, Integer> batchingContextOk = - new Batch<>(integerDescriptor, request, null, null); - executor.validateBatch(batchingContextOk); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/BatchTest.java b/gax/src/test/java/com/google/api/gax/rpc/BatchTest.java deleted file mode 100644 index 44a2401e9..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/BatchTest.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static com.google.api.gax.rpc.testing.FakeBatchableApi.SQUARER_BATCHING_DESC; - -import com.google.api.gax.batching.ElementCounter; -import com.google.api.gax.rpc.Batch.BatchByteCounter; -import com.google.api.gax.rpc.Batch.BatchElementCounter; -import com.google.api.gax.rpc.Batch.BatchMergerImpl; -import com.google.api.gax.rpc.testing.FakeBatchableApi; -import com.google.api.gax.rpc.testing.FakeBatchableApi.LabeledIntList; -import com.google.common.truth.Truth; -import java.util.ArrayList; -import java.util.List; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; - -@RunWith(JUnit4.class) -public class BatchTest { - - @Test - public void testConstructor() { - LabeledIntList request = new LabeledIntList("lable", 2); - Batch> batch = createBatch(request); - - Truth.assertThat(batch.getRequest()).isEqualTo(request); - Truth.assertThat(batch.getCallable()).isSameInstanceAs(batch.getCallable()); - Truth.assertThat(batch.getRequestIssuerList().size()).isEqualTo(1); - Truth.assertThat(batch.getByteCount()).isEqualTo(2); - } - - @Test - public void testMerge() { - LabeledIntList request1 = new LabeledIntList("lable", 1); - Batch> batch1 = createBatch(request1); - - LabeledIntList request2 = new LabeledIntList("lable", 2); - Batch> batch2 = createBatch(request2); - - batch1.merge(batch2); - - Truth.assertThat(batch1.getByteCount()).isEqualTo(3); - } - - @Test - public void testMergeStartEmpty() { - LabeledIntList request1 = new LabeledIntList("lable", new ArrayList()); - Batch> batch1 = createBatch(request1, null); - Truth.assertThat(batch1.getCallable()).isNull(); - - LabeledIntList request2 = new LabeledIntList("lable", 2); - Batch> batch2 = createBatch(request2); - - batch1.merge(batch2); - - Truth.assertThat(batch1.getByteCount()).isEqualTo(2); - Truth.assertThat(batch1.getCallable()).isNotNull(); - Truth.assertThat(batch1.getCallable()).isSameInstanceAs(batch2.getCallable()); - } - - @Test - public void testBatchElementCounter() { - ElementCounter>> counter = - new BatchElementCounter<>(SQUARER_BATCHING_DESC); - LabeledIntList request = new LabeledIntList("lable", 3); - Batch> batch = createBatch(request); - - Truth.assertThat(counter.count(batch)).isEqualTo(1); - } - - @Test - public void testBatchByteCounter() { - ElementCounter>> counter = new BatchByteCounter<>(); - LabeledIntList request = new LabeledIntList("lable", 3); - Batch> batch = createBatch(request); - - Truth.assertThat(counter.count(batch)).isEqualTo(3); - } - - @Test - public void testBatchMergerImpl() { - LabeledIntList request1 = new LabeledIntList("lable", 1); - Batch> batch1 = createBatch(request1); - - LabeledIntList request2 = new LabeledIntList("lable", 2); - Batch> batch2 = createBatch(request2); - - BatchMergerImpl> batchMerger = new BatchMergerImpl<>(); - batchMerger.merge(batch1, batch2); - - Truth.assertThat(batch1.getByteCount()).isEqualTo(3); - } - - private Batch> createBatch(LabeledIntList request) { - @SuppressWarnings("unchecked") - UnaryCallable> callable = - Mockito.mock(UnaryCallable.class); - return createBatch(request, callable); - } - - private Batch> createBatch( - LabeledIntList request, - UnaryCallable> callable) { - BatchingDescriptor> batchingDescriptor = SQUARER_BATCHING_DESC; - BatchedFuture> batchedFuture = new BatchedFuture<>(); - - return new Batch<>(batchingDescriptor, request, callable, batchedFuture); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/BatchedFutureTest.java b/gax/src/test/java/com/google/api/gax/rpc/BatchedFutureTest.java deleted file mode 100644 index 55ed0c226..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/BatchedFutureTest.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static com.google.common.util.concurrent.MoreExecutors.directExecutor; - -import com.google.api.core.ApiFunction; -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.common.truth.Truth; -import java.util.concurrent.TimeUnit; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class BatchedFutureTest { - @Test - public void testSet() throws Exception { - BatchedFuture future = BatchedFuture.create(); - Truth.assertThat(future.isDone()).isFalse(); - future.set(42); - Truth.assertThat(future.get()).isEqualTo(42); - Truth.assertThat(future.get(1, TimeUnit.HOURS)).isEqualTo(42); - Truth.assertThat(future.isDone()).isTrue(); - } - - @Test - public void testTransform() throws Exception { - BatchedFuture inputFuture = BatchedFuture.create(); - ApiFuture transformedFuture = - ApiFutures.transform( - inputFuture, - new ApiFunction() { - @Override - public String apply(Integer input) { - return input.toString(); - } - }, - directExecutor()); - inputFuture.set(6); - Truth.assertThat(transformedFuture.get()).isEqualTo("6"); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/BatchedRequestIssuerTest.java b/gax/src/test/java/com/google/api/gax/rpc/BatchedRequestIssuerTest.java deleted file mode 100644 index 293252afc..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/BatchedRequestIssuerTest.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.common.truth.Truth; -import java.util.concurrent.ExecutionException; -import org.junit.Assert; -import org.junit.Test; - -public class BatchedRequestIssuerTest { - - @Test - public void test() throws Exception { - BatchedFuture batchedFuture = BatchedFuture.create(); - BatchedRequestIssuer issuer = new BatchedRequestIssuer<>(batchedFuture, 2); - issuer.setResponse(1); - - Truth.assertThat(batchedFuture.isDone()).isFalse(); - issuer.sendResult(); - - Truth.assertThat(batchedFuture.isDone()).isTrue(); - Truth.assertThat(batchedFuture.get()).isEqualTo(1); - } - - @Test - public void testNullResult() throws Exception { - BatchedFuture batchedFuture = BatchedFuture.create(); - BatchedRequestIssuer issuer = new BatchedRequestIssuer<>(batchedFuture, 2); - issuer.setResponse(null); - - Truth.assertThat(batchedFuture.isDone()).isFalse(); - issuer.sendResult(); - - Truth.assertThat(batchedFuture.isDone()).isTrue(); - Truth.assertThat(batchedFuture.get()).isNull(); - } - - @Test - public void testException() throws Exception { - Exception thrownException = new IllegalArgumentException("bad!"); - - BatchedFuture batchedFuture = BatchedFuture.create(); - BatchedRequestIssuer issuer = new BatchedRequestIssuer<>(batchedFuture, 2); - issuer.setException(thrownException); - - Truth.assertThat(batchedFuture.isDone()).isFalse(); - issuer.sendResult(); - - Truth.assertThat(batchedFuture.isDone()).isTrue(); - try { - batchedFuture.get(); - Assert.fail("BatchedFuture should have thrown an exception"); - } catch (ExecutionException e) { - Truth.assertThat(e.getCause()).isInstanceOf(IllegalArgumentException.class); - } - } - - @Test - public void testNoResult() { - try { - BatchedFuture batchedFuture = BatchedFuture.create(); - BatchedRequestIssuer issuer = new BatchedRequestIssuer<>(batchedFuture, 2); - issuer.sendResult(); - Assert.fail("BatchedFuture should have thrown an exception"); - } catch (IllegalStateException expected) { - Truth.assertThat(expected) - .hasMessageThat() - .contains("Neither response nor exception were set in BatchedRequestIssuer"); - } - } - - @Test - public void testResponseAndException() { - try { - Exception thrownException = new IllegalArgumentException("bad!"); - BatchedFuture batchedFuture = BatchedFuture.create(); - BatchedRequestIssuer issuer = new BatchedRequestIssuer<>(batchedFuture, 2); - issuer.setResponse(1); - issuer.setException(thrownException); - Assert.fail("BatchedFuture should have thrown an exception"); - } catch (IllegalStateException expected) { - Truth.assertThat(expected) - .hasMessageThat() - .contains("Cannot set both exception and response"); - } - } - - @Test - public void testExceptionAndResponse() { - try { - Exception thrownException = new IllegalArgumentException("bad!"); - BatchedFuture batchedFuture = BatchedFuture.create(); - BatchedRequestIssuer issuer = new BatchedRequestIssuer<>(batchedFuture, 2); - issuer.setException(thrownException); - issuer.setResponse(1); - Assert.fail("BatchedFuture should have thrown an exception"); - } catch (IllegalStateException expected) { - Truth.assertThat(expected) - .hasMessageThat() - .contains("Cannot set both exception and response"); - } - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/BatcherFactoryTest.java b/gax/src/test/java/com/google/api/gax/rpc/BatcherFactoryTest.java deleted file mode 100644 index 254ba2831..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/BatcherFactoryTest.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static com.google.api.gax.rpc.testing.FakeBatchableApi.SquarerBatchingDescriptor; - -import com.google.api.gax.batching.BatchingSettings; -import com.google.api.gax.batching.FlowControlSettings; -import com.google.api.gax.batching.FlowController; -import com.google.api.gax.batching.FlowController.LimitExceededBehavior; -import com.google.api.gax.batching.PartitionKey; -import com.google.api.gax.batching.ThresholdBatcher; -import com.google.api.gax.rpc.testing.FakeBatchableApi.LabeledIntList; -import com.google.common.truth.Truth; -import java.util.List; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class BatcherFactoryTest { - private ScheduledExecutorService batchingExecutor; - - @Before - public void setUp() { - batchingExecutor = new ScheduledThreadPoolExecutor(1); - } - - @After - public void tearDown() { - batchingExecutor.shutdownNow(); - } - - @Test - public void testGetPushingBatcher() { - BatchingSettings batchingSettings = - BatchingSettings.newBuilder() - .setDelayThreshold(Duration.ofSeconds(1)) - .setElementCountThreshold(2L) - .setRequestByteThreshold(1000L) - .build(); - FlowControlSettings flowControlSettings = - FlowControlSettings.newBuilder() - .setLimitExceededBehavior(LimitExceededBehavior.Ignore) - .build(); - FlowController flowController = new FlowController(flowControlSettings); - BatcherFactory> batcherFactory = - new BatcherFactory<>( - new SquarerBatchingDescriptor(), batchingSettings, batchingExecutor, flowController); - Truth.assertThat(batcherFactory.getBatchingSettings()).isSameInstanceAs(batchingSettings); - - ThresholdBatcher>> batcherFoo = - batcherFactory.getPushingBatcher(new PartitionKey("foo")); - - ThresholdBatcher>> batcherFoo2 = - batcherFactory.getPushingBatcher(new PartitionKey("foo")); - - ThresholdBatcher>> batcherBar = - batcherFactory.getPushingBatcher(new PartitionKey("bar")); - - Truth.assertThat(batcherFoo).isSameInstanceAs(batcherFoo2); - Truth.assertThat(batcherFoo).isNotSameInstanceAs(batcherBar); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/BatchingCallSettingsTest.java b/gax/src/test/java/com/google/api/gax/rpc/BatchingCallSettingsTest.java deleted file mode 100644 index baafb1044..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/BatchingCallSettingsTest.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.gax.batching.BatchingSettings; -import com.google.api.gax.batching.FlowController; -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.common.collect.Sets; -import com.google.common.truth.Truth; -import java.util.Set; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class BatchingCallSettingsTest { - - @Test - public void testEmptyBuilder() { - @SuppressWarnings("unchecked") - BatchingDescriptor batchingDescriptor = - Mockito.mock(BatchingDescriptor.class); - BatchingCallSettings.Builder builder = - BatchingCallSettings.newBuilder(batchingDescriptor); - - Truth.assertThat(builder.getBatchingDescriptor()).isSameInstanceAs(batchingDescriptor); - Truth.assertThat(builder.getBatchingSettings()).isNull(); - Truth.assertThat(builder.getFlowController()).isNull(); - Truth.assertThat(builder.getRetryableCodes().size()).isEqualTo(0); - Truth.assertThat(builder.getRetrySettings()).isNotNull(); - - BatchingSettings batchingSettings = - BatchingSettings.newBuilder().setElementCountThreshold(1L).build(); - builder.setBatchingSettings(batchingSettings); - BatchingCallSettings settings = builder.build(); - - Truth.assertThat(settings.getBatchingDescriptor()).isSameInstanceAs(batchingDescriptor); - Truth.assertThat(settings.getBatchingSettings()).isSameInstanceAs(batchingSettings); - Truth.assertThat(settings.getFlowController()).isNotNull(); - Truth.assertThat(settings.getRetryableCodes().size()).isEqualTo(0); - Truth.assertThat(settings.getRetrySettings()).isNotNull(); - } - - @Test - public void testBuilder() { - @SuppressWarnings("unchecked") - BatchingDescriptor batchingDescriptor = - Mockito.mock(BatchingDescriptor.class); - BatchingCallSettings.Builder builder = - BatchingCallSettings.newBuilder(batchingDescriptor); - - BatchingSettings batchingSettings = - BatchingSettings.newBuilder().setElementCountThreshold(1L).build(); - FlowController flowController = Mockito.mock(FlowController.class); - Set retryCodes = Sets.newHashSet(Code.UNAVAILABLE); - RetrySettings retrySettings = - RetrySettings.newBuilder() - .setInitialRetryDelay(Duration.ofMillis(5)) - .setMaxRetryDelay(Duration.ofSeconds(1)) - .setRetryDelayMultiplier(2) - .setInitialRpcTimeout(Duration.ofMillis(100)) - .setMaxRpcTimeout(Duration.ofMillis(200)) - .setRpcTimeoutMultiplier(1.1) - .setJittered(true) - .setMaxAttempts(10) - .build(); - - builder.setBatchingSettings(batchingSettings); - builder.setFlowController(flowController); - builder.setRetryableCodes(retryCodes); - builder.setRetrySettings(retrySettings); - - Truth.assertThat(builder.getBatchingDescriptor()).isSameInstanceAs(batchingDescriptor); - Truth.assertThat(builder.getBatchingSettings()).isSameInstanceAs(batchingSettings); - Truth.assertThat(builder.getFlowController()).isSameInstanceAs(flowController); - Truth.assertThat(builder.getRetryableCodes().size()).isEqualTo(1); - Truth.assertThat(builder.getRetrySettings()).isEqualTo(retrySettings); - - BatchingCallSettings settings = builder.build(); - - Truth.assertThat(settings.getBatchingDescriptor()).isSameInstanceAs(batchingDescriptor); - Truth.assertThat(settings.getBatchingSettings()).isSameInstanceAs(batchingSettings); - Truth.assertThat(settings.getFlowController()).isSameInstanceAs(flowController); - Truth.assertThat(settings.getRetryableCodes().size()).isEqualTo(1); - Truth.assertThat(settings.getRetrySettings()).isEqualTo(retrySettings); - } - - @Test - public void testBuilderFromSettings() throws Exception { - @SuppressWarnings("unchecked") - BatchingDescriptor batchingDescriptor = - Mockito.mock(BatchingDescriptor.class); - BatchingCallSettings.Builder builder = - BatchingCallSettings.newBuilder(batchingDescriptor); - - BatchingSettings batchingSettings = - BatchingSettings.newBuilder().setElementCountThreshold(1L).build(); - FlowController flowController = Mockito.mock(FlowController.class); - Set retryCodes = Sets.newHashSet(Code.UNAVAILABLE); - RetrySettings retrySettings = - RetrySettings.newBuilder() - .setInitialRetryDelay(Duration.ofMillis(5)) - .setMaxRetryDelay(Duration.ofSeconds(1)) - .setRetryDelayMultiplier(2) - .setInitialRpcTimeout(Duration.ofMillis(100)) - .setMaxRpcTimeout(Duration.ofMillis(200)) - .setRpcTimeoutMultiplier(1.1) - .setJittered(true) - .setMaxAttempts(10) - .build(); - - builder.setBatchingSettings(batchingSettings); - builder.setFlowController(flowController); - builder.setRetryableCodes(retryCodes); - builder.setRetrySettings(retrySettings); - - BatchingCallSettings settings = builder.build(); - BatchingCallSettings.Builder newBuilder = settings.toBuilder(); - - Truth.assertThat(newBuilder.getBatchingDescriptor()).isSameInstanceAs(batchingDescriptor); - Truth.assertThat(newBuilder.getBatchingSettings()).isSameInstanceAs(batchingSettings); - Truth.assertThat(newBuilder.getFlowController()).isSameInstanceAs(flowController); - Truth.assertThat(newBuilder.getRetryableCodes().size()).isEqualTo(1); - Truth.assertThat(newBuilder.getRetrySettings()).isEqualTo(retrySettings); - } - - @Test - public void testNoFlowControlSettings() throws Exception { - @SuppressWarnings("unchecked") - BatchingDescriptor batchingDescriptor = - Mockito.mock(BatchingDescriptor.class); - BatchingCallSettings.Builder builder = - BatchingCallSettings.newBuilder(batchingDescriptor); - - BatchingSettings batchingSettings = - BatchingSettings.newBuilder().setElementCountThreshold(1L).build(); - - builder.setBatchingSettings(batchingSettings); - - BatchingCallSettings settings = builder.build(); - - Truth.assertThat(settings.getFlowController()).isNotNull(); - } - - @Test - public void testToString() { - @SuppressWarnings("unchecked") - BatchingDescriptor batchingDescriptor = - Mockito.mock(BatchingDescriptor.class); - BatchingCallSettings.Builder builder = - BatchingCallSettings.newBuilder(batchingDescriptor); - - BatchingSettings batchingSettings = - BatchingSettings.newBuilder().setElementCountThreshold(1L).build(); - FlowController flowController = Mockito.mock(FlowController.class); - Set retryCodes = Sets.newHashSet(Code.UNAVAILABLE); - RetrySettings retrySettings = RetrySettings.newBuilder().build(); - - builder - .setRetryableCodes(retryCodes) - .setRetrySettings(retrySettings) - .setBatchingSettings(batchingSettings) - .setFlowController(flowController); - - Truth.assertThat(builder.build().toString()).contains("retryableCodes=" + retryCodes); - Truth.assertThat(builder.build().toString()).contains("retrySettings=" + retrySettings); - Truth.assertThat(builder.build().toString()).contains("batchingSettings=" + batchingSettings); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/BatchingCallableTest.java b/gax/src/test/java/com/google/api/gax/rpc/BatchingCallableTest.java deleted file mode 100644 index a0234a441..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/BatchingCallableTest.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.ApiFuture; -import com.google.api.gax.batching.BatchingSettings; -import com.google.api.gax.batching.FlowControlSettings; -import com.google.api.gax.batching.FlowController; -import com.google.api.gax.batching.FlowController.LimitExceededBehavior; -import com.google.api.gax.rpc.testing.FakeBatchableApi; -import com.google.api.gax.rpc.testing.FakeBatchableApi.LabeledIntList; -import com.google.api.gax.rpc.testing.FakeBatchableApi.SquarerBatchingDescriptor; -import com.google.api.gax.rpc.testing.FakeCallContext; -import com.google.common.truth.Truth; -import java.util.List; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class BatchingCallableTest { - private ScheduledExecutorService batchingExecutor; - - @Before - public void setUp() { - batchingExecutor = new ScheduledThreadPoolExecutor(2); - } - - @After - public void tearDown() { - batchingExecutor.shutdownNow(); - } - - @Test - public void testBatchedCall() throws Exception { - - BatchingSettings batchingSettings = - BatchingSettings.newBuilder() - .setDelayThreshold(Duration.ofSeconds(10)) - .setElementCountThreshold(2L) - .setRequestByteThreshold(1000L) - .build(); - FlowControlSettings flowControlSettings = - FlowControlSettings.newBuilder() - .setLimitExceededBehavior(LimitExceededBehavior.Ignore) - .build(); - FlowController flowController = new FlowController(flowControlSettings); - BatcherFactory> batcherFactory = - new BatcherFactory<>( - new SquarerBatchingDescriptor(), batchingSettings, batchingExecutor, flowController); - - BatchingCallable> batchingCallable = - new BatchingCallable<>( - FakeBatchableApi.callLabeledIntSquarer, - FakeBatchableApi.SQUARER_BATCHING_DESC, - batcherFactory); - - LabeledIntList request1 = new LabeledIntList("label", 2); - ApiFuture> future1 = - batchingCallable.futureCall(request1, FakeCallContext.createDefault()); - // Assume it won't take 10 seconds (the batching delay threshold) to check the first future - Truth.assertThat(future1.isDone()).isFalse(); - - LabeledIntList request2 = new LabeledIntList("label", 3); - ApiFuture> future2 = - batchingCallable.futureCall(request2, FakeCallContext.createDefault()); - - List response1 = future1.get(); - List response2 = future2.get(); - - Truth.assertThat(response1.size()).isEqualTo(1); - Truth.assertThat(response1.get(0)).isEqualTo(2 * 2); - - Truth.assertThat(response2.size()).isEqualTo(1); - Truth.assertThat(response2.get(0)).isEqualTo(3 * 3); - } - - @Test - public void testUnbatchedCall() throws Exception { - - BatchingSettings batchingSettings = BatchingSettings.newBuilder().setIsEnabled(false).build(); - FlowControlSettings flowControlSettings = - FlowControlSettings.newBuilder() - .setLimitExceededBehavior(LimitExceededBehavior.Ignore) - .build(); - FlowController flowController = new FlowController(flowControlSettings); - BatcherFactory> batcherFactory = - new BatcherFactory<>( - new SquarerBatchingDescriptor(), batchingSettings, batchingExecutor, flowController); - - BatchingCallable> batchingCallable = - new BatchingCallable<>( - FakeBatchableApi.callLabeledIntSquarer, - FakeBatchableApi.SQUARER_BATCHING_DESC, - batcherFactory); - - LabeledIntList request1 = new LabeledIntList("label", 2); - ApiFuture> future1 = - batchingCallable.futureCall(request1, FakeCallContext.createDefault()); - List response1 = future1.get(); - - Truth.assertThat(response1.size()).isEqualTo(1); - Truth.assertThat(response1.get(0)).isEqualTo(2 * 2); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/BatchingTest.java b/gax/src/test/java/com/google/api/gax/rpc/BatchingTest.java deleted file mode 100644 index 2b4a07596..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/BatchingTest.java +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static com.google.api.gax.rpc.testing.FakeBatchableApi.SQUARER_BATCHING_DESC; -import static com.google.api.gax.rpc.testing.FakeBatchableApi.callLabeledIntSquarer; - -import com.google.api.core.ApiFuture; -import com.google.api.gax.batching.BatchingSettings; -import com.google.api.gax.batching.FlowControlSettings; -import com.google.api.gax.batching.FlowController.LimitExceededBehavior; -import com.google.api.gax.batching.TrackedFlowController; -import com.google.api.gax.rpc.testing.FakeBatchableApi.LabeledIntList; -import com.google.api.gax.rpc.testing.FakeCallContext; -import com.google.api.gax.rpc.testing.FakeCallableFactory; -import com.google.api.gax.rpc.testing.FakeChannel; -import com.google.api.gax.rpc.testing.FakeTransportChannel; -import com.google.common.truth.Truth; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class BatchingTest { - - private ScheduledExecutorService batchingExecutor; - private ClientContext clientContext; - - @Before - public void setUp() { - batchingExecutor = new ScheduledThreadPoolExecutor(1); - clientContext = - ClientContext.newBuilder() - .setExecutor(batchingExecutor) - .setDefaultCallContext(FakeCallContext.createDefault()) - .setTransportChannel(FakeTransportChannel.create(new FakeChannel())) - .build(); - } - - @After - public void teardown() { - batchingExecutor.shutdownNow(); - } - - @Test - public void batching() throws Exception { - BatchingSettings batchingSettings = - BatchingSettings.newBuilder() - .setDelayThreshold(Duration.ofSeconds(1)) - .setElementCountThreshold(2L) - .build(); - BatchingCallSettings> batchingCallSettings = - BatchingCallSettings.newBuilder(SQUARER_BATCHING_DESC) - .setBatchingSettings(batchingSettings) - .build(); - UnaryCallable> callable = - FakeCallableFactory.createBatchingCallable( - callLabeledIntSquarer, batchingCallSettings, clientContext); - ApiFuture> f1 = callable.futureCall(new LabeledIntList("one", 1, 2)); - ApiFuture> f2 = callable.futureCall(new LabeledIntList("one", 3, 4)); - Truth.assertThat(f1.get()).isEqualTo(Arrays.asList(1, 4)); - Truth.assertThat(f2.get()).isEqualTo(Arrays.asList(9, 16)); - } - - @Test - public void batchingWithFlowControl() throws Exception { - BatchingSettings batchingSettings = - BatchingSettings.newBuilder() - .setDelayThreshold(Duration.ofSeconds(1)) - .setElementCountThreshold(4L) - .setRequestByteThreshold(null) - .setFlowControlSettings( - FlowControlSettings.newBuilder() - .setLimitExceededBehavior(LimitExceededBehavior.Block) - .setMaxOutstandingElementCount(10L) - .setMaxOutstandingRequestBytes(10L) - .build()) - .build(); - TrackedFlowController trackedFlowController = - new TrackedFlowController(batchingSettings.getFlowControlSettings()); - - Truth.assertThat(trackedFlowController.getElementsReserved()).isEqualTo(0); - Truth.assertThat(trackedFlowController.getElementsReleased()).isEqualTo(0); - Truth.assertThat(trackedFlowController.getBytesReserved()).isEqualTo(0); - Truth.assertThat(trackedFlowController.getBytesReleased()).isEqualTo(0); - Truth.assertThat(trackedFlowController.getCallsToReserve()).isEqualTo(0); - Truth.assertThat(trackedFlowController.getCallsToRelease()).isEqualTo(0); - - LabeledIntList requestA = new LabeledIntList("one", 1, 2); - LabeledIntList requestB = new LabeledIntList("one", 3, 4); - - BatchingCallSettings> batchingCallSettings = - BatchingCallSettings.newBuilder(SQUARER_BATCHING_DESC) - .setBatchingSettings(batchingSettings) - .setFlowController(trackedFlowController) - .build(); - Callables.BatchingCreateResult> batchingCreateResult = - Callables.batchingImpl(callLabeledIntSquarer, batchingCallSettings, clientContext); - ApiFuture> f1 = - batchingCreateResult - .getUnaryCallable() - .futureCall(requestA, FakeCallContext.createDefault()); - ApiFuture> f2 = - batchingCreateResult - .getUnaryCallable() - .futureCall(requestB, FakeCallContext.createDefault()); - Truth.assertThat(f1.get()).isEqualTo(Arrays.asList(1, 4)); - Truth.assertThat(f2.get()).isEqualTo(Arrays.asList(9, 16)); - - batchingCreateResult - .getBatcherFactory() - .getPushingBatcher(SQUARER_BATCHING_DESC.getBatchPartitionKey(requestA)) - .pushCurrentBatch() - .get(); - - // Check that the number of bytes is correct even when requests are merged, and the merged - // request consumes fewer bytes. - Truth.assertThat(trackedFlowController.getElementsReserved()).isEqualTo(4); - Truth.assertThat(trackedFlowController.getElementsReleased()).isEqualTo(4); - Truth.assertThat(trackedFlowController.getBytesReserved()).isEqualTo(8); - Truth.assertThat(trackedFlowController.getBytesReleased()).isEqualTo(8); - Truth.assertThat(trackedFlowController.getCallsToReserve()).isEqualTo(2); - Truth.assertThat(trackedFlowController.getCallsToRelease()).isEqualTo(1); - } - - @Test - public void batchingDisabled() throws Exception { - BatchingSettings batchingSettings = BatchingSettings.newBuilder().setIsEnabled(false).build(); - - BatchingCallSettings> batchingCallSettings = - BatchingCallSettings.newBuilder(SQUARER_BATCHING_DESC) - .setBatchingSettings(batchingSettings) - .build(); - UnaryCallable> callable = - FakeCallableFactory.createBatchingCallable( - callLabeledIntSquarer, batchingCallSettings, clientContext); - ApiFuture> f1 = callable.futureCall(new LabeledIntList("one", 1, 2)); - ApiFuture> f2 = callable.futureCall(new LabeledIntList("one", 3, 4)); - Truth.assertThat(f1.get()).isEqualTo(Arrays.asList(1, 4)); - Truth.assertThat(f2.get()).isEqualTo(Arrays.asList(9, 16)); - } - - @Test - public void batchingWithBlockingCallThreshold() throws Exception { - BatchingSettings batchingSettings = - BatchingSettings.newBuilder() - .setDelayThreshold(Duration.ofSeconds(1)) - .setElementCountThreshold(2L) - .build(); - BatchingCallSettings> batchingCallSettings = - BatchingCallSettings.newBuilder(SQUARER_BATCHING_DESC) - .setBatchingSettings(batchingSettings) - .build(); - UnaryCallable> callable = - FakeCallableFactory.createBatchingCallable( - callLabeledIntSquarer, batchingCallSettings, clientContext); - ApiFuture> f1 = callable.futureCall(new LabeledIntList("one", 1)); - ApiFuture> f2 = callable.futureCall(new LabeledIntList("one", 3)); - Truth.assertThat(f1.get()).isEqualTo(Arrays.asList(1)); - Truth.assertThat(f2.get()).isEqualTo(Arrays.asList(9)); - } - - private static UnaryCallable> callLabeledIntExceptionThrower = - new UnaryCallable>() { - @Override - public ApiFuture> futureCall(LabeledIntList request, ApiCallContext context) { - return RetryingTest.>immediateFailedFuture( - new IllegalArgumentException("I FAIL!!")); - } - }; - - @Test - public void batchingException() throws Exception { - BatchingSettings batchingSettings = - BatchingSettings.newBuilder() - .setDelayThreshold(Duration.ofSeconds(1)) - .setElementCountThreshold(2L) - .build(); - BatchingCallSettings> batchingCallSettings = - BatchingCallSettings.newBuilder(SQUARER_BATCHING_DESC) - .setBatchingSettings(batchingSettings) - .build(); - UnaryCallable> callable = - FakeCallableFactory.createBatchingCallable( - callLabeledIntExceptionThrower, batchingCallSettings, clientContext); - ApiFuture> f1 = callable.futureCall(new LabeledIntList("one", 1, 2)); - ApiFuture> f2 = callable.futureCall(new LabeledIntList("one", 3, 4)); - try { - f1.get(); - Assert.fail("Expected exception from batching call"); - } catch (ExecutionException e) { - // expected - } - try { - f2.get(); - Assert.fail("Expected exception from batching call"); - } catch (ExecutionException e) { - // expected - } - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/BidiStreamingCallableTest.java b/gax/src/test/java/com/google/api/gax/rpc/BidiStreamingCallableTest.java deleted file mode 100644 index 76ecb1d51..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/BidiStreamingCallableTest.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.api.gax.rpc.testing.FakeCallContext; -import com.google.api.gax.rpc.testing.FakeCallableFactory; -import com.google.api.gax.rpc.testing.FakeChannel; -import com.google.api.gax.rpc.testing.FakeStatusCode; -import com.google.api.gax.rpc.testing.FakeStreamingApi.BidiStreamingStashCallable; -import com.google.api.gax.rpc.testing.FakeTransportChannel; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import org.junit.Test; - -public class BidiStreamingCallableTest { - private ClientContext clientContext = - ClientContext.newBuilder() - .setDefaultCallContext(FakeCallContext.createDefault()) - .setTransportChannel(FakeTransportChannel.create(new FakeChannel())) - .build(); - - @Test - public void bidiStreaming_ResponseObserver() { - BidiStreamingStashCallable callIntList = - new BidiStreamingStashCallable<>(Arrays.asList(0, 1, 2)); - - BidiStreamingCallable callable = - FakeCallableFactory.createBidiStreamingCallable( - callIntList, - StreamingCallSettings.newBuilder().build(), - clientContext); - - AccumulatingStreamObserver responseObserver = new AccumulatingStreamObserver(); - - ClientStream stream = callable.splitCall(responseObserver); - stream.send(3); - stream.send(4); - stream.send(5); - stream.closeSend(); - - assertThat(responseObserver.getValues()).containsExactly(0, 1, 2).inOrder(); - assertThat(callIntList.getActualRequests()).containsExactly(3, 4, 5).inOrder(); - } - - @Test - public void bidiStreaming_BidiStreamObserver() throws InterruptedException { - BidiStreamingStashCallable callIntList = - new BidiStreamingStashCallable<>(Arrays.asList(0, 1, 2)); - - BidiStreamingCallable callable = - FakeCallableFactory.createBidiStreamingCallable( - callIntList, - StreamingCallSettings.newBuilder().build(), - clientContext); - - AccumulatingBidiObserver observer = new AccumulatingBidiObserver(Arrays.asList(3, 4, 5)); - callable.call(observer); - - assertThat(observer.getResponses()).containsExactly(0, 1, 2).inOrder(); - assertThat(callIntList.getActualRequests()).containsExactly(3, 4, 5).inOrder(); - } - - @Test - public void bidiStreaming_BidiStream() { - BidiStreamingStashCallable callIntList = - new BidiStreamingStashCallable<>(Arrays.asList(0, 1, 2)); - BidiStreamingCallable callable = - FakeCallableFactory.createBidiStreamingCallable( - callIntList, - StreamingCallSettings.newBuilder().build(), - clientContext); - - BidiStream stream = callIntList.call(); - stream.send(3); - stream.send(4); - stream.send(5); - stream.closeSend(); - - assertThat(callIntList.getActualRequests()).containsExactly(3, 4, 5).inOrder(); - assertThat(stream).containsExactly(0, 1, 2).inOrder(); - } - - private static class AccumulatingBidiObserver implements BidiStreamObserver { - private final List received = new ArrayList<>(); - private Throwable error; - private final CountDownLatch latch = new CountDownLatch(1); - - private final Iterator toSend; - - AccumulatingBidiObserver(Collection toSend) { - this.toSend = toSend.iterator(); - } - - @Override - public void onStart(StreamController controller) { - // no-op - } - - @Override - public void onResponse(Integer response) { - received.add(response); - } - - @Override - public void onComplete() { - latch.countDown(); - } - - @Override - public void onError(Throwable t) { - error = t; - latch.countDown(); - } - - @Override - public void onReady(ClientStream stream) { - while (toSend.hasNext()) { - if (stream.isSendReady()) { - stream.send(toSend.next()); - } else { - // It's OK we haven't consumed the whole iterator; - // onReady will be called again when the network becomes free. - return; - } - } - // We ran out of things to send. - stream.closeSend(); - } - - List getResponses() throws InterruptedException { - latch.await(); - if (error != null) { - throw ApiExceptionFactory.createException(error, FakeStatusCode.of(Code.UNKNOWN), false); - } - return received; - } - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/CallableTest.java b/gax/src/test/java/com/google/api/gax/rpc/CallableTest.java deleted file mode 100644 index eaa0be04c..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/CallableTest.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.api.core.SettableApiFuture; -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.rpc.testing.FakeCallContext; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.Spy; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.mockito.quality.Strictness; -import org.threeten.bp.Duration; - -public class CallableTest { - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS); - - @Mock private UnaryCallable innerCallable; - private SettableApiFuture innerResult; - - @Mock private ServerStreamingCallable innerServerStreamingCallable; - - private RetrySettings retrySettings = - RetrySettings.newBuilder() - .setInitialRpcTimeout(Duration.ofMillis(5L)) - .setMaxRpcTimeout(Duration.ofMillis(5L)) - .setTotalTimeout(Duration.ofMillis(10L)) - .build(); - - @Spy private ApiCallContext callContext = FakeCallContext.createDefault(); - - @Spy - private ApiCallContext callContextWithRetrySettings = - FakeCallContext.createDefault().withRetrySettings(retrySettings); - - private ClientContext clientContext = - ClientContext.newBuilder().setDefaultCallContext(callContext).build(); - - @Test - public void testNonRetriedCallable() throws Exception { - innerResult = SettableApiFuture.create(); - when(innerCallable.futureCall(anyString(), any(ApiCallContext.class))).thenReturn(innerResult); - Duration timeout = Duration.ofMillis(5L); - - UnaryCallSettings callSettings = - UnaryCallSettings.newUnaryCallSettingsBuilder().setSimpleTimeoutNoRetries(timeout).build(); - UnaryCallable callable = - Callables.retrying(innerCallable, callSettings, clientContext); - innerResult.set("No, my refrigerator is not running!"); - - callable.futureCall("Is your refrigerator running?", callContext); - verify(callContext, atLeastOnce()).getRetrySettings(); - verify(callContext).getTimeout(); - verify(callContext).withTimeout(timeout); - } - - @Test - public void testNonRetriedCallableWithRetrySettings() throws Exception { - innerResult = SettableApiFuture.create(); - when(innerCallable.futureCall(anyString(), any(ApiCallContext.class))).thenReturn(innerResult); - - UnaryCallSettings callSettings = - UnaryCallSettings.newUnaryCallSettingsBuilder() - .setSimpleTimeoutNoRetries(Duration.ofMillis(10L)) - .build(); - UnaryCallable callable = - Callables.retrying(innerCallable, callSettings, clientContext); - innerResult.set("No, my refrigerator is not running!"); - - Duration timeout = retrySettings.getInitialRpcTimeout(); - - callable.futureCall("Is your refrigerator running?", callContextWithRetrySettings); - - verify(callContextWithRetrySettings, atLeastOnce()).getRetrySettings(); - verify(callContextWithRetrySettings).getTimeout(); - verify(callContextWithRetrySettings).withTimeout(timeout); - } - - @Test - public void testNonRetriedServerStreamingCallable() throws Exception { - Duration timeout = Duration.ofMillis(5L); - ServerStreamingCallSettings callSettings = - ServerStreamingCallSettings.newBuilder().setSimpleTimeoutNoRetries(timeout).build(); - ServerStreamingCallable callable = - Callables.retrying(innerServerStreamingCallable, callSettings, clientContext); - - callable.call("Is your refrigerator running?", callContext); - - verify(callContext, atLeastOnce()).getRetrySettings(); - verify(callContext).getTimeout(); - verify(callContext).withTimeout(timeout); - } - - @Test - public void testNonRetriedServerStreamingCallableWithRetrySettings() throws Exception { - ServerStreamingCallSettings callSettings = - ServerStreamingCallSettings.newBuilder() - .setSimpleTimeoutNoRetries(Duration.ofMillis(10L)) - .build(); - ServerStreamingCallable callable = - Callables.retrying(innerServerStreamingCallable, callSettings, clientContext); - - Duration timeout = retrySettings.getTotalTimeout(); - - callable.call("Is your refrigerator running?", callContextWithRetrySettings); - - verify(callContextWithRetrySettings, atLeastOnce()).getRetrySettings(); - verify(callContextWithRetrySettings).getTimeout(); - verify(callContextWithRetrySettings).withTimeout(timeout); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/CancellationHelpers.java b/gax/src/test/java/com/google/api/gax/rpc/CancellationHelpers.java deleted file mode 100644 index 446090bac..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/CancellationHelpers.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.ApiFuture; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.locks.LockSupport; - -/** - * CancellationHelpers provides helpers for cancellation tests which perform cancellation in a - * deterministic way. - */ -public class CancellationHelpers { - - public static void cancelInThreadAfterLatchCountDown( - final ApiFuture resultFuture, final CountDownLatch latch) { - Thread t = - new Thread( - new Runnable() { - @Override - public void run() { - try { - latch.await(); - while (!resultFuture.cancel(true) && !resultFuture.isDone()) { - LockSupport.parkNanos(1000L); - } - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - }); - t.start(); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/CancellationTest.java b/gax/src/test/java/com/google/api/gax/rpc/CancellationTest.java deleted file mode 100644 index bb36d863c..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/CancellationTest.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.AbstractApiFuture; -import com.google.api.core.ApiFuture; -import com.google.api.core.SettableApiFuture; -import com.google.api.gax.core.FakeApiClock; -import com.google.api.gax.core.RecordingScheduler; -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.rpc.testing.FakeCallContext; -import com.google.api.gax.rpc.testing.FakeCallableFactory; -import com.google.api.gax.rpc.testing.FakeChannel; -import com.google.api.gax.rpc.testing.FakeStatusCode; -import com.google.api.gax.rpc.testing.FakeTransportChannel; -import com.google.common.collect.Lists; -import com.google.common.truth.Truth; -import java.util.List; -import java.util.concurrent.CancellationException; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class CancellationTest { - - @SuppressWarnings("unchecked") - private UnaryCallable callInt = Mockito.mock(UnaryCallable.class); - - private static final RetrySettings FAST_RETRY_SETTINGS = - RetrySettings.newBuilder() - .setInitialRetryDelay(Duration.ofMillis(2L)) - .setRetryDelayMultiplier(1) - .setMaxRetryDelay(Duration.ofMillis(2L)) - .setInitialRpcTimeout(Duration.ofMillis(2L)) - .setRpcTimeoutMultiplier(1) - .setMaxRpcTimeout(Duration.ofMillis(2L)) - .setTotalTimeout(Duration.ofMillis(20L)) - .build(); - - private static final RetrySettings SLOW_RETRY_SETTINGS = - RetrySettings.newBuilder() - .setInitialRetryDelay(Duration.ofMillis(3000L)) - .setRetryDelayMultiplier(1) - .setMaxRetryDelay(Duration.ofMillis(3000L)) - .setInitialRpcTimeout(Duration.ofMillis(3000L)) - .setRpcTimeoutMultiplier(1) - .setMaxRpcTimeout(Duration.ofMillis(3000L)) - .setTotalTimeout(Duration.ofMillis(3000L)) - .build(); - - private FakeApiClock fakeClock; - private RecordingScheduler executor; - private ClientContext clientContext; - - @Before - public void resetClock() { - fakeClock = new FakeApiClock(System.nanoTime()); - executor = RecordingScheduler.create(fakeClock); - clientContext = - ClientContext.newBuilder() - .setExecutor(executor) - .setClock(fakeClock) - .setDefaultCallContext(FakeCallContext.createDefault()) - .setTransportChannel(FakeTransportChannel.create(new FakeChannel())) - .build(); - } - - @After - public void teardown() { - executor.shutdownNow(); - } - - @Test - public void cancellationBeforeGetOnRetryingCallable() throws Exception { - try { - Mockito.when(callInt.futureCall((Integer) Mockito.any(), (ApiCallContext) Mockito.any())) - .thenReturn(SettableApiFuture.create()); - - UnaryCallSettings callSettings = - RetryingTest.createSettings(FAST_RETRY_SETTINGS); - UnaryCallable callable = - FakeCallableFactory.createUnaryCallable(callInt, callSettings, clientContext); - - ApiFuture resultFuture = callable.futureCall(0); - resultFuture.cancel(true); - resultFuture.get(); - Assert.fail("Callable should have thrown an exception"); - } catch (CancellationException expected) { - Truth.assertThat(expected).hasMessageThat().contains("Task was cancelled"); - } - } - - private static class CancellationTrackingFuture extends AbstractApiFuture { - private volatile boolean cancelled = false; - - public static CancellationTrackingFuture create() { - return new CancellationTrackingFuture<>(); - } - - private CancellationTrackingFuture() {} - - @Override - protected void interruptTask() { - cancelled = true; - } - - public boolean isCancelled() { - return cancelled; - } - } - - private static class LatchCountDownFutureCallable - extends UnaryCallable { - private CountDownLatch callLatch; - private List> injectedFutures; - - @SuppressWarnings("unchecked") - public LatchCountDownFutureCallable( - CountDownLatch callLatch, ApiFuture injectedFuture) { - this(callLatch, Lists.newArrayList(injectedFuture)); - } - - public LatchCountDownFutureCallable( - CountDownLatch callLatch, List> injectedFutures) { - this.callLatch = callLatch; - this.injectedFutures = Lists.newArrayList(injectedFutures); - } - - @Override - public ApiFuture futureCall(RequestT request, ApiCallContext context) { - callLatch.countDown(); - return injectedFutures.remove(0); - } - } - - @Test - public void cancellationDuringFirstCall() throws Exception { - CancellationTrackingFuture innerFuture = CancellationTrackingFuture.create(); - CountDownLatch callIssuedLatch = new CountDownLatch(1); - UnaryCallable innerCallable = - new LatchCountDownFutureCallable<>(callIssuedLatch, innerFuture); - - UnaryCallSettings callSettings = - RetryingTest.createSettings(FAST_RETRY_SETTINGS); - UnaryCallable callable = - FakeCallableFactory.createUnaryCallable( - innerCallable, - callSettings, - clientContext.toBuilder().setExecutor(new ScheduledThreadPoolExecutor(1)).build()); - - ApiFuture resultFuture = callable.futureCall(0); - CancellationHelpers.cancelInThreadAfterLatchCountDown(resultFuture, callIssuedLatch); - CancellationException gotException = null; - try { - resultFuture.get(); - } catch (CancellationException e) { - gotException = e; - } - Truth.assertThat(gotException).isNotNull(); - Truth.assertThat(innerFuture.isCancelled()).isTrue(); - } - - @Test - public void cancellationDuringRetryDelay() throws Exception { - Throwable throwable = - new UnavailableException(null, FakeStatusCode.of(StatusCode.Code.UNAVAILABLE), true); - CancellationTrackingFuture innerFuture = CancellationTrackingFuture.create(); - Mockito.when(callInt.futureCall((Integer) Mockito.any(), (ApiCallContext) Mockito.any())) - .thenReturn(RetryingTest.immediateFailedFuture(throwable)) - .thenReturn(innerFuture); - - CountDownLatch retryScheduledLatch = new CountDownLatch(1); - LatchCountDownScheduler scheduler = LatchCountDownScheduler.get(retryScheduledLatch, 0L, 0L); - UnaryCallSettings callSettings = - RetryingTest.createSettings(SLOW_RETRY_SETTINGS); - UnaryCallable callable = - FakeCallableFactory.createUnaryCallable( - callInt, callSettings, clientContext.toBuilder().setExecutor(scheduler).build()); - - ApiFuture resultFuture = callable.futureCall(0); - CancellationHelpers.cancelInThreadAfterLatchCountDown(resultFuture, retryScheduledLatch); - CancellationException gotException = null; - try { - resultFuture.get(); - } catch (CancellationException e) { - gotException = e; - } - Truth.assertThat(gotException).isNotNull(); - Truth.assertThat(resultFuture.isDone()).isTrue(); - Truth.assertThat(resultFuture.isCancelled()).isTrue(); - Truth.assertThat(innerFuture.isCancelled()).isFalse(); - - scheduler.shutdownNow(); - } - - @Test - public void cancellationDuringSecondCall() throws Exception { - Throwable throwable = - new UnavailableException(null, FakeStatusCode.of(StatusCode.Code.UNAVAILABLE), true); - ApiFuture failingFuture = RetryingTest.immediateFailedFuture(throwable); - CancellationTrackingFuture innerFuture = CancellationTrackingFuture.create(); - CountDownLatch callIssuedLatch = new CountDownLatch(2); - @SuppressWarnings("unchecked") - UnaryCallable innerCallable = - new LatchCountDownFutureCallable<>( - callIssuedLatch, Lists.newArrayList(failingFuture, innerFuture)); - - UnaryCallSettings callSettings = - RetryingTest.createSettings(FAST_RETRY_SETTINGS); - UnaryCallable callable = - FakeCallableFactory.createUnaryCallable( - innerCallable, - callSettings, - clientContext.toBuilder().setExecutor(new ScheduledThreadPoolExecutor(1)).build()); - - ApiFuture resultFuture = callable.futureCall(0); - CancellationHelpers.cancelInThreadAfterLatchCountDown(resultFuture, callIssuedLatch); - CancellationException gotException = null; - try { - resultFuture.get(); - } catch (CancellationException e) { - gotException = e; - } - Truth.assertThat(gotException).isNotNull(); - Truth.assertThat(resultFuture.isDone()).isTrue(); - Truth.assertThat(resultFuture.isCancelled()).isTrue(); - Truth.assertThat(innerFuture.isDone()).isTrue(); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/CheckingAttemptCallableTest.java b/gax/src/test/java/com/google/api/gax/rpc/CheckingAttemptCallableTest.java deleted file mode 100644 index 92554616b..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/CheckingAttemptCallableTest.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.api.core.SettableApiFuture; -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.retrying.RetryingFuture; -import com.google.api.gax.retrying.TimedAttemptSettings; -import com.google.api.gax.rpc.testing.FakeCallContext; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.junit.MockitoJUnitRunner; -import org.mockito.stubbing.Answer; -import org.threeten.bp.Duration; - -@RunWith(MockitoJUnitRunner.class) -public class CheckingAttemptCallableTest { - @Mock UnaryCallable mockInnerCallable; - ArgumentCaptor capturedCallContext; - @Mock RetryingFuture mockExternalFuture; - TimedAttemptSettings currentAttemptSettings; - - @Before - public void setUp() { - capturedCallContext = ArgumentCaptor.forClass(ApiCallContext.class); - Mockito.when(mockInnerCallable.futureCall(Mockito.any(), capturedCallContext.capture())) - .thenReturn(SettableApiFuture.create()); - - currentAttemptSettings = - TimedAttemptSettings.newBuilder() - .setGlobalSettings(RetrySettings.newBuilder().build()) - .setAttemptCount(0) - .setOverallAttemptCount(0) - .setFirstAttemptStartTimeNanos(0) - .setRetryDelay(Duration.ofSeconds(1)) - .setRandomizedRetryDelay(Duration.ofSeconds(1)) - .setRpcTimeout(Duration.ZERO) - .build(); - - Mockito.when(mockExternalFuture.getAttemptSettings()) - .thenAnswer( - new Answer() { - @Override - public TimedAttemptSettings answer(InvocationOnMock invocation) throws Throwable { - return currentAttemptSettings; - } - }); - } - - @Test - public void testRpcTimeout() { - CheckingAttemptCallable callable = - new CheckingAttemptCallable<>(mockInnerCallable, FakeCallContext.createDefault()); - callable.setExternalFuture(mockExternalFuture); - - // Make sure that the rpc timeout is set - Duration timeout = Duration.ofSeconds(10); - currentAttemptSettings = currentAttemptSettings.toBuilder().setRpcTimeout(timeout).build(); - - callable.call(); - - assertThat(capturedCallContext.getValue().getTimeout()).isEqualTo(timeout); - - // Make sure that subsequent attempts can extend the time out - Duration longerTimeout = Duration.ofSeconds(20); - currentAttemptSettings = - currentAttemptSettings.toBuilder().setRpcTimeout(longerTimeout).build(); - callable.call(); - assertThat(capturedCallContext.getValue().getTimeout()).isEqualTo(longerTimeout); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/ClientContextTest.java b/gax/src/test/java/com/google/api/gax/rpc/ClientContextTest.java deleted file mode 100644 index 7fe418dd6..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/ClientContextTest.java +++ /dev/null @@ -1,772 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import com.google.api.core.ApiClock; -import com.google.api.gax.core.BackgroundResource; -import com.google.api.gax.core.CredentialsProvider; -import com.google.api.gax.core.ExecutorProvider; -import com.google.api.gax.core.FixedCredentialsProvider; -import com.google.api.gax.core.FixedExecutorProvider; -import com.google.api.gax.rpc.mtls.MtlsProvider; -import com.google.api.gax.rpc.mtls.MtlsProvider.MtlsEndpointUsagePolicy; -import com.google.api.gax.rpc.testing.FakeChannel; -import com.google.api.gax.rpc.testing.FakeClientSettings; -import com.google.api.gax.rpc.testing.FakeMtlsProvider; -import com.google.api.gax.rpc.testing.FakeStubSettings; -import com.google.api.gax.rpc.testing.FakeTransportChannel; -import com.google.auth.Credentials; -import com.google.auth.oauth2.GoogleCredentials; -import com.google.common.collect.ImmutableMap; -import com.google.common.truth.Truth; -import java.io.IOException; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Executor; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class ClientContextTest { - - private static class InterceptingExecutor extends ScheduledThreadPoolExecutor { - boolean shutdownCalled = false; - - public InterceptingExecutor(int corePoolSize) { - super(corePoolSize); - } - - public void shutdown() { - shutdownCalled = true; - } - } - - private static class FakeExecutorProvider implements ExecutorProvider { - ScheduledExecutorService executor; - boolean shouldAutoClose; - - FakeExecutorProvider(ScheduledExecutorService executor, boolean shouldAutoClose) { - this.executor = executor; - this.shouldAutoClose = shouldAutoClose; - } - - @Override - public boolean shouldAutoClose() { - return shouldAutoClose; - } - - @Override - public ScheduledExecutorService getExecutor() { - return executor; - } - } - - private static class FakeTransportProvider implements TransportChannelProvider { - final Executor executor; - final FakeTransportChannel transport; - final boolean shouldAutoClose; - final Map headers; - final Credentials credentials; - - FakeTransportProvider( - FakeTransportChannel transport, - Executor executor, - boolean shouldAutoClose, - Map headers, - Credentials credentials) { - this.transport = transport; - this.executor = executor; - this.shouldAutoClose = shouldAutoClose; - this.headers = headers; - this.transport.setHeaders(headers); - this.credentials = credentials; - } - - @Override - public boolean shouldAutoClose() { - return shouldAutoClose; - } - - @Override - public boolean needsExecutor() { - return executor == null; - } - - @Override - public TransportChannelProvider withExecutor(ScheduledExecutorService executor) { - return withExecutor((Executor) executor); - } - - @Override - public TransportChannelProvider withExecutor(Executor executor) { - return new FakeTransportProvider( - this.transport, executor, this.shouldAutoClose, this.headers, this.credentials); - } - - @Override - public boolean needsHeaders() { - return headers == null; - } - - @Override - public TransportChannelProvider withHeaders(Map headers) { - return new FakeTransportProvider( - this.transport, this.executor, this.shouldAutoClose, headers, this.credentials); - } - - @Override - public boolean needsEndpoint() { - return false; - } - - @Override - public TransportChannelProvider withEndpoint(String endpoint) { - return this; - } - - @Override - public boolean acceptsPoolSize() { - return false; - } - - @Override - public TransportChannelProvider withPoolSize(int size) { - throw new UnsupportedOperationException( - "FakeTransportProvider doesn't allow pool size customization"); - } - - @Override - public TransportChannel getTransportChannel() throws IOException { - if (needsCredentials()) { - throw new IllegalStateException("Needs Credentials"); - } - transport.setExecutor(executor); - return transport; - } - - @Override - public String getTransportName() { - return "FakeTransport"; - } - - @Override - public boolean needsCredentials() { - return credentials == null; - } - - @Override - public TransportChannelProvider withCredentials(Credentials credentials) { - return new FakeTransportProvider( - this.transport, this.executor, this.shouldAutoClose, this.headers, credentials); - } - } - - @Test - public void testNoAutoCloseContextNeedsNoExecutor() throws Exception { - runTest(false, false, false, false); - } - - @Test - public void testWithAutoCloseContextNeedsNoExecutor() throws Exception { - runTest(true, false, false, false); - } - - @Test - public void testWithAutoCloseContextNeedsExecutor() throws Exception { - runTest(true, true, false, false); - } - - @Test - public void testNeedsHeaders() throws Exception { - runTest(false, false, true, false); - } - - @Test(expected = IllegalArgumentException.class) - public void testNeedsHeadersCollision() throws Exception { - runTest(false, false, true, true); - } - - private void runTest( - boolean shouldAutoClose, - boolean contextNeedsExecutor, - boolean needHeaders, - boolean headersCollision) - throws Exception { - FakeClientSettings.Builder builder = new FakeClientSettings.Builder(); - - InterceptingExecutor executor = new InterceptingExecutor(1); - ExecutorProvider executorProvider = new FakeExecutorProvider(executor, shouldAutoClose); - Map headers = ImmutableMap.of("k1", "v1", "k2", "v2"); - FakeTransportChannel transportChannel = FakeTransportChannel.create(new FakeChannel()); - FakeTransportProvider transportProvider = - new FakeTransportProvider( - transportChannel, - contextNeedsExecutor ? null : executor, - shouldAutoClose, - needHeaders ? null : headers, - null); - Credentials credentials = Mockito.mock(Credentials.class); - ApiClock clock = Mockito.mock(ApiClock.class); - Watchdog watchdog = - Watchdog.create( - Mockito.mock(ApiClock.class), - Duration.ZERO, - Mockito.mock(ScheduledExecutorService.class)); - Duration watchdogCheckInterval = Duration.ofSeconds(11); - - builder.setExecutorProvider(executorProvider); - builder.setTransportChannelProvider(transportProvider); - builder.setCredentialsProvider(FixedCredentialsProvider.create(credentials)); - builder.setWatchdogProvider(FixedWatchdogProvider.create(watchdog)); - builder.setWatchdogCheckInterval(watchdogCheckInterval); - builder.setClock(clock); - - HeaderProvider headerProvider = Mockito.mock(HeaderProvider.class); - Mockito.when(headerProvider.getHeaders()).thenReturn(ImmutableMap.of("k1", "v1")); - HeaderProvider internalHeaderProvider = Mockito.mock(HeaderProvider.class); - if (headersCollision) { - Mockito.when(internalHeaderProvider.getHeaders()).thenReturn(ImmutableMap.of("k1", "v1")); - } else { - Mockito.when(internalHeaderProvider.getHeaders()).thenReturn(ImmutableMap.of("k2", "v2")); - } - - builder.setHeaderProvider(headerProvider); - builder.setInternalHeaderProvider(internalHeaderProvider); - - FakeClientSettings settings = builder.build(); - ClientContext clientContext = ClientContext.create(settings); - - Truth.assertThat(clientContext.getExecutor()).isSameInstanceAs(executor); - Truth.assertThat(clientContext.getTransportChannel()).isSameInstanceAs(transportChannel); - - FakeTransportChannel actualChannel = (FakeTransportChannel) clientContext.getTransportChannel(); - assert actualChannel != null; - Truth.assertThat(actualChannel.getHeaders()).isEqualTo(headers); - Truth.assertThat(clientContext.getCredentials()).isSameInstanceAs(credentials); - Truth.assertThat(clientContext.getClock()).isSameInstanceAs(clock); - Truth.assertThat(clientContext.getStreamWatchdog()).isSameInstanceAs(watchdog); - Truth.assertThat(clientContext.getStreamWatchdogCheckInterval()) - .isEqualTo(watchdogCheckInterval); - - Truth.assertThat(clientContext.getHeaders()).isEqualTo(ImmutableMap.of("k1", "v1")); - Truth.assertThat(clientContext.getInternalHeaders()).isEqualTo(ImmutableMap.of("k2", "v2")); - - Truth.assertThat(executor.shutdownCalled).isFalse(); - Truth.assertThat(transportChannel.isShutdown()).isFalse(); - - List resources = clientContext.getBackgroundResources(); - - if (!resources.isEmpty()) { - // This is slightly too implementation-specific, but we need to ensure that executor is shut - // down after the transportChannel: https://github.com/googleapis/gax-java/issues/785 - Truth.assertThat(resources.size()).isEqualTo(2); - Truth.assertThat(transportChannel.isShutdown()).isNotEqualTo(shouldAutoClose); - Truth.assertThat(executor.shutdownCalled).isNotEqualTo(shouldAutoClose); - resources.get(0).shutdown(); - Truth.assertThat(transportChannel.isShutdown()).isEqualTo(shouldAutoClose); - Truth.assertThat(executor.shutdownCalled).isNotEqualTo(shouldAutoClose); - resources.get(1).shutdown(); - Truth.assertThat(transportChannel.isShutdown()).isEqualTo(shouldAutoClose); - Truth.assertThat(executor.shutdownCalled).isEqualTo(shouldAutoClose); - } - } - - @Test - public void testWatchdogProvider() throws IOException { - FakeClientSettings.Builder builder = new FakeClientSettings.Builder(); - - InterceptingExecutor executor = new InterceptingExecutor(1); - FakeTransportChannel transportChannel = FakeTransportChannel.create(new FakeChannel()); - FakeTransportProvider transportProvider = - new FakeTransportProvider(transportChannel, executor, true, null, null); - ApiClock clock = Mockito.mock(ApiClock.class); - - builder.setClock(clock); - builder.setCredentialsProvider( - FixedCredentialsProvider.create(Mockito.mock(Credentials.class))); - builder.setExecutorProvider(new FakeExecutorProvider(executor, true)); - builder.setTransportChannelProvider(transportProvider); - - Duration watchdogCheckInterval = Duration.ofSeconds(11); - builder.setWatchdogProvider( - InstantiatingWatchdogProvider.create() - .withClock(clock) - .withCheckInterval(watchdogCheckInterval) - .withExecutor(executor)); - builder.setWatchdogCheckInterval(watchdogCheckInterval); - - HeaderProvider headerProvider = Mockito.mock(HeaderProvider.class); - Mockito.when(headerProvider.getHeaders()).thenReturn(ImmutableMap.of("k1", "v1")); - HeaderProvider internalHeaderProvider = Mockito.mock(HeaderProvider.class); - - Mockito.when(internalHeaderProvider.getHeaders()).thenReturn(ImmutableMap.of("k2", "v2")); - builder.setHeaderProvider(headerProvider); - builder.setInternalHeaderProvider(internalHeaderProvider); - - ClientContext context = ClientContext.create(builder.build()); - List resources = context.getBackgroundResources(); - assertThat(resources.get(2)).isInstanceOf(Watchdog.class); - } - - @Test - public void testMergeHeaders_getQuotaProjectIdFromHeadersProvider() throws IOException { - final String QUOTA_PROJECT_ID_KEY = "x-goog-user-project"; - final String QUOTA_PROJECT_ID_FROM_SETTINGS = "quota_project_id_from_settings"; - FakeClientSettings.Builder builder = new FakeClientSettings.Builder(); - - InterceptingExecutor executor = new InterceptingExecutor(1); - FakeTransportChannel transportChannel = FakeTransportChannel.create(new FakeChannel()); - FakeTransportProvider transportProvider = - new FakeTransportProvider(transportChannel, executor, true, null, null); - - HeaderProvider headerProvider = Mockito.mock(HeaderProvider.class); - Mockito.when(headerProvider.getHeaders()).thenReturn(ImmutableMap.of("header_k1", "v1")); - HeaderProvider internalHeaderProvider = Mockito.mock(HeaderProvider.class); - Mockito.when(internalHeaderProvider.getHeaders()) - .thenReturn(ImmutableMap.of("internal_header_k1", "v1")); - - builder.setTransportChannelProvider(transportProvider); - builder.setCredentialsProvider( - FixedCredentialsProvider.create(Mockito.mock(Credentials.class))); - builder.setHeaderProvider(headerProvider); - builder.setInternalHeaderProvider(internalHeaderProvider); - builder.setQuotaProjectId(QUOTA_PROJECT_ID_FROM_SETTINGS); - - ClientContext context = ClientContext.create(builder.build()); - List resources = context.getBackgroundResources(); - FakeTransportChannel fakeTransportChannel = (FakeTransportChannel) resources.get(0); - assertThat(fakeTransportChannel.getHeaders().size()) - .isEqualTo( - headerProvider.getHeaders().size() + internalHeaderProvider.getHeaders().size() + 1); - assertThat(fakeTransportChannel.getHeaders().get(QUOTA_PROJECT_ID_KEY)) - .isEqualTo(QUOTA_PROJECT_ID_FROM_SETTINGS); - } - - @Test - public void testMergeHeaders_getQuotaProjectIdFromSettings() throws IOException { - final String QUOTA_PROJECT_ID_KEY = "x-goog-user-project"; - final String QUOTA_PROJECT_ID_FROM_HEADERS = "quota_project_id_from_headers"; - final String QUOTA_PROJECT_ID_FROM_INTERNAL_HEADERS = "quota_project_id_from_internal_headers"; - final String QUOTA_PROJECT_ID_FROM_SETTINGS = "quota_project_id_from_settings"; - FakeClientSettings.Builder builder = new FakeClientSettings.Builder(); - - InterceptingExecutor executor = new InterceptingExecutor(1); - FakeTransportChannel transportChannel = FakeTransportChannel.create(new FakeChannel()); - FakeTransportProvider transportProvider = - new FakeTransportProvider(transportChannel, executor, true, null, null); - - HeaderProvider headerProvider = - new HeaderProvider() { - @Override - public Map getHeaders() { - return ImmutableMap.of(QUOTA_PROJECT_ID_KEY, QUOTA_PROJECT_ID_FROM_HEADERS, "k2", "v2"); - } - }; - HeaderProvider internalHeaderProvider = - new HeaderProvider() { - @Override - public Map getHeaders() { - return ImmutableMap.of( - QUOTA_PROJECT_ID_KEY, - QUOTA_PROJECT_ID_FROM_INTERNAL_HEADERS, - "internal_header_k1", - "v1"); - } - }; - - builder.setTransportChannelProvider(transportProvider); - builder.setCredentialsProvider( - FixedCredentialsProvider.create(Mockito.mock(Credentials.class))); - builder.setHeaderProvider(headerProvider); - builder.setInternalHeaderProvider(internalHeaderProvider); - builder.setQuotaProjectId(QUOTA_PROJECT_ID_FROM_SETTINGS); - - ClientContext context = ClientContext.create(builder.build()); - List resources = context.getBackgroundResources(); - FakeTransportChannel fakeTransportChannel = (FakeTransportChannel) resources.get(0); - assertThat(fakeTransportChannel.getHeaders().size()) - .isEqualTo( - headerProvider.getHeaders().size() + internalHeaderProvider.getHeaders().size() - 1); - assertThat(fakeTransportChannel.getHeaders().get(QUOTA_PROJECT_ID_KEY)) - .isEqualTo(QUOTA_PROJECT_ID_FROM_SETTINGS); - } - - @Test - public void testMergeHeaders_noQuotaProjectIdSet() throws IOException { - final String QUOTA_PROJECT_ID_KEY = "x-goog-user-project"; - FakeClientSettings.Builder builder = new FakeClientSettings.Builder(); - - InterceptingExecutor executor = new InterceptingExecutor(1); - FakeTransportChannel transportChannel = FakeTransportChannel.create(new FakeChannel()); - FakeTransportProvider transportProvider = - new FakeTransportProvider(transportChannel, executor, true, null, null); - - HeaderProvider headerProvider = Mockito.mock(HeaderProvider.class); - Mockito.when(headerProvider.getHeaders()).thenReturn(ImmutableMap.of("header_k1", "v1")); - HeaderProvider internalHeaderProvider = Mockito.mock(HeaderProvider.class); - Mockito.when(internalHeaderProvider.getHeaders()) - .thenReturn(ImmutableMap.of("internal_header_k1", "v1")); - - builder.setTransportChannelProvider(transportProvider); - builder.setCredentialsProvider( - FixedCredentialsProvider.create(Mockito.mock(Credentials.class))); - builder.setHeaderProvider(headerProvider); - builder.setInternalHeaderProvider(internalHeaderProvider); - - ClientContext context = ClientContext.create(builder.build()); - List resources = context.getBackgroundResources(); - FakeTransportChannel fakeTransportChannel = (FakeTransportChannel) resources.get(0); - assertThat(fakeTransportChannel.getHeaders().size()) - .isEqualTo(headerProvider.getHeaders().size() + internalHeaderProvider.getHeaders().size()); - assertThat(fakeTransportChannel.getHeaders().containsKey(QUOTA_PROJECT_ID_KEY)).isFalse(); - } - - @Test - public void testHidingQuotaProjectId_quotaSetFromSetting() throws IOException { - final String QUOTA_PROJECT_ID_KEY = "x-goog-user-project"; - final String QUOTA_PROJECT_ID_FROM_CREDENTIALS_VALUE = "quota_project_id_from_credentials"; - FakeClientSettings.Builder builder = new FakeClientSettings.Builder(); - - InterceptingExecutor executor = new InterceptingExecutor(1); - FakeTransportChannel transportChannel = FakeTransportChannel.create(new FakeChannel()); - FakeTransportProvider transportProvider = - new FakeTransportProvider(transportChannel, executor, true, null, null); - Map> metaDataWithQuota = - ImmutableMap.of( - "k1", - Collections.singletonList("v1"), - QUOTA_PROJECT_ID_KEY, - Collections.singletonList(QUOTA_PROJECT_ID_FROM_CREDENTIALS_VALUE)); - final Credentials credentialsWithQuotaProjectId = Mockito.mock(GoogleCredentials.class); - Mockito.when(credentialsWithQuotaProjectId.getRequestMetadata(null)) - .thenReturn(metaDataWithQuota); - HeaderProvider headerProviderWithQuota = Mockito.mock(HeaderProvider.class); - HeaderProvider internalHeaderProvider = Mockito.mock(HeaderProvider.class); - - builder.setExecutorProvider(new FakeExecutorProvider(executor, true)); - builder.setTransportChannelProvider(transportProvider); - builder.setCredentialsProvider( - new CredentialsProvider() { - @Override - public Credentials getCredentials() throws IOException { - return credentialsWithQuotaProjectId; - } - }); - builder.setHeaderProvider(headerProviderWithQuota); - builder.setInternalHeaderProvider(internalHeaderProvider); - builder.setQuotaProjectId(QUOTA_PROJECT_ID_FROM_CREDENTIALS_VALUE); - - ClientContext clientContext = ClientContext.create(builder.build()); - assertThat(clientContext.getCredentials().getRequestMetadata().size()) - .isEqualTo(metaDataWithQuota.size() - 1); - assertThat( - clientContext.getCredentials().getRequestMetadata().containsKey(QUOTA_PROJECT_ID_KEY)) - .isFalse(); - } - - @Test - public void testHidingQuotaProjectId_noQuotaSetFromSetting() throws IOException { - FakeClientSettings.Builder builder = new FakeClientSettings.Builder(); - - InterceptingExecutor executor = new InterceptingExecutor(1); - FakeTransportChannel transportChannel = FakeTransportChannel.create(new FakeChannel()); - FakeTransportProvider transportProvider = - new FakeTransportProvider(transportChannel, executor, true, null, null); - Map> metaData = ImmutableMap.of("k1", Collections.singletonList("v1")); - final Credentials credentialsWithoutQuotaProjectId = Mockito.mock(GoogleCredentials.class); - Mockito.when(credentialsWithoutQuotaProjectId.getRequestMetadata(null)).thenReturn(metaData); - HeaderProvider headerProviderWithQuota = Mockito.mock(HeaderProvider.class); - HeaderProvider internalHeaderProvider = Mockito.mock(HeaderProvider.class); - - builder.setExecutorProvider(new FakeExecutorProvider(executor, true)); - builder.setTransportChannelProvider(transportProvider); - builder.setCredentialsProvider( - new CredentialsProvider() { - @Override - public Credentials getCredentials() throws IOException { - return credentialsWithoutQuotaProjectId; - } - }); - builder.setHeaderProvider(headerProviderWithQuota); - builder.setInternalHeaderProvider(internalHeaderProvider); - - ClientContext clientContext = ClientContext.create(builder.build()); - assertThat(clientContext.getCredentials().getRequestMetadata(null)).isEqualTo(metaData); - } - - @Test - public void testUserAgentInternalOnly() throws Exception { - TransportChannelProvider transportChannelProvider = - new FakeTransportProvider( - FakeTransportChannel.create(new FakeChannel()), null, true, null, null); - - ClientSettings.Builder builder = - new FakeClientSettings.Builder() - .setExecutorProvider( - FixedExecutorProvider.create(Mockito.mock(ScheduledExecutorService.class))) - .setTransportChannelProvider(transportChannelProvider) - .setCredentialsProvider( - FixedCredentialsProvider.create(Mockito.mock(GoogleCredentials.class))); - - builder.setInternalHeaderProvider(FixedHeaderProvider.create("user-agent", "internal-agent")); - - ClientContext clientContext = ClientContext.create(builder.build()); - FakeTransportChannel transportChannel = - (FakeTransportChannel) clientContext.getTransportChannel(); - - assertThat(transportChannel.getHeaders()).containsEntry("user-agent", "internal-agent"); - } - - @Test - public void testUserAgentExternalOnly() throws Exception { - TransportChannelProvider transportChannelProvider = - new FakeTransportProvider( - FakeTransportChannel.create(new FakeChannel()), null, true, null, null); - - ClientSettings.Builder builder = - new FakeClientSettings.Builder() - .setExecutorProvider( - FixedExecutorProvider.create(Mockito.mock(ScheduledExecutorService.class))) - .setTransportChannelProvider(transportChannelProvider) - .setCredentialsProvider( - FixedCredentialsProvider.create(Mockito.mock(GoogleCredentials.class))); - - builder.setHeaderProvider(FixedHeaderProvider.create("user-agent", "user-supplied-agent")); - - ClientContext clientContext = ClientContext.create(builder.build()); - FakeTransportChannel transportChannel = - (FakeTransportChannel) clientContext.getTransportChannel(); - - assertThat(transportChannel.getHeaders()).containsEntry("user-agent", "user-supplied-agent"); - } - - @Test - public void testUserAgentConcat() throws Exception { - TransportChannelProvider transportChannelProvider = - new FakeTransportProvider( - FakeTransportChannel.create(new FakeChannel()), null, true, null, null); - - ClientSettings.Builder builder = - new FakeClientSettings.Builder() - .setExecutorProvider( - FixedExecutorProvider.create(Mockito.mock(ScheduledExecutorService.class))) - .setTransportChannelProvider(transportChannelProvider) - .setCredentialsProvider( - FixedCredentialsProvider.create(Mockito.mock(GoogleCredentials.class))); - - builder.setHeaderProvider(FixedHeaderProvider.create("user-agent", "user-supplied-agent")); - builder.setInternalHeaderProvider(FixedHeaderProvider.create("user-agent", "internal-agent")); - - ClientContext clientContext = ClientContext.create(builder.build()); - FakeTransportChannel transportChannel = - (FakeTransportChannel) clientContext.getTransportChannel(); - - assertThat(transportChannel.getHeaders()) - .containsEntry("user-agent", "user-supplied-agent internal-agent"); - } - - private static String endpoint = "https://foo.googleapis.com"; - private static String mtlsEndpoint = "https://foo.mtls.googleapis.com"; - - @Test - public void testAutoUseMtlsEndpoint() throws IOException { - // Test the case client certificate exists and mTLS endpoint is selected. - boolean switchToMtlsEndpointAllowed = true; - MtlsProvider provider = - new FakeMtlsProvider( - true, - MtlsEndpointUsagePolicy.AUTO, - FakeMtlsProvider.createTestMtlsKeyStore(), - "", - false); - String endpointSelected = - ClientContext.getEndpoint(endpoint, mtlsEndpoint, switchToMtlsEndpointAllowed, provider); - assertEquals(mtlsEndpoint, endpointSelected); - } - - @Test - public void testEndpointNotOverridable() throws IOException { - // Test the case that switching to mTLS endpoint is not allowed so the original endpoint is - // selected. - boolean switchToMtlsEndpointAllowed = false; - MtlsProvider provider = - new FakeMtlsProvider( - true, - MtlsEndpointUsagePolicy.AUTO, - FakeMtlsProvider.createTestMtlsKeyStore(), - "", - false); - String endpointSelected = - ClientContext.getEndpoint(endpoint, mtlsEndpoint, switchToMtlsEndpointAllowed, provider); - assertEquals(endpoint, endpointSelected); - } - - @Test - public void testNoClientCertificate() throws IOException { - // Test the case that client certificates doesn't exists so the original endpoint is selected. - boolean switchToMtlsEndpointAllowed = true; - MtlsProvider provider = - new FakeMtlsProvider(true, MtlsEndpointUsagePolicy.AUTO, null, "", false); - String endpointSelected = - ClientContext.getEndpoint(endpoint, mtlsEndpoint, switchToMtlsEndpointAllowed, provider); - assertEquals(endpoint, endpointSelected); - } - - @Test - public void testAlwaysUseMtlsEndpoint() throws IOException { - // Test the case that mTLS endpoint is always used. - boolean switchToMtlsEndpointAllowed = true; - MtlsProvider provider = - new FakeMtlsProvider(false, MtlsEndpointUsagePolicy.ALWAYS, null, "", false); - String endpointSelected = - ClientContext.getEndpoint(endpoint, mtlsEndpoint, switchToMtlsEndpointAllowed, provider); - assertEquals(mtlsEndpoint, endpointSelected); - } - - @Test - public void testNeverUseMtlsEndpoint() throws IOException { - // Test the case that mTLS endpoint is never used. - boolean switchToMtlsEndpointAllowed = true; - MtlsProvider provider = - new FakeMtlsProvider( - true, - MtlsEndpointUsagePolicy.NEVER, - FakeMtlsProvider.createTestMtlsKeyStore(), - "", - false); - String endpointSelected = - ClientContext.getEndpoint(endpoint, mtlsEndpoint, switchToMtlsEndpointAllowed, provider); - assertEquals(endpoint, endpointSelected); - } - - @Test - public void testGetKeyStoreThrows() throws IOException { - // Test the case that getKeyStore throws exceptions. - try { - boolean switchToMtlsEndpointAllowed = true; - MtlsProvider provider = - new FakeMtlsProvider(true, MtlsEndpointUsagePolicy.AUTO, null, "", true); - ClientContext.getEndpoint(endpoint, mtlsEndpoint, switchToMtlsEndpointAllowed, provider); - fail("should throw an exception"); - } catch (IOException e) { - assertTrue( - "expected getKeyStore to throw an exception", - e.getMessage().contains("getKeyStore throws exception")); - } - } - - @Test - public void testSwitchToMtlsEndpointAllowed() throws IOException { - StubSettings settings = new FakeStubSettings.Builder().setEndpoint(endpoint).build(); - assertFalse(settings.getSwitchToMtlsEndpointAllowed()); - assertEquals(endpoint, settings.getEndpoint()); - - settings = - new FakeStubSettings.Builder() - .setEndpoint(endpoint) - .setSwitchToMtlsEndpointAllowed(true) - .build(); - assertTrue(settings.getSwitchToMtlsEndpointAllowed()); - assertEquals(endpoint, settings.getEndpoint()); - - // Test setEndpoint sets the switchToMtlsEndpointAllowed value to false. - settings = - new FakeStubSettings.Builder() - .setSwitchToMtlsEndpointAllowed(true) - .setEndpoint(endpoint) - .build(); - assertFalse(settings.getSwitchToMtlsEndpointAllowed()); - assertEquals(endpoint, settings.getEndpoint()); - } - - @Test - public void testExecutorSettings() throws Exception { - TransportChannelProvider transportChannelProvider = - new FakeTransportProvider( - FakeTransportChannel.create(new FakeChannel()), null, true, null, null); - - ClientSettings.Builder builder = - new FakeClientSettings.Builder() - .setTransportChannelProvider(transportChannelProvider) - .setCredentialsProvider( - FixedCredentialsProvider.create(Mockito.mock(GoogleCredentials.class))); - - // By default, if executor is not set, channel provider should not have an executor set - ClientContext context = ClientContext.create(builder.build()); - FakeTransportChannel transportChannel = (FakeTransportChannel) context.getTransportChannel(); - assertThat(transportChannel.getExecutor()).isNull(); - - ExecutorProvider channelExecutorProvider = - FixedExecutorProvider.create(Mockito.mock(ScheduledExecutorService.class)); - builder.setTransportChannelProvider( - transportChannelProvider.withExecutor((Executor) channelExecutorProvider.getExecutor())); - context = ClientContext.create(builder.build()); - transportChannel = (FakeTransportChannel) context.getTransportChannel(); - assertThat(transportChannel.getExecutor()) - .isSameInstanceAs(channelExecutorProvider.getExecutor()); - - ExecutorProvider executorProvider = - FixedExecutorProvider.create(Mockito.mock(ScheduledExecutorService.class)); - assertThat(channelExecutorProvider.getExecutor()) - .isNotSameInstanceAs(executorProvider.getExecutor()); - - // For backward compatibility, if executor is set from stubSettings.setExecutor, and transport - // channel already has an executor, the ExecutorProvider set in stubSettings won't override - // transport channel's executor - builder.setExecutorProvider(executorProvider); - context = ClientContext.create(builder.build()); - transportChannel = (FakeTransportChannel) context.getTransportChannel(); - assertThat(transportChannel.getExecutor()) - .isSameInstanceAs(channelExecutorProvider.getExecutor()); - - // For backward compatibility, if executor is set from stubSettings.setExecutor, and transport - // channel doesn't have an executor, transport channel will get the executor from - // stubSettings.setExecutor - builder.setExecutorProvider(executorProvider); - builder.setTransportChannelProvider( - new FakeTransportProvider( - FakeTransportChannel.create(new FakeChannel()), null, true, null, null)); - context = ClientContext.create(builder.build()); - transportChannel = (FakeTransportChannel) context.getTransportChannel(); - assertThat(transportChannel.getExecutor()).isSameInstanceAs(executorProvider.getExecutor()); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/ClientSettingsTest.java b/gax/src/test/java/com/google/api/gax/rpc/ClientSettingsTest.java deleted file mode 100644 index b39d59cbd..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/ClientSettingsTest.java +++ /dev/null @@ -1,545 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static org.junit.Assert.fail; - -import com.google.api.core.ApiClock; -import com.google.api.core.ApiFunction; -import com.google.api.core.NanoClock; -import com.google.api.gax.core.CredentialsProvider; -import com.google.api.gax.core.ExecutorProvider; -import com.google.api.gax.core.FixedCredentialsProvider; -import com.google.api.gax.core.FixedExecutorProvider; -import com.google.api.gax.core.InstantiatingExecutorProvider; -import com.google.api.gax.core.NoCredentialsProvider; -import com.google.api.gax.rpc.testing.FakeCallContext; -import com.google.api.gax.rpc.testing.FakeClientSettings; -import com.google.auth.Credentials; -import com.google.auth.oauth2.GoogleCredentials; -import com.google.common.collect.ImmutableMap; -import com.google.common.truth.Truth; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ScheduledExecutorService; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class ClientSettingsTest { - private static final String QUOTA_PROJECT_ID_KEY = "x-goog-user-project"; - private static final String QUOTA_PROJECT_ID_FROM_HEADER_VALUE = "quota_project_id_from_headers"; - private static final String QUOTA_PROJECT_ID_FROM_BUILDERS = "quota_project_id_from_builders"; - private static final String QUOTA_PROJECT_ID_FROM_INTERNAL_HEADER_VALUE = - "quota_project_id_from_internal_headers"; - private static final String QUOTA_PROJECT_ID_FROM_CREDENTIALS_VALUE = - "quota_project_id_from_credentials"; - private static final String QUOTA_PROJECT_ID_FROM_CONTEXT = - "quota_project_id_from_client_context"; - private static final String JSON_KEY_QUOTA_PROJECT_ID = - "{\n" - + " \"private_key_id\": \"somekeyid\",\n" - + " \"private_key\": \"-----BEGIN PRIVATE KEY-----\\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggS" - + "kAgEAAoIBAQC+K2hSuFpAdrJI\\nnCgcDz2M7t7bjdlsadsasad+fvRSW6TjNQZ3p5LLQY1kSZRqBqylRkzteMOyHg" - + "aR\\n0Pmxh3ILCND5men43j3h4eDbrhQBuxfEMalkG92sL+PNQSETY2tnvXryOvmBRwa/\\nQP/9dJfIkIDJ9Fw9N4" - + "Bhhhp6mCcRpdQjV38H7JsyJ7lih/oNjECgYAt\\nknddadwkwewcVxHFhcZJO+XWf6ofLUXpRwiTZakGMn8EE1uVa2" - + "LgczOjwWHGi99MFjxSer5m9\\n1tCa3/KEGKiS/YL71JvjwX3mb+cewlkcmweBKZHM2JPTk0ZednFSpVZMtycjkbLa" - + "\\ndYOS8V85AgMBewECggEBAKksaldajfDZDV6nGqbFjMiizAKJolr/M3OQw16K6o3/\\n0S31xIe3sSlgW0+UbYlF" - + "4U8KifhManD1apVSC3csafaspP4RZUHFhtBywLO9pR5c\\nr6S5aLp+gPWFyIp1pfXbWGvc5VY/v9x7ya1VEa6rXvL" - + "sKupSeWAW4tMj3eo/64ge\\nsdaceaLYw52KeBYiT6+vpsnYrEkAHO1fF/LavbLLOFJmFTMxmsNaG0tuiJHgjshB\\" - + "n82DpMCbXG9YcCgI/DbzuIjsdj2JC1cascSP//3PmefWysucBQe7Jryb6NQtASmnv\\nCdDw/0jmZTEjpe4S1lxfHp" - + "lAhHFtdgYTvyYtaLZiVVkCgYEA8eVpof2rceecw/I6\\n5ng1q3Hl2usdWV/4mZMvR0fOemacLLfocX6IYxT1zA1FF" - + "JlbXSRsJMf/Qq39mOR2\\nSpW+hr4jCoHeRVYLgsbggtrevGmILAlNoqCMpGZ6vDmJpq6ECV9olliDvpPgWOP+\\nm" - + "YPDreFBGxWvQrADNbRt2dmGsrsCgYEAyUHqB2wvJHFqdmeBsaacewzV8x9WgmeX\\ngUIi9REwXlGDW0Mz50dxpxcK" - + "CAYn65+7TCnY5O/jmL0VRxU1J2mSWyWTo1C+17L0\\n3fUqjxL1pkefwecxwecvC+gFFYdJ4CQ/MHHXU81Lwl1iWdF" - + "Cd2UoGddYaOF+KNeM\\nHC7cmqra+JsCgYEAlUNywzq8nUg7282E+uICfCB0LfwejuymR93CtsFgb7cRd6ak\\nECR" - + "8FGfCpH8ruWJINllbQfcHVCX47ndLZwqv3oVFKh6pAS/vVI4dpOepP8++7y1u\\ncoOvtreXCX6XqfrWDtKIvv0vjl" - + "HBhhhp6mCcRpdQjV38H7JsyJ7lih/oNjECgYAt\\nkndj5uNl5SiuVxHFhcZJO+XWf6ofLUregtevZakGMn8EE1uVa" - + "2AY7eafmoU/nZPT\\n00YB0TBATdCbn/nBSuKDESkhSg9s2GEKQZG5hBmL5uCMfo09z3SfxZIhJdlerreP\\nJ7gSi" - + "dI12N+EZxYd4xIJh/HFDgp7RRO87f+WJkofMQKBgGTnClK1VMaCRbJZPriw\\nEfeFCoOX75MxKwXs6xgrw4W//AYG" - + "GUjDt83lD6AZP6tws7gJ2IwY/qP7+lyhjEqN\\nHtfPZRGFkGZsdaksdlaksd323423d+15/UvrlRSFPNj1tWQmNKk" - + "XyRDW4IG1Oa2p\\nrALStNBx5Y9t0/LQnFI4w3aG\\n-----END PRIVATE KEY-----\\n\",\n" - + " \"project_id\": \"someprojectid\",\n" - + " \"client_email\": \"someclientid@developer.gserviceaccount.com\",\n" - + " \"client_id\": \"someclientid.apps.googleusercontent.com\",\n" - + " \"type\": \"service_account\",\n" - + " \"quota_project_id\": \"" - + QUOTA_PROJECT_ID_FROM_CREDENTIALS_VALUE - + "\"\n" - + "}"; - - private static final GoogleCredentials credentialsWithQuotaProject = - loadCredentials(JSON_KEY_QUOTA_PROJECT_ID); - - @Test - public void testEmptyBuilder() throws Exception { - FakeClientSettings.Builder builder = new FakeClientSettings.Builder(); - Truth.assertThat(builder.getExecutorProvider()).isNull(); - Truth.assertThat(builder.getBackgroundExecutorProvider()) - .isInstanceOf(InstantiatingExecutorProvider.class); - Truth.assertThat(builder.getTransportChannelProvider()).isNull(); - Truth.assertThat(builder.getCredentialsProvider()).isInstanceOf(NoCredentialsProvider.class); - Truth.assertThat(builder.getClock()).isInstanceOf(NanoClock.class); - Truth.assertThat(builder.getHeaderProvider()).isInstanceOf(NoHeaderProvider.class); - Truth.assertThat(builder.getInternalHeaderProvider()).isInstanceOf(NoHeaderProvider.class); - Truth.assertThat(builder.getWatchdogProvider()) - .isInstanceOf(InstantiatingWatchdogProvider.class); - Truth.assertThat(builder.getWatchdogCheckInterval()).isGreaterThan(Duration.ZERO); - Truth.assertThat(builder.getQuotaProjectId()).isNull(); - - FakeClientSettings settings = builder.build(); - Truth.assertThat(settings.getExecutorProvider()) - .isSameInstanceAs(builder.getExecutorProvider()); - Truth.assertThat(settings.getBackgroundExecutorProvider()) - .isSameInstanceAs(builder.getBackgroundExecutorProvider()); - Truth.assertThat(settings.getTransportChannelProvider()) - .isSameInstanceAs(builder.getTransportChannelProvider()); - Truth.assertThat(settings.getCredentialsProvider()) - .isSameInstanceAs(builder.getCredentialsProvider()); - Truth.assertThat(settings.getClock()).isSameInstanceAs(builder.getClock()); - Truth.assertThat(settings.getHeaderProvider()).isSameInstanceAs(builder.getHeaderProvider()); - Truth.assertThat(settings.getInternalHeaderProvider()) - .isSameInstanceAs(builder.getInternalHeaderProvider()); - Truth.assertThat(settings.getWatchdogProvider()) - .isInstanceOf(InstantiatingWatchdogProvider.class); - Truth.assertThat(settings.getWatchdogCheckInterval()).isGreaterThan(Duration.ZERO); - Truth.assertThat((settings.getQuotaProjectId())).isSameInstanceAs(builder.getQuotaProjectId()); - - String settingsString = settings.toString(); - Truth.assertThat(settingsString).contains("executorProvider"); - Truth.assertThat(settingsString).contains("backgroundExecutorProvider"); - Truth.assertThat(settingsString).contains("transportChannelProvider"); - Truth.assertThat(settingsString).contains("credentialsProvider"); - Truth.assertThat(settingsString).contains("clock"); - Truth.assertThat(settingsString).contains("headerProvider"); - Truth.assertThat(settingsString).contains("watchdogProvider"); - Truth.assertThat(settingsString).contains("watchdogCheckInterval"); - Truth.assertThat(settingsString).contains(("quotaProjectId")); - } - - @Test - public void testBuilder() throws Exception { - FakeClientSettings.Builder builder = new FakeClientSettings.Builder(); - - ExecutorProvider executorProvider = Mockito.mock(ExecutorProvider.class); - TransportChannelProvider transportProvider = Mockito.mock(TransportChannelProvider.class); - CredentialsProvider credentialsProvider = Mockito.mock(CredentialsProvider.class); - ApiClock clock = Mockito.mock(ApiClock.class); - HeaderProvider headerProvider = Mockito.mock(HeaderProvider.class); - HeaderProvider internalHeaderProvider = Mockito.mock(HeaderProvider.class); - WatchdogProvider watchdogProvider = Mockito.mock(WatchdogProvider.class); - Duration watchdogCheckInterval = Duration.ofSeconds(13); - String quotaProjectId = "test_quota_project_id"; - - builder.setExecutorProvider(executorProvider); - builder.setTransportChannelProvider(transportProvider); - builder.setCredentialsProvider(credentialsProvider); - builder.setHeaderProvider(headerProvider); - builder.setInternalHeaderProvider(internalHeaderProvider); - builder.setClock(clock); - builder.setWatchdogProvider(watchdogProvider); - builder.setWatchdogCheckInterval(watchdogCheckInterval); - builder.setQuotaProjectId(quotaProjectId); - - // For backward compatibility, backgroundExecutorProvider is set to executorProvider - Truth.assertThat(builder.getExecutorProvider()).isSameInstanceAs(executorProvider); - Truth.assertThat(builder.getBackgroundExecutorProvider()).isSameInstanceAs(executorProvider); - Truth.assertThat(builder.getTransportChannelProvider()).isSameInstanceAs(transportProvider); - Truth.assertThat(builder.getCredentialsProvider()).isSameInstanceAs(credentialsProvider); - Truth.assertThat(builder.getClock()).isSameInstanceAs(clock); - Truth.assertThat(builder.getHeaderProvider()).isSameInstanceAs(headerProvider); - Truth.assertThat(builder.getInternalHeaderProvider()).isSameInstanceAs(internalHeaderProvider); - Truth.assertThat(builder.getWatchdogProvider()).isSameInstanceAs(watchdogProvider); - Truth.assertThat(builder.getWatchdogCheckInterval()).isSameInstanceAs(watchdogCheckInterval); - Truth.assertThat(builder.getQuotaProjectId()).isEqualTo(quotaProjectId); - - String builderString = builder.toString(); - Truth.assertThat(builderString).contains("executorProvider"); - Truth.assertThat(builderString).contains("backgroundExecutorProvider"); - Truth.assertThat(builderString).contains("transportChannelProvider"); - Truth.assertThat(builderString).contains("credentialsProvider"); - Truth.assertThat(builderString).contains("clock"); - Truth.assertThat(builderString).contains("headerProvider"); - Truth.assertThat(builderString).contains("internalHeaderProvider"); - Truth.assertThat(builderString).contains("watchdogProvider"); - Truth.assertThat(builderString).contains("watchdogCheckInterval"); - Truth.assertThat(builderString).contains("quotaProjectId"); - } - - @Test - public void testBuilderFromClientContext() throws Exception { - final String QUOTA_PROJECT_ID_FROM_CONTEXT = "some_quota_project_id_from_context"; - ApiClock clock = Mockito.mock(ApiClock.class); - ApiCallContext callContext = FakeCallContext.createDefault(); - Map headers = Collections.singletonMap("spiffykey", "spiffyvalue"); - Watchdog watchdog = - Watchdog.create( - Mockito.mock(ApiClock.class), - Duration.ZERO, - Mockito.mock(ScheduledExecutorService.class)); - Duration watchdogCheckInterval = Duration.ofSeconds(12); - - ClientContext clientContext = - ClientContext.newBuilder() - .setExecutor(Mockito.mock(ScheduledExecutorService.class)) - .setTransportChannel(Mockito.mock(TransportChannel.class)) - .setCredentials(Mockito.mock(Credentials.class)) - .setClock(clock) - .setDefaultCallContext(callContext) - .setHeaders(headers) - .setStreamWatchdog(watchdog) - .setStreamWatchdogCheckInterval(watchdogCheckInterval) - .setQuotaProjectId(QUOTA_PROJECT_ID_FROM_CONTEXT) - .build(); - - FakeClientSettings.Builder builder = new FakeClientSettings.Builder(clientContext); - - Truth.assertThat(builder.getExecutorProvider()).isInstanceOf(FixedExecutorProvider.class); - Truth.assertThat(builder.getBackgroundExecutorProvider()) - .isInstanceOf(FixedExecutorProvider.class); - Truth.assertThat(builder.getExecutorProvider()) - .isSameInstanceAs(builder.getBackgroundExecutorProvider()); - Truth.assertThat(builder.getTransportChannelProvider()) - .isInstanceOf(FixedTransportChannelProvider.class); - Truth.assertThat(builder.getCredentialsProvider()).isInstanceOf(FixedCredentialsProvider.class); - Truth.assertThat(builder.getClock()).isSameInstanceAs(clock); - Truth.assertThat(builder.getHeaderProvider().getHeaders()) - .containsEntry("spiffykey", "spiffyvalue"); - Truth.assertThat(builder.getWatchdogProvider()).isInstanceOf(FixedWatchdogProvider.class); - Truth.assertThat(builder.getWatchdogProvider().getWatchdog()).isSameInstanceAs(watchdog); - Truth.assertThat(builder.getWatchdogCheckInterval()).isEqualTo(watchdogCheckInterval); - Truth.assertThat(builder.getQuotaProjectId()).isEqualTo(QUOTA_PROJECT_ID_FROM_CONTEXT); - } - - @Test - public void testBuilderFromSettings() throws Exception { - FakeClientSettings.Builder builder = new FakeClientSettings.Builder(); - - ExecutorProvider executorProvider = Mockito.mock(ExecutorProvider.class); - TransportChannelProvider transportProvider = Mockito.mock(TransportChannelProvider.class); - CredentialsProvider credentialsProvider = Mockito.mock(CredentialsProvider.class); - ApiClock clock = Mockito.mock(ApiClock.class); - HeaderProvider headerProvider = Mockito.mock(HeaderProvider.class); - HeaderProvider internalHeaderProvider = Mockito.mock(HeaderProvider.class); - WatchdogProvider watchdogProvider = Mockito.mock(WatchdogProvider.class); - Duration watchdogCheckInterval = Duration.ofSeconds(14); - String quotaProjectId = "test_builder_from_settings_quotaProjectId"; - - builder.setExecutorProvider(executorProvider); - builder.setTransportChannelProvider(transportProvider); - builder.setCredentialsProvider(credentialsProvider); - builder.setClock(clock); - builder.setHeaderProvider(headerProvider); - builder.setInternalHeaderProvider(internalHeaderProvider); - builder.setWatchdogProvider(watchdogProvider); - builder.setWatchdogCheckInterval(watchdogCheckInterval); - builder.setQuotaProjectId(quotaProjectId); - - FakeClientSettings settings = builder.build(); - FakeClientSettings.Builder newBuilder = new FakeClientSettings.Builder(settings); - - Truth.assertThat(newBuilder.getExecutorProvider()).isSameInstanceAs(executorProvider); - Truth.assertThat(newBuilder.getBackgroundExecutorProvider()).isSameInstanceAs(executorProvider); - Truth.assertThat(newBuilder.getTransportChannelProvider()).isSameInstanceAs(transportProvider); - Truth.assertThat(newBuilder.getCredentialsProvider()).isSameInstanceAs(credentialsProvider); - Truth.assertThat(newBuilder.getClock()).isSameInstanceAs(clock); - Truth.assertThat(newBuilder.getHeaderProvider()).isSameInstanceAs(headerProvider); - Truth.assertThat(newBuilder.getInternalHeaderProvider()) - .isSameInstanceAs(internalHeaderProvider); - Truth.assertThat(newBuilder.getWatchdogProvider()).isSameInstanceAs(watchdogProvider); - Truth.assertThat(newBuilder.getWatchdogCheckInterval()).isEqualTo(watchdogCheckInterval); - Truth.assertThat(newBuilder.getQuotaProjectId()).isEqualTo(quotaProjectId); - } - - @Test - public void testApplyToAllUnaryMethods() throws Exception { - List> builders = new ArrayList<>(); - builders.add(UnaryCallSettings.newUnaryCallSettingsBuilder()); - builders.add(UnaryCallSettings.newUnaryCallSettingsBuilder()); - // using an array to have a mutable integer - final int[] count = {0}; - ClientSettings.Builder.applyToAllUnaryMethods( - builders, - new ApiFunction, Void>() { - @Override - public Void apply(UnaryCallSettings.Builder input) { - if (count[0] == 0) { - input.setRetryableCodes(StatusCode.Code.UNAVAILABLE); - } else { - input.setRetryableCodes(StatusCode.Code.DEADLINE_EXCEEDED); - } - count[0] += 1; - return null; - } - }); - - Truth.assertThat(builders.get(0).getRetryableCodes()) - .containsExactly(StatusCode.Code.UNAVAILABLE); - Truth.assertThat(builders.get(1).getRetryableCodes()) - .containsExactly(StatusCode.Code.DEADLINE_EXCEEDED); - } - - static GoogleCredentials loadCredentials(String credentialFile) { - try { - InputStream keyStream = new ByteArrayInputStream(credentialFile.getBytes()); - return GoogleCredentials.fromStream(keyStream); - } catch (IOException e) { - fail("Couldn't create fake JSON credentials."); - } - return null; - } - - @Test - public void testBuilderFromSettings_QuotaProjectId() { - - CredentialsProvider credentialsProvider_no_quota = Mockito.mock(CredentialsProvider.class); - HeaderProvider headerProvider_no_quota = Mockito.mock(HeaderProvider.class); - HeaderProvider internalHeaderProvider_no_quota = Mockito.mock(HeaderProvider.class); - HeaderProvider headerProvider_with_quota = - new HeaderProvider() { - @Override - public Map getHeaders() { - return Collections.singletonMap( - QUOTA_PROJECT_ID_KEY, QUOTA_PROJECT_ID_FROM_HEADER_VALUE); - } - }; - HeaderProvider internalHeaderProvider_with_quota = - new HeaderProvider() { - @Override - public Map getHeaders() { - return Collections.singletonMap( - QUOTA_PROJECT_ID_KEY, QUOTA_PROJECT_ID_FROM_INTERNAL_HEADER_VALUE); - } - }; - CredentialsProvider credentialsProvider_with_quota = - new CredentialsProvider() { - @Override - public Credentials getCredentials() throws IOException { - return credentialsWithQuotaProject; - } - }; - - // Case for setting quota_project_id from builder only - // expect value is from builders - FakeClientSettings.Builder builder_setQuotaOnly = new FakeClientSettings.Builder(); - builder_setQuotaOnly.setCredentialsProvider(credentialsProvider_no_quota); - builder_setQuotaOnly.setHeaderProvider(headerProvider_no_quota); - builder_setQuotaOnly.setInternalHeaderProvider(internalHeaderProvider_no_quota); - builder_setQuotaOnly.setQuotaProjectId(QUOTA_PROJECT_ID_FROM_BUILDERS); - - // Case for setting quota_project_id from HeaderProvider Only - // expect value is from HeaderProvider - FakeClientSettings.Builder builder_setQuotaFromHeadersOnly = new FakeClientSettings.Builder(); - builder_setQuotaFromHeadersOnly.setHeaderProvider(headerProvider_with_quota); - - // Case for setting quota_project_id from HeaderProvider and set from builders - // expect value is from builders - FakeClientSettings.Builder builder_setQuotaFromHeadersAndBuilders = - new FakeClientSettings.Builder(); - builder_setQuotaFromHeadersOnly.setHeaderProvider(headerProvider_with_quota); - builder_setQuotaFromHeadersAndBuilders.setQuotaProjectId(QUOTA_PROJECT_ID_FROM_BUILDERS); - - // Case for setting quota_project_id from InternalHeaderProvider and set from builders - // expect value is from InternalHeaderProvider - FakeClientSettings.Builder builder_setQuotaFromInternalHeadersOnly = - new FakeClientSettings.Builder(); - builder_setQuotaFromInternalHeadersOnly.setInternalHeaderProvider( - internalHeaderProvider_with_quota); - - // Case for setting quota_project_id from InternalHeaderProvider and set from builders - // expect value is from builders - FakeClientSettings.Builder builder_setQuotaFromInternalHeadersAndBuilders = - new FakeClientSettings.Builder(); - builder_setQuotaFromInternalHeadersAndBuilders.setInternalHeaderProvider( - internalHeaderProvider_with_quota); - builder_setQuotaFromInternalHeadersAndBuilders.setQuotaProjectId( - QUOTA_PROJECT_ID_FROM_BUILDERS); - - // Case for setting quota_project_id from CredentialProvider Only - // expect value is from CredentialProvider - FakeClientSettings.Builder builder_setQuotaFromCredentialsProvider = - new FakeClientSettings.Builder(); - builder_setQuotaFromCredentialsProvider.setCredentialsProvider(credentialsProvider_with_quota); - - // Case for setting quota_project_id from CredentialProvider and Builders - // expect value is from builders - FakeClientSettings.Builder builder_setQuotaFromCredentialsProviderAndBuilder = - new FakeClientSettings.Builder(); - builder_setQuotaFromCredentialsProviderAndBuilder.setCredentialsProvider( - credentialsProvider_with_quota); - builder_setQuotaFromCredentialsProviderAndBuilder.setQuotaProjectId( - QUOTA_PROJECT_ID_FROM_BUILDERS); - - // Case for setting quota_project_id from All three sources - // expect value is from builders - FakeClientSettings.Builder builder_setQuotaFromAllSources = new FakeClientSettings.Builder(); - builder_setQuotaFromAllSources.setHeaderProvider(headerProvider_with_quota); - builder_setQuotaFromAllSources.setInternalHeaderProvider(headerProvider_with_quota); - builder_setQuotaFromAllSources.setCredentialsProvider(credentialsProvider_with_quota); - builder_setQuotaFromAllSources.setQuotaProjectId(QUOTA_PROJECT_ID_FROM_BUILDERS); - - // Case for setting quota_project_id from All three sources but set from builders first - // expect value is from builders - FakeClientSettings.Builder builder_setQuotaFromAllSourcesOrder = - new FakeClientSettings.Builder(); - builder_setQuotaFromAllSourcesOrder.setQuotaProjectId(QUOTA_PROJECT_ID_FROM_BUILDERS); - builder_setQuotaFromAllSourcesOrder.setHeaderProvider(headerProvider_with_quota); - builder_setQuotaFromAllSourcesOrder.setInternalHeaderProvider(headerProvider_with_quota); - builder_setQuotaFromAllSourcesOrder.setCredentialsProvider(credentialsProvider_with_quota); - - Truth.assertThat(builder_setQuotaOnly.getQuotaProjectId()) - .isEqualTo(QUOTA_PROJECT_ID_FROM_BUILDERS); - Truth.assertThat(builder_setQuotaFromHeadersOnly.getQuotaProjectId()) - .isEqualTo(QUOTA_PROJECT_ID_FROM_HEADER_VALUE); - Truth.assertThat(builder_setQuotaFromHeadersAndBuilders.getQuotaProjectId()) - .isEqualTo(QUOTA_PROJECT_ID_FROM_BUILDERS); - Truth.assertThat((builder_setQuotaFromInternalHeadersOnly).getQuotaProjectId()) - .isEqualTo(QUOTA_PROJECT_ID_FROM_INTERNAL_HEADER_VALUE); - Truth.assertThat(builder_setQuotaFromInternalHeadersAndBuilders.getQuotaProjectId()) - .isEqualTo(QUOTA_PROJECT_ID_FROM_BUILDERS); - Truth.assertThat(builder_setQuotaFromCredentialsProviderAndBuilder.getQuotaProjectId()) - .isEqualTo(QUOTA_PROJECT_ID_FROM_BUILDERS); - Truth.assertThat(builder_setQuotaFromAllSources.getQuotaProjectId()) - .isEqualTo(QUOTA_PROJECT_ID_FROM_BUILDERS); - Truth.assertThat(builder_setQuotaFromAllSourcesOrder.getQuotaProjectId()) - .isEqualTo(QUOTA_PROJECT_ID_FROM_BUILDERS); - } - - @Test - public void testBuilderFromClientContext_QuotaProjectId() { - ApiCallContext callContext = FakeCallContext.createDefault(); - - ClientContext clientContextQuotaOnly = - ClientContext.newBuilder() - .setTransportChannel(Mockito.mock(TransportChannel.class)) - .setDefaultCallContext(callContext) - .setQuotaProjectId(QUOTA_PROJECT_ID_FROM_CONTEXT) - .build(); - FakeClientSettings.Builder builderQuotaOnly = - new FakeClientSettings.Builder(clientContextQuotaOnly); - - ClientContext clientContextCredentialOnly = - ClientContext.newBuilder() - .setTransportChannel(Mockito.mock(TransportChannel.class)) - .setDefaultCallContext(callContext) - .setCredentials(credentialsWithQuotaProject) - .build(); - FakeClientSettings.Builder builderCredentialOnly = - new FakeClientSettings.Builder(clientContextCredentialOnly); - - ClientContext clientContextCredentialAndQuota = - ClientContext.newBuilder() - .setTransportChannel(Mockito.mock(TransportChannel.class)) - .setDefaultCallContext(callContext) - .setCredentials(credentialsWithQuotaProject) - .setQuotaProjectId(QUOTA_PROJECT_ID_FROM_CONTEXT) - .build(); - FakeClientSettings.Builder builderCredentialAndQuota = - new FakeClientSettings.Builder(clientContextCredentialAndQuota); - - ClientContext clientContextHeadersOnly = - ClientContext.newBuilder() - .setTransportChannel(Mockito.mock(TransportChannel.class)) - .setDefaultCallContext(callContext) - .setHeaders(ImmutableMap.of(QUOTA_PROJECT_ID_KEY, QUOTA_PROJECT_ID_FROM_HEADER_VALUE)) - .build(); - FakeClientSettings.Builder builderHeadersOnly = - new FakeClientSettings.Builder(clientContextHeadersOnly); - - ClientContext clientContextHeadersAndQuota = - ClientContext.newBuilder() - .setTransportChannel(Mockito.mock(TransportChannel.class)) - .setDefaultCallContext(callContext) - .setQuotaProjectId(QUOTA_PROJECT_ID_FROM_CONTEXT) - .setHeaders(ImmutableMap.of(QUOTA_PROJECT_ID_KEY, QUOTA_PROJECT_ID_FROM_HEADER_VALUE)) - .build(); - FakeClientSettings.Builder builderHeadersAndQuota = - new FakeClientSettings.Builder(clientContextHeadersAndQuota); - - ClientContext clientContextInternalHeadersOnly = - ClientContext.newBuilder() - .setTransportChannel(Mockito.mock(TransportChannel.class)) - .setDefaultCallContext(callContext) - .setInternalHeaders( - ImmutableMap.of(QUOTA_PROJECT_ID_KEY, QUOTA_PROJECT_ID_FROM_INTERNAL_HEADER_VALUE)) - .build(); - FakeClientSettings.Builder builderInternalHeadersOnly = - new FakeClientSettings.Builder(clientContextInternalHeadersOnly); - - ClientContext clientContextInternalHeadersAndQuota = - ClientContext.newBuilder() - .setTransportChannel(Mockito.mock(TransportChannel.class)) - .setDefaultCallContext(callContext) - .setInternalHeaders( - ImmutableMap.of(QUOTA_PROJECT_ID_KEY, QUOTA_PROJECT_ID_FROM_INTERNAL_HEADER_VALUE)) - .setQuotaProjectId(QUOTA_PROJECT_ID_FROM_CONTEXT) - .build(); - FakeClientSettings.Builder builderInternalHeadersAndQuota = - new FakeClientSettings.Builder(clientContextInternalHeadersAndQuota); - - ClientContext clientContextQuotaFromAllSources = - ClientContext.newBuilder() - .setTransportChannel(Mockito.mock(TransportChannel.class)) - .setDefaultCallContext(callContext) - .setHeaders( - ImmutableMap.of(QUOTA_PROJECT_ID_KEY, QUOTA_PROJECT_ID_FROM_INTERNAL_HEADER_VALUE)) - .setCredentials(credentialsWithQuotaProject) - .setQuotaProjectId(QUOTA_PROJECT_ID_FROM_CONTEXT) - .setInternalHeaders( - ImmutableMap.of(QUOTA_PROJECT_ID_KEY, QUOTA_PROJECT_ID_FROM_INTERNAL_HEADER_VALUE)) - .build(); - FakeClientSettings.Builder builderQuotaFromAllSources = - new FakeClientSettings.Builder(clientContextQuotaFromAllSources); - - Truth.assertThat(builderQuotaOnly.getQuotaProjectId()).isEqualTo(QUOTA_PROJECT_ID_FROM_CONTEXT); - Truth.assertThat(builderCredentialOnly.getQuotaProjectId()) - .isEqualTo(QUOTA_PROJECT_ID_FROM_CREDENTIALS_VALUE); - Truth.assertThat(builderCredentialAndQuota.getQuotaProjectId()) - .isEqualTo(QUOTA_PROJECT_ID_FROM_CONTEXT); - Truth.assertThat(builderHeadersOnly.getQuotaProjectId()) - .isEqualTo(QUOTA_PROJECT_ID_FROM_HEADER_VALUE); - Truth.assertThat(builderHeadersAndQuota.getQuotaProjectId()) - .isEqualTo(QUOTA_PROJECT_ID_FROM_CONTEXT); - Truth.assertThat(builderInternalHeadersOnly.getQuotaProjectId()) - .isEqualTo(QUOTA_PROJECT_ID_FROM_INTERNAL_HEADER_VALUE); - Truth.assertThat(builderInternalHeadersAndQuota.getQuotaProjectId()) - .isEqualTo(QUOTA_PROJECT_ID_FROM_CONTEXT); - Truth.assertThat(builderQuotaFromAllSources.getQuotaProjectId()) - .isEqualTo(QUOTA_PROJECT_ID_FROM_CONTEXT); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/ErrorDetailsTest.java b/gax/src/test/java/com/google/api/gax/rpc/ErrorDetailsTest.java deleted file mode 100644 index 8edef41bf..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/ErrorDetailsTest.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static org.junit.Assert.assertThrows; - -import com.google.common.collect.ImmutableList; -import com.google.common.truth.Truth; -import com.google.protobuf.Any; -import com.google.protobuf.ByteString; -import com.google.protobuf.Duration; -import com.google.rpc.BadRequest; -import com.google.rpc.BadRequest.FieldViolation; -import com.google.rpc.DebugInfo; -import com.google.rpc.ErrorInfo; -import com.google.rpc.Help; -import com.google.rpc.Help.Link; -import com.google.rpc.LocalizedMessage; -import com.google.rpc.PreconditionFailure; -import com.google.rpc.QuotaFailure; -import com.google.rpc.QuotaFailure.Violation; -import com.google.rpc.RequestInfo; -import com.google.rpc.ResourceInfo; -import com.google.rpc.RetryInfo; -import java.util.Collections; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class ErrorDetailsTest { - - private static final ErrorInfo ERROR_INFO = - ErrorInfo.newBuilder() - .setDomain("googleapis.com") - .setReason("SERVICE_DISABLED") - .putAllMetadata(Collections.emptyMap()) - .build(); - - private static final RetryInfo RETRY_INFO = - RetryInfo.newBuilder().setRetryDelay(Duration.newBuilder().setSeconds(213).build()).build(); - - private static final DebugInfo DEBUG_INFO = - DebugInfo.newBuilder() - .setDetail("No more details available") - .addStackEntries("Does not matter") - .build(); - - private static final QuotaFailure QUOTA_FAILURE = - QuotaFailure.newBuilder() - .addViolations( - Violation.newBuilder() - .setDescription("new violation") - .setSubject("This is a breaking news") - .build()) - .build(); - - private static final PreconditionFailure PRECONDITION_FAILURE = - PreconditionFailure.newBuilder() - .addViolations( - PreconditionFailure.Violation.newBuilder() - .setDescription("new violation") - .setSubject("This is a breaking news") - .setType("Unknown") - .build()) - .build(); - - private static final BadRequest BAD_REQUEST = - BadRequest.newBuilder() - .addFieldViolations( - FieldViolation.newBuilder() - .setDescription("new field violation") - .setField("unknown field") - .build()) - .build(); - - private static final RequestInfo REQUEST_INFO = - RequestInfo.newBuilder() - .setRequestId("ukajsdkansdk123") - .setServingData("no data available") - .build(); - - private static final ResourceInfo RESOURCE_INFO = - ResourceInfo.newBuilder() - .setDescription("not available") - .setResourceName("my resource") - .setResourceType("mystery") - .setOwner("myself") - .build(); - - private static final Help HELP = - Help.newBuilder() - .addLinks(Link.newBuilder().setDescription("new link").setUrl("https://abc.com").build()) - .build(); - - private static final LocalizedMessage LOCALIZED_MESSAGE = - LocalizedMessage.newBuilder().setLocale("en").setMessage("nothing").build(); - - ErrorDetails errorDetails; - - @Before - public void setUp() throws Exception { - ImmutableList rawErrorMessages = - ImmutableList.of( - Any.pack(ERROR_INFO), - Any.pack(RETRY_INFO), - Any.pack(DEBUG_INFO), - Any.pack(QUOTA_FAILURE), - Any.pack(PRECONDITION_FAILURE), - Any.pack(BAD_REQUEST), - Any.pack(REQUEST_INFO), - Any.pack(RESOURCE_INFO), - Any.pack(HELP), - Any.pack(LOCALIZED_MESSAGE)); - - errorDetails = ErrorDetails.builder().setRawErrorMessages(rawErrorMessages).build(); - } - - @Test - public void unpack_shouldReturnNullIfRawErrorMessagesIsNull() { - errorDetails = ErrorDetails.builder().setRawErrorMessages(null).build(); - - Truth.assertThat(errorDetails.unpack(ErrorInfo.class)).isNull(); - } - - @Test - public void unpack_shouldReturnNullIfErrorMessageTypeDoesNotExist() { - errorDetails = - ErrorDetails.builder().setRawErrorMessages(ImmutableList.of(Any.pack(ERROR_INFO))).build(); - - Truth.assertThat(errorDetails.unpack(DebugInfo.class)).isNull(); - } - - @Test - public void unpack_shouldThrowExceptionIfUnpackingErrorMassageFailed() { - Any malformedErrorType = - Any.newBuilder() - .setTypeUrl("type.googleapis.com/google.rpc.ErrorInfo") - .setValue(ByteString.copyFromUtf8("This is an invalid message!")) - .build(); - errorDetails = - ErrorDetails.builder().setRawErrorMessages(ImmutableList.of(malformedErrorType)).build(); - ProtocolBufferParsingException exception = - assertThrows( - ProtocolBufferParsingException.class, () -> errorDetails.unpack(ErrorInfo.class)); - Truth.assertThat(exception.getMessage()) - .isEqualTo( - String.format( - "Failed to unpack %s from raw error messages", ErrorInfo.class.getSimpleName())); - } - - @Test - public void unpack_shouldReturnDesiredErrorMessageTypeIfItExist() { - Truth.assertThat(errorDetails.unpack(ErrorInfo.class)).isEqualTo(ERROR_INFO); - } - - @Test - public void errorInfo_shouldUnpackErrorInfoProtoMessage() { - Truth.assertThat(errorDetails.getErrorInfo()).isEqualTo(ERROR_INFO); - } - - @Test - public void retryInfo_shouldUnpackRetryInfoProtoMessage() { - Truth.assertThat(errorDetails.getRetryInfo()).isEqualTo(RETRY_INFO); - } - - @Test - public void debugInfo_shouldUnpackDebugInfoProtoMessage() { - Truth.assertThat(errorDetails.getDebugInfo()).isEqualTo(DEBUG_INFO); - } - - @Test - public void quotaFailure_shouldUnpackQuotaFailureProtoMessage() { - Truth.assertThat(errorDetails.getQuotaFailure()).isEqualTo(QUOTA_FAILURE); - } - - @Test - public void preconditionFailure_shouldUnpackPreconditionFailureProtoMessage() { - Truth.assertThat(errorDetails.getPreconditionFailure()).isEqualTo(PRECONDITION_FAILURE); - } - - @Test - public void badRequest_shouldUnpackBadRequestProtoMessage() { - Truth.assertThat(errorDetails.getBadRequest()).isEqualTo(BAD_REQUEST); - } - - @Test - public void requestInfo_shouldUnpackRequestInfoProtoMessage() { - Truth.assertThat(errorDetails.getRequestInfo()).isEqualTo(REQUEST_INFO); - } - - @Test - public void resourceInfo_shouldUnpackResourceInfoProtoMessage() { - Truth.assertThat(errorDetails.getResourceInfo()).isEqualTo(RESOURCE_INFO); - } - - @Test - public void help_shouldUnpackHelpProtoMessage() { - Truth.assertThat(errorDetails.getHelp()).isEqualTo(HELP); - } - - @Test - public void localizedMessage_shouldUnpackLocalizedMessageProtoMessage() { - Truth.assertThat(errorDetails.getHelp()).isEqualTo(HELP); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/FirstElementCallableTest.java b/gax/src/test/java/com/google/api/gax/rpc/FirstElementCallableTest.java deleted file mode 100644 index e26ce719e..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/FirstElementCallableTest.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.ApiFuture; -import com.google.api.gax.rpc.testing.MockStreamingApi.MockServerStreamingCall; -import com.google.api.gax.rpc.testing.MockStreamingApi.MockServerStreamingCallable; -import com.google.common.truth.Truth; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class FirstElementCallableTest { - private MockServerStreamingCallable upstream; - private FirstElementCallable callable; - - @Before - public void setup() { - upstream = new MockServerStreamingCallable<>(); - callable = new FirstElementCallable<>(upstream); - } - - @Test - public void testHappyPath() throws InterruptedException, ExecutionException { - ApiFuture result = callable.futureCall("request"); - MockServerStreamingCall call = upstream.popLastCall(); - - Truth.assertThat(call.getController().isAutoFlowControlEnabled()).isFalse(); - - Truth.assertThat(call.getController().popLastPull()).isEqualTo(1); - call.getController().getObserver().onResponse("response"); - Truth.assertThat(result.get()).isEqualTo("response"); - - Truth.assertThat(call.getController().getObserver()).isNotNull(); - } - - @Test - public void testEarlyTermination() throws Exception { - ApiFuture result = callable.futureCall("request"); - MockServerStreamingCall call = upstream.popLastCall(); - - // callable should request a single element on start - Truth.assertThat(call.getController().isAutoFlowControlEnabled()).isFalse(); - Truth.assertThat(call.getController().popLastPull()).isEqualTo(1); - - // Then the user promptly cancels it - result.cancel(true); - - // The cancellation should propagate to the inner callable - Truth.assertThat(call.getController().isCancelled()).isTrue(); - // Then we fake a cancellation going the other way (it will be wrapped in StatusRuntimeException - // for grpc) - call.getController() - .getObserver() - .onError(new RuntimeException("Some other upstream cancellation notice")); - - Throwable actualError = null; - try { - result.get(1, TimeUnit.SECONDS); - } catch (Throwable e) { - actualError = e; - } - - // However, that exception will be ignored and will be replaced by a generic - // CancellationException - Truth.assertThat(actualError).isInstanceOf(CancellationException.class); - } - - @Test - public void testNoResults() throws Exception { - ApiFuture result = callable.futureCall("request"); - MockServerStreamingCall call = upstream.popLastCall(); - - Truth.assertThat(call.getController().isAutoFlowControlEnabled()).isFalse(); - - call.getController().getObserver().onComplete(); - Truth.assertThat(result.get()).isNull(); - } - - @Test - public void testErrorAfterResultIsIgnored() throws Exception { - ApiFuture result = callable.futureCall("request"); - MockServerStreamingCall call = upstream.popLastCall(); - - Truth.assertThat(call.getController().isAutoFlowControlEnabled()).isFalse(); - call.getController().getObserver().onResponse("response"); - call.getController() - .getObserver() - .onError(new RuntimeException("some error that will be ignored")); - - Truth.assertThat(result.get()).isEqualTo("response"); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/FixedHeaderProviderTest.java b/gax/src/test/java/com/google/api/gax/rpc/FixedHeaderProviderTest.java deleted file mode 100644 index 8bffbed0e..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/FixedHeaderProviderTest.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.gax.rpc; - -import static org.junit.Assert.assertEquals; - -import com.google.common.collect.ImmutableMap; -import java.util.Map; -import org.junit.Test; - -public class FixedHeaderProviderTest { - @Test - public void testCreateSuccess() { - Map headers = - ImmutableMap.of("User-Agent", "hello1", "Custom-Header", "hello2"); - FixedHeaderProvider headerProvider = FixedHeaderProvider.create(headers); - assertEquals(headers, headerProvider.getHeaders()); - } - - @Test(expected = IllegalArgumentException.class) - public void testCreateFail() { - Map headers = ImmutableMap.of("User-Agent", "hello1", "user-agent", "hello2"); - FixedHeaderProvider.create(headers); - } - - @Test - public void testCreateVarargSuccess() { - Map headers = - ImmutableMap.of("User-Agent", "hello1", "Custom-Header", "hello2"); - FixedHeaderProvider headerProvider = - FixedHeaderProvider.create("User-Agent", "hello1", "Custom-Header", "hello2"); - assertEquals(headers, headerProvider.getHeaders()); - } - - @Test(expected = IllegalArgumentException.class) - public void testCreateVarargFail() { - FixedHeaderProvider.create("User-Agent", "hello1", "user-agent", "hello2"); - } - - @Test(expected = IllegalArgumentException.class) - public void testCreateVarargOddNumberOfParamsFail() { - FixedHeaderProvider.create("User-Agent", "hello1", "Custom-Header"); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/FixedTransportChannelProviderTest.java b/gax/src/test/java/com/google/api/gax/rpc/FixedTransportChannelProviderTest.java deleted file mode 100644 index 66187657d..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/FixedTransportChannelProviderTest.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.gax.rpc.testing.FakeChannel; -import com.google.api.gax.rpc.testing.FakeTransportChannel; -import com.google.auth.oauth2.ComputeEngineCredentials; -import com.google.common.truth.Truth; -import java.util.Collections; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class FixedTransportChannelProviderTest { - @Test - public void testBasic() throws Exception { - TransportChannel transportChannel = FakeTransportChannel.create(new FakeChannel()); - FixedTransportChannelProvider provider = FixedTransportChannelProvider.create(transportChannel); - - Truth.assertThat(provider.shouldAutoClose()).isFalse(); - - Truth.assertThat(provider.needsExecutor()).isFalse(); - - Exception thrownException = null; - try { - provider.withExecutor(new ScheduledThreadPoolExecutor(0)); - } catch (Exception e) { - thrownException = e; - } - Truth.assertThat(thrownException).isInstanceOf(UnsupportedOperationException.class); - - Truth.assertThat(provider.needsHeaders()).isFalse(); - - thrownException = null; - try { - provider.withHeaders(Collections.emptyMap()); - } catch (Exception e) { - thrownException = e; - } - Truth.assertThat(thrownException).isInstanceOf(UnsupportedOperationException.class); - - Truth.assertThat(provider.needsEndpoint()).isFalse(); - - thrownException = null; - try { - provider.withEndpoint("localhost:8080"); - } catch (Exception e) { - thrownException = e; - } - Truth.assertThat(thrownException).isInstanceOf(UnsupportedOperationException.class); - - Truth.assertThat(provider.needsCredentials()).isFalse(); - - thrownException = null; - try { - provider.withCredentials(ComputeEngineCredentials.create()); - } catch (Exception e) { - thrownException = e; - } - Truth.assertThat(thrownException).isInstanceOf(UnsupportedOperationException.class); - - Truth.assertThat(provider.acceptsPoolSize()).isFalse(); - - thrownException = null; - try { - provider.withPoolSize(1); - } catch (Exception e) { - thrownException = e; - } - Truth.assertThat(thrownException).isInstanceOf(UnsupportedOperationException.class); - - Truth.assertThat(provider.getTransportChannel()).isSameInstanceAs(transportChannel); - - Truth.assertThat(provider.getTransportName()) - .isEqualTo(FakeTransportChannel.getFakeTransportName()); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/FixedWatchdogProviderTest.java b/gax/src/test/java/com/google/api/gax/rpc/FixedWatchdogProviderTest.java deleted file mode 100644 index 9fb965937..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/FixedWatchdogProviderTest.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.api.core.ApiClock; -import java.util.concurrent.ScheduledExecutorService; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class FixedWatchdogProviderTest { - @Test - public void testNull() { - WatchdogProvider provider = FixedWatchdogProvider.create(null); - assertThat(provider.getWatchdog()).isNull(); - } - - @Test - public void testSameInstance() { - Watchdog watchdog = - Watchdog.create( - Mockito.mock(ApiClock.class), - Duration.ZERO, - Mockito.mock(ScheduledExecutorService.class)); - - WatchdogProvider provider = FixedWatchdogProvider.create(watchdog); - assertThat(provider.getWatchdog()).isSameInstanceAs(watchdog); - } - - @Test - public void testNoModifications() { - Watchdog watchdog = - Watchdog.create( - Mockito.mock(ApiClock.class), - Duration.ZERO, - Mockito.mock(ScheduledExecutorService.class)); - WatchdogProvider provider = FixedWatchdogProvider.create(watchdog); - - assertThat(provider.needsCheckInterval()).isFalse(); - assertThat(provider.needsClock()).isFalse(); - assertThat(provider.needsExecutor()).isFalse(); - assertThat(provider.shouldAutoClose()).isFalse(); - - Throwable actualError = null; - try { - provider.withCheckInterval(Duration.ofSeconds(10)); - } catch (Throwable t) { - actualError = t; - } - assertThat(actualError).isInstanceOf(UnsupportedOperationException.class); - - actualError = null; - try { - provider.withClock(Mockito.mock(ApiClock.class)); - } catch (Throwable t) { - actualError = t; - } - assertThat(actualError).isInstanceOf(UnsupportedOperationException.class); - - actualError = null; - try { - provider.withExecutor(Mockito.mock(ScheduledExecutorService.class)); - } catch (Throwable t) { - actualError = t; - } - assertThat(actualError).isInstanceOf(UnsupportedOperationException.class); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/InstantiatingWatchdogProviderTest.java b/gax/src/test/java/com/google/api/gax/rpc/InstantiatingWatchdogProviderTest.java deleted file mode 100644 index 0607dc717..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/InstantiatingWatchdogProviderTest.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.api.core.ApiClock; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.junit.MockitoJUnitRunner; -import org.threeten.bp.Duration; - -@RunWith(MockitoJUnitRunner.class) -public class InstantiatingWatchdogProviderTest { - @Mock private ScheduledExecutorService executor; - @Mock private ApiClock clock; - private Duration checkInterval = Duration.ofSeconds(11); - - @Test - public void happyPath() { - WatchdogProvider provider = InstantiatingWatchdogProvider.create(); - - assertThat(provider.needsExecutor()).isTrue(); - provider = provider.withExecutor(executor); - - assertThat(provider.needsClock()).isTrue(); - provider = provider.withClock(clock); - - assertThat(provider.needsCheckInterval()).isTrue(); - provider = provider.withCheckInterval(checkInterval); - - assertThat(provider.shouldAutoClose()).isTrue(); - - Watchdog watchdog = provider.getWatchdog(); - Mockito.verify(executor) - .scheduleAtFixedRate( - watchdog, checkInterval.toMillis(), checkInterval.toMillis(), TimeUnit.MILLISECONDS); - } - - @Test - public void requiresExecutor() { - WatchdogProvider provider = - InstantiatingWatchdogProvider.create().withCheckInterval(checkInterval).withClock(clock); - - Throwable actualError = null; - try { - provider.getWatchdog(); - } catch (Throwable t) { - actualError = t; - } - assertThat(actualError).isInstanceOf(IllegalStateException.class); - } - - @Test - public void requiresCheckInterval() { - WatchdogProvider provider = - InstantiatingWatchdogProvider.create().withExecutor(executor).withClock(clock); - - Throwable actualError = null; - try { - provider.getWatchdog(); - } catch (Throwable t) { - actualError = t; - } - assertThat(actualError).isInstanceOf(IllegalStateException.class); - } - - @Test - public void requiresClock() { - WatchdogProvider provider = - InstantiatingWatchdogProvider.create() - .withExecutor(executor) - .withCheckInterval(checkInterval); - - Throwable actualError = null; - try { - provider.getWatchdog(); - } catch (Throwable t) { - actualError = t; - } - assertThat(actualError).isInstanceOf(IllegalStateException.class); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/LatchCountDownScheduler.java b/gax/src/test/java/com/google/api/gax/rpc/LatchCountDownScheduler.java deleted file mode 100644 index 492dbb7d7..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/LatchCountDownScheduler.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.when; - -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import org.mockito.Mockito; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -public abstract class LatchCountDownScheduler implements ScheduledExecutorService { - public static LatchCountDownScheduler get( - final CountDownLatch latch, - final long delayBeforeCountDown, - final long extraDelayAfterCountDown) { - LatchCountDownScheduler mock = Mockito.mock(LatchCountDownScheduler.class); - - // mock class fields: - final ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(1); - - // mock class methods: - // ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit); - when(mock.schedule(any(Runnable.class), anyLong(), any(TimeUnit.class))) - .then( - new Answer>() { - @Override - public ScheduledFuture answer(InvocationOnMock invocation) throws Throwable { - Object[] args = invocation.getArguments(); - Long delay = (Long) args[1]; - TimeUnit timeUnit = (TimeUnit) args[2]; - delay += timeUnit.convert(extraDelayAfterCountDown, TimeUnit.MILLISECONDS); - latch.countDown(); - if (delayBeforeCountDown > 0L) { - Thread.sleep(delayBeforeCountDown); - } - return executor.schedule((Runnable) args[0], delay, timeUnit); - } - }); - // List shutdownNow() - when(mock.shutdownNow()) - .then( - new Answer>() { - @Override - public List answer(InvocationOnMock invocation) throws Throwable { - return executor.shutdownNow(); - } - }); - - return mock; - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/OperationCallSettingsTest.java b/gax/src/test/java/com/google/api/gax/rpc/OperationCallSettingsTest.java deleted file mode 100644 index f3f9f603b..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/OperationCallSettingsTest.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.ApiFunction; -import com.google.api.gax.longrunning.OperationSnapshot; -import com.google.api.gax.retrying.TimedRetryAlgorithm; -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.common.truth.Truth; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; - -@RunWith(JUnit4.class) -public class OperationCallSettingsTest { - - @Test - public void testEmptyBuilder() { - OperationCallSettings.Builder builder = OperationCallSettings.newBuilder(); - - Truth.assertThat(builder.getResponseTransformer()).isNull(); - Truth.assertThat(builder.getMetadataTransformer()).isNull(); - Truth.assertThat(builder.getInitialCallSettings()).isNull(); - Truth.assertThat(builder.getPollingAlgorithm()).isNull(); - } - - @Test - public void testBuilder() { - OperationCallSettings.Builder builder = - OperationCallSettings.newBuilder(); - - UnaryCallSettings initialCallSettings = - UnaryCallSettings.newUnaryCallSettingsBuilder() - .setRetryableCodes(Code.UNAVAILABLE) - .build(); - TimedRetryAlgorithm pollingAlgorithm = Mockito.mock(TimedRetryAlgorithm.class); - ResponseTransformer responseTransformer = new ResponseTransformer(); - MetadataTransformer metadataTransformer = new MetadataTransformer(); - - builder.setPollingAlgorithm(pollingAlgorithm); - builder.setResponseTransformer(responseTransformer); - builder.setMetadataTransformer(metadataTransformer); - builder.setInitialCallSettings(initialCallSettings); - - Truth.assertThat(builder.getInitialCallSettings()).isSameInstanceAs(initialCallSettings); - - OperationCallSettings settings = builder.build(); - - Truth.assertThat(settings.getPollingAlgorithm()).isSameInstanceAs(pollingAlgorithm); - Truth.assertThat(settings.getResponseTransformer()).isSameInstanceAs(responseTransformer); - Truth.assertThat(settings.getMetadataTransformer()).isSameInstanceAs(metadataTransformer); - Truth.assertThat(settings.getInitialCallSettings()).isNotNull(); - Truth.assertThat(settings.getInitialCallSettings().getRetryableCodes().size()).isEqualTo(1); - } - - @Test - public void testBuilderFromSettings() throws Exception { - OperationCallSettings.Builder builder = - OperationCallSettings.newBuilder(); - - UnaryCallSettings initialCallSettings = - UnaryCallSettings.newUnaryCallSettingsBuilder() - .setRetryableCodes(Code.UNAVAILABLE) - .build(); - TimedRetryAlgorithm pollingAlgorithm = Mockito.mock(TimedRetryAlgorithm.class); - ResponseTransformer responseTransformer = new ResponseTransformer(); - MetadataTransformer metadataTransformer = new MetadataTransformer(); - - builder.setPollingAlgorithm(pollingAlgorithm); - builder.setResponseTransformer(responseTransformer); - builder.setMetadataTransformer(metadataTransformer); - builder.setInitialCallSettings(initialCallSettings); - - Truth.assertThat(builder.getInitialCallSettings()).isSameInstanceAs(initialCallSettings); - - OperationCallSettings settings = builder.build(); - OperationCallSettings.Builder newBuilder = settings.toBuilder(); - - Truth.assertThat(newBuilder.getPollingAlgorithm()).isSameInstanceAs(pollingAlgorithm); - Truth.assertThat(newBuilder.getResponseTransformer()).isSameInstanceAs(responseTransformer); - Truth.assertThat(newBuilder.getMetadataTransformer()).isSameInstanceAs(metadataTransformer); - Truth.assertThat(newBuilder.getInitialCallSettings()).isNotNull(); - Truth.assertThat(newBuilder.getInitialCallSettings().getRetryableCodes().size()).isEqualTo(1); - } - - private static class ResponseTransformer implements ApiFunction { - @Override - public String apply(OperationSnapshot operationSnapshot) { - return (String) operationSnapshot.getResponse(); - } - } - - private static class MetadataTransformer implements ApiFunction { - @Override - public Long apply(OperationSnapshot operationSnapshot) { - return (Long) operationSnapshot.getMetadata(); - } - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/OperationCallableImplTest.java b/gax/src/test/java/com/google/api/gax/rpc/OperationCallableImplTest.java deleted file mode 100644 index 5779f72f7..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/OperationCallableImplTest.java +++ /dev/null @@ -1,1306 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import com.google.api.core.ApiFunction; -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.api.core.ListenableFutureToApiFuture; -import com.google.api.gax.core.FakeApiClock; -import com.google.api.gax.core.RecordingScheduler; -import com.google.api.gax.longrunning.OperationFuture; -import com.google.api.gax.longrunning.OperationFutureImpl; -import com.google.api.gax.longrunning.OperationSnapshot; -import com.google.api.gax.longrunning.OperationTimedPollAlgorithm; -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.rpc.testing.FakeCallContext; -import com.google.api.gax.rpc.testing.FakeCallableFactory; -import com.google.api.gax.rpc.testing.FakeChannel; -import com.google.api.gax.rpc.testing.FakeOperationApi.OperationStashCallable; -import com.google.api.gax.rpc.testing.FakeOperationSnapshot; -import com.google.api.gax.rpc.testing.FakeStatusCode; -import com.google.api.gax.rpc.testing.FakeTransportChannel; -import com.google.auth.Credentials; -import com.google.common.collect.Lists; -import com.google.common.truth.Truth; -import com.google.common.util.concurrent.Futures; -import java.awt.Color; -import java.io.IOException; -import java.util.Currency; -import java.util.List; -import java.util.concurrent.CancellationException; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.locks.LockSupport; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class OperationCallableImplTest { - - private static final RetrySettings FAST_RETRY_SETTINGS = - RetrySettings.newBuilder() - .setInitialRetryDelay(Duration.ofMillis(2L)) - .setRetryDelayMultiplier(1) - .setMaxRetryDelay(Duration.ofMillis(2L)) - .setInitialRpcTimeout(Duration.ofMillis(2L)) - .setRpcTimeoutMultiplier(1) - .setMaxRpcTimeout(Duration.ofMillis(2L)) - .setTotalTimeout(Duration.ofMillis(10L)) - .build(); - - private static final RetrySettings FAST_RECHECKING_SETTINGS = - RetrySettings.newBuilder() - .setInitialRetryDelay(Duration.ofMillis(1L)) - .setRetryDelayMultiplier(1) - .setMaxRetryDelay(Duration.ofMillis(1L)) - .setInitialRpcTimeout( - Duration.ZERO) // supposed to be ignored, but are not actually, so we set to zero - .setMaxAttempts(0) - .setJittered(false) - .setRpcTimeoutMultiplier( - 1) // supposed to be ignored, but are not actually, so we set to one - .setMaxRpcTimeout( - Duration.ZERO) // supposed to be ignored, but are not actually, so we set to zero - .setTotalTimeout(Duration.ofMillis(5L)) - .build(); - - private FakeChannel initialChannel; - private TransportChannel pollTransportChannel; - private RecordingScheduler executor; - private ClientContext initialContext; - private OperationCallSettings callSettings; - - private FakeApiClock clock; - private OperationTimedPollAlgorithm pollingAlgorithm; - - @Before - public void setUp() throws IOException { - initialChannel = mock(FakeChannel.class); - pollTransportChannel = mock(TransportChannel.class); - TransportChannelProvider operationsChannelProvider = mock(TransportChannelProvider.class); - when(operationsChannelProvider.getTransportChannel()).thenReturn(pollTransportChannel); - - clock = new FakeApiClock(0L); - executor = RecordingScheduler.create(clock); - pollingAlgorithm = OperationTimedPollAlgorithm.create(FAST_RECHECKING_SETTINGS, clock); - - UnaryCallSettings initialCallSettings = - UnaryCallSettings.newUnaryCallSettingsBuilder() - .setRetrySettings(FAST_RETRY_SETTINGS.toBuilder().setMaxAttempts(1).build()) - .build(); - - callSettings = - OperationCallSettings.newBuilder() - .setInitialCallSettings(initialCallSettings) - .setResponseTransformer(new ResponseTransformer()) - .setMetadataTransformer(new MetadataTransformer()) - .setPollingAlgorithm(pollingAlgorithm) - .build(); - - initialContext = getClientContext(initialChannel, executor); - } - - private static class ResponseTransformer implements ApiFunction { - @Override - public Color apply(OperationSnapshot operationSnapshot) { - if (!operationSnapshot.getErrorCode().getCode().equals(StatusCode.Code.OK)) { - throw ApiExceptionFactory.createException( - "Operation with name \"" - + operationSnapshot.getName() - + "\" failed with status = " - + operationSnapshot.getErrorCode() - + " and message = " - + operationSnapshot.getErrorMessage(), - null, - operationSnapshot.getErrorCode(), - false); - } - if (operationSnapshot.getResponse() == null) { - return null; - } - if (!(operationSnapshot.getResponse() instanceof Color)) { - String errorMessage = - "type mismatch: expected " - + Color.class.getName() - + ", found " - + operationSnapshot.getResponse().getClass().getName(); - throw new ApiException(errorMessage, null, FakeStatusCode.of(StatusCode.Code.OK), false); - } else { - return (Color) operationSnapshot.getResponse(); - } - } - } - - private static class MetadataTransformer implements ApiFunction { - @Override - public Currency apply(OperationSnapshot operationSnapshot) { - if (operationSnapshot.getMetadata() == null) { - return null; - } - if (!(operationSnapshot.getMetadata() instanceof Currency)) { - String errorMessage = - "type mismatch: expected " - + Currency.class.getName() - + ", found " - + operationSnapshot.getMetadata().getClass().getName(); - throw new ApiException(errorMessage, null, FakeStatusCode.of(StatusCode.Code.OK), false); - } else { - return (Currency) operationSnapshot.getMetadata(); - } - } - } - - @After - public void tearDown() { - executor.shutdown(); - } - - @Test - public void testCall() { - Color resp = getColor(1.0f); - Currency meta = Currency.getInstance("UAH"); - OperationSnapshot resultOperation = getOperation("testCall", resp, null, meta, true); - UnaryCallable initialCallable = - mockGetOpSnapshotCallable(StatusCode.Code.OK, resultOperation); - LongRunningClient longRunningClient = new UnsupportedOperationApi(); - - OperationCallable callable = - FakeCallableFactory.createOperationCallable( - initialCallable, callSettings, initialContext, longRunningClient); - - Color response = callable.call(2, FakeCallContext.createDefault()); - Truth.assertThat(response).isEqualTo(resp); - assertThat(executor.getIterationsCount()).isEqualTo(0); - } - - @Test - public void testResumeFutureCall() throws Exception { - String opName = "testResumeFutureCall"; - Color resp = getColor(0.5f); - Currency meta = Currency.getInstance("UAH"); - OperationSnapshot resultOperation = getOperation(opName, resp, null, meta, true); - LongRunningClient longRunningClient = mockGetOperation(StatusCode.Code.OK, resultOperation); - - ClientContext mockContext = getClientContext(new FakeChannel(), executor); - OperationCallable callable = - FakeCallableFactory.createOperationCallable( - getUnexpectedStartCallable(), callSettings, mockContext, longRunningClient); - - OperationFuture future = callable.resumeFutureCall(opName); - - assertFutureSuccessMetaSuccess(opName, future, resp, meta); - assertThat(executor.getIterationsCount()).isEqualTo(0); - } - - @Test - public void testCancelOperation() throws Exception { - String opName = "testCancelOperation"; - LongRunningClient longRunningClient = mockCancelOperation(StatusCode.Code.OK); - - ClientContext mockContext = getClientContext(new FakeChannel(), executor); - OperationCallable callable = - FakeCallableFactory.createOperationCallable( - getUnexpectedStartCallable(), callSettings, mockContext, longRunningClient); - - ApiFuture future = callable.cancel(opName); - assertThat(future.get()).isNull(); - } - - @Test - public void testFutureCallInitialDone() throws Exception { - String opName = "testFutureCallInitialDone"; - Color resp = getColor(0.5f); - Currency meta = Currency.getInstance("UAH"); - OperationSnapshot resultOperation = getOperation(opName, resp, null, meta, true); - UnaryCallable initialCallable = - mockGetOpSnapshotCallable(StatusCode.Code.OK, resultOperation); - LongRunningClient longRunningClient = new UnsupportedOperationApi(); - - OperationCallable callable = - FakeCallableFactory.createOperationCallable( - initialCallable, callSettings, initialContext, longRunningClient); - - OperationFuture future = - callable.futureCall(2, FakeCallContext.createDefault()); - - assertFutureSuccessMetaSuccess(opName, future, resp, meta); - assertThat(executor.getIterationsCount()).isEqualTo(0); - } - - @Test - public void testFutureCallInitialError() throws Exception { - String opName = "testFutureCallInitialError"; - Color resp = getColor(1.0f); - Currency meta = Currency.getInstance("UAH"); - OperationSnapshot resultOperation = getOperation(opName, resp, null, meta, true); - UnaryCallable initialCallable = - mockGetOpSnapshotCallable(StatusCode.Code.UNAVAILABLE, resultOperation); - LongRunningClient longRunningClient = new UnsupportedOperationApi(); - - OperationCallable callable = - FakeCallableFactory.createOperationCallable( - initialCallable, callSettings, initialContext, longRunningClient); - - OperationFuture future = - callable.futureCall(2, FakeCallContext.createDefault()); - - assertFutureFailMetaFail(future, null, FakeStatusCode.of(StatusCode.Code.UNAVAILABLE)); - assertThat(executor.getIterationsCount()).isEqualTo(0); - } - - @Test - public void testFutureCallInitialDoneWithError() throws Exception { - String opName = "testFutureCallInitialDoneWithError"; - StatusCode errorCode = FakeStatusCode.of(StatusCode.Code.ALREADY_EXISTS); - Currency meta = Currency.getInstance("UAH"); - OperationSnapshot resultOperation = - getOperation(opName, null, errorCode, meta, true, "Already exists error"); - UnaryCallable initialCallable = - mockGetOpSnapshotCallable(StatusCode.Code.OK, resultOperation); - LongRunningClient longRunningClient = new UnsupportedOperationApi(); - - OperationCallable callable = - FakeCallableFactory.createOperationCallable( - initialCallable, callSettings, initialContext, longRunningClient); - - OperationFuture future = - callable.futureCall(2, FakeCallContext.createDefault()); - - String errorMessage = - "Operation with name \"" - + opName - + "\" failed with status = " - + errorCode - + " and message = " - + "Already exists error"; - assertFutureFailMetaSuccess( - future, meta, FakeStatusCode.of(StatusCode.Code.ALREADY_EXISTS), errorMessage); - assertThat(executor.getIterationsCount()).isEqualTo(0); - } - - @Test - public void testFutureCallInitialDoneWrongType() throws Exception { - String opName = "testFutureCallInitialDoneWrongType"; - Currency resp = Currency.getInstance("USD"); - Currency meta = Currency.getInstance("UAH"); - OperationSnapshot resultOperation = getOperation(opName, resp, null, meta, true); - UnaryCallable initialCallable = - mockGetOpSnapshotCallable(StatusCode.Code.OK, resultOperation); - LongRunningClient longRunningClient = new UnsupportedOperationApi(); - - OperationCallable callable = - FakeCallableFactory.createOperationCallable( - initialCallable, callSettings, initialContext, longRunningClient); - - OperationFuture future = - callable.futureCall(2, FakeCallContext.createDefault()); - - assertFutureFailMetaSuccess( - future, - meta, - FakeStatusCode.of(StatusCode.Code.OK), - "type mismatch: expected java.awt.Color, found java.util.Currency"); - assertThat(executor.getIterationsCount()).isEqualTo(0); - } - - @Test - public void testFutureCallInitialDoneMetaWrongType() throws Exception { - String opName = "testFutureCallInitialDoneMetaWrongType"; - Color resp = getColor(1.0f); - Color meta = getColor(1.0f); - OperationSnapshot resultOperation = getOperation(opName, resp, null, meta, true); - UnaryCallable initialCallable = - mockGetOpSnapshotCallable(StatusCode.Code.OK, resultOperation); - LongRunningClient longRunningClient = new UnsupportedOperationApi(); - - OperationCallable callable = - FakeCallableFactory.createOperationCallable( - initialCallable, callSettings, initialContext, longRunningClient); - - OperationFuture future = - callable.futureCall(2, FakeCallContext.createDefault()); - - assertFutureSuccessMetaFail(future, resp, FakeStatusCode.of(StatusCode.Code.OK)); - assertThat(executor.getIterationsCount()).isEqualTo(0); - } - - @Test - public void testFutureCallInitialCancel() throws Exception { - String opName = "testFutureCallInitialCancel"; - OperationSnapshot initialOperation = getOperation(opName, null, null, null, false); - OperationSnapshot resultOperation = getOperation(opName, null, null, null, false); - UnaryCallable initialCallable = - mockGetOpSnapshotCallable(StatusCode.Code.OK, initialOperation); - LongRunningClient longRunningClient = mockGetOperation(StatusCode.Code.OK, resultOperation); - - OperationCallableImpl callableImpl = - Callables.longRunningOperationImpl( - initialCallable, callSettings, initialContext, longRunningClient); - - OperationFutureImpl future = - callableImpl.futureCall( - new ListenableFutureToApiFuture<>( - Futures.immediateCancelledFuture()), - FakeCallContext.createDefault()); - - Exception exception = null; - try { - future.get(3, TimeUnit.SECONDS); - } catch (CancellationException e) { - exception = e; - } - - assertThat(exception).isNotNull(); - assertThat(future.isDone()).isTrue(); - assertThat(future.isCancelled()).isTrue(); - assertThat(future.getInitialFuture().isDone()).isTrue(); - assertThat(future.getInitialFuture().isCancelled()).isTrue(); - - assertFutureCancelMetaCancel(future); - assertThat(executor.getIterationsCount()).isEqualTo(0); - } - - @Test - public void testFutureCallInitialOperationUnexpectedFail() throws Exception { - String opName = "testFutureCallInitialOperationUnexpectedFail"; - OperationSnapshot initialOperation = getOperation(opName, null, null, null, false); - OperationSnapshot resultOperation = getOperation(opName, null, null, null, false); - UnaryCallable initialCallable = - mockGetOpSnapshotCallable(StatusCode.Code.OK, initialOperation); - LongRunningClient longRunningClient = mockGetOperation(StatusCode.Code.OK, resultOperation); - - OperationCallableImpl callableImpl = - Callables.longRunningOperationImpl( - initialCallable, callSettings, initialContext, longRunningClient); - - RuntimeException thrownException = new RuntimeException(); - - ApiFuture initialFuture = ApiFutures.immediateFailedFuture(thrownException); - OperationFuture future = - callableImpl.futureCall(initialFuture, FakeCallContext.createDefault()); - - assertFutureFailMetaFail(future, RuntimeException.class, null); - assertThat(executor.getIterationsCount()).isEqualTo(0); - } - - @Test - public void testFutureCallPollDoneOnFirst() throws Exception { - String opName = "testFutureCallPollDoneOnFirst"; - Color resp = getColor(0.5f); - Currency meta = Currency.getInstance("UAH"); - OperationSnapshot initialOperation = getOperation(opName, null, null, null, false); - OperationSnapshot resultOperation = getOperation(opName, resp, null, meta, true); - UnaryCallable initialCallable = - mockGetOpSnapshotCallable(StatusCode.Code.OK, initialOperation); - LongRunningClient longRunningClient = mockGetOperation(StatusCode.Code.OK, resultOperation); - - OperationCallable callable = - FakeCallableFactory.createOperationCallable( - initialCallable, callSettings, initialContext, longRunningClient); - - OperationFuture future = - callable.futureCall(2, FakeCallContext.createDefault()); - - assertFutureSuccessMetaSuccess(opName, future, resp, meta); - assertThat(executor.getIterationsCount()).isEqualTo(0); - } - - @Test - public void testFutureCallPollDoneOnSecond() throws Exception { - String opName = "testFutureCallPollDoneOnSecond"; - Color resp = getColor(0.5f); - Currency meta1 = Currency.getInstance("UAH"); - Currency meta2 = Currency.getInstance("USD"); - OperationSnapshot initialOperation = getOperation(opName, null, null, null, false); - OperationSnapshot resultOperation1 = getOperation(opName, null, null, meta1, false); - OperationSnapshot resultOperation2 = getOperation(opName, resp, null, meta2, true); - UnaryCallable initialCallable = - mockGetOpSnapshotCallable(StatusCode.Code.OK, initialOperation); - LongRunningClient longRunningClient = - mockGetOperation(StatusCode.Code.OK, resultOperation1, resultOperation2); - - OperationCallable callable = - FakeCallableFactory.createOperationCallable( - initialCallable, callSettings, initialContext, longRunningClient); - - OperationFuture future = - callable.futureCall(2, FakeCallContext.createDefault()); - - assertFutureSuccessMetaSuccess(opName, future, resp, meta2); - assertThat(executor.getIterationsCount()).isEqualTo(1); - } - - @Test - public void testFutureCallPollRPCTimeout() throws Exception { - String opName = "testFutureCallPollRPCTimeout"; - pollingAlgorithm = - OperationTimedPollAlgorithm.create( - FAST_RECHECKING_SETTINGS - .toBuilder() - // Update the polling algorithm to set per-RPC timeouts instead of the default zero. - // - // This is non-standard, as these fields have been documented as "should be ignored" - // for LRO polling. They are not actually ignored in code, so they changing them - // here has an actual affect. This test verifies that they work as such, but in - // practice generated clients set the RPC timeouts to 0 to be ignored. - .setInitialRpcTimeout(Duration.ofMillis(100)) - .setMaxRpcTimeout(Duration.ofSeconds(1)) - .setRpcTimeoutMultiplier(2) - .setTotalTimeout(Duration.ofSeconds(5L)) - .build(), - clock); - callSettings = callSettings.toBuilder().setPollingAlgorithm(pollingAlgorithm).build(); - - Color resp = getColor(0.5f); - Currency meta1 = Currency.getInstance("UAH"); - Currency meta2 = Currency.getInstance("USD"); - OperationSnapshot initialOperation = getOperation(opName, null, null, null, false); - OperationSnapshot resultOperation1 = getOperation(opName, null, null, meta1, false); - OperationSnapshot resultOperation2 = getOperation(opName, null, null, meta1, false); - OperationSnapshot resultOperation3 = getOperation(opName, resp, null, meta2, true); - - UnaryCallable initialCallable = - mockGetOpSnapshotCallable(StatusCode.Code.OK, initialOperation); - - LongRunningClient longRunningClient = Mockito.mock(LongRunningClient.class); - @SuppressWarnings("unchecked") - UnaryCallable getOpCallable = Mockito.mock(UnaryCallable.class); - ArgumentCaptor callContextCaptor = - ArgumentCaptor.forClass(ApiCallContext.class); - Mockito.when(longRunningClient.getOperationCallable()).thenReturn(getOpCallable); - - Mockito.when(getOpCallable.futureCall(Mockito.any(), callContextCaptor.capture())) - .thenReturn(ApiFutures.immediateFuture(resultOperation1)) - .thenReturn(ApiFutures.immediateFuture(resultOperation2)) - .thenReturn(ApiFutures.immediateFuture(resultOperation3)); - - OperationCallable callable = - FakeCallableFactory.createOperationCallable( - initialCallable, callSettings, initialContext, longRunningClient); - - callable.futureCall(2, FakeCallContext.createDefault()).get(10, TimeUnit.SECONDS); - - List actualTimeouts = Lists.newArrayList(); - - for (ApiCallContext callContext : callContextCaptor.getAllValues()) { - actualTimeouts.add(callContext.getTimeout()); - } - - List expectedTimeouts = - Lists.newArrayList(Duration.ofMillis(100), Duration.ofMillis(200), Duration.ofMillis(400)); - assertThat(actualTimeouts).isEqualTo(expectedTimeouts); - } - - @Test - public void testFutureCallContextPropagation() throws Exception { - String opName = "testFutureCallContextPropagation"; - - Color resp = getColor(0.5f); - Currency meta = Currency.getInstance("USD"); - OperationSnapshot initialOperation = getOperation(opName, null, null, null, false); - OperationSnapshot resultOperation = getOperation(opName, resp, null, meta, true); - - UnaryCallable initialCallable = - mockGetOpSnapshotCallable(StatusCode.Code.OK, initialOperation); - - LongRunningClient longRunningClient = Mockito.mock(LongRunningClient.class); - @SuppressWarnings("unchecked") - UnaryCallable getOpCallable = Mockito.mock(UnaryCallable.class); - ArgumentCaptor callContextCaptor = - ArgumentCaptor.forClass(ApiCallContext.class); - Mockito.when(longRunningClient.getOperationCallable()).thenReturn(getOpCallable); - - Mockito.when(getOpCallable.futureCall(Mockito.any(), callContextCaptor.capture())) - .thenReturn(ApiFutures.immediateFuture(resultOperation)); - - OperationCallable callable = - FakeCallableFactory.createOperationCallable( - initialCallable, callSettings, initialContext, longRunningClient); - - ApiCallContext callContext = FakeCallContext.createDefault().withTimeout(Duration.ofMillis(10)); - - callable.futureCall(2, callContext).get(10, TimeUnit.SECONDS); - - assertThat(callContextCaptor.getValue().getTimeout()).isEqualTo(Duration.ofMillis(10)); - } - - @Test - public void testFutureCallPollDoneOnMany() throws Exception { - final int iterationsCount = 1000; - String opName = "testFutureCallPollDoneOnMany"; - Color resp = getColor(0.5f); - Currency meta = Currency.getInstance("UAH"); - - OperationSnapshot initialOperation = getOperation(opName, null, null, null, false); - - OperationSnapshot[] pollOperations = new OperationSnapshot[iterationsCount]; - for (int i = 0; i < iterationsCount - 1; i++) { - pollOperations[i] = getOperation(opName, null, null, meta, false); - } - pollOperations[iterationsCount - 1] = getOperation(opName, resp, null, meta, true); - UnaryCallable initialCallable = - mockGetOpSnapshotCallable(StatusCode.Code.OK, initialOperation); - LongRunningClient longRunningClient = mockGetOperation(StatusCode.Code.OK, pollOperations); - - pollingAlgorithm = - OperationTimedPollAlgorithm.create( - FAST_RECHECKING_SETTINGS - .toBuilder() - .setTotalTimeout(Duration.ofMillis(iterationsCount)) - .build(), - clock); - callSettings = callSettings.toBuilder().setPollingAlgorithm(pollingAlgorithm).build(); - - OperationCallable callable = - FakeCallableFactory.createOperationCallable( - initialCallable, callSettings, initialContext, longRunningClient); - - OperationFuture future = - callable.futureCall(2, FakeCallContext.createDefault()); - - Truth.assertThat(future.get(5, TimeUnit.SECONDS)).isEqualTo(resp); - assertFutureSuccessMetaSuccess(opName, future, resp, meta); - - assertThat(executor.getIterationsCount()).isEqualTo(iterationsCount - 1); - } - - @Test - public void testFutureCallPollError() throws Exception { - String opName = "testFutureCallPollError"; - Currency meta = Currency.getInstance("UAH"); - Color resp = getColor(1.0f); - OperationSnapshot initialOperation = getOperation(opName, resp, null, meta, false); - UnaryCallable initialCallable = - mockGetOpSnapshotCallable(StatusCode.Code.OK, initialOperation); - OperationSnapshot resultOperation = getOperation(opName, resp, null, meta, false); - LongRunningClient longRunningClient = - mockGetOperation(StatusCode.Code.ALREADY_EXISTS, resultOperation); - - OperationCallable callable = - FakeCallableFactory.createOperationCallable( - initialCallable, callSettings, initialContext, longRunningClient); - OperationFuture future = - callable.futureCall(2, FakeCallContext.createDefault()); - - assertFutureFailMetaFail(future, null, FakeStatusCode.of(StatusCode.Code.ALREADY_EXISTS)); - assertThat(executor.getIterationsCount()).isEqualTo(0); - } - - @Test - public void testFutureCallPollDoneWithError() throws Exception { - String opName = "testFutureCallPollDoneWithError"; - Currency meta = Currency.getInstance("UAH"); - Color resp = getColor(1.0f); - OperationSnapshot initialOperation = - getOperation(opName, resp, null, meta, false, "Already exists error"); - UnaryCallable initialCallable = - mockGetOpSnapshotCallable(StatusCode.Code.OK, initialOperation); - - StatusCode errorCode = FakeStatusCode.of(StatusCode.Code.ALREADY_EXISTS); - OperationSnapshot resultOperation = - getOperation(opName, null, errorCode, meta, true, "Already exists error"); - LongRunningClient longRunningClient = mockGetOperation(StatusCode.Code.OK, resultOperation); - - OperationCallable callable = - FakeCallableFactory.createOperationCallable( - initialCallable, callSettings, initialContext, longRunningClient); - OperationFuture future = - callable.futureCall(2, FakeCallContext.createDefault()); - - String errorMessage = - "Operation with name \"" - + opName - + "\" failed with status = " - + errorCode - + " and message = " - + "Already exists error"; - assertFutureFailMetaSuccess( - future, meta, FakeStatusCode.of(StatusCode.Code.ALREADY_EXISTS), errorMessage); - assertThat(executor.getIterationsCount()).isEqualTo(0); - } - - @Test - public void testFutureCallPollCancelOnTimeoutExceeded() throws Exception { - String opName = "testFutureCallPollCancelOnPollingTimeoutExceeded"; - OperationSnapshot initialOperation = getOperation(opName, null, null, null, false); - OperationSnapshot resultOperation = getOperation(opName, null, null, null, false); - UnaryCallable initialCallable = - mockGetOpSnapshotCallable(StatusCode.Code.OK, initialOperation); - LongRunningClient longRunningClient = mockGetOperation(StatusCode.Code.OK, resultOperation); - - OperationCallable callable = - FakeCallableFactory.createOperationCallable( - initialCallable, callSettings, initialContext, longRunningClient); - OperationFuture future = - callable.futureCall(2, FakeCallContext.createDefault()); - - assertFutureCancelMetaCancel(future); - assertThat(executor.getIterationsCount()).isEqualTo(5); - } - - @Test - public void testFutureCallPollCancelOnLongTimeoutExceeded() throws Exception { - final int iterationsCount = 1000; - String opName = "testFutureCallPollCancelOnLongTimeoutExceeded"; - OperationSnapshot initialOperation = getOperation(opName, null, null, null, false); - - OperationSnapshot[] pollOperations = new OperationSnapshot[iterationsCount]; - for (int i = 0; i < iterationsCount; i++) { - pollOperations[i] = getOperation(opName, null, null, null, false); - } - UnaryCallable initialCallable = - mockGetOpSnapshotCallable(StatusCode.Code.OK, initialOperation); - LongRunningClient longRunningClient = mockGetOperation(StatusCode.Code.OK, pollOperations); - - pollingAlgorithm = - OperationTimedPollAlgorithm.create( - FAST_RECHECKING_SETTINGS.toBuilder().setTotalTimeout(Duration.ofMillis(1000L)).build(), - clock); - callSettings = callSettings.toBuilder().setPollingAlgorithm(pollingAlgorithm).build(); - - OperationCallable callable = - FakeCallableFactory.createOperationCallable( - initialCallable, callSettings, initialContext, longRunningClient); - - OperationFuture future = - callable.futureCall(2, FakeCallContext.createDefault()); - - assertFutureCancelMetaCancel(future); - assertThat(executor.getIterationsCount()).isEqualTo(iterationsCount); - } - - @Test - public void testFutureCancelImmediately() throws Exception { - int iterationsCount = 3; - String opName = "testCancelImmediately"; - Color resp = getColor(0.5f); - Currency meta = Currency.getInstance("UAH"); - OperationSnapshot initialOperation = getOperation(opName, null, null, null, false); - UnaryCallable initialCallable = - mockGetOpSnapshotCallable(StatusCode.Code.OK, initialOperation); - - OperationSnapshot[] pollOperations = new OperationSnapshot[iterationsCount]; - for (int i = 0; i < iterationsCount; i++) { - pollOperations[i] = getOperation(opName, null, null, null, false); - } - pollOperations[iterationsCount - 1] = getOperation(opName, resp, null, meta, true); - - LongRunningClient longRunningClient = mockGetOperation(StatusCode.Code.OK, pollOperations); - - CountDownLatch retryScheduledLatch = new CountDownLatch(1); - LatchCountDownScheduler scheduler = LatchCountDownScheduler.get(retryScheduledLatch, 0L, 20L); - - ClientContext schedulerContext = getClientContext(initialChannel, scheduler); - OperationCallable callable = - FakeCallableFactory.createOperationCallable( - initialCallable, callSettings, schedulerContext, longRunningClient); - OperationFuture future = - callable.futureCall(2, FakeCallContext.createDefault()); - - while (!future.cancel(true) && !future.isDone()) { - LockSupport.parkNanos(1000L); - } - - assertFutureCancelMetaCancel(future); - scheduler.shutdownNow(); - } - - @Test - public void testFutureCancelInTheMiddle() throws Exception { - int iterationsCount = 1000; - String opName = "testCancelInTheMiddle"; - Color resp = getColor(0.5f); - Currency meta = Currency.getInstance("UAH"); - OperationSnapshot resultOperation = getOperation(opName, null, null, null, false); - UnaryCallable initialCallable = - mockGetOpSnapshotCallable(StatusCode.Code.OK, resultOperation); - - OperationSnapshot[] pollOperations = new OperationSnapshot[iterationsCount]; - for (int i = 0; i < iterationsCount - 1; i++) { - pollOperations[i] = getOperation(opName, null, null, null, false); - } - pollOperations[iterationsCount - 1] = getOperation(opName, resp, null, meta, true); - LongRunningClient longRunningClient = mockGetOperation(StatusCode.Code.OK, pollOperations); - - CountDownLatch retryScheduledLatch = new CountDownLatch(10); - LatchCountDownScheduler scheduler = LatchCountDownScheduler.get(retryScheduledLatch, 0L, 1L); - - ClientContext schedulerContext = getClientContext(initialChannel, scheduler); - OperationCallable callable = - FakeCallableFactory.createOperationCallable( - initialCallable, callSettings, schedulerContext, longRunningClient); - OperationFuture future = - callable.futureCall(2, FakeCallContext.createDefault()); - - CancellationHelpers.cancelInThreadAfterLatchCountDown(future, retryScheduledLatch); - - assertFutureCancelMetaCancel(future); - } - - @Test - public void testInitialServerSideCancel() throws Exception { - String opName = "testInitialServerSideCancel"; - StatusCode errorCode = FakeStatusCode.of(StatusCode.Code.CANCELLED); - Currency meta = Currency.getInstance("UAH"); - OperationSnapshot resultOperation = getOperation(opName, null, errorCode, meta, true); - UnaryCallable initialCallable = - mockGetOpSnapshotCallable(StatusCode.Code.OK, resultOperation); - LongRunningClient longRunningClient = new UnsupportedOperationApi(); - - OperationCallable callable = - FakeCallableFactory.createOperationCallable( - initialCallable, callSettings, initialContext, longRunningClient); - - OperationFuture future = - callable.futureCall(2, FakeCallContext.createDefault()); - - String errorMessage = - "Operation with name \"" - + opName - + "\" failed with status = " - + errorCode - + " and message = " - + "null"; - assertFutureFailMetaSuccess( - future, meta, FakeStatusCode.of(StatusCode.Code.CANCELLED), errorMessage); - assertThat(executor.getIterationsCount()).isEqualTo(0); - } - - @Test - public void testPollServerSideCancel() throws Exception { - String opName = "testPollServerSideCancel"; - StatusCode errorCode = FakeStatusCode.of(StatusCode.Code.CANCELLED); - Currency meta = Currency.getInstance("UAH"); - OperationSnapshot initialOperation = getOperation(opName, null, null, meta, false); - UnaryCallable initialCallable = - mockGetOpSnapshotCallable(StatusCode.Code.OK, initialOperation); - OperationSnapshot resultOperation1 = getOperation(opName, null, null, null, false); - OperationSnapshot resultOperation2 = getOperation(opName, null, errorCode, meta, true); - LongRunningClient longRunningClient = - mockGetOperation(StatusCode.Code.OK, resultOperation1, resultOperation2); - - OperationCallable callable = - FakeCallableFactory.createOperationCallable( - initialCallable, callSettings, initialContext, longRunningClient); - - OperationFuture future = - callable.futureCall(2, FakeCallContext.createDefault()); - - String errorMessage = - "Operation with name \"" - + opName - + "\" failed with status = " - + errorCode - + " and message = " - + "null"; - assertFutureFailMetaSuccess( - future, meta, FakeStatusCode.of(StatusCode.Code.CANCELLED), errorMessage); - assertThat(executor.getIterationsCount()).isEqualTo(1); - } - - @Test - public void call() { - ApiCallContext defaultCallContext = FakeCallContext.createDefault(); - OperationStashCallable stashCallable = new OperationStashCallable(); - OperationCallable callable = - stashCallable.withDefaultCallContext(defaultCallContext); - - String response = callable.call(1); - Truth.assertThat(response).isEqualTo("1"); - Truth.assertThat(stashCallable.getContext()).isSameInstanceAs(defaultCallContext); - } - - @Test - public void callWithContext() { - FakeChannel channel = new FakeChannel(); - Credentials credentials = Mockito.mock(Credentials.class); - ApiCallContext context = - FakeCallContext.createDefault().withChannel(channel).withCredentials(credentials); - OperationStashCallable stashCallable = new OperationStashCallable(); - OperationCallable callable = - stashCallable.withDefaultCallContext(FakeCallContext.createDefault()); - - String response = callable.call(2, context); - Truth.assertThat(response).isEqualTo("2"); - FakeCallContext actualContext = (FakeCallContext) stashCallable.getContext(); - Truth.assertThat(actualContext.getChannel()).isSameInstanceAs(channel); - Truth.assertThat(actualContext.getCredentials()).isSameInstanceAs(credentials); - } - - @Test - public void callResume() throws Exception { - ApiCallContext defaultCallContext = FakeCallContext.createDefault(); - OperationStashCallable stashCallable = new OperationStashCallable(); - OperationCallable callable = - stashCallable.withDefaultCallContext(defaultCallContext); - - OperationFuture operationFuture = callable.futureCall(45); - - String response = callable.resumeFutureCall(operationFuture.getName()).get(); - Truth.assertThat(response).isEqualTo("45"); - Truth.assertThat(stashCallable.getResumeContext()).isSameInstanceAs(defaultCallContext); - } - - @Test - public void callResumeWithContext() throws Exception { - FakeChannel channel = new FakeChannel(); - Credentials credentials = Mockito.mock(Credentials.class); - ApiCallContext context = - FakeCallContext.createDefault().withChannel(channel).withCredentials(credentials); - OperationStashCallable stashCallable = new OperationStashCallable(); - OperationCallable callable = - stashCallable.withDefaultCallContext(FakeCallContext.createDefault()); - - OperationFuture operationFuture = callable.futureCall(45); - - String response = callable.resumeFutureCall(operationFuture.getName(), context).get(); - Truth.assertThat(response).isEqualTo("45"); - FakeCallContext actualContext = (FakeCallContext) stashCallable.getResumeContext(); - Truth.assertThat(actualContext.getChannel()).isSameInstanceAs(channel); - Truth.assertThat(actualContext.getCredentials()).isSameInstanceAs(credentials); - } - - @Test - public void callCancel() throws Exception { - ApiCallContext defaultCallContext = FakeCallContext.createDefault(); - OperationStashCallable stashCallable = new OperationStashCallable(); - OperationCallable callable = - stashCallable.withDefaultCallContext(defaultCallContext); - - OperationFuture operationFuture = callable.futureCall(45); - - callable.cancel(operationFuture.getName()).get(); - Truth.assertThat(stashCallable.wasCancelCalled()).isTrue(); - Truth.assertThat(stashCallable.getCancelContext()).isSameInstanceAs(defaultCallContext); - } - - @Test - public void callCancelWithContext() throws Exception { - FakeChannel channel = new FakeChannel(); - Credentials credentials = Mockito.mock(Credentials.class); - ApiCallContext context = - FakeCallContext.createDefault().withChannel(channel).withCredentials(credentials); - OperationStashCallable stashCallable = new OperationStashCallable(); - OperationCallable callable = - stashCallable.withDefaultCallContext(FakeCallContext.createDefault()); - - OperationFuture operationFuture = callable.futureCall(45); - - callable.cancel(operationFuture.getName(), context).get(); - Truth.assertThat(stashCallable.wasCancelCalled()).isTrue(); - FakeCallContext actualContext = (FakeCallContext) stashCallable.getCancelContext(); - Truth.assertThat(actualContext.getChannel()).isSameInstanceAs(channel); - Truth.assertThat(actualContext.getCredentials()).isSameInstanceAs(credentials); - } - - private void assertFutureSuccessMetaSuccess( - String opName, OperationFuture future, Color resp, Currency meta) - throws InterruptedException, ExecutionException, TimeoutException { - assertThat(future.getName()).isEqualTo(opName); - Truth.assertThat(future.get(3, TimeUnit.SECONDS)).isEqualTo(resp); - assertThat(future.isDone()).isTrue(); - assertThat(future.isCancelled()).isFalse(); - Truth.assertThat(future.get()).isEqualTo(resp); - - Truth.assertThat(future.peekMetadata().get()).isEqualTo(meta); - assertThat(future.peekMetadata()).isSameInstanceAs(future.peekMetadata()); - assertThat(future.peekMetadata().isDone()).isTrue(); - assertThat(future.peekMetadata().isCancelled()).isFalse(); - - Truth.assertThat(future.getMetadata().get()).isEqualTo(meta); - assertThat(future.getMetadata()).isSameInstanceAs(future.getMetadata()); - assertThat(future.getMetadata().isDone()).isTrue(); - assertThat(future.getMetadata().isCancelled()).isFalse(); - } - - private void assertFutureFailMetaFail( - OperationFuture future, - Class exceptionClass, - FakeStatusCode statusCode) - throws TimeoutException, InterruptedException { - Exception exception = null; - try { - future.get(3, TimeUnit.SECONDS); - } catch (ExecutionException e) { - exception = e; - } - - assertThat(exception).isNotNull(); - if (statusCode != null) { - assertExceptionMatchesCode(statusCode, exception.getCause()); - ApiException cause = (ApiException) exception.getCause(); - assertThat(cause.getStatusCode()).isEqualTo(statusCode); - } else { - assertThat(exception.getCause().getClass()).isEqualTo(exceptionClass); - } - assertThat(future.isDone()).isTrue(); - assertThat(future.isCancelled()).isFalse(); - - try { - future.peekMetadata().get(3, TimeUnit.SECONDS); - } catch (ExecutionException e) { - exception = e; - } - assertThat(exception).isNotNull(); - if (statusCode != null) { - assertExceptionMatchesCode(statusCode, exception.getCause()); - ApiException cause = (ApiException) exception.getCause(); - assertThat(cause.getStatusCode()).isEqualTo(statusCode); - } else { - assertThat(exception.getCause().getClass()).isEqualTo(exceptionClass); - } - assertThat(future.peekMetadata()).isSameInstanceAs(future.peekMetadata()); - assertThat(future.peekMetadata().isDone()).isTrue(); - assertThat(future.peekMetadata().isCancelled()).isFalse(); - - try { - future.getMetadata().get(3, TimeUnit.SECONDS); - } catch (ExecutionException e) { - exception = e; - } - assertThat(exception).isNotNull(); - if (statusCode != null) { - assertExceptionMatchesCode(statusCode, exception.getCause()); - ApiException cause = (ApiException) exception.getCause(); - assertThat(cause.getStatusCode()).isEqualTo(statusCode); - } else { - assertThat(exception.getCause().getClass()).isEqualTo(exceptionClass); - } - assertThat(future.getMetadata()).isSameInstanceAs(future.getMetadata()); - assertThat(future.getMetadata().isDone()).isTrue(); - assertThat(future.getMetadata().isCancelled()).isFalse(); - } - - private void assertFutureFailMetaSuccess( - OperationFuture future, - Currency meta, - FakeStatusCode statusCode, - String errorMessage) - throws TimeoutException, InterruptedException, ExecutionException { - Exception exception = null; - try { - future.get(3, TimeUnit.SECONDS); - } catch (ExecutionException e) { - exception = e; - } - - assertThat(exception).isNotNull(); - assertExceptionMatchesCode(statusCode, exception.getCause()); - ApiException cause = (ApiException) exception.getCause(); - assertThat(cause.getStatusCode()).isEqualTo(statusCode); - assertThat(cause.getMessage()).isEqualTo(errorMessage); - assertThat(future.isDone()).isTrue(); - assertThat(future.isCancelled()).isFalse(); - - Truth.assertThat(future.peekMetadata().get()).isEqualTo(meta); - assertThat(future.peekMetadata()).isSameInstanceAs(future.peekMetadata()); - assertThat(future.peekMetadata().isDone()).isTrue(); - assertThat(future.peekMetadata().isCancelled()).isFalse(); - - Truth.assertThat(future.getMetadata().get()).isEqualTo(meta); - assertThat(future.getMetadata()).isSameInstanceAs(future.getMetadata()); - assertThat(future.getMetadata().isDone()).isTrue(); - assertThat(future.getMetadata().isCancelled()).isFalse(); - } - - private void assertFutureSuccessMetaFail( - OperationFuture future, Color resp, FakeStatusCode statusCode) - throws TimeoutException, InterruptedException, ExecutionException { - Exception exception = null; - Truth.assertThat(future.get(3, TimeUnit.SECONDS)).isEqualTo(resp); - assertThat(future.isDone()).isTrue(); - assertThat(future.isCancelled()).isFalse(); - Truth.assertThat(future.get()).isEqualTo(resp); - - try { - future.peekMetadata().get(3, TimeUnit.SECONDS); - } catch (ExecutionException e) { - exception = e; - } - assertThat(future.peekMetadata()).isSameInstanceAs(future.peekMetadata()); - assertThat(exception).isNotNull(); - assertExceptionMatchesCode(statusCode, exception.getCause()); - ApiException cause = (ApiException) exception.getCause(); - assertThat(cause.getStatusCode()).isEqualTo(statusCode); - assertThat(future.peekMetadata().isDone()).isTrue(); - assertThat(future.peekMetadata().isCancelled()).isFalse(); - - try { - future.getMetadata().get(3, TimeUnit.SECONDS); - } catch (ExecutionException e) { - exception = e; - } - assertThat(future.getMetadata()).isSameInstanceAs(future.getMetadata()); - assertThat(exception).isNotNull(); - assertExceptionMatchesCode(statusCode, exception.getCause()); - cause = (ApiException) exception.getCause(); - assertThat(cause.getStatusCode()).isEqualTo(statusCode); - assertThat(future.getMetadata().isDone()).isTrue(); - assertThat(future.getMetadata().isCancelled()).isFalse(); - } - - private void assertFutureCancelMetaCancel(OperationFuture future) - throws InterruptedException, ExecutionException, TimeoutException { - Exception exception = null; - try { - future.get(3, TimeUnit.SECONDS); - } catch (CancellationException e) { - exception = e; - } - assertThat(exception).isNotNull(); - assertThat(future.isDone()).isTrue(); - assertThat(future.isCancelled()).isTrue(); - - try { - future.peekMetadata().get(); - } catch (CancellationException e) { - exception = e; - } - assertThat(future.peekMetadata()).isSameInstanceAs(future.peekMetadata()); - assertThat(exception).isNotNull(); - assertThat(future.peekMetadata().isDone()).isTrue(); - assertThat(future.peekMetadata().isCancelled()).isTrue(); - - try { - future.getMetadata().get(); - } catch (CancellationException e) { - exception = e; - } - assertThat(future.getMetadata()).isSameInstanceAs(future.getMetadata()); - assertThat(exception).isNotNull(); - assertThat(future.getMetadata().isDone()).isTrue(); - assertThat(future.getMetadata().isCancelled()).isTrue(); - } - - private Color getColor(float blueValue) { - return new Color(0.0f, 0.0f, blueValue); - } - - private ClientContext getClientContext(FakeChannel channel, ScheduledExecutorService executor) { - return ClientContext.newBuilder() - .setTransportChannel(FakeTransportChannel.create(channel)) - .setExecutor(executor) - .setDefaultCallContext(FakeCallContext.createDefault()) - .build(); - } - - private OperationSnapshot getOperation( - String name, - Object response, - StatusCode errorCode, - Object metadata, - boolean done, - String errorMessage) { - FakeOperationSnapshot.Builder builder = - FakeOperationSnapshot.newBuilder().setName(name).setDone(done); - if (response != null) { - builder.setResponse(response); - } - if (errorCode != null) { - builder.setErrorCode(errorCode); - } else { - builder.setErrorCode(FakeStatusCode.of(StatusCode.Code.OK)); - } - if (metadata != null) { - builder.setMetadata(metadata); - } - if (errorMessage != null) { - builder.setErrorMessage(errorMessage); - } - return builder.build(); - } - - private OperationSnapshot getOperation( - String name, Object response, StatusCode errorCode, Object metadata, boolean done) { - return getOperation(name, response, errorCode, metadata, done, null); - } - - private UnaryCallable mockGetOpSnapshotCallable( - final StatusCode.Code returnStatusCode, final OperationSnapshot... results) { - return new UnaryCallable() { - private int index = 0; - - @Override - public ApiFuture futureCall(RequestT request, ApiCallContext context) { - FakeCallContext fakeCallContext = (FakeCallContext) context; - if (fakeCallContext != null - && fakeCallContext.getTimeout() != null - && fakeCallContext.getTimeout().isZero()) { - throw new DeadlineExceededException( - "Invalid timeout of 0 s", - null, - FakeStatusCode.of(StatusCode.Code.DEADLINE_EXCEEDED), - true); - } - OperationSnapshot response = results[index]; - if (index < results.length - 1) { - index += 1; - } - return newFuture(returnStatusCode, response); - } - }; - } - - private UnaryCallable getUnexpectedStartCallable() { - return new UnaryCallable() { - @Override - public ApiFuture futureCall(Integer request, ApiCallContext context) { - return ApiFutures.immediateFailedFuture( - new UnsupportedOperationException("Unexpected call to start operation")); - } - }; - } - - private class UnsupportedOperationApi implements LongRunningClient { - @Override - public UnaryCallable getOperationCallable() { - throw new UnsupportedOperationException("Didn't expect call to getOperationCallable()"); - } - - @Override - public UnaryCallable cancelOperationCallable() { - throw new UnsupportedOperationException("Didn't expect call to cancelOperationCallable()"); - } - - @Override - public UnaryCallable deleteOperationCallable() { - throw new UnsupportedOperationException("Didn't expect call to deleteOperationCallable()"); - } - } - - private LongRunningClient mockGetOperation( - final StatusCode.Code returnStatusCode, final OperationSnapshot... results) { - return new UnsupportedOperationApi() { - private UnaryCallable getOperationCallable = - mockGetOpSnapshotCallable(returnStatusCode, results); - - @Override - public UnaryCallable getOperationCallable() { - return getOperationCallable; - } - }; - } - - private LongRunningClient mockCancelOperation(final StatusCode.Code returnStatusCode) { - return new UnsupportedOperationApi() { - private UnaryCallable cancelOperationCallable = - new UnaryCallable() { - @Override - public ApiFuture futureCall(String request, ApiCallContext context) { - return newFuture(returnStatusCode, null); - } - }; - - @Override - public UnaryCallable cancelOperationCallable() { - return cancelOperationCallable; - } - }; - } - - private ApiFuture newFuture( - StatusCode.Code returnStatusCode, ResponseT response) { - if (StatusCode.Code.OK.equals(returnStatusCode)) { - return ApiFutures.immediateFuture(response); - } else { - return ApiFutures.immediateFailedFuture( - ApiExceptionFactory.createException(null, FakeStatusCode.of(returnStatusCode), false)); - } - } - - private void assertExceptionMatchesCode(FakeStatusCode code, Throwable exception) { - Class expectedClass; - switch (code.getCode()) { - case CANCELLED: - expectedClass = CancelledException.class; - break; - // case NOT_FOUND: - // expectedClass = NotFoundException.class; - // break; - case UNKNOWN: - expectedClass = UnknownException.class; - break; - // case INVALID_ARGUMENT: - // expectedClass = InvalidArgumentException.class; - // break; - case DEADLINE_EXCEEDED: - expectedClass = DeadlineExceededException.class; - break; - case ALREADY_EXISTS: - expectedClass = AlreadyExistsException.class; - break; - // case PERMISSION_DENIED: - // expectedClass = PermissionDeniedException.class; - // break; - // case RESOURCE_EXHAUSTED: - // expectedClass = ResourceExhaustedException.class; - // break; - case FAILED_PRECONDITION: - expectedClass = FailedPreconditionException.class; - break; - // case ABORTED: - // expectedClass = AbortedException.class; - // break; - // case OUT_OF_RANGE: - // expectedClass = OutOfRangeException.class; - // break; - // case INTERNAL: - // expectedClass = InternalException.class; - // break; - case UNAVAILABLE: - expectedClass = UnavailableException.class; - break; - // case DATA_LOSS: - // expectedClass = DataLossException.class; - // break; - // case UNAUTHENTICATED: - // expectedClass = UnauthenticatedException.class; - // break; - - default: - expectedClass = ApiException.class; - } - assertThat(exception).isInstanceOf(expectedClass); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/PagedCallSettingsTest.java b/gax/src/test/java/com/google/api/gax/rpc/PagedCallSettingsTest.java deleted file mode 100644 index 25c6b8064..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/PagedCallSettingsTest.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.common.collect.Sets; -import com.google.common.truth.Truth; -import java.util.Set; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class PagedCallSettingsTest { - - @Test - public void testEmptyBuilder() { - @SuppressWarnings("unchecked") - PagedListResponseFactory pagedListResponseFactory = - Mockito.mock(PagedListResponseFactory.class); - PagedCallSettings.Builder builder = - PagedCallSettings.newBuilder(pagedListResponseFactory); - - Truth.assertThat(builder.getPagedListResponseFactory()) - .isSameInstanceAs(pagedListResponseFactory); - Truth.assertThat(builder.getRetryableCodes().size()).isEqualTo(0); - Truth.assertThat(builder.getRetrySettings()).isNotNull(); - - PagedCallSettings settings = builder.build(); - - Truth.assertThat(settings.getPagedListResponseFactory()) - .isSameInstanceAs(pagedListResponseFactory); - Truth.assertThat(settings.getRetryableCodes().size()).isEqualTo(0); - Truth.assertThat(settings.getRetrySettings()).isNotNull(); - } - - @Test - public void testBuilder() { - @SuppressWarnings("unchecked") - PagedListResponseFactory pagedListResponseFactory = - Mockito.mock(PagedListResponseFactory.class); - PagedCallSettings.Builder builder = - PagedCallSettings.newBuilder(pagedListResponseFactory); - - Set retryCodes = Sets.newHashSet(Code.UNAVAILABLE); - RetrySettings retrySettings = - RetrySettings.newBuilder() - .setInitialRetryDelay(Duration.ofMillis(5)) - .setMaxRetryDelay(Duration.ofSeconds(1)) - .setRetryDelayMultiplier(2) - .setInitialRpcTimeout(Duration.ofMillis(100)) - .setMaxRpcTimeout(Duration.ofMillis(200)) - .setRpcTimeoutMultiplier(1.1) - .setJittered(true) - .setMaxAttempts(10) - .build(); - - builder.setRetryableCodes(retryCodes); - builder.setRetrySettings(retrySettings); - - Truth.assertThat(builder.getRetryableCodes().size()).isEqualTo(1); - Truth.assertThat(builder.getRetrySettings()).isEqualTo(retrySettings); - - PagedCallSettings settings = builder.build(); - - Truth.assertThat(settings.getRetryableCodes().size()).isEqualTo(1); - Truth.assertThat(settings.getRetrySettings()).isEqualTo(retrySettings); - } - - @Test - public void testBuilderFromSettings() throws Exception { - @SuppressWarnings("unchecked") - PagedListResponseFactory pagedListResponseFactory = - Mockito.mock(PagedListResponseFactory.class); - PagedCallSettings.Builder builder = - PagedCallSettings.newBuilder(pagedListResponseFactory); - - Set retryCodes = Sets.newHashSet(Code.UNAVAILABLE); - RetrySettings retrySettings = - RetrySettings.newBuilder() - .setInitialRetryDelay(Duration.ofMillis(5)) - .setMaxRetryDelay(Duration.ofSeconds(1)) - .setRetryDelayMultiplier(2) - .setInitialRpcTimeout(Duration.ofMillis(100)) - .setMaxRpcTimeout(Duration.ofMillis(200)) - .setRpcTimeoutMultiplier(1.1) - .setJittered(true) - .setMaxAttempts(10) - .build(); - - builder.setRetryableCodes(retryCodes); - builder.setRetrySettings(retrySettings); - - Truth.assertThat(builder.getRetryableCodes().size()).isEqualTo(1); - Truth.assertThat(builder.getRetrySettings()).isEqualTo(retrySettings); - - PagedCallSettings settings = builder.build(); - PagedCallSettings.Builder newBuilder = settings.toBuilder(); - - Truth.assertThat(newBuilder.getRetryableCodes().size()).isEqualTo(1); - Truth.assertThat(newBuilder.getRetrySettings()).isEqualTo(retrySettings); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/PagedCallableTest.java b/gax/src/test/java/com/google/api/gax/rpc/PagedCallableTest.java deleted file mode 100644 index de1dfaf6b..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/PagedCallableTest.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.gax.rpc.testing.FakeCallContext; -import com.google.api.gax.rpc.testing.FakePagedApi.ListIntegersPagedResponse; -import com.google.api.gax.rpc.testing.FakePagedApi.ListIntegersPagedResponseFactory; -import com.google.api.gax.rpc.testing.FakePagedApi.PagedStashCallable; -import com.google.common.collect.ImmutableList; -import com.google.common.truth.Truth; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class PagedCallableTest { - - @Test - public void futureCall() { - List> results = - Arrays.asList( - Arrays.asList(0, 1, 2), Arrays.asList(3, 4), Collections.emptyList()); - PagedStashCallable callable = new PagedStashCallable(results); - PagedCallable, ListIntegersPagedResponse> pagedCallable = - new PagedCallable<>(callable, new ListIntegersPagedResponseFactory()); - - Truth.assertThat( - ImmutableList.copyOf( - pagedCallable.call(0, FakeCallContext.createDefault()).iterateAll())) - .containsExactly(0, 1, 2, 3, 4) - .inOrder(); - } - - @Test - public void testToString() { - PagedStashCallable stash = new PagedStashCallable(null); - PagedCallable, ListIntegersPagedResponse> pagedCallable = - new PagedCallable<>(stash, new ListIntegersPagedResponseFactory()); - Truth.assertThat(pagedCallable.toString()).contains("paged"); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/PagingTest.java b/gax/src/test/java/com/google/api/gax/rpc/PagingTest.java deleted file mode 100644 index e1655b6bf..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/PagingTest.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.ApiFutures; -import com.google.api.gax.paging.FixedSizeCollection; -import com.google.api.gax.paging.Page; -import com.google.api.gax.rpc.testing.FakeCallContext; -import com.google.api.gax.rpc.testing.FakeCallableFactory; -import com.google.api.gax.rpc.testing.FakeChannel; -import com.google.api.gax.rpc.testing.FakePagedApi.ListIntegersPagedResponse; -import com.google.api.gax.rpc.testing.FakePagedApi.ListIntegersPagedResponseFactory; -import com.google.api.gax.rpc.testing.FakeTransportChannel; -import com.google.api.pathtemplate.ValidationException; -import com.google.common.collect.ImmutableList; -import com.google.common.truth.Truth; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; - -@RunWith(JUnit4.class) -public class PagingTest { - private ClientContext clientContext; - - @Before - public void setUp() { - clientContext = - ClientContext.newBuilder() - .setDefaultCallContext(FakeCallContext.createDefault()) - .setTransportChannel(FakeTransportChannel.create(new FakeChannel())) - .build(); - } - - @SuppressWarnings("unchecked") - UnaryCallable> callIntList = Mockito.mock(UnaryCallable.class); - - @Test - public void nonPaged() { - ArgumentCaptor requestCapture = ArgumentCaptor.forClass(Integer.class); - Mockito.when(callIntList.futureCall(requestCapture.capture(), (ApiCallContext) Mockito.any())) - .thenReturn(ApiFutures.immediateFuture(Arrays.asList(0, 1, 2))) - .thenReturn(ApiFutures.immediateFuture(Arrays.asList(3, 4))) - .thenReturn(ApiFutures.immediateFuture(Collections.emptyList())); - UnaryCallable> callable = - FakeCallableFactory.createUnpagedCallable( - callIntList, - PagedCallSettings.newBuilder(new ListIntegersPagedResponseFactory()).build(), - clientContext); - Truth.assertThat(ImmutableList.copyOf(callable.call(0))).containsExactly(0, 1, 2).inOrder(); - Truth.assertThat(ImmutableList.copyOf(callable.call(2))).containsExactly(3, 4).inOrder(); - Truth.assertThat(ImmutableList.copyOf(callable.call(4))).isEmpty(); - Truth.assertThat(requestCapture.getAllValues()).containsExactly(0, 2, 4).inOrder(); - } - - @Test - public void paged() { - ArgumentCaptor requestCapture = ArgumentCaptor.forClass(Integer.class); - Mockito.when(callIntList.futureCall(requestCapture.capture(), (ApiCallContext) Mockito.any())) - .thenReturn(ApiFutures.immediateFuture(Arrays.asList(0, 1, 2))) - .thenReturn(ApiFutures.immediateFuture(Arrays.asList(3, 4))) - .thenReturn(ApiFutures.immediateFuture(Collections.emptyList())); - UnaryCallable callable = - FakeCallableFactory.createPagedCallable( - callIntList, - PagedCallSettings.newBuilder(new ListIntegersPagedResponseFactory()).build(), - clientContext); - Truth.assertThat(ImmutableList.copyOf(callable.call(0).iterateAll())) - .containsExactly(0, 1, 2, 3, 4) - .inOrder(); - Truth.assertThat(requestCapture.getAllValues()).containsExactly(0, 2, 4).inOrder(); - } - - @Test - public void pagedByPage() { - ArgumentCaptor requestCapture = ArgumentCaptor.forClass(Integer.class); - Mockito.when(callIntList.futureCall(requestCapture.capture(), (ApiCallContext) Mockito.any())) - .thenReturn(ApiFutures.immediateFuture(Arrays.asList(0, 1, 2))) - .thenReturn(ApiFutures.immediateFuture(Arrays.asList(3, 4))) - .thenReturn(ApiFutures.immediateFuture(Collections.emptyList())); - - Page page = - FakeCallableFactory.createPagedCallable( - callIntList, - PagedCallSettings.newBuilder(new ListIntegersPagedResponseFactory()).build(), - clientContext) - .call(0) - .getPage(); - - Truth.assertThat(page.getValues()).containsExactly(0, 1, 2).inOrder(); - Truth.assertThat(page.hasNextPage()).isTrue(); - - page = page.getNextPage(); - Truth.assertThat(page.getValues()).containsExactly(3, 4).inOrder(); - Truth.assertThat(page.hasNextPage()).isTrue(); - - page = page.getNextPage(); - Truth.assertThat(page.getValues()).isEmpty(); - Truth.assertThat(page.hasNextPage()).isFalse(); - Truth.assertThat(page.getNextPage()).isNull(); - Truth.assertThat(requestCapture.getAllValues()).containsExactly(0, 2, 4).inOrder(); - } - - @Test - public void pagedByFixedSizeCollection() { - ArgumentCaptor requestCapture = ArgumentCaptor.forClass(Integer.class); - Mockito.when(callIntList.futureCall(requestCapture.capture(), (ApiCallContext) Mockito.any())) - .thenReturn(ApiFutures.immediateFuture(Arrays.asList(0, 1, 2))) - .thenReturn(ApiFutures.immediateFuture(Arrays.asList(3, 4))) - .thenReturn(ApiFutures.immediateFuture(Arrays.asList(5, 6, 7))) - .thenReturn(ApiFutures.immediateFuture(Collections.emptyList())); - FixedSizeCollection fixedSizeCollection = - FakeCallableFactory.createPagedCallable( - callIntList, - PagedCallSettings.newBuilder(new ListIntegersPagedResponseFactory()).build(), - clientContext) - .call(0) - .expandToFixedSizeCollection(5); - - Truth.assertThat(fixedSizeCollection.getValues()).containsExactly(0, 1, 2, 3, 4).inOrder(); - Truth.assertThat(fixedSizeCollection.getNextCollection().getValues()) - .containsExactly(5, 6, 7) - .inOrder(); - Truth.assertThat(requestCapture.getAllValues()).containsExactly(0, 2, 4, 7).inOrder(); - } - - @Test(expected = ValidationException.class) - public void pagedFixedSizeCollectionTooManyElements() { - Mockito.when(callIntList.futureCall((Integer) Mockito.any(), (ApiCallContext) Mockito.any())) - .thenReturn(ApiFutures.immediateFuture(Arrays.asList(0, 1, 2))) - .thenReturn(ApiFutures.immediateFuture(Arrays.asList(3, 4))) - .thenReturn(ApiFutures.immediateFuture(Collections.emptyList())); - - FakeCallableFactory.createPagedCallable( - callIntList, - PagedCallSettings.newBuilder(new ListIntegersPagedResponseFactory()).build(), - clientContext) - .call(0) - .expandToFixedSizeCollection(4); - } - - @Test(expected = ValidationException.class) - public void pagedFixedSizeCollectionTooSmallCollectionSize() { - Mockito.when(callIntList.futureCall((Integer) Mockito.any(), (ApiCallContext) Mockito.any())) - .thenReturn(ApiFutures.immediateFuture(Arrays.asList(0, 1))) - .thenReturn(ApiFutures.immediateFuture(Collections.emptyList())); - - FakeCallableFactory.createPagedCallable( - callIntList, - PagedCallSettings.newBuilder(new ListIntegersPagedResponseFactory()).build(), - clientContext) - .call(0) - .expandToFixedSizeCollection(2); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/RequestParamsBuilderTest.java b/gax/src/test/java/com/google/api/gax/rpc/RequestParamsBuilderTest.java deleted file mode 100644 index 30f4d7e62..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/RequestParamsBuilderTest.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.gax.rpc; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.api.pathtemplate.PathTemplate; -import java.util.Map; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class RequestParamsBuilderTest { - - private RequestParamsBuilder requestParamsBuilder; - - @Before - public void setUp() { - requestParamsBuilder = RequestParamsBuilder.create(); - } - - @Test - public void add_happyPath() { - Map actual = - getRoutingHeaders( - "projects/**/{table_location=instances/*}", - "projects/my_cozy_home/instances/living_room"); - assertThat(actual).containsExactly("table_location", "instances/living_room"); - } - - @Test - public void build_shouldKeepLastEntryIfMultipleEntriesHaveTheSameKeyRatherThanErrorOut() { - requestParamsBuilder.add( - "projects/my_cozy_home/instances/living_room", - "table_location", - PathTemplate.create("projects/**/{table_location=instances/*}")); - requestParamsBuilder.add( - "projects/my_cozy_home/instances/living_room", - "table_location", - PathTemplate.create("{table_location=**}")); - requestParamsBuilder.add( - "projects/my_cozy_home/instances/living_room", - "routing_id", - PathTemplate.create("{routing_id=**}")); - Map actual = requestParamsBuilder.build(); - - // Should contain two entries instead of three, also should only keep the last entry if there - // are multiple entries with the same key - assertThat(actual) - .containsExactly( - "table_location", - "projects/my_cozy_home/instances/living_room", - "routing_id", - "projects/my_cozy_home/instances/living_room"); - } - - @Test - public void add_matchedValuesWithNoRoutingHeaderKey() { - Map actual = getRoutingHeaders("projects/**", "projects/my_cozy_home/"); - assertThat(actual).isEmpty(); - } - - @Test - public void add_emptyMatchedValues() { - Map actual = - getRoutingHeaders("projects/**/{table_location=instances/*}", "projects/does_not_matter"); - assertThat(actual).isEmpty(); - } - - @Test - public void add_nullFieldValue() { - Map actual = getRoutingHeaders("projects/**", null); - assertThat(actual).isEmpty(); - } - - private Map getRoutingHeaders(String patternString, String fieldValue) { - PathTemplate pathTemplate = PathTemplate.create(patternString); - requestParamsBuilder.add(fieldValue, "table_location", pathTemplate); - return requestParamsBuilder.build(); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/RequestUrlParamsEncoderTest.java b/gax/src/test/java/com/google/api/gax/rpc/RequestUrlParamsEncoderTest.java deleted file mode 100644 index 3239bd148..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/RequestUrlParamsEncoderTest.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.gax.rpc; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.mockito.Mockito.when; - -import com.google.common.collect.ImmutableMap; -import java.util.Collections; -import java.util.Map; -import org.junit.Test; -import org.mockito.Mockito; - -public class RequestUrlParamsEncoderTest { - - @Test - public void testEncodeValidationSuccess() throws Exception { - @SuppressWarnings("unchecked") - RequestParamsExtractor extractor = - getMockExtractor(2, ImmutableMap.of("param1", "value+1", "param2", "value+2+%26")); - - RequestUrlParamsEncoder encoder = new RequestUrlParamsEncoder<>(extractor, true); - String encodedParams = encoder.encode(2); - - assertEquals("param1=value+1¶m2=value+2+%26", encodedParams); - } - - @Test(expected = IllegalArgumentException.class) - public void testEncodeValidationFail() throws Exception { - RequestParamsExtractor extractor = - getMockExtractor(1, ImmutableMap.of("param1", "value+1", "param2", "value+2+&")); - RequestUrlParamsEncoder encoder = new RequestUrlParamsEncoder<>(extractor, true); - encoder.encode(1); - } - - @Test - public void testEncodeNoValidationSuccess() throws Exception { - RequestParamsExtractor extractor = - getMockExtractor(1, ImmutableMap.of("param1", "value+1", "param2", "value+2+&")); - RequestUrlParamsEncoder encoder = new RequestUrlParamsEncoder<>(extractor, false); - String encodedParams = encoder.encode(1); - - assertEquals("param1=value+1¶m2=value+2+&", encodedParams); - } - - @Test(expected = IllegalArgumentException.class) - public void testEncodeNullName() throws Exception { - RequestParamsExtractor extractor = - getMockExtractor(1, Collections.singletonMap((String) null, "value1")); - RequestUrlParamsEncoder encoder = new RequestUrlParamsEncoder<>(extractor, false); - encoder.encode(1); - } - - @Test - public void testEncodeNullValue() throws Exception { - RequestParamsExtractor extractor = - getMockExtractor(1, Collections.singletonMap("param1", (String) null)); - RequestUrlParamsEncoder encoder = new RequestUrlParamsEncoder<>(extractor, false); - String encodedParams = encoder.encode(1); - assertEquals("", encodedParams); - } - - @Test - public void testEncodeEmptyValue() throws Exception { - RequestParamsExtractor extractor = - getMockExtractor(1, Collections.singletonMap("param1", "")); - RequestUrlParamsEncoder encoder = new RequestUrlParamsEncoder<>(extractor, false); - String encodedParams = encoder.encode(1); - assertEquals("param1=", encodedParams); - } - - @Test - public void testEncodeNullAndEmptyParams() throws Exception { - RequestParamsExtractor extractor = - getMockExtractor(1, Collections.emptyMap()); - RequestUrlParamsEncoder encoder = new RequestUrlParamsEncoder<>(extractor, false); - String encodedParams = encoder.encode(1); - assertEquals("", encodedParams); - - extractor = getMockExtractor(1, null); - encoder = new RequestUrlParamsEncoder<>(extractor, false); - NullPointerException exception = null; - try { - encoder.encode(1); - } catch (NullPointerException e) { - exception = e; - } - assertNotNull(exception); - } - - private RequestParamsExtractor getMockExtractor( - Integer input, Map output) { - @SuppressWarnings("unchecked") - RequestParamsExtractor extractor = - (RequestParamsExtractor) Mockito.mock(RequestParamsExtractor.class); - when(extractor.extract(input)).thenReturn(output); - return extractor; - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/RetryingTest.java b/gax/src/test/java/com/google/api/gax/rpc/RetryingTest.java deleted file mode 100644 index b58bd2c2c..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/RetryingTest.java +++ /dev/null @@ -1,454 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.api.gax.core.FakeApiClock; -import com.google.api.gax.core.RecordingScheduler; -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.api.gax.rpc.testing.FakeCallContext; -import com.google.api.gax.rpc.testing.FakeCallableFactory; -import com.google.api.gax.rpc.testing.FakeChannel; -import com.google.api.gax.rpc.testing.FakeStatusCode; -import com.google.api.gax.rpc.testing.FakeTransportChannel; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Sets; -import com.google.common.truth.Truth; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.UncheckedExecutionException; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class RetryingTest { - - @SuppressWarnings("unchecked") - private UnaryCallable callInt = Mockito.mock(UnaryCallable.class); - - private RecordingScheduler executor; - private FakeApiClock fakeClock; - private ClientContext clientContext; - - private static final RetrySettings FAST_RETRY_SETTINGS = - RetrySettings.newBuilder() - .setInitialRetryDelay(Duration.ofMillis(2L)) - .setRetryDelayMultiplier(1) - .setMaxRetryDelay(Duration.ofMillis(2L)) - .setInitialRpcTimeout(Duration.ofMillis(2L)) - .setRpcTimeoutMultiplier(1) - .setMaxRpcTimeout(Duration.ofMillis(2L)) - .setTotalTimeout(Duration.ofMillis(10L)) - .build(); - private static final RetrySettings FAILING_RETRY_SETTINGS = - RetrySettings.newBuilder() - .setMaxAttempts(2) - .setInitialRetryDelay(Duration.ofNanos(0L)) - .setRetryDelayMultiplier(1) - .setMaxRetryDelay(Duration.ofMillis(0L)) - .setInitialRpcTimeout(Duration.ofNanos(1L)) - .setRpcTimeoutMultiplier(1) - .setMaxRpcTimeout(Duration.ofNanos(1L)) - .setTotalTimeout(Duration.ofNanos(1L)) - .build(); - - @Before - public void resetClock() { - fakeClock = new FakeApiClock(System.nanoTime()); - executor = RecordingScheduler.create(fakeClock); - clientContext = - ClientContext.newBuilder() - .setExecutor(executor) - .setClock(fakeClock) - .setDefaultCallContext(FakeCallContext.createDefault()) - .setTransportChannel(FakeTransportChannel.create(new FakeChannel())) - .build(); - } - - @After - public void teardown() { - executor.shutdownNow(); - } - - static ApiFuture immediateFailedFuture(Throwable t) { - return ApiFutures.immediateFailedFuture(t); - } - - @Test - public void retry() { - Throwable throwable = - new UnavailableException(null, FakeStatusCode.of(StatusCode.Code.UNAVAILABLE), true); - Mockito.when(callInt.futureCall((Integer) Mockito.any(), (ApiCallContext) Mockito.any())) - .thenReturn(RetryingTest.immediateFailedFuture(throwable)) - .thenReturn(RetryingTest.immediateFailedFuture(throwable)) - .thenReturn(RetryingTest.immediateFailedFuture(throwable)) - .thenReturn(ApiFutures.immediateFuture(2)); - - assertRetrying(FAST_RETRY_SETTINGS); - } - - @Test - public void retryUsingContext() { - Throwable throwable = - new UnavailableException(null, FakeStatusCode.of(StatusCode.Code.INTERNAL), false); - Mockito.when(callInt.futureCall(Mockito.any(), Mockito.any())) - .thenReturn(RetryingTest.immediateFailedFuture(throwable)) - .thenReturn(RetryingTest.immediateFailedFuture(throwable)) - .thenReturn(RetryingTest.immediateFailedFuture(throwable)) - .thenReturn(ApiFutures.immediateFuture(2)); - - assertRetryingUsingContext( - FAILING_RETRY_SETTINGS, - FakeCallContext.createDefault() - .withRetrySettings(FAST_RETRY_SETTINGS) - .withRetryableCodes(Sets.newHashSet(StatusCode.Code.INTERNAL))); - } - - @Test(expected = ApiException.class) - public void retryTotalTimeoutExceeded() { - Throwable throwable = - new UnavailableException(null, FakeStatusCode.of(StatusCode.Code.UNAVAILABLE), true); - Mockito.when(callInt.futureCall((Integer) Mockito.any(), (ApiCallContext) Mockito.any())) - .thenReturn(RetryingTest.immediateFailedFuture(throwable)) - .thenReturn(ApiFutures.immediateFuture(2)); - - RetrySettings retrySettings = - FAST_RETRY_SETTINGS - .toBuilder() - .setInitialRetryDelay(Duration.ofMillis(Integer.MAX_VALUE)) - .setMaxRetryDelay(Duration.ofMillis(Integer.MAX_VALUE)) - .build(); - - assertRetrying(retrySettings); - } - - @Test - public void retryUsingContextTotalTimeoutExceeded() { - Throwable throwable = - new UnavailableException(null, FakeStatusCode.of(StatusCode.Code.INTERNAL), false); - Mockito.when(callInt.futureCall((Integer) Mockito.any(), (ApiCallContext) Mockito.any())) - .thenReturn(RetryingTest.immediateFailedFuture(throwable)) - .thenReturn(ApiFutures.immediateFuture(2)); - - RetrySettings retrySettings = - FAST_RETRY_SETTINGS - .toBuilder() - .setInitialRetryDelay(Duration.ofMillis(Integer.MAX_VALUE)) - .setMaxRetryDelay(Duration.ofMillis(Integer.MAX_VALUE)) - .build(); - - try { - assertRetryingUsingContext( - FAILING_RETRY_SETTINGS, - FakeCallContext.createDefault() - .withRetrySettings(retrySettings) - .withRetryableCodes(Sets.newHashSet(StatusCode.Code.INTERNAL))); - fail("missing expected exception"); - } catch (ApiException e) { - assertEquals(Code.INTERNAL, e.getStatusCode().getCode()); - } - } - - @Test(expected = ApiException.class) - public void retryMaxAttemptsExceeded() { - Throwable throwable = - new UnavailableException(null, FakeStatusCode.of(StatusCode.Code.UNAVAILABLE), true); - Mockito.when(callInt.futureCall((Integer) Mockito.any(), (ApiCallContext) Mockito.any())) - .thenReturn(RetryingTest.immediateFailedFuture(throwable)) - .thenReturn(RetryingTest.immediateFailedFuture(throwable)) - .thenReturn(ApiFutures.immediateFuture(2)); - - assertRetrying(FAST_RETRY_SETTINGS.toBuilder().setMaxAttempts(2).build()); - } - - @Test - public void retryUsingContextMaxAttemptsExceeded() { - Throwable throwable = - new UnavailableException(null, FakeStatusCode.of(StatusCode.Code.INTERNAL), false); - Mockito.when(callInt.futureCall((Integer) Mockito.any(), (ApiCallContext) Mockito.any())) - .thenReturn(RetryingTest.immediateFailedFuture(throwable)) - .thenReturn(RetryingTest.immediateFailedFuture(throwable)) - .thenReturn(ApiFutures.immediateFuture(2)); - - try { - assertRetryingUsingContext( - FAILING_RETRY_SETTINGS, - FakeCallContext.createDefault() - .withRetrySettings(FAST_RETRY_SETTINGS.toBuilder().setMaxAttempts(2).build()) - .withRetryableCodes(Sets.newHashSet(StatusCode.Code.INTERNAL))); - fail("missing expected exception"); - } catch (ApiException e) { - assertEquals(Code.INTERNAL, e.getStatusCode().getCode()); - } - } - - @Test - public void retryWithinMaxAttempts() { - Throwable throwable = - new UnavailableException(null, FakeStatusCode.of(StatusCode.Code.UNAVAILABLE), true); - Mockito.when(callInt.futureCall((Integer) Mockito.any(), (ApiCallContext) Mockito.any())) - .thenReturn(RetryingTest.immediateFailedFuture(throwable)) - .thenReturn(RetryingTest.immediateFailedFuture(throwable)) - .thenReturn(ApiFutures.immediateFuture(2)); - - assertRetrying(FAST_RETRY_SETTINGS.toBuilder().setMaxAttempts(3).build()); - } - - @Test - public void retryUsingContextWithinMaxAttempts() { - Throwable throwable = - new UnavailableException(null, FakeStatusCode.of(StatusCode.Code.INTERNAL), false); - Mockito.when(callInt.futureCall((Integer) Mockito.any(), (ApiCallContext) Mockito.any())) - .thenReturn(RetryingTest.immediateFailedFuture(throwable)) - .thenReturn(RetryingTest.immediateFailedFuture(throwable)) - .thenReturn(ApiFutures.immediateFuture(2)); - - assertRetryingUsingContext( - FAILING_RETRY_SETTINGS, - FakeCallContext.createDefault() - .withRetrySettings(FAST_RETRY_SETTINGS.toBuilder().setMaxAttempts(3).build()) - .withRetryableCodes(Sets.newHashSet(StatusCode.Code.INTERNAL))); - } - - @Test - public void retryWithOnlyMaxAttempts() { - Throwable throwable = - new UnavailableException(null, FakeStatusCode.of(StatusCode.Code.UNAVAILABLE), true); - Mockito.when(callInt.futureCall(Mockito.any(), Mockito.any())) - .thenReturn(RetryingTest.immediateFailedFuture(throwable)) - .thenReturn(RetryingTest.immediateFailedFuture(throwable)) - .thenReturn(ApiFutures.immediateFuture(2)); - - RetrySettings retrySettings = RetrySettings.newBuilder().setMaxAttempts(3).build(); - - assertRetrying(retrySettings); - Mockito.verify(callInt, Mockito.times(3)) - .futureCall(Mockito.any(), Mockito.any()); - } - - @Test - public void retryUsingContextWithOnlyMaxAttempts() { - Throwable throwable = - new UnavailableException(null, FakeStatusCode.of(StatusCode.Code.INTERNAL), false); - Mockito.when(callInt.futureCall(Mockito.any(), Mockito.any())) - .thenReturn(RetryingTest.immediateFailedFuture(throwable)) - .thenReturn(RetryingTest.immediateFailedFuture(throwable)) - .thenReturn(ApiFutures.immediateFuture(2)); - - RetrySettings retrySettings = RetrySettings.newBuilder().setMaxAttempts(3).build(); - - assertRetryingUsingContext( - FAILING_RETRY_SETTINGS, - FakeCallContext.createDefault() - .withRetrySettings(retrySettings) - .withRetryableCodes(Sets.newHashSet(StatusCode.Code.INTERNAL))); - Mockito.verify(callInt, Mockito.times(3)) - .futureCall(Mockito.any(), Mockito.any()); - } - - @Test - public void retryWithoutRetrySettings() { - Mockito.when(callInt.futureCall(Mockito.any(), Mockito.any())) - .thenReturn(ApiFutures.immediateFuture(2)); - - RetrySettings retrySettings = RetrySettings.newBuilder().build(); - - assertRetrying(retrySettings); - Mockito.verify(callInt).futureCall(Mockito.any(), Mockito.any()); - } - - @Test - public void retryUsingContextWithoutRetrySettings() { - Mockito.when(callInt.futureCall(Mockito.any(), Mockito.any())) - .thenReturn(ApiFutures.immediateFuture(2)); - - RetrySettings retrySettings = RetrySettings.newBuilder().build(); - - assertRetryingUsingContext( - FAILING_RETRY_SETTINGS, FakeCallContext.createDefault().withRetrySettings(retrySettings)); - Mockito.verify(callInt).futureCall(Mockito.any(), Mockito.any()); - } - - @Test - public void retryOnStatusUnknown() { - Throwable throwable = - new UnknownException(null, FakeStatusCode.of(StatusCode.Code.UNKNOWN), true); - Mockito.when(callInt.futureCall((Integer) Mockito.any(), (ApiCallContext) Mockito.any())) - .thenReturn(RetryingTest.immediateFailedFuture(throwable)) - .thenReturn(RetryingTest.immediateFailedFuture(throwable)) - .thenReturn(RetryingTest.immediateFailedFuture(throwable)) - .thenReturn(ApiFutures.immediateFuture(2)); - - assertRetrying(FAST_RETRY_SETTINGS); - } - - @Test - public void retryOnUnexpectedException() { - Throwable throwable = - new UnknownException("foobar", null, FakeStatusCode.of(StatusCode.Code.UNKNOWN), false); - Mockito.when(callInt.futureCall((Integer) Mockito.any(), (ApiCallContext) Mockito.any())) - .thenReturn(RetryingTest.immediateFailedFuture(throwable)); - try { - assertRetrying(FAST_RETRY_SETTINGS); - Assert.fail("Callable should have thrown an exception"); - } catch (ApiException expected) { - Truth.assertThat(expected).isSameInstanceAs(throwable); - } - } - - @Test - public void retryNoRecover() { - Throwable throwable = - new FailedPreconditionException( - "foobar", null, FakeStatusCode.of(StatusCode.Code.FAILED_PRECONDITION), false); - Mockito.when(callInt.futureCall((Integer) Mockito.any(), (ApiCallContext) Mockito.any())) - .thenReturn(RetryingTest.immediateFailedFuture(throwable)) - .thenReturn(ApiFutures.immediateFuture(2)); - try { - assertRetrying(FAST_RETRY_SETTINGS); - Assert.fail("Callable should have thrown an exception"); - } catch (ApiException expected) { - Truth.assertThat(expected).isSameInstanceAs(throwable); - } - } - - @Test - public void retryUsingContextNoRecover() { - Throwable throwable = - new FailedPreconditionException( - "foobar", null, FakeStatusCode.of(StatusCode.Code.FAILED_PRECONDITION), false); - Mockito.when(callInt.futureCall((Integer) Mockito.any(), (ApiCallContext) Mockito.any())) - .thenReturn(RetryingTest.immediateFailedFuture(throwable)) - .thenReturn(ApiFutures.immediateFuture(2)); - try { - assertRetryingUsingContext( - FAILING_RETRY_SETTINGS, - FakeCallContext.createDefault() - .withRetrySettings(FAST_RETRY_SETTINGS) - .withRetryableCodes( - Sets.newHashSet(Code.UNAVAILABLE, Code.DEADLINE_EXCEEDED, Code.UNKNOWN))); - Assert.fail("Callable should have thrown an exception"); - } catch (ApiException expected) { - Truth.assertThat(expected).isSameInstanceAs(throwable); - } - } - - @Test - public void retryKeepFailing() { - Throwable throwable = - new UnavailableException( - "foobar", null, FakeStatusCode.of(StatusCode.Code.UNAVAILABLE), true); - Mockito.when(callInt.futureCall((Integer) Mockito.any(), (ApiCallContext) Mockito.any())) - .thenReturn(RetryingTest.immediateFailedFuture(throwable)); - UnaryCallSettings callSettings = createSettings(FAST_RETRY_SETTINGS); - UnaryCallable callable = - FakeCallableFactory.createUnaryCallable(callInt, callSettings, clientContext); - // Need to advance time inside the call. - ApiFuture future = callable.futureCall(1); - try { - Futures.getUnchecked(future); - Assert.fail("Callable should have thrown an exception"); - } catch (UncheckedExecutionException expected) { - Truth.assertThat(expected).hasCauseThat().isSameInstanceAs(throwable); - } - } - - @Test - public void testKnownStatusCode() { - ImmutableSet retryable = ImmutableSet.of(StatusCode.Code.UNAVAILABLE); - Mockito.when(callInt.futureCall((Integer) Mockito.any(), (ApiCallContext) Mockito.any())) - .thenReturn( - RetryingTest.immediateFailedFuture( - new FailedPreconditionException( - "known", null, FakeStatusCode.of(StatusCode.Code.FAILED_PRECONDITION), false))); - UnaryCallSettings callSettings = - UnaryCallSettings.newUnaryCallSettingsBuilder() - .setRetryableCodes(retryable) - .build(); - UnaryCallable callable = - FakeCallableFactory.createUnaryCallable(callInt, callSettings, clientContext); - try { - callable.call(1); - Assert.fail("Callable should have thrown an exception"); - } catch (FailedPreconditionException expected) { - Truth.assertThat(expected.getMessage()).isEqualTo("known"); - } - } - - @Test - public void testUnknownStatusCode() { - ImmutableSet retryable = ImmutableSet.of(); - Mockito.when(callInt.futureCall((Integer) Mockito.any(), (ApiCallContext) Mockito.any())) - .thenReturn(RetryingTest.immediateFailedFuture(new RuntimeException("unknown"))); - UnaryCallSettings callSettings = - UnaryCallSettings.newUnaryCallSettingsBuilder() - .setRetryableCodes(retryable) - .build(); - UnaryCallable callable = - FakeCallableFactory.createUnaryCallable(callInt, callSettings, clientContext); - try { - callable.call(1); - Assert.fail("Callable should have thrown an exception"); - } catch (RuntimeException expected) { - Truth.assertThat(expected).isInstanceOf(RuntimeException.class); - } - } - - public static UnaryCallSettings createSettings(RetrySettings retrySettings) { - return UnaryCallSettings.newUnaryCallSettingsBuilder() - .setRetryableCodes(Code.UNAVAILABLE) - .setRetrySettings(retrySettings) - .build(); - } - - private void assertRetrying(RetrySettings retrySettings) { - UnaryCallSettings callSettings = createSettings(retrySettings); - UnaryCallable callable = - FakeCallableFactory.createUnaryCallable(callInt, callSettings, clientContext); - Truth.assertThat(callable.call(1)).isEqualTo(2); - } - - private void assertRetryingUsingContext(RetrySettings retrySettings, ApiCallContext context) { - UnaryCallSettings callSettings = createSettings(retrySettings); - UnaryCallable callable = - FakeCallableFactory.createUnaryCallable(callInt, callSettings, clientContext); - Truth.assertThat(callable.call(1, context)).isEqualTo(2); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/ServerStreamTest.java b/gax/src/test/java/com/google/api/gax/rpc/ServerStreamTest.java deleted file mode 100644 index b0cdc30ce..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/ServerStreamTest.java +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.gax.rpc.testing.MockStreamingApi.MockStreamController; -import com.google.common.collect.Lists; -import com.google.common.truth.Truth; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.concurrent.Callable; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class ServerStreamTest { - private ServerStream stream; - private MockStreamController controller; - private ExecutorService executor; - - @Before - public void setUp() { - stream = new ServerStream<>(); - controller = new MockStreamController<>(stream.observer()); - - stream.observer().onStart(controller); - executor = Executors.newCachedThreadPool(); - } - - @After - public void tearDown() { - executor.shutdownNow(); - } - - @Test - public void testEmptyStream() { - stream.observer().onComplete(); - - Truth.assertThat(Lists.newArrayList(stream)).isEmpty(); - } - - @Test - public void testMultipleItemStream() throws Exception { - Future producerFuture = - executor.submit( - new Callable() { - @Override - public Void call() { - for (int i = 0; i < 5; i++) { - int requestCount = controller.popLastPull(); - - Truth.assertWithMessage("ServerStream should request one item at a time") - .that(requestCount) - .isEqualTo(1); - - stream.observer().onResponse(i); - } - stream.observer().onComplete(); - return null; - } - }); - - Future> consumerFuture = - executor.submit( - new Callable>() { - @Override - public List call() { - return Lists.newArrayList(stream); - } - }); - - producerFuture.get(60, TimeUnit.SECONDS); - List results = consumerFuture.get(); - Truth.assertThat(results).containsExactly(0, 1, 2, 3, 4); - } - - @Test - public void testEarlyTermination() throws Exception { - Future taskFuture = - executor.submit( - new Callable() { - @Override - public Void call() { - int i = 0; - while (controller.popLastPull() > 0) { - stream.observer().onResponse(i++); - } - controller.waitForCancel(); - stream.observer().onError(new CancellationException("cancelled")); - return null; - } - }); - - List results = Lists.newArrayList(); - for (Integer result : stream) { - results.add(result); - - if (result == 1) { - stream.cancel(); - } - } - - taskFuture.get(30, TimeUnit.SECONDS); - - Truth.assertThat(results).containsExactly(0, 1); - } - - @Test - public void testErrorPropagation() { - ClassCastException e = new ClassCastException("fake error"); - - stream.observer().onError(e); - - Throwable actualError = null; - try { - Truth.assertThat(Lists.newArrayList(stream)).isNotNull(); - } catch (Throwable t) { - actualError = t; - } - - Truth.assertThat(actualError).hasMessageThat().contains(e.getMessage()); - Truth.assertThat(actualError).isEqualTo(e); - } - - @Test - public void testNoErrorsBetweenHasNextAndNext() { - Iterator it = stream.iterator(); - - controller.popLastPull(); - stream.observer().onResponse(1); - - Truth.assertThat(it.hasNext()).isTrue(); - - RuntimeException fakeError = new RuntimeException("fake"); - stream.observer().onError(fakeError); - Truth.assertThat(it.next()).isEqualTo(1); - - // Now the error should be thrown - try { - it.next(); - throw new RuntimeException("ServerStream never threw an error!"); - } catch (RuntimeException e) { - Truth.assertThat(e).isSameInstanceAs(fakeError); - } - } - - @Test - public void testReady() { - Iterator it = stream.iterator(); - Truth.assertThat(stream.isReceiveReady()).isFalse(); - - controller.popLastPull(); - stream.observer().onResponse(1); - Truth.assertThat(stream.isReceiveReady()).isTrue(); - - it.next(); - Truth.assertThat(stream.isReceiveReady()).isFalse(); - } - - @Test - public void testNextAfterEOF() { - Iterator it = stream.iterator(); - stream.observer().onComplete(); - - // Precondition - Truth.assertThat(it.hasNext()).isFalse(); - - Throwable actualError = null; - try { - it.next(); - } catch (Throwable t) { - actualError = t; - } - Truth.assertThat(actualError).isInstanceOf(NoSuchElementException.class); - } - - @Test - public void testAfterError() { - Iterator it = stream.iterator(); - - RuntimeException expectError = new RuntimeException("my upstream error"); - stream.observer().onError(expectError); - - Throwable actualError = null; - - try { - @SuppressWarnings("unused") - boolean ignored = it.hasNext(); - } catch (Throwable t) { - actualError = t; - } - - Truth.assertThat(actualError).isEqualTo(expectError); - - try { - it.next(); - } catch (Throwable t) { - actualError = t; - } - Truth.assertThat(actualError).isEqualTo(expectError); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/ServerStreamingAttemptCallableTest.java b/gax/src/test/java/com/google/api/gax/rpc/ServerStreamingAttemptCallableTest.java deleted file mode 100644 index a0c8b833f..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/ServerStreamingAttemptCallableTest.java +++ /dev/null @@ -1,524 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.AbstractApiFuture; -import com.google.api.core.ApiFuture; -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.retrying.RetryingFuture; -import com.google.api.gax.retrying.ServerStreamingAttemptException; -import com.google.api.gax.retrying.StreamResumptionStrategy; -import com.google.api.gax.retrying.TimedAttemptSettings; -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.api.gax.rpc.testing.FakeApiException; -import com.google.api.gax.rpc.testing.FakeCallContext; -import com.google.api.gax.rpc.testing.MockStreamingApi.MockServerStreamingCall; -import com.google.api.gax.rpc.testing.MockStreamingApi.MockServerStreamingCallable; -import com.google.api.gax.tracing.BaseApiTracer; -import com.google.common.collect.Queues; -import com.google.common.truth.Truth; -import java.util.concurrent.BlockingDeque; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class ServerStreamingAttemptCallableTest { - private MockServerStreamingCallable innerCallable; - private AccumulatingObserver observer; - private FakeRetryingFuture fakeRetryingFuture; - private StreamResumptionStrategy resumptionStrategy; - private static Duration totalTimeout = Duration.ofHours(1); - private FakeCallContext mockedCallContext; - - @Before - public void setUp() { - innerCallable = new MockServerStreamingCallable<>(); - observer = new AccumulatingObserver(true); - resumptionStrategy = new MyStreamResumptionStrategy(); - mockedCallContext = Mockito.mock(FakeCallContext.class); - } - - private ServerStreamingAttemptCallable createCallable() { - return createCallable(FakeCallContext.createDefault()); - } - - private ServerStreamingAttemptCallable createCallable(ApiCallContext context) { - ServerStreamingAttemptCallable callable = - new ServerStreamingAttemptCallable<>( - innerCallable, resumptionStrategy, "request", context, observer); - - fakeRetryingFuture = new FakeRetryingFuture(callable); - callable.setExternalFuture(fakeRetryingFuture); - - return callable; - } - - @Test - public void testUserProvidedContextTimeout() { - // Mock up the ApiCallContext as if the user provided a timeout and streamWaitTimeout. - Mockito.doReturn(BaseApiTracer.getInstance()).when(mockedCallContext).getTracer(); - Mockito.doReturn(Duration.ofHours(5)).when(mockedCallContext).getTimeout(); - Mockito.doReturn(Duration.ofHours(5)).when(mockedCallContext).getStreamWaitTimeout(); - - ServerStreamingAttemptCallable callable = createCallable(mockedCallContext); - callable.start(); - - // Ensure that the callable did not overwrite the user provided timeouts - Mockito.verify(mockedCallContext, Mockito.times(1)).getTimeout(); - Mockito.verify(mockedCallContext, Mockito.never()).withTimeout(totalTimeout); - Mockito.verify(mockedCallContext, Mockito.times(1)).getStreamWaitTimeout(); - Mockito.verify(mockedCallContext, Mockito.never()) - .withStreamWaitTimeout(Mockito.any(Duration.class)); - - // Should notify outer observer - Truth.assertThat(observer.controller).isNotNull(); - - // Should configure the inner controller correctly. - MockServerStreamingCall call = innerCallable.popLastCall(); - Truth.assertThat(call.getController().isAutoFlowControlEnabled()).isTrue(); - Truth.assertThat(call.getRequest()).isEqualTo("request"); - - // Send a response in auto flow mode. - call.getController().getObserver().onResponse("response1"); - call.getController().getObserver().onResponse("response2"); - call.getController().getObserver().onComplete(); - - // Make sure the responses are received - Truth.assertThat(observer.responses).containsExactly("response1", "response2").inOrder(); - fakeRetryingFuture.assertSuccess(); - } - - @Test - public void testNoUserProvidedContextTimeout() { - // Mock up the ApiCallContext as if the user did not provide custom timeouts. - Mockito.doReturn(BaseApiTracer.getInstance()).when(mockedCallContext).getTracer(); - Mockito.doReturn(null).when(mockedCallContext).getTimeout(); - Mockito.doReturn(null).when(mockedCallContext).getStreamWaitTimeout(); - Mockito.doReturn(mockedCallContext).when(mockedCallContext).withTimeout(totalTimeout); - Mockito.doReturn(mockedCallContext) - .when(mockedCallContext) - .withStreamWaitTimeout(Mockito.any(Duration.class)); - - ServerStreamingAttemptCallable callable = createCallable(mockedCallContext); - callable.start(); - - // Ensure that the callable configured the timeouts via the Settings in the - // absence of user-defined timeouts. - Mockito.verify(mockedCallContext, Mockito.times(1)).getTimeout(); - Mockito.verify(mockedCallContext, Mockito.times(1)).withTimeout(totalTimeout); - Mockito.verify(mockedCallContext, Mockito.times(1)).getStreamWaitTimeout(); - Mockito.verify(mockedCallContext, Mockito.times(1)) - .withStreamWaitTimeout(Mockito.any(Duration.class)); - - // Should notify outer observer - Truth.assertThat(observer.controller).isNotNull(); - - // Should configure the inner controller correctly. - MockServerStreamingCall call = innerCallable.popLastCall(); - Truth.assertThat(call.getController().isAutoFlowControlEnabled()).isTrue(); - Truth.assertThat(call.getRequest()).isEqualTo("request"); - - // Send a response in auto flow mode. - call.getController().getObserver().onResponse("response1"); - call.getController().getObserver().onResponse("response2"); - call.getController().getObserver().onComplete(); - - // Make sure the responses are received - Truth.assertThat(observer.responses).containsExactly("response1", "response2").inOrder(); - fakeRetryingFuture.assertSuccess(); - } - - @Test - public void testNoErrorsAutoFlow() { - ServerStreamingAttemptCallable callable = createCallable(); - callable.start(); - - // Should notify outer observer - Truth.assertThat(observer.controller).isNotNull(); - - // Should configure the inner controller correctly. - MockServerStreamingCall call = innerCallable.popLastCall(); - Truth.assertThat(call.getController().isAutoFlowControlEnabled()).isTrue(); - Truth.assertThat(call.getRequest()).isEqualTo("request"); - - // Send a response in auto flow mode. - call.getController().getObserver().onResponse("response1"); - call.getController().getObserver().onResponse("response2"); - call.getController().getObserver().onComplete(); - - // Make sure the responses are received - Truth.assertThat(observer.responses).containsExactly("response1", "response2").inOrder(); - fakeRetryingFuture.assertSuccess(); - } - - @Test - public void testNoErrorsManualFlow() { - observer = new AccumulatingObserver(false); - ServerStreamingAttemptCallable callable = createCallable(); - callable.start(); - - // Should notify outer observer. - Truth.assertThat(observer.controller).isNotNull(); - - // Should configure the inner controller correctly. - MockServerStreamingCall call = innerCallable.popLastCall(); - Truth.assertThat(call.getController().isAutoFlowControlEnabled()).isFalse(); - Truth.assertThat(call.getRequest()).isEqualTo("request"); - - // Request and send message 1. - observer.controller.request(1); - Truth.assertThat(call.getController().popLastPull()).isEqualTo(1); - call.getController().getObserver().onResponse("response1"); - - // Request & send message 1. - observer.controller.request(1); - Truth.assertThat(call.getController().popLastPull()).isEqualTo(1); - call.getController().getObserver().onResponse("response2"); - - call.getController().getObserver().onComplete(); - - // Make sure the responses are received - Truth.assertThat(observer.responses).containsExactly("response1", "response2").inOrder(); - fakeRetryingFuture.assertSuccess(); - } - - @Test - @SuppressWarnings("ConstantConditions") - public void testInitialRetry() { - resumptionStrategy = new MyStreamResumptionStrategy(); - ServerStreamingAttemptCallable callable = createCallable(); - callable.start(); - - MockServerStreamingCall call = innerCallable.popLastCall(); - - // Send initial error - FakeApiException initialError = new FakeApiException(null, Code.UNAVAILABLE, true); - call.getController().getObserver().onError(initialError); - - // Should notify the outer future - Throwable outerError = null; - try { - fakeRetryingFuture.getAttemptResult().get(1, TimeUnit.SECONDS); - } catch (ExecutionException e) { - outerError = e.getCause(); - } catch (Throwable e) { - outerError = e; - } - Truth.assertThat(outerError).isInstanceOf(ServerStreamingAttemptException.class); - Truth.assertThat(((ServerStreamingAttemptException) outerError).hasSeenResponses()).isFalse(); - Truth.assertThat(((ServerStreamingAttemptException) outerError).canResume()).isTrue(); - Truth.assertThat(outerError.getCause()).isEqualTo(initialError); - - // Make the retry call - callable.call(); - call = innerCallable.popLastCall(); - - // Verify the request and send a response - Truth.assertThat(call.getRequest()).isEqualTo("request > 0"); - } - - @Test - @SuppressWarnings("ConstantConditions") - public void testMidRetry() { - resumptionStrategy = new MyStreamResumptionStrategy(); - ServerStreamingAttemptCallable callable = createCallable(); - callable.start(); - - MockServerStreamingCall call = innerCallable.popLastCall(); - - // Respond to the initial request with a coupple responses and an error. - Truth.assertThat(call.getRequest()).isEqualTo("request"); - call.getController().getObserver().onResponse("response1"); - call.getController().getObserver().onResponse("response2"); - - FakeApiException innerError = new FakeApiException(null, Code.UNAVAILABLE, true); - call.getController().getObserver().onError(innerError); - - // Should notify the outer future - Throwable outerError = null; - try { - fakeRetryingFuture.getAttemptResult().get(1, TimeUnit.SECONDS); - } catch (ExecutionException e) { - outerError = e.getCause(); - } catch (Throwable e) { - outerError = e; - } - Truth.assertThat(outerError).isInstanceOf(ServerStreamingAttemptException.class); - Truth.assertThat(((ServerStreamingAttemptException) outerError).hasSeenResponses()).isTrue(); - Truth.assertThat(((ServerStreamingAttemptException) outerError).canResume()).isTrue(); - Truth.assertThat(outerError.getCause()).isEqualTo(innerError); - - // Make the retry call - callable.call(); - call = innerCallable.popLastCall(); - - // Verify that the request was narrowed and send a response - Truth.assertThat(call.getRequest()).isEqualTo("request > 2"); - call.getController().getObserver().onResponse("response3"); - Truth.assertThat(observer.responses) - .containsExactly("response1", "response2", "response3") - .inOrder(); - } - - @Test - public void testRequestCountIsPreserved() { - observer = new AccumulatingObserver(false); - ServerStreamingAttemptCallable callable = createCallable(); - callable.start(); - - observer.controller.request(5); - - Truth.assertThat(observer.controller).isNotNull(); - MockServerStreamingCall call = innerCallable.popLastCall(); - Truth.assertThat(call).isNotNull(); - Truth.assertThat(call.getController().isAutoFlowControlEnabled()).isFalse(); - - Truth.assertThat(call.getController().popLastPull()).isEqualTo(5); - // decrement - call.getController().getObserver().onResponse("response"); - // and then error - call.getController() - .getObserver() - .onError(new FakeApiException(null, Code.UNAUTHENTICATED, true)); - - // Make the retry call - callable.call(); - call = innerCallable.popLastCall(); - - // Verify that the count is correct - Truth.assertThat(call.getController().popLastPull()).isEqualTo(4); - } - - @Test - public void testCancel() { - observer = new AccumulatingObserver(false); - ServerStreamingAttemptCallable callable = createCallable(); - callable.start(); - - observer.controller.request(1); - - Truth.assertThat(observer.controller).isNotNull(); - MockServerStreamingCall call = innerCallable.popLastCall(); - Truth.assertThat(call).isNotNull(); - Truth.assertThat(call.getController().isAutoFlowControlEnabled()).isFalse(); - - observer.controller.cancel(); - - // Check upstream is cancelled - Truth.assertThat(call.getController().isCancelled()).isTrue(); - - // and after upstream cancellation is processed, downstream is cancelled, but the cause is - // replaced - RuntimeException innerException = - new RuntimeException("Some internal representation of cancel"); - call.getController().getObserver().onError(innerException); - - Throwable outerError = null; - try { - fakeRetryingFuture.getAttemptResult().get(1, TimeUnit.SECONDS); - } catch (ExecutionException e) { - outerError = e.getCause(); - } catch (Throwable e) { - outerError = e; - } - - Truth.assertThat(outerError).isInstanceOf(ServerStreamingAttemptException.class); - Truth.assertThat(outerError.getCause()).isInstanceOf(CancellationException.class); - - // Make sure that the stack trace of the cancellation is preserved - boolean includesMeInStackTrace = false; - for (StackTraceElement e : outerError.getCause().getStackTrace()) { - if (ServerStreamingAttemptCallableTest.class.getName().equals(e.getClassName())) { - includesMeInStackTrace = true; - break; - } - } - Truth.assertWithMessage("Cancel caller included in stack trace") - .that(includesMeInStackTrace) - .isTrue(); - } - - @Test - public void testResponseSubstitution() { - resumptionStrategy = - new MyStreamResumptionStrategy() { - @Override - public String processResponse(String response) { - return super.processResponse(response) + "+suffix"; - } - }; - - observer = new AccumulatingObserver(false); - ServerStreamingAttemptCallable callable = createCallable(); - callable.start(); - - MockServerStreamingCall call = innerCallable.popLastCall(); - - // Send initial response & then error - call.getController().getObserver().onResponse("first"); - call.getController().getObserver().onError(new FakeApiException(null, Code.UNAVAILABLE, true)); - - // Make the retry call - callable.call(); - call = innerCallable.popLastCall(); - - // Send another couple of responses (the first one will be ignored) - call.getController().getObserver().onResponse("second"); - call.getController().getObserver().onResponse("third"); - call.getController().getObserver().onComplete(); - - // Verify the request and send a response - Truth.assertThat(observer.responses) - .containsExactly("first+suffix", "second+suffix", "third+suffix"); - } - - static class MyStreamResumptionStrategy implements StreamResumptionStrategy { - private int responseCount; - - @Override - public StreamResumptionStrategy createNew() { - return new MyStreamResumptionStrategy(); - } - - @Override - public String processResponse(String response) { - responseCount++; - return response; - } - - @Override - public String getResumeRequest(String originalRequest) { - return originalRequest + " > " + responseCount; - } - - @Override - public boolean canResume() { - return true; - } - } - - static class AccumulatingObserver implements ResponseObserver { - final boolean autoFlow; - StreamController controller; - final BlockingDeque responses = Queues.newLinkedBlockingDeque(); - private Throwable error; - private boolean complete; - - AccumulatingObserver(boolean autoFlow) { - this.autoFlow = autoFlow; - } - - @Override - public void onStart(StreamController controller) { - this.controller = controller; - if (!autoFlow) { - controller.disableAutoInboundFlowControl(); - } - } - - @Override - public void onResponse(String response) { - responses.add(response); - } - - @Override - public void onError(Throwable t) { - this.error = t; - } - - @Override - public void onComplete() { - this.complete = true; - } - } - - private static class FakeRetryingFuture extends AbstractApiFuture - implements RetryingFuture { - private final ServerStreamingAttemptCallable attemptCallable; - private ApiFuture attemptFuture; - private TimedAttemptSettings attemptSettings; - - FakeRetryingFuture(ServerStreamingAttemptCallable attemptCallable) { - this.attemptCallable = attemptCallable; - attemptSettings = - TimedAttemptSettings.newBuilder() - .setGlobalSettings(RetrySettings.newBuilder().setTotalTimeout(totalTimeout).build()) - .setFirstAttemptStartTimeNanos(0) - .setAttemptCount(0) - .setOverallAttemptCount(0) - .setRandomizedRetryDelay(Duration.ofMillis(1)) - .setRetryDelay(Duration.ofMillis(1)) - .setRpcTimeout(Duration.ofMinutes(1)) - .build(); - } - - @Override - public void setAttemptFuture(ApiFuture attemptFuture) { - this.attemptFuture = attemptFuture; - } - - @Override - public ServerStreamingAttemptCallable getCallable() { - return attemptCallable; - } - - @Override - public TimedAttemptSettings getAttemptSettings() { - return attemptSettings; - } - - @Override - public ApiFuture peekAttemptResult() { - throw new UnsupportedOperationException(); - } - - @Override - public ApiFuture getAttemptResult() { - return attemptFuture; - } - - void assertSuccess() { - Throwable actualError = null; - try { - attemptFuture.get(1, TimeUnit.SECONDS); - } catch (Throwable t) { - actualError = t; - } - Truth.assertThat(actualError).isNull(); - } - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/ServerStreamingCallSettingsTest.java b/gax/src/test/java/com/google/api/gax/rpc/ServerStreamingCallSettingsTest.java deleted file mode 100644 index a14268f8d..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/ServerStreamingCallSettingsTest.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.common.collect.ImmutableSet; -import java.util.Set; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class ServerStreamingCallSettingsTest { - @Test - public void retryableCodesAreNotLost() { - Set codes = ImmutableSet.of(Code.UNAVAILABLE, Code.RESOURCE_EXHAUSTED); - ServerStreamingCallSettings.Builder builder = - ServerStreamingCallSettings.newBuilder(); - builder.setRetryableCodes(codes); - - assertThat(builder.getRetryableCodes()).containsExactlyElementsIn(codes); - assertThat(builder.build().getRetryableCodes()).containsExactlyElementsIn(codes); - assertThat(builder.build().toBuilder().getRetryableCodes()).containsExactlyElementsIn(codes); - } - - @Test - public void retryableCodesVarArgs() { - ServerStreamingCallSettings.Builder builder = - ServerStreamingCallSettings.newBuilder().setRetryableCodes(Code.UNKNOWN, Code.ABORTED); - - assertThat(builder.getRetryableCodes()).containsExactly(Code.UNKNOWN, Code.ABORTED); - } - - @Test - public void retryableSettingsAreNotLost() { - RetrySettings retrySettings = - RetrySettings.newBuilder() - .setInitialRetryDelay(Duration.ofMillis(5)) - .setMaxRetryDelay(Duration.ofSeconds(1)) - .setRetryDelayMultiplier(2) - .setInitialRpcTimeout(Duration.ofMillis(100)) - .setMaxRpcTimeout(Duration.ofMillis(200)) - .setRpcTimeoutMultiplier(1.1) - .setJittered(true) - .setMaxAttempts(10) - .build(); - - ServerStreamingCallSettings.Builder builder = - ServerStreamingCallSettings.newBuilder(); - builder.setRetrySettings(retrySettings); - - assertThat(builder.getRetrySettings()).isEqualTo(retrySettings); - assertThat(builder.build().getRetrySettings()).isEqualTo(retrySettings); - assertThat(builder.build().toBuilder().getRetrySettings()).isEqualTo(retrySettings); - } - - @Test - public void idleTimeoutIsNotLost() { - Duration idleTimeout = Duration.ofSeconds(5); - - ServerStreamingCallSettings.Builder builder = - ServerStreamingCallSettings.newBuilder(); - builder.setIdleTimeout(idleTimeout); - - assertThat(builder.getIdleTimeout()).isEqualTo(idleTimeout); - assertThat(builder.build().getIdleTimeout()).isEqualTo(idleTimeout); - assertThat(builder.build().toBuilder().getIdleTimeout()).isEqualTo(idleTimeout); - } - - @Test - public void testRetrySettingsBuilder() { - RetrySettings initialSettings = - RetrySettings.newBuilder() - .setInitialRetryDelay(Duration.ofMillis(5)) - .setMaxRetryDelay(Duration.ofSeconds(1)) - .setRetryDelayMultiplier(2) - .setInitialRpcTimeout(Duration.ofMillis(100)) - .setMaxRpcTimeout(Duration.ofMillis(200)) - .setRpcTimeoutMultiplier(1.1) - .setJittered(true) - .setMaxAttempts(10) - .build(); - - ServerStreamingCallSettings.Builder builder = - ServerStreamingCallSettings.newBuilder().setRetrySettings(initialSettings); - - builder.retrySettings().setMaxRetryDelay(Duration.ofMinutes(1)); - - assertThat(builder.getRetrySettings().getMaxRetryDelay()).isEqualTo(Duration.ofMinutes(1)); - assertThat(builder.build().getRetrySettings().getMaxRetryDelay()) - .isEqualTo(Duration.ofMinutes(1)); - } - - @Test - public void testToString() { - RetrySettings retrySettings = RetrySettings.newBuilder().build(); - Set retryableCodes = ImmutableSet.of(StatusCode.Code.DEADLINE_EXCEEDED); - Duration idleTime = Duration.ofSeconds(100); - ServerStreamingCallSettings serverCallSettings = - ServerStreamingCallSettings.newBuilder() - .setRetrySettings(retrySettings) - .setRetryableCodes(retryableCodes) - .setIdleTimeout(idleTime) - .build(); - assertThat(serverCallSettings.toString()).contains("idleTimeout=" + idleTime); - assertThat(serverCallSettings.toString()).contains("retryableCodes=" + retryableCodes); - assertThat(serverCallSettings.toString()).contains("retrySettings=" + retrySettings); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/ServerStreamingCallableTest.java b/gax/src/test/java/com/google/api/gax/rpc/ServerStreamingCallableTest.java deleted file mode 100644 index ca292257f..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/ServerStreamingCallableTest.java +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.gax.rpc.testing.FakeCallContext; -import com.google.api.gax.rpc.testing.FakeCallableFactory; -import com.google.api.gax.rpc.testing.FakeChannel; -import com.google.api.gax.rpc.testing.FakeSimpleApi.StashCallable; -import com.google.api.gax.rpc.testing.FakeStreamingApi.ServerStreamingStashCallable; -import com.google.api.gax.rpc.testing.FakeTransportChannel; -import com.google.auth.Credentials; -import com.google.common.collect.ImmutableList; -import com.google.common.truth.Truth; -import java.util.Arrays; -import java.util.List; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; - -@RunWith(JUnit4.class) -public class ServerStreamingCallableTest { - private ClientContext clientContext; - - @Before - public void setUp() { - clientContext = - ClientContext.newBuilder() - .setDefaultCallContext(FakeCallContext.createDefault()) - .setTransportChannel(FakeTransportChannel.create(new FakeChannel())) - .build(); - } - - @Test - public void serverStreaming() { - ServerStreamingStashCallable callIntList = - new ServerStreamingStashCallable<>(Arrays.asList(0, 1, 2)); - - ServerStreamingCallable callable = - FakeCallableFactory.createServerStreamingCallable( - callIntList, - StreamingCallSettings.newBuilder().build(), - clientContext); - - AccumulatingStreamObserver responseObserver = new AccumulatingStreamObserver(); - callable.call(0, responseObserver); - Truth.assertThat(ImmutableList.copyOf(responseObserver.getValues())) - .containsExactly(0, 1, 2) - .inOrder(); - Truth.assertThat(callIntList.getActualRequest()).isEqualTo(0); - } - - @Test - public void testServerStreamingCall() { - ApiCallContext defaultCallContext = FakeCallContext.createDefault(); - ServerStreamingStashCallable stashCallable = - new ServerStreamingStashCallable<>(); - ServerStreamingCallable callable = - stashCallable.withDefaultCallContext(defaultCallContext); - @SuppressWarnings("unchecked") - StateCheckingResponseObserver observer = - Mockito.mock(StateCheckingResponseObserver.class); - Integer request = 1; - callable.call(request, observer); - Truth.assertThat(stashCallable.getActualObserver()).isSameInstanceAs(observer); - Truth.assertThat(stashCallable.getActualRequest()).isSameInstanceAs(request); - Truth.assertThat(stashCallable.getContext()).isSameInstanceAs(defaultCallContext); - } - - @Test - public void testServerStreamingCallWithContext() { - FakeChannel channel = new FakeChannel(); - Credentials credentials = Mockito.mock(Credentials.class); - ApiCallContext context = - FakeCallContext.createDefault().withChannel(channel).withCredentials(credentials); - ServerStreamingStashCallable stashCallable = - new ServerStreamingStashCallable<>(); - ServerStreamingCallable callable = - stashCallable.withDefaultCallContext(FakeCallContext.createDefault()); - @SuppressWarnings("unchecked") - ResponseObserver observer = Mockito.mock(StateCheckingResponseObserver.class); - Integer request = 1; - callable.call(request, observer, context); - Truth.assertThat(stashCallable.getActualObserver()).isSameInstanceAs(observer); - Truth.assertThat(stashCallable.getActualRequest()).isSameInstanceAs(request); - FakeCallContext actualContext = (FakeCallContext) stashCallable.getContext(); - Truth.assertThat(actualContext.getChannel()).isSameInstanceAs(channel); - Truth.assertThat(actualContext.getCredentials()).isSameInstanceAs(credentials); - } - - @Test - public void blockingServerStreaming() { - ServerStreamingStashCallable callIntList = - new ServerStreamingStashCallable<>(Arrays.asList(0, 1, 2)); - - ServerStreamingCallable callable = - FakeCallableFactory.createServerStreamingCallable( - callIntList, - StreamingCallSettings.newBuilder().build(), - clientContext); - Truth.assertThat(ImmutableList.copyOf(callable.call(0))).containsExactly(0, 1, 2).inOrder(); - Truth.assertThat(callIntList.getActualRequest()).isEqualTo(0); - } - - @Test - public void testIteratedServerStreamingCall() { - ApiCallContext defaultCallContext = FakeCallContext.createDefault(); - ServerStreamingStashCallable stashCallable = - new ServerStreamingStashCallable<>(); - ServerStreamingCallable callable = - stashCallable.withDefaultCallContext(defaultCallContext); - Integer request = 1; - callable.call(request); - Truth.assertThat(stashCallable.getActualRequest()).isSameInstanceAs(request); - Truth.assertThat(stashCallable.getContext()).isSameInstanceAs(defaultCallContext); - } - - @Test - public void testIteratedServerStreamingCallWithContext() { - FakeChannel channel = new FakeChannel(); - Credentials credentials = Mockito.mock(Credentials.class); - ApiCallContext context = - FakeCallContext.createDefault().withChannel(channel).withCredentials(credentials); - ServerStreamingStashCallable stashCallable = - new ServerStreamingStashCallable<>(); - ServerStreamingCallable callable = - stashCallable.withDefaultCallContext(FakeCallContext.createDefault()); - Integer request = 1; - callable.call(request, context); - Truth.assertThat(stashCallable.getActualRequest()).isSameInstanceAs(request); - FakeCallContext actualContext = (FakeCallContext) stashCallable.getContext(); - Truth.assertThat(actualContext.getChannel()).isSameInstanceAs(channel); - Truth.assertThat(actualContext.getCredentials()).isSameInstanceAs(credentials); - } - - @Test - public void testFirstElementCall() { - ServerStreamingStashCallable callIntList = - new ServerStreamingStashCallable<>(Arrays.asList(0, 1, 2)); - - ServerStreamingCallable streamingCallable = - FakeCallableFactory.createServerStreamingCallable( - callIntList, - StreamingCallSettings.newBuilder().build(), - clientContext); - - UnaryCallable callable = streamingCallable.first(); - Truth.assertThat(callable.call(0)).isEqualTo(0); - Truth.assertThat(callIntList.getActualRequest()).isEqualTo(0); - } - - @Test - public void testFirstElementCallWithDefaultContext() { - ApiCallContext defaultCallContext = FakeCallContext.createDefault(); - - final StashCallable stashFirstCallable = new StashCallable<>(11); - - ServerStreamingStashCallable stashCallable = - new ServerStreamingStashCallable() { - @Override - public UnaryCallable first() { - return stashFirstCallable; - } - }; - - UnaryCallable firstCallable = - stashCallable.withDefaultCallContext(defaultCallContext).first(); - Integer request = 1; - firstCallable.call(request); - Truth.assertThat(stashFirstCallable.getRequest()).isSameInstanceAs(request); - Truth.assertThat(stashFirstCallable.getContext()).isSameInstanceAs(defaultCallContext); - } - - @Test - public void testFirstElementCallWithContext() { - FakeChannel channel = new FakeChannel(); - Credentials credentials = Mockito.mock(Credentials.class); - ApiCallContext context = - FakeCallContext.createDefault().withChannel(channel).withCredentials(credentials); - ServerStreamingStashCallable stashCallable = - new ServerStreamingStashCallable<>(); - - UnaryCallable firstCallable = - stashCallable.first().withDefaultCallContext(FakeCallContext.createDefault()); - Integer request = 1; - firstCallable.call(request, context); - Truth.assertThat(stashCallable.getActualRequest()).isSameInstanceAs(request); - FakeCallContext actualContext = (FakeCallContext) stashCallable.getContext(); - Truth.assertThat(actualContext.getChannel()).isSameInstanceAs(channel); - Truth.assertThat(actualContext.getCredentials()).isSameInstanceAs(credentials); - } - - @Test - public void testAllElementCall() { - ServerStreamingStashCallable callIntList = - new ServerStreamingStashCallable<>(Arrays.asList(0, 1, 2)); - - ServerStreamingCallable streamingCallable = - FakeCallableFactory.createServerStreamingCallable( - callIntList, - StreamingCallSettings.newBuilder().build(), - clientContext); - - UnaryCallable> callable = streamingCallable.all(); - Truth.assertThat(callable.call(0)).containsExactly(0, 1, 2).inOrder(); - Truth.assertThat(callIntList.getActualRequest()).isEqualTo(0); - } - - @Test - public void testAllElementCallWithDefaultContext() { - ApiCallContext defaultCallContext = FakeCallContext.createDefault(); - ServerStreamingStashCallable stashCallable = - new ServerStreamingStashCallable<>(); - - UnaryCallable> firstCallable = - stashCallable.all().withDefaultCallContext(defaultCallContext); - Integer request = 1; - firstCallable.call(request); - Truth.assertThat(stashCallable.getActualRequest()).isSameInstanceAs(request); - Truth.assertThat(stashCallable.getContext()).isSameInstanceAs(defaultCallContext); - } - - @Test - public void testAllElementCallWithContext() { - FakeChannel channel = new FakeChannel(); - Credentials credentials = Mockito.mock(Credentials.class); - ApiCallContext context = - FakeCallContext.createDefault().withChannel(channel).withCredentials(credentials); - ServerStreamingStashCallable stashCallable = - new ServerStreamingStashCallable<>(); - - UnaryCallable> firstCallable = - stashCallable.all().withDefaultCallContext(FakeCallContext.createDefault()); - Integer request = 1; - firstCallable.call(request, context); - Truth.assertThat(stashCallable.getActualRequest()).isSameInstanceAs(request); - FakeCallContext actualContext = (FakeCallContext) stashCallable.getContext(); - Truth.assertThat(actualContext.getChannel()).isSameInstanceAs(channel); - Truth.assertThat(actualContext.getCredentials()).isSameInstanceAs(credentials); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/SpoolingCallableTest.java b/gax/src/test/java/com/google/api/gax/rpc/SpoolingCallableTest.java deleted file mode 100644 index c968c2c87..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/SpoolingCallableTest.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.ApiFuture; -import com.google.api.gax.rpc.testing.MockStreamingApi.MockServerStreamingCall; -import com.google.api.gax.rpc.testing.MockStreamingApi.MockServerStreamingCallable; -import com.google.common.truth.Truth; -import java.util.List; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class SpoolingCallableTest { - private MockServerStreamingCallable upstream; - private SpoolingCallable callable; - - @Before - public void setup() { - upstream = new MockServerStreamingCallable<>(); - callable = new SpoolingCallable<>(upstream); - } - - @Test - public void testHappyPath() throws InterruptedException, ExecutionException { - ApiFuture> result = callable.futureCall("request"); - MockServerStreamingCall call = upstream.popLastCall(); - - Truth.assertThat(call.getController().isAutoFlowControlEnabled()).isTrue(); - - call.getController().getObserver().onResponse("response1"); - call.getController().getObserver().onResponse("response2"); - call.getController().getObserver().onComplete(); - - Truth.assertThat(result.get()).containsExactly("response1", "response2").inOrder(); - } - - @Test - public void testEarlyTermination() throws Exception { - ApiFuture> result = callable.futureCall("request"); - MockServerStreamingCall call = upstream.popLastCall(); - - // The caller cancels the stream while receiving responses - call.getController().getObserver().onResponse("response1"); - result.cancel(true); - call.getController().getObserver().onResponse("response2"); - - // The cancellation should propagate upstream - Truth.assertThat(call.getController().isCancelled()).isTrue(); - // Then we fake a cancellation going the other way (it will be wrapped in StatusRuntimeException - // for grpc) - call.getController() - .getObserver() - .onError(new RuntimeException("Some other upstream cancellation indicator")); - - // However the inner cancellation exception will be masked by an outer CancellationException - try { - result.get(); - Assert.fail("Callable should have thrown an exception"); - } catch (CancellationException expected) { - Truth.assertThat(expected).hasMessageThat().contains("Task was cancelled."); - } - } - - @Test - public void testNoResults() throws Exception { - ApiFuture> result = callable.futureCall("request"); - MockServerStreamingCall call = upstream.popLastCall(); - - call.getController().getObserver().onComplete(); - - Truth.assertThat(result.get()).isEmpty(); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/StreamingCallableTest.java b/gax/src/test/java/com/google/api/gax/rpc/StreamingCallableTest.java deleted file mode 100644 index f946aff92..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/StreamingCallableTest.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static org.junit.Assert.assertSame; - -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.api.gax.rpc.testing.FakeCallContext; -import com.google.api.gax.rpc.testing.FakeCallableFactory; -import com.google.api.gax.rpc.testing.FakeChannel; -import com.google.api.gax.rpc.testing.FakeStatusCode; -import com.google.api.gax.rpc.testing.FakeStreamingApi.ClientStreamingStashCallable; -import com.google.api.gax.rpc.testing.FakeTransportChannel; -import com.google.auth.Credentials; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.common.truth.Truth; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; - -@RunWith(JUnit4.class) -public class StreamingCallableTest { - private ClientContext clientContext; - - @Before - public void setUp() { - clientContext = - ClientContext.newBuilder() - .setDefaultCallContext(FakeCallContext.createDefault()) - .setTransportChannel(FakeTransportChannel.create(new FakeChannel())) - .build(); - } - - private static class AccumulatingStreamObserver implements ApiStreamObserver { - private List values = new ArrayList<>(); - private Throwable error; - private boolean completed = false; - - @Override - public void onNext(Integer value) { - values.add(value); - } - - @Override - public void onError(Throwable t) { - error = t; - } - - @Override - public void onCompleted() { - completed = true; - } - - public List getValues() { - if (!completed) { - throw new IllegalStateException("Stream not completed."); - } - if (error != null) { - throw ApiExceptionFactory.createException(error, FakeStatusCode.of(Code.UNKNOWN), false); - } - return values; - } - } - - @Test - public void clientStreaming() { - ClientStreamingStashCallable callIntList = - new ClientStreamingStashCallable<>(100); - - ClientStreamingCallable callable = - FakeCallableFactory.createClientStreamingCallable( - callIntList, - StreamingCallSettings.newBuilder().build(), - clientContext); - - AccumulatingStreamObserver responseObserver = new AccumulatingStreamObserver(); - ApiStreamObserver requestObserver = callable.clientStreamingCall(responseObserver); - requestObserver.onNext(0); - requestObserver.onNext(2); - requestObserver.onNext(4); - requestObserver.onCompleted(); - - Truth.assertThat(ImmutableList.copyOf(responseObserver.getValues())) - .containsExactly(100) - .inOrder(); - Truth.assertThat(callIntList.getActualRequests()).containsExactly(0, 2, 4).inOrder(); - } - - @Test - @SuppressWarnings("unchecked") - public void testClientStreamingCall() { - ApiCallContext defaultCallContext = FakeCallContext.createDefault(); - ClientStreamingStashCallable stashCallable = - new ClientStreamingStashCallable<>(); - ApiStreamObserver observer = Mockito.mock(ApiStreamObserver.class); - ClientStreamingCallable callable = - stashCallable.withDefaultCallContext(defaultCallContext); - callable.clientStreamingCall(observer); - assertSame(observer, stashCallable.getActualObserver()); - assertSame(defaultCallContext, stashCallable.getContext()); - } - - @Test - @SuppressWarnings("unchecked") - public void testClientStreamingCallWithContext() { - FakeChannel channel = new FakeChannel(); - Credentials credentials = Mockito.mock(Credentials.class); - RetrySettings retrySettings = Mockito.mock(RetrySettings.class); - Set retryableCodes = - ImmutableSet.of( - StatusCode.Code.INTERNAL, - StatusCode.Code.UNAVAILABLE, - StatusCode.Code.DEADLINE_EXCEEDED); - ApiCallContext context = - FakeCallContext.createDefault() - .withChannel(channel) - .withCredentials(credentials) - .withRetrySettings(retrySettings) - .withRetryableCodes(retryableCodes); - ClientStreamingStashCallable stashCallable = - new ClientStreamingStashCallable<>(); - ApiStreamObserver observer = Mockito.mock(ApiStreamObserver.class); - ClientStreamingCallable callable = - stashCallable.withDefaultCallContext(FakeCallContext.createDefault()); - callable.clientStreamingCall(observer, context); - assertSame(observer, stashCallable.getActualObserver()); - FakeCallContext actualContext = (FakeCallContext) stashCallable.getContext(); - assertSame(channel, actualContext.getChannel()); - assertSame(credentials, actualContext.getCredentials()); - assertSame(retrySettings, actualContext.getRetrySettings()); - assertSame(retryableCodes, actualContext.getRetryableCodes()); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/StreamingRetryAlgorithmTest.java b/gax/src/test/java/com/google/api/gax/rpc/StreamingRetryAlgorithmTest.java deleted file mode 100644 index 740000723..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/StreamingRetryAlgorithmTest.java +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static com.google.common.truth.Truth.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import com.google.api.core.ApiClock; -import com.google.api.gax.retrying.BasicResultRetryAlgorithm; -import com.google.api.gax.retrying.ExponentialRetryAlgorithm; -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.retrying.RetryingContext; -import com.google.api.gax.retrying.ServerStreamingAttemptException; -import com.google.api.gax.retrying.StreamingRetryAlgorithm; -import com.google.api.gax.retrying.TimedAttemptSettings; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class StreamingRetryAlgorithmTest { - private static final RetrySettings DEFAULT_RETRY_SETTINGS = - RetrySettings.newBuilder() - .setInitialRetryDelay(Duration.ofMillis(10L)) - .setInitialRpcTimeout(Duration.ofMillis(100L)) - .setMaxAttempts(10) - .setMaxRetryDelay(Duration.ofSeconds(10L)) - .setMaxRpcTimeout(Duration.ofSeconds(30L)) - .setRetryDelayMultiplier(1.4) - .setRpcTimeoutMultiplier(1.5) - .setTotalTimeout(Duration.ofMinutes(10L)) - .build(); - - private static final RetrySettings CONTEXT_RETRY_SETTINGS = - RetrySettings.newBuilder() - .setInitialRetryDelay(Duration.ofMillis(20L)) - .setInitialRpcTimeout(Duration.ofMillis(200L)) - .setMaxAttempts(10) - .setMaxRetryDelay(Duration.ofSeconds(20L)) - .setMaxRpcTimeout(Duration.ofSeconds(60L)) - .setRetryDelayMultiplier(2.4) - .setRpcTimeoutMultiplier(2.5) - .setTotalTimeout(Duration.ofMinutes(20L)) - .build(); - - @Test - public void testFirstAttemptUsesDefaultSettings() { - RetryingContext context = mock(RetryingContext.class); - BasicResultRetryAlgorithm resultAlgorithm = new BasicResultRetryAlgorithm<>(); - ExponentialRetryAlgorithm timedAlgorithm = - new ExponentialRetryAlgorithm(DEFAULT_RETRY_SETTINGS, mock(ApiClock.class)); - - StreamingRetryAlgorithm algorithm = - new StreamingRetryAlgorithm<>(resultAlgorithm, timedAlgorithm); - - TimedAttemptSettings attempt = algorithm.createFirstAttempt(context); - assertThat(attempt.getGlobalSettings()).isSameInstanceAs(DEFAULT_RETRY_SETTINGS); - assertThat(attempt.getRpcTimeout()).isEqualTo(DEFAULT_RETRY_SETTINGS.getInitialRpcTimeout()); - } - - @Test - public void testFirstAttemptUsesContextSettings() { - RetryingContext context = mock(RetryingContext.class); - when(context.getRetrySettings()).thenReturn(CONTEXT_RETRY_SETTINGS); - BasicResultRetryAlgorithm resultAlgorithm = new BasicResultRetryAlgorithm<>(); - ExponentialRetryAlgorithm timedAlgorithm = - new ExponentialRetryAlgorithm(DEFAULT_RETRY_SETTINGS, mock(ApiClock.class)); - - StreamingRetryAlgorithm algorithm = - new StreamingRetryAlgorithm<>(resultAlgorithm, timedAlgorithm); - - TimedAttemptSettings attempt = algorithm.createFirstAttempt(context); - assertThat(attempt.getGlobalSettings()).isSameInstanceAs(CONTEXT_RETRY_SETTINGS); - assertThat(attempt.getRpcTimeout()).isEqualTo(CONTEXT_RETRY_SETTINGS.getInitialRpcTimeout()); - } - - @Test - public void testNextAttemptReturnsNullWhenShouldNotRetry() { - RetryingContext context = mock(RetryingContext.class); - @SuppressWarnings("unchecked") - BasicResultRetryAlgorithm resultAlgorithm = mock(BasicResultRetryAlgorithm.class); - UnavailableException exception = mock(UnavailableException.class); - when(resultAlgorithm.shouldRetry(context, exception, null)).thenReturn(false); - ExponentialRetryAlgorithm timedAlgorithm = - new ExponentialRetryAlgorithm(DEFAULT_RETRY_SETTINGS, mock(ApiClock.class)); - - StreamingRetryAlgorithm algorithm = - new StreamingRetryAlgorithm<>(resultAlgorithm, timedAlgorithm); - - TimedAttemptSettings attempt = - algorithm.createNextAttempt(context, exception, null, mock(TimedAttemptSettings.class)); - assertThat(attempt).isNull(); - - TimedAttemptSettings attemptWithoutContext = - algorithm.createNextAttempt(exception, null, mock(TimedAttemptSettings.class)); - assertThat(attemptWithoutContext).isNull(); - } - - @Test - public void testNextAttemptReturnsResultAlgorithmSettingsWhenShouldRetry() { - RetryingContext context = mock(RetryingContext.class); - @SuppressWarnings("unchecked") - BasicResultRetryAlgorithm resultAlgorithm = mock(BasicResultRetryAlgorithm.class); - UnavailableException exception = mock(UnavailableException.class); - when(resultAlgorithm.shouldRetry(context, exception, null)).thenReturn(true); - TimedAttemptSettings next = mock(TimedAttemptSettings.class); - when(resultAlgorithm.createNextAttempt( - Mockito.eq(context), - Mockito.eq(exception), - Mockito.isNull(), - any(TimedAttemptSettings.class))) - .thenReturn(next); - ExponentialRetryAlgorithm timedAlgorithm = - new ExponentialRetryAlgorithm(DEFAULT_RETRY_SETTINGS, mock(ApiClock.class)); - - StreamingRetryAlgorithm algorithm = - new StreamingRetryAlgorithm<>(resultAlgorithm, timedAlgorithm); - - TimedAttemptSettings first = algorithm.createFirstAttempt(context); - TimedAttemptSettings attempt = algorithm.createNextAttempt(context, exception, null, first); - assertThat(attempt).isSameInstanceAs(next); - } - - @Test - public void testNextAttemptResetsTimedSettings() { - RetryingContext context = mock(RetryingContext.class); - BasicResultRetryAlgorithm resultAlgorithm = new BasicResultRetryAlgorithm<>(); - - ServerStreamingAttemptException exception = mock(ServerStreamingAttemptException.class); - when(exception.canResume()).thenReturn(true); - when(exception.hasSeenResponses()).thenReturn(true); - UnavailableException cause = mock(UnavailableException.class); - when(exception.getCause()).thenReturn(cause); - - ExponentialRetryAlgorithm timedAlgorithm = - new ExponentialRetryAlgorithm(DEFAULT_RETRY_SETTINGS, mock(ApiClock.class)); - StreamingRetryAlgorithm algorithm = - new StreamingRetryAlgorithm<>(resultAlgorithm, timedAlgorithm); - - TimedAttemptSettings first = algorithm.createFirstAttempt(context); - TimedAttemptSettings second = - algorithm.createNextAttempt(context, mock(Exception.class), null, first); - TimedAttemptSettings third = algorithm.createNextAttempt(context, exception, null, second); - assertThat(third.getFirstAttemptStartTimeNanos()) - .isEqualTo(first.getFirstAttemptStartTimeNanos()); - // The timeout values are reset to the second call. - assertThat(third.getRpcTimeout()).isEqualTo(second.getRpcTimeout()); - } - - @Test - public void testShouldNotRetryIfAttemptIsNonResumable() { - RetryingContext context = mock(RetryingContext.class); - - ServerStreamingAttemptException exception = mock(ServerStreamingAttemptException.class); - when(exception.canResume()).thenReturn(false); - UnavailableException cause = mock(UnavailableException.class); - when(exception.getCause()).thenReturn(cause); - - BasicResultRetryAlgorithm resultAlgorithm = new BasicResultRetryAlgorithm<>(); - - ExponentialRetryAlgorithm timedAlgorithm = - new ExponentialRetryAlgorithm(DEFAULT_RETRY_SETTINGS, mock(ApiClock.class)); - StreamingRetryAlgorithm algorithm = - new StreamingRetryAlgorithm<>(resultAlgorithm, timedAlgorithm); - - // This should return false because the attempt exception indicates that it is non-resumable. - boolean shouldRetry = - algorithm.shouldRetry(context, exception, null, mock(TimedAttemptSettings.class)); - assertThat(shouldRetry).isFalse(); - - boolean shouldRetryWithoutContext = - algorithm.shouldRetry(exception, null, mock(TimedAttemptSettings.class)); - assertThat(shouldRetryWithoutContext).isFalse(); - } - - @Test - public void testShouldRetryIfAllSayYes() { - RetryingContext context = mock(RetryingContext.class); - - ServerStreamingAttemptException exception = mock(ServerStreamingAttemptException.class); - when(exception.canResume()).thenReturn(true); - UnavailableException cause = mock(UnavailableException.class); - when(exception.getCause()).thenReturn(cause); - - BasicResultRetryAlgorithm resultAlgorithm = new BasicResultRetryAlgorithm<>(); - - ExponentialRetryAlgorithm timedAlgorithm = mock(ExponentialRetryAlgorithm.class); - when(timedAlgorithm.shouldRetry(Mockito.eq(context), any(TimedAttemptSettings.class))) - .thenReturn(true); - StreamingRetryAlgorithm algorithm = - new StreamingRetryAlgorithm<>(resultAlgorithm, timedAlgorithm); - - boolean shouldRetry = - algorithm.shouldRetry(context, exception, null, mock(TimedAttemptSettings.class)); - assertThat(shouldRetry).isTrue(); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/TranslatingUnaryCallableTest.java b/gax/src/test/java/com/google/api/gax/rpc/TranslatingUnaryCallableTest.java deleted file mode 100644 index af9534143..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/TranslatingUnaryCallableTest.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import com.google.api.core.ApiFunction; -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.common.truth.Truth; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class TranslatingUnaryCallableTest { - - @Test - public void translate() throws Exception { - TranslatingUnaryCallable callable = - TranslatingUnaryCallable.create( - new UnaryCallable() { - @Override - public ApiFuture futureCall(Integer request, ApiCallContext context) { - return ApiFutures.immediateFuture(request + 1); - } - }, - new ApiFunction() { - @Override - public Integer apply(String s) { - return Integer.parseInt(s); - } - }, - new ApiFunction() { - @Override - public String apply(Integer integer) { - return integer.toString(); - } - }); - Truth.assertThat(callable.futureCall("3").get()).isEqualTo("4"); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/UnaryCallSettingsTest.java b/gax/src/test/java/com/google/api/gax/rpc/UnaryCallSettingsTest.java deleted file mode 100644 index 6838d5725..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/UnaryCallSettingsTest.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; - -import com.google.api.gax.retrying.RetrySettings; -import com.google.common.collect.ImmutableSet; -import java.util.Set; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class UnaryCallSettingsTest { - - @Test - public void testSetSimpleTimeoutNoRetries() { - UnaryCallSettings.Builder builder = new UnaryCallSettings.Builder(); - builder.setSimpleTimeoutNoRetries(Duration.ofSeconds(13)); - - assertThat(builder.getRetryableCodes().size()).isEqualTo(0); - assertThat(builder.getRetrySettings().getMaxAttempts()).isEqualTo(1); - assertThat(builder.getRetrySettings().getTotalTimeout()).isEqualTo(Duration.ofSeconds(13)); - } - - @Test - public void testEquals() { - UnaryCallSettings.Builder builder = new UnaryCallSettings.Builder(); - builder.setSimpleTimeoutNoRetries(Duration.ofSeconds(13)); - - UnaryCallSettings settings13 = builder.build(); - assertEquals(settings13, settings13); - assertNotEquals(settings13, null); - assertNotEquals(settings13, "a string"); - assertEquals(settings13.hashCode(), settings13.hashCode()); - - UnaryCallSettings.Builder builder5 = new UnaryCallSettings.Builder(); - builder5.setSimpleTimeoutNoRetries(Duration.ofSeconds(5)); - - UnaryCallSettings settings5 = builder5.build(); - assertNotEquals(settings13, settings5); - assertNotEquals(settings13.hashCode(), settings5.hashCode()); - } - - @Test - public void testEquals_retrySettings() { - RetrySettings initialSettings = - RetrySettings.newBuilder() - .setInitialRetryDelay(Duration.ofMillis(5)) - .setMaxRetryDelay(Duration.ofSeconds(1)) - .setRetryDelayMultiplier(2) - .setInitialRpcTimeout(Duration.ofMillis(100)) - .setMaxRpcTimeout(Duration.ofMillis(200)) - .setRpcTimeoutMultiplier(1.1) - .setJittered(true) - .setMaxAttempts(10) - .build(); - - UnaryCallSettings.Builder builder = new UnaryCallSettings.Builder(); - UnaryCallSettings settingsNoRetry = builder.build(); - - builder.setRetrySettings(initialSettings); - UnaryCallSettings settingsRetry = builder.build(); - - assertNotEquals(settingsRetry, settingsNoRetry); - } - - @Test - public void testEquals_retryableCodes() { - UnaryCallSettings.Builder builder = new UnaryCallSettings.Builder(); - UnaryCallSettings settingsNoCodes = builder.build(); - - builder.setRetryableCodes(StatusCode.Code.CANCELLED); - UnaryCallSettings settingsCodes = builder.build(); - - assertNotEquals(settingsCodes, settingsNoCodes); - - UnaryCallSettings settingsCodes2 = builder.build(); - assertEquals(settingsCodes, settingsCodes2); - } - - @Test - public void testRetrySettingsBuilder() { - RetrySettings initialSettings = - RetrySettings.newBuilder() - .setInitialRetryDelay(Duration.ofMillis(5)) - .setMaxRetryDelay(Duration.ofSeconds(1)) - .setRetryDelayMultiplier(2) - .setInitialRpcTimeout(Duration.ofMillis(100)) - .setMaxRpcTimeout(Duration.ofMillis(200)) - .setRpcTimeoutMultiplier(1.1) - .setJittered(true) - .setMaxAttempts(10) - .build(); - - UnaryCallSettings.Builder builder = - new UnaryCallSettings.Builder().setRetrySettings(initialSettings); - - builder.retrySettings().setMaxRetryDelay(Duration.ofMinutes(1)); - - assertThat(builder.getRetrySettings().getMaxRetryDelay()).isEqualTo(Duration.ofMinutes(1)); - assertThat(builder.build().getRetrySettings().getMaxRetryDelay()) - .isEqualTo(Duration.ofMinutes(1)); - } - - @Test - public void testToString() { - RetrySettings retrySettings = RetrySettings.newBuilder().build(); - Set retryableCodes = ImmutableSet.of(StatusCode.Code.DEADLINE_EXCEEDED); - UnaryCallSettings unaryCallSettings = - UnaryCallSettings.newUnaryCallSettingsBuilder() - .setRetrySettings(retrySettings) - .setRetryableCodes(retryableCodes) - .build(); - assertThat(unaryCallSettings.toString()).contains("retryableCodes=" + retryableCodes); - assertThat(unaryCallSettings.toString()).contains("retrySettings=" + retrySettings); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/UnaryCallableTest.java b/gax/src/test/java/com/google/api/gax/rpc/UnaryCallableTest.java deleted file mode 100644 index 0e16545d4..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/UnaryCallableTest.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2016 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; - -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.rpc.testing.FakeCallContext; -import com.google.api.gax.rpc.testing.FakeChannel; -import com.google.api.gax.rpc.testing.FakeSimpleApi.StashCallable; -import com.google.auth.Credentials; -import com.google.common.collect.ImmutableSet; -import java.util.Set; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; - -/** Tests for {@link UnaryCallable}. */ -@RunWith(JUnit4.class) -public class UnaryCallableTest { - - @Test - public void simpleCall() throws Exception { - StashCallable stashCallable = new StashCallable<>(1); - - Integer response = stashCallable.call(2, FakeCallContext.createDefault()); - assertEquals(Integer.valueOf(1), response); - FakeCallContext callContext = (FakeCallContext) stashCallable.getContext(); - assertNull(callContext.getChannel()); - assertNull(callContext.getCredentials()); - } - - @Test - public void call() throws Exception { - ApiCallContext defaultCallContext = FakeCallContext.createDefault(); - StashCallable stashCallable = new StashCallable<>(1); - UnaryCallable callable = - stashCallable.withDefaultCallContext(defaultCallContext); - - Integer response = callable.call(2); - assertEquals(Integer.valueOf(1), response); - assertNotNull(stashCallable.getContext()); - assertSame(defaultCallContext, stashCallable.getContext()); - } - - @Test - public void callWithContext() throws Exception { - FakeChannel channel = new FakeChannel(); - Credentials credentials = Mockito.mock(Credentials.class); - RetrySettings retrySettings = Mockito.mock(RetrySettings.class); - Set retryableCodes = - ImmutableSet.of( - StatusCode.Code.INTERNAL, - StatusCode.Code.UNAVAILABLE, - StatusCode.Code.DEADLINE_EXCEEDED); - ApiCallContext context = - FakeCallContext.createDefault() - .withChannel(channel) - .withCredentials(credentials) - .withRetrySettings(retrySettings) - .withRetryableCodes(retryableCodes); - StashCallable stashCallable = new StashCallable<>(1); - UnaryCallable callable = - stashCallable.withDefaultCallContext(FakeCallContext.createDefault()); - - Integer response = callable.call(2, context); - assertEquals(Integer.valueOf(1), response); - FakeCallContext actualContext = (FakeCallContext) stashCallable.getContext(); - assertSame(channel, actualContext.getChannel()); - assertSame(credentials, actualContext.getCredentials()); - assertSame(retrySettings, actualContext.getRetrySettings()); - assertThat(actualContext.getRetryableCodes()).containsExactlyElementsIn(retryableCodes); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/WatchdogTest.java b/gax/src/test/java/com/google/api/gax/rpc/WatchdogTest.java deleted file mode 100644 index e20218452..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/WatchdogTest.java +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.api.core.SettableApiFuture; -import com.google.api.gax.core.BackgroundResource; -import com.google.api.gax.core.FakeApiClock; -import com.google.api.gax.rpc.testing.MockStreamingApi.MockServerStreamingCall; -import com.google.api.gax.rpc.testing.MockStreamingApi.MockServerStreamingCallable; -import com.google.common.collect.Queues; -import java.util.Queue; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class WatchdogTest { - private static final ScheduledExecutorService EXECUTOR = Executors.newScheduledThreadPool(1); - - private FakeApiClock clock; - private final Duration checkInterval = Duration.ofMillis(1000); - private Duration waitTime = Duration.ofSeconds(10); - private Duration idleTime = Duration.ofMinutes(5); - - private Watchdog watchdog; - private MockServerStreamingCallable callable; - private AccumulatingObserver innerObserver; - private MockServerStreamingCall call; - - @Before - public void setUp() { - clock = new FakeApiClock(0); - watchdog = Watchdog.create(clock, checkInterval, EXECUTOR); - - callable = new MockServerStreamingCallable<>(); - innerObserver = new AccumulatingObserver<>(); - callable.call("request", watchdog.watch(innerObserver, waitTime, idleTime)); - call = callable.popLastCall(); - } - - @Test - public void testRequestPassthrough() throws Exception { - innerObserver.controller.get().request(1); - assertThat(call.getController().popLastPull()).isEqualTo(1); - } - - @Test - public void testWaitTimeout() throws Exception { - innerObserver.controller.get(1, TimeUnit.MILLISECONDS).request(1); - - clock.incrementNanoTime(waitTime.toNanos() - 1); - watchdog.run(); - assertThat(call.getController().isCancelled()).isFalse(); - - clock.incrementNanoTime(1); - watchdog.run(); - assertThat(call.getController().isCancelled()).isTrue(); - call.getController() - .getObserver() - .onError(new RuntimeException("Some upstream exception representing cancellation")); - - Throwable actualError = null; - try { - innerObserver.done.get(); - } catch (ExecutionException t) { - actualError = t.getCause(); - } - assertThat(actualError).isInstanceOf(WatchdogTimeoutException.class); - } - - @Test - public void testIdleTimeout() throws InterruptedException { - clock.incrementNanoTime(idleTime.toNanos() - 1); - watchdog.run(); - assertThat(call.getController().isCancelled()).isFalse(); - - clock.incrementNanoTime(1); - watchdog.run(); - assertThat(call.getController().isCancelled()).isTrue(); - call.getController() - .getObserver() - .onError(new RuntimeException("Some upstream exception representing cancellation")); - - Throwable actualError = null; - try { - innerObserver.done.get(); - } catch (ExecutionException t) { - actualError = t.getCause(); - } - assertThat(actualError).isInstanceOf(WatchdogTimeoutException.class); - } - - @Test - public void testTimedOutBeforeStart() throws InterruptedException { - MockServerStreamingCallable callable1 = new MockServerStreamingCallable<>(); - AccumulatingObserver downstreamObserver1 = new AccumulatingObserver<>(); - ResponseObserver observer = watchdog.watch(downstreamObserver1, waitTime, idleTime); - clock.incrementNanoTime(idleTime.toNanos() + 1); - // This should not remove callable1 from watched list - watchdog.run(); - assertThat(downstreamObserver1.done.isDone()).isFalse(); - - callable1.call("request", observer); - // This should cancel callable1 - watchdog.run(); - MockServerStreamingCall call1 = callable1.popLastCall(); - assertThat(call1.getController().isCancelled()).isTrue(); - call1.getController().getObserver().onError(new CancellationException("User cancelled")); - Throwable error = null; - try { - downstreamObserver1.done.get(); - } catch (ExecutionException t) { - error = t.getCause(); - } - assertThat(error).isInstanceOf(WatchdogTimeoutException.class); - } - - @Test - public void testMultiple() throws Exception { - // Start stream1 - AccumulatingObserver downstreamObserver1 = new AccumulatingObserver<>(); - callable.call("request", watchdog.watch(downstreamObserver1, waitTime, idleTime)); - MockServerStreamingCall call1 = callable.popLastCall(); - downstreamObserver1.controller.get().request(1); - - // Start stream2 - AccumulatingObserver downstreamObserver2 = new AccumulatingObserver<>(); - callable.call("req2", watchdog.watch(downstreamObserver2, waitTime, idleTime)); - MockServerStreamingCall call2 = callable.popLastCall(); - downstreamObserver2.controller.get().request(1); - - // Give stream1 a response at the last possible moment - clock.incrementNanoTime(waitTime.toNanos()); - call1.getController().getObserver().onResponse("resp1"); - - // run the callable - watchdog.run(); - - // Call1 should be ok - assertThat(call1.getController().isCancelled()).isFalse(); - // Should not throw - assertThat(downstreamObserver1.done.isDone()).isFalse(); - - // Call2 should be timed out - assertThat(call2.getController().isCancelled()).isTrue(); - call2.getController().getObserver().onError(new CancellationException("User cancelled")); - Throwable error = null; - try { - downstreamObserver2.done.get(); - } catch (ExecutionException t) { - error = t.getCause(); - } - assertThat(error).isInstanceOf(WatchdogTimeoutException.class); - } - - @Test - @SuppressWarnings("unchecked") - public void testWatchdogBeingClosed() { - ScheduledFuture future = Mockito.mock(ScheduledFuture.class); - ScheduledExecutorService mockExecutor = getMockExecutorService(future); - Watchdog underTest = Watchdog.create(clock, checkInterval, mockExecutor); - assertThat(underTest).isInstanceOf(BackgroundResource.class); - - underTest.close(); - underTest.shutdown(); - - Mockito.verify(mockExecutor) - .scheduleAtFixedRate( - underTest, checkInterval.toMillis(), checkInterval.toMillis(), TimeUnit.MILLISECONDS); - Mockito.verify(future, Mockito.times(2)).cancel(false); - - underTest.shutdownNow(); - Mockito.verify(future).cancel(true); - Mockito.verifyNoMoreInteractions(mockExecutor); - } - - @Test - public void awaitTermination_shouldReturnTrueIfFutureIsDone() throws Exception { - int duration = 1000; - TimeUnit timeUnit = TimeUnit.MILLISECONDS; - ScheduledFuture future = Mockito.mock(ScheduledFuture.class); - ScheduledExecutorService mockExecutor = getMockExecutorService(future); - Watchdog watchdog = Watchdog.create(clock, checkInterval, mockExecutor); - watchdog.shutdown(); - - boolean actual = watchdog.awaitTermination(duration, timeUnit); - - assertThat(actual).isTrue(); - } - - @Test - public void awaitTermination_shouldReturnFalseIfGettingFutureTimedOut() throws Exception { - int duration = 1000; - TimeUnit timeUnit = TimeUnit.MILLISECONDS; - ScheduledFuture future = Mockito.mock(ScheduledFuture.class); - Mockito.doThrow(new TimeoutException()).when(future).get(duration, timeUnit); - ScheduledExecutorService mockExecutor = getMockExecutorService(future); - Watchdog watchdog = Watchdog.create(clock, checkInterval, mockExecutor); - - boolean actual = watchdog.awaitTermination(duration, timeUnit); - - assertThat(actual).isFalse(); - } - - @Test - public void awaitTermination_shouldReturnTrueIfFutureIsAlreadyCancelled() throws Exception { - int duration = 1000; - TimeUnit timeUnit = TimeUnit.MILLISECONDS; - ScheduledFuture future = Mockito.mock(ScheduledFuture.class); - Mockito.doThrow(new CancellationException()).when(future).get(duration, timeUnit); - ScheduledExecutorService mockExecutor = getMockExecutorService(future); - Watchdog watchdog = Watchdog.create(clock, checkInterval, mockExecutor); - - boolean actual = watchdog.awaitTermination(duration, timeUnit); - - assertThat(actual).isTrue(); - } - - @Test - public void awaitTermination_shouldReturnFalseIfGettingFutureThrowsExecutionException() - throws Exception { - int duration = 1000; - TimeUnit timeUnit = TimeUnit.MILLISECONDS; - ScheduledFuture future = Mockito.mock(ScheduledFuture.class); - Mockito.doThrow(new ExecutionException(new RuntimeException())) - .when(future) - .get(duration, timeUnit); - ScheduledExecutorService mockExecutor = getMockExecutorService(future); - Watchdog watchdog = Watchdog.create(clock, checkInterval, mockExecutor); - - boolean actual = watchdog.awaitTermination(duration, timeUnit); - - assertThat(actual).isTrue(); - } - - private ScheduledExecutorService getMockExecutorService(ScheduledFuture future) { - ScheduledExecutorService mockExecutor = Mockito.mock(ScheduledExecutorService.class); - Mockito.when( - mockExecutor.scheduleAtFixedRate( - Mockito.any(Watchdog.class), - Mockito.anyLong(), - Mockito.anyLong(), - Mockito.any(TimeUnit.class))) - .thenReturn(future); - return mockExecutor; - } - - static class AccumulatingObserver implements ResponseObserver { - SettableApiFuture controller = SettableApiFuture.create(); - Queue responses = Queues.newLinkedBlockingDeque(); - SettableApiFuture done = SettableApiFuture.create(); - - @Override - public void onStart(StreamController controller) { - controller.disableAutoInboundFlowControl(); - this.controller.set(controller); - } - - @Override - public void onResponse(T response) { - responses.add(response); - } - - @Override - public void onError(Throwable t) { - done.setException(t); - } - - @Override - public void onComplete() { - done.set(null); - } - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/internal/ApiCallContextOptionsTest.java b/gax/src/test/java/com/google/api/gax/rpc/internal/ApiCallContextOptionsTest.java deleted file mode 100644 index cf4f785bb..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/internal/ApiCallContextOptionsTest.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc.internal; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.api.gax.rpc.ApiCallContext; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class ApiCallContextOptionsTest { - - private static final ApiCallContext.Key INTEGER_KEY = ApiCallContext.Key.create("key1"); - private static final ApiCallContext.Key STRING_KEY = ApiCallContext.Key.create("key2"); - private static final ApiCallContext.Key DOUBLE_KEY = ApiCallContext.Key.create("key3"); - - @Test - public void testWithOption() { - ApiCallContextOptions options = - ApiCallContextOptions.getDefaultOptions() - .withOption(INTEGER_KEY, 1) - .withOption(STRING_KEY, "test") - .withOption(DOUBLE_KEY, 2.0); - assertThat(options.getOption(INTEGER_KEY)).isEqualTo(1); - assertThat(options.getOption(STRING_KEY)).isEqualTo("test"); - assertThat(options.getOption(DOUBLE_KEY)).isEqualTo(2.0); - - ApiCallContextOptions updatedOptions = options.withOption(INTEGER_KEY, 10); - assertThat(updatedOptions.getOption(INTEGER_KEY)).isEqualTo(10); - assertThat(options.getOption(STRING_KEY)).isEqualTo("test"); - assertThat(options.getOption(DOUBLE_KEY)).isEqualTo(2.0); - } - - @Test - public void testMergeEmpty() { - ApiCallContextOptions options = - ApiCallContextOptions.getDefaultOptions() - .withOption(INTEGER_KEY, 1) - .withOption(STRING_KEY, "test"); - - ApiCallContextOptions defaultOptions = ApiCallContextOptions.getDefaultOptions(); - - ApiCallContextOptions mergedOptions1 = options.merge(defaultOptions); - assertThat(mergedOptions1.getOption(INTEGER_KEY)).isEqualTo(1); - assertThat(mergedOptions1.getOption(STRING_KEY)).isEqualTo("test"); - - ApiCallContextOptions mergedOptions2 = defaultOptions.merge(options); - assertThat(mergedOptions2.getOption(INTEGER_KEY)).isEqualTo(1); - assertThat(mergedOptions2.getOption(STRING_KEY)).isEqualTo("test"); - } - - @Test - public void testMergeDifferentKeys() { - ApiCallContextOptions options1 = - ApiCallContextOptions.getDefaultOptions() - .withOption(INTEGER_KEY, 1) - .withOption(STRING_KEY, "test"); - ApiCallContextOptions options2 = - ApiCallContextOptions.getDefaultOptions().withOption(DOUBLE_KEY, 5.0); - ApiCallContextOptions mergedOptions = options1.merge(options2); - assertThat(mergedOptions.getOption(INTEGER_KEY)).isEqualTo(1); - assertThat(mergedOptions.getOption(STRING_KEY)).isEqualTo("test"); - assertThat(mergedOptions.getOption(DOUBLE_KEY)).isEqualTo(5.0); - } - - @Test - public void testMergeDuplicateKeys() { - ApiCallContextOptions options1 = - ApiCallContextOptions.getDefaultOptions() - .withOption(INTEGER_KEY, 1) - .withOption(STRING_KEY, "test"); - ApiCallContextOptions options2 = - ApiCallContextOptions.getDefaultOptions() - .withOption(STRING_KEY, "newTest") - .withOption(DOUBLE_KEY, 5.0); - ApiCallContextOptions mergedOptions = options1.merge(options2); - assertThat(mergedOptions.getOption(INTEGER_KEY)).isEqualTo(1); - assertThat(mergedOptions.getOption(STRING_KEY)).isEqualTo("newTest"); - assertThat(mergedOptions.getOption(DOUBLE_KEY)).isEqualTo(5.0); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/internal/HeadersTest.java b/gax/src/test/java/com/google/api/gax/rpc/internal/HeadersTest.java deleted file mode 100644 index ebcb9bd39..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/internal/HeadersTest.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.gax.rpc.internal; - -import static com.google.common.truth.Truth.assertThat; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class HeadersTest { - - @Test - public void testMergeHeaders() { - Map> headers1 = createHeaders("key1", "value1", "key1", "value2"); - Map> headers2 = createHeaders("key1", "value2", "key2", "value2"); - Map> mergedHeaders = Headers.mergeHeaders(headers1, headers2); - Map> expectedHeaders = - createHeaders("key1", "value1", "key1", "value2", "key1", "value2", "key2", "value2"); - assertThat(mergedHeaders).containsExactlyEntriesIn(expectedHeaders); - } - - @Test - public void testMergeHeadersEmpty() { - Map> headers1 = createHeaders(); - Map> headers2 = createHeaders("key1", "value1", "key2", "value2"); - Map> mergedHeaders = Headers.mergeHeaders(headers1, headers2); - Map> expectedHeaders = createHeaders("key1", "value1", "key2", "value2"); - assertThat(mergedHeaders).containsExactlyEntriesIn(expectedHeaders); - } - - private static Map> createHeaders(String... keyValues) { - Map> headers = new HashMap<>(); - for (int i = 0; i < keyValues.length; i += 2) { - String key = keyValues[i]; - String value = keyValues[i + 1]; - if (!headers.containsKey(key)) { - headers.put(key, new ArrayList()); - } - headers.get(key).add(value); - } - return headers; - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/internal/QuotaProjectIdHidingCredentialsTest.java b/gax/src/test/java/com/google/api/gax/rpc/internal/QuotaProjectIdHidingCredentialsTest.java deleted file mode 100644 index af36e0a5b..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/internal/QuotaProjectIdHidingCredentialsTest.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc.internal; - -import com.google.auth.Credentials; -import com.google.auth.oauth2.GoogleCredentials; -import com.google.common.collect.ImmutableMap; -import java.io.IOException; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mockito; - -@RunWith(JUnit4.class) -public class QuotaProjectIdHidingCredentialsTest { - private static final String QUOTA_PROJECT_ID_KEY = "x-goog-user-project"; - private static final String QUOTA_PROJECT_ID_FROM_CREDENTIALS_VALUE = - "quota_project_id_from_credentials"; - - @Test - public void quotaProjectIdHidingCredentials_getRequestMetadata() throws IOException { - // Credentials with quota project id - Map> metaDataWithQuota = - ImmutableMap.of( - "k1", - Collections.singletonList("v1"), - QUOTA_PROJECT_ID_KEY, - Collections.singletonList(QUOTA_PROJECT_ID_FROM_CREDENTIALS_VALUE)); - Credentials credentialsWithQuotaProjectId = Mockito.mock(GoogleCredentials.class); - Mockito.when(credentialsWithQuotaProjectId.getRequestMetadata(null)) - .thenReturn(metaDataWithQuota); - QuotaProjectIdHidingCredentials quotaProjectIdHidingCredentials = - new QuotaProjectIdHidingCredentials(credentialsWithQuotaProjectId); - Map> metaDataHidingQuota = - quotaProjectIdHidingCredentials.getRequestMetadata(); - - Assert.assertTrue(metaDataWithQuota.containsKey(QUOTA_PROJECT_ID_KEY)); - Assert.assertFalse(metaDataHidingQuota.containsKey(QUOTA_PROJECT_ID_KEY)); - Assert.assertEquals(metaDataWithQuota.size() - 1, metaDataHidingQuota.size()); - - // Credentials without quota project id - Map> metaDataWithoutQuota = - ImmutableMap.of("k1", Collections.singletonList("v1")); - Credentials credentialsWithoutQuotaProjectId = Mockito.mock(GoogleCredentials.class); - Mockito.when(credentialsWithoutQuotaProjectId.getRequestMetadata(null)) - .thenReturn(metaDataWithoutQuota); - QuotaProjectIdHidingCredentials quotaProjectIdHidingCredentialsWithout = - new QuotaProjectIdHidingCredentials(credentialsWithoutQuotaProjectId); - Map> metaDataHidingQuotaWithout = - quotaProjectIdHidingCredentials.getRequestMetadata(); - - Assert.assertEquals( - quotaProjectIdHidingCredentialsWithout.getRequestMetadata(), metaDataWithoutQuota); - } - - @Test - public void quotaProjectIdHidingCredentials_getAuthenticationType() throws IOException { - final String mockType = "mock_type"; - Credentials credentials = Mockito.mock(GoogleCredentials.class); - Mockito.when(credentials.getAuthenticationType()).thenReturn(mockType); - Mockito.when(credentials.hasRequestMetadata()).thenReturn(true); - Mockito.when(credentials.hasRequestMetadataOnly()).thenReturn(false); - - QuotaProjectIdHidingCredentials quotaProjectIdHidingCredentials = - new QuotaProjectIdHidingCredentials(credentials); - quotaProjectIdHidingCredentials.refresh(); - - Assert.assertEquals(quotaProjectIdHidingCredentials.getAuthenticationType(), mockType); - Assert.assertTrue(quotaProjectIdHidingCredentials.hasRequestMetadata()); - Assert.assertFalse(quotaProjectIdHidingCredentials.hasRequestMetadataOnly()); - - Mockito.verify(credentials, Mockito.atLeastOnce()).refresh(); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/mtls/AbstractMtlsTransportChannelTest.java b/gax/src/test/java/com/google/api/gax/rpc/mtls/AbstractMtlsTransportChannelTest.java deleted file mode 100644 index a75c7b812..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/mtls/AbstractMtlsTransportChannelTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.gax.rpc.mtls; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import com.google.api.gax.rpc.mtls.MtlsProvider.MtlsEndpointUsagePolicy; -import com.google.api.gax.rpc.testing.FakeMtlsProvider; -import java.io.IOException; -import java.security.GeneralSecurityException; -import org.junit.Test; - -public abstract class AbstractMtlsTransportChannelTest { - /** - * Returns the mTLS object from the created transport channel. mTLS object is created with mTLS - * keystore. For HttpJsonTransportChannel, the mTLS object is the SslContext; for - * GrpcTransportChannel, the mTLS object is the ChannelCredentials. The transport channel is mTLS - * if and only if the related mTLS object is not null. - */ - protected abstract Object getMtlsObjectFromTransportChannel(MtlsProvider provider) - throws IOException, GeneralSecurityException; - - @Test - public void testNotUseClientCertificate() throws IOException, GeneralSecurityException { - MtlsProvider provider = - new FakeMtlsProvider(false, MtlsEndpointUsagePolicy.AUTO, null, "", false); - assertNull(getMtlsObjectFromTransportChannel(provider)); - } - - @Test - public void testUseClientCertificate() throws IOException, GeneralSecurityException { - MtlsProvider provider = - new FakeMtlsProvider( - true, - MtlsEndpointUsagePolicy.AUTO, - FakeMtlsProvider.createTestMtlsKeyStore(), - "", - false); - assertNotNull(getMtlsObjectFromTransportChannel(provider)); - } - - @Test - public void testNoClientCertificate() throws IOException, GeneralSecurityException { - MtlsProvider provider = - new FakeMtlsProvider(true, MtlsEndpointUsagePolicy.AUTO, null, "", false); - assertNull(getMtlsObjectFromTransportChannel(provider)); - } - - @Test - public void testGetKeyStoreThrows() throws GeneralSecurityException { - // Test the case where provider.getKeyStore() throws. - MtlsProvider provider = - new FakeMtlsProvider(true, MtlsEndpointUsagePolicy.AUTO, null, "", true); - try { - getMtlsObjectFromTransportChannel(provider); - fail("should throw an exception"); - } catch (IOException e) { - assertTrue( - "expected getKeyStore to throw an exception", - e.getMessage().contains("getKeyStore throws exception")); - } - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/mtls/MtlsProviderTest.java b/gax/src/test/java/com/google/api/gax/rpc/mtls/MtlsProviderTest.java deleted file mode 100644 index 49be7aab5..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/mtls/MtlsProviderTest.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.gax.rpc.mtls; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.security.GeneralSecurityException; -import java.util.List; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class MtlsProviderTest { - private static class TestCertProviderCommandProcess extends Process { - private boolean runForever; - private int exitValue; - - public TestCertProviderCommandProcess(int exitValue, boolean runForever) { - this.runForever = runForever; - this.exitValue = exitValue; - } - - @Override - public OutputStream getOutputStream() { - return null; - } - - @Override - public InputStream getInputStream() { - return null; - } - - @Override - public InputStream getErrorStream() { - return null; - } - - @Override - public int waitFor() throws InterruptedException { - return 0; - } - - @Override - public int exitValue() { - if (runForever) { - throw new IllegalThreadStateException(); - } - return exitValue; - } - - @Override - public void destroy() {} - } - - static class TestProcessProvider implements MtlsProvider.ProcessProvider { - private int exitCode; - - public TestProcessProvider(int exitCode) { - this.exitCode = exitCode; - } - - @Override - public Process createProcess(InputStream metadata) throws IOException { - return new TestCertProviderCommandProcess(exitCode, false); - } - } - - @Test - public void testUseMtlsEndpointAlways() { - MtlsProvider mtlsProvider = - new MtlsProvider( - name -> name.equals("GOOGLE_API_USE_MTLS_ENDPOINT") ? "always" : "false", - new TestProcessProvider(0), - "/path/to/missing/file"); - assertEquals( - MtlsProvider.MtlsEndpointUsagePolicy.ALWAYS, mtlsProvider.getMtlsEndpointUsagePolicy()); - } - - @Test - public void testUseMtlsEndpointAuto() { - MtlsProvider mtlsProvider = - new MtlsProvider( - name -> name.equals("GOOGLE_API_USE_MTLS_ENDPOINT") ? "auto" : "false", - new TestProcessProvider(0), - "/path/to/missing/file"); - assertEquals( - MtlsProvider.MtlsEndpointUsagePolicy.AUTO, mtlsProvider.getMtlsEndpointUsagePolicy()); - } - - @Test - public void testUseMtlsEndpointNever() { - MtlsProvider mtlsProvider = - new MtlsProvider( - name -> name.equals("GOOGLE_API_USE_MTLS_ENDPOINT") ? "never" : "false", - new TestProcessProvider(0), - "/path/to/missing/file"); - assertEquals( - MtlsProvider.MtlsEndpointUsagePolicy.NEVER, mtlsProvider.getMtlsEndpointUsagePolicy()); - } - - @Test - public void testUseMtlsClientCertificateTrue() { - MtlsProvider mtlsProvider = - new MtlsProvider( - name -> name.equals("GOOGLE_API_USE_MTLS_ENDPOINT") ? "auto" : "true", - new TestProcessProvider(0), - "/path/to/missing/file"); - assertTrue(mtlsProvider.useMtlsClientCertificate()); - } - - @Test - public void testUseMtlsClientCertificateFalse() { - MtlsProvider mtlsProvider = - new MtlsProvider( - name -> name.equals("GOOGLE_API_USE_MTLS_ENDPOINT") ? "auto" : "false", - new TestProcessProvider(0), - "/path/to/missing/file"); - assertFalse(mtlsProvider.useMtlsClientCertificate()); - } - - @Test - public void testGetKeyStore() throws IOException { - MtlsProvider mtlsProvider = - new MtlsProvider( - name -> name.equals("GOOGLE_API_USE_MTLS_ENDPOINT") ? "always" : "false", - new TestProcessProvider(0), - "/path/to/missing/file"); - assertNull(mtlsProvider.getKeyStore()); - } - - @Test - public void testGetKeyStoreNonZeroExitCode() - throws IOException, InterruptedException, GeneralSecurityException { - try { - InputStream metadata = - this.getClass() - .getClassLoader() - .getResourceAsStream("com/google/api/gax/rpc/mtls/mtlsCertAndKey.pem"); - MtlsProvider.getKeyStore(metadata, new TestProcessProvider(1)); - fail("should throw an exception"); - } catch (IOException e) { - assertTrue( - "expected to fail with nonzero exit code", - e.getMessage().contains("Cert provider command failed with exit code: 1")); - } - } - - @Test - public void testExtractCertificateProviderCommand() throws IOException { - InputStream inputStream = - this.getClass() - .getClassLoader() - .getResourceAsStream("com/google/api/gax/rpc/mtls/mtls_context_aware_metadata.json"); - List command = MtlsProvider.extractCertificateProviderCommand(inputStream); - assertEquals(2, command.size()); - assertEquals("some_binary", command.get(0)); - assertEquals("some_argument", command.get(1)); - } - - @Test - public void testRunCertificateProviderCommandSuccess() throws IOException, InterruptedException { - Process certCommandProcess = new TestCertProviderCommandProcess(0, false); - int exitValue = MtlsProvider.runCertificateProviderCommand(certCommandProcess, 100); - assertEquals(0, exitValue); - } - - @Test - public void testRunCertificateProviderCommandTimeout() throws InterruptedException { - Process certCommandProcess = new TestCertProviderCommandProcess(0, true); - try { - MtlsProvider.runCertificateProviderCommand(certCommandProcess, 100); - fail("should throw an exception"); - } catch (IOException e) { - assertTrue( - "expected to fail with timeout", - e.getMessage().contains("cert provider command timed out")); - } - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeApiException.java b/gax/src/test/java/com/google/api/gax/rpc/testing/FakeApiException.java deleted file mode 100644 index e76b9fafb..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeApiException.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc.testing; - -import com.google.api.core.BetaApi; -import com.google.api.core.InternalApi; -import com.google.api.gax.rpc.ApiException; - -@InternalApi("for testing") -public class FakeApiException extends ApiException { - - @BetaApi - public FakeApiException(Throwable cause, FakeStatusCode.Code statusCode, boolean retryable) { - super(cause, FakeStatusCode.of(statusCode), retryable); - } - - @BetaApi - public FakeApiException( - String message, Throwable cause, FakeStatusCode.Code statusCode, boolean retryable) { - super(message, cause, FakeStatusCode.of(statusCode), retryable); - } - - /** - * Returns the status code of the underlying exception. In cases where the underlying status code - * can't be determined, the status code will be FakeStatusCode.Code.UNKNOWN. - */ - public FakeStatusCode getStatusCode() { - return (FakeStatusCode) super.getStatusCode(); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeBatchableApi.java b/gax/src/test/java/com/google/api/gax/rpc/testing/FakeBatchableApi.java deleted file mode 100644 index 525815f34..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeBatchableApi.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc.testing; - -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.api.core.InternalApi; -import com.google.api.gax.batching.BatchEntry; -import com.google.api.gax.batching.BatchingRequestBuilder; -import com.google.api.gax.batching.PartitionKey; -import com.google.api.gax.batching.RequestBuilder; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.BatchedRequestIssuer; -import com.google.api.gax.rpc.BatchingDescriptor; -import com.google.api.gax.rpc.UnaryCallable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -@InternalApi("for testing") -public class FakeBatchableApi { - - public static class LabeledIntList { - public String label; - public List ints; - - public LabeledIntList(String label, Integer... numbers) { - this(label, new ArrayList<>(Arrays.asList(numbers))); - } - - public LabeledIntList(String label, List ints) { - this.label = label; - this.ints = ints; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - LabeledIntList that = (LabeledIntList) o; - - if (!label.equals(that.label)) { - return false; - } - return ints.equals(that.ints); - } - - @Override - public int hashCode() { - int result = label.hashCode(); - result = 31 * result + ints.hashCode(); - return result; - } - - public LabeledIntList clone() { - return new LabeledIntList(this.label, new ArrayList<>(this.ints)); - } - } - - public static LabeledIntSquarerCallable callLabeledIntSquarer = new LabeledIntSquarerCallable(); - - public static class LabeledIntSquarerCallable - extends UnaryCallable> { - - @Override - public ApiFuture> futureCall(LabeledIntList request, ApiCallContext context) { - List result = new ArrayList<>(); - for (Integer i : request.ints) { - result.add(i * i); - } - return ApiFutures.immediateFuture(result); - } - } - - public static SquarerBatchingDescriptor SQUARER_BATCHING_DESC = new SquarerBatchingDescriptor(); - - public static class SquarerBatchingDescriptor - implements BatchingDescriptor> { - - @Override - public PartitionKey getBatchPartitionKey(LabeledIntList request) { - return new PartitionKey(request.label); - } - - @Override - public RequestBuilder getRequestBuilder() { - return new RequestBuilder() { - - LabeledIntList list; - - @Override - public void appendRequest(LabeledIntList request) { - if (list == null) { - list = request; - } else { - list.ints.addAll(request.ints); - } - } - - @Override - public LabeledIntList build() { - return list; - } - }; - } - - @Override - public void splitResponse( - List batchResponse, - Collection>> batch) { - int batchMessageIndex = 0; - for (BatchedRequestIssuer> responder : batch) { - List messageIds = new ArrayList<>(); - long messageCount = responder.getMessageCount(); - for (int i = 0; i < messageCount; i++) { - messageIds.add(batchResponse.get(batchMessageIndex)); - batchMessageIndex += 1; - } - responder.setResponse(messageIds); - } - } - - @Override - public void splitException( - Throwable throwable, Collection>> batch) { - for (BatchedRequestIssuer> responder : batch) { - responder.setException(throwable); - } - } - - @Override - public long countElements(LabeledIntList request) { - return request.ints.size(); - } - - @Override - public long countBytes(LabeledIntList request) { - long counter = 0; - for (Integer i : request.ints) { - counter += i; - } - // Limit the byte size to simulate merged messages having smaller serialized size than the sum - // of their components. - return Math.min(counter, 5); - } - } - - public static SquarerBatchingDescriptorV2 SQUARER_BATCHING_DESC_V2 = - new SquarerBatchingDescriptorV2(); - - public static class SquarerBatchingDescriptorV2 - implements com.google.api.gax.batching.BatchingDescriptor< - Integer, Integer, LabeledIntList, List> { - - @Override - public BatchingRequestBuilder newRequestBuilder( - final LabeledIntList prototype) { - return new BatchingRequestBuilder() { - final LabeledIntList labelList = prototype.clone(); - - @Override - public void add(Integer element) { - labelList.ints.add(element); - } - - @Override - public LabeledIntList build() { - return labelList; - } - }; - } - - @Override - public void splitResponse( - List batchResponse, List> batch) { - for (int i = 0; i < batchResponse.size(); i++) { - batch.get(i).getResultFuture().set(batchResponse.get(i)); - } - } - - @Override - public void splitException(Throwable throwable, List> batch) { - for (BatchEntry entry : batch) { - entry.getResultFuture().setException(throwable); - } - } - - @Override - public long countBytes(Integer element) { - return 1; - } - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeCallContext.java b/gax/src/test/java/com/google/api/gax/rpc/testing/FakeCallContext.java deleted file mode 100644 index 84d40e11c..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeCallContext.java +++ /dev/null @@ -1,425 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc.testing; - -import com.google.api.core.InternalApi; -import com.google.api.gax.retrying.RetrySettings; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.ClientContext; -import com.google.api.gax.rpc.StatusCode; -import com.google.api.gax.rpc.TransportChannel; -import com.google.api.gax.rpc.internal.ApiCallContextOptions; -import com.google.api.gax.rpc.internal.Headers; -import com.google.api.gax.tracing.ApiTracer; -import com.google.api.gax.tracing.BaseApiTracer; -import com.google.auth.Credentials; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import org.threeten.bp.Duration; - -@InternalApi("for testing") -public class FakeCallContext implements ApiCallContext { - private final Credentials credentials; - private final FakeChannel channel; - private final Duration timeout; - private final Duration streamWaitTimeout; - private final Duration streamIdleTimeout; - private final ImmutableMap> extraHeaders; - private final ApiCallContextOptions options; - private final ApiTracer tracer; - private final RetrySettings retrySettings; - private final ImmutableSet retryableCodes; - - private FakeCallContext( - Credentials credentials, - FakeChannel channel, - Duration timeout, - Duration streamWaitTimeout, - Duration streamIdleTimeout, - ImmutableMap> extraHeaders, - ApiCallContextOptions options, - ApiTracer tracer, - RetrySettings retrySettings, - Set retryableCodes) { - this.credentials = credentials; - this.channel = channel; - this.timeout = timeout; - this.streamWaitTimeout = streamWaitTimeout; - this.streamIdleTimeout = streamIdleTimeout; - this.extraHeaders = extraHeaders; - this.options = options; - this.tracer = tracer; - this.retrySettings = retrySettings; - this.retryableCodes = retryableCodes == null ? null : ImmutableSet.copyOf(retryableCodes); - } - - public static FakeCallContext createDefault() { - return new FakeCallContext( - null, - null, - null, - null, - null, - ImmutableMap.>of(), - ApiCallContextOptions.getDefaultOptions(), - null, - null, - null); - } - - @Override - public FakeCallContext nullToSelf(ApiCallContext inputContext) { - FakeCallContext fakeCallContext; - if (inputContext == null) { - fakeCallContext = this; - } else { - if (!(inputContext instanceof FakeCallContext)) { - throw new IllegalArgumentException( - "context must be an instance of FakeCallContext, but found " - + inputContext.getClass().getName()); - } - fakeCallContext = (FakeCallContext) inputContext; - } - return fakeCallContext; - } - - @Override - public ApiCallContext merge(ApiCallContext inputCallContext) { - if (inputCallContext == null) { - return this; - } - if (!(inputCallContext instanceof FakeCallContext)) { - throw new IllegalArgumentException( - "context must be an instance of FakeCallContext, but found " - + inputCallContext.getClass().getName()); - } - FakeCallContext fakeCallContext = (FakeCallContext) inputCallContext; - - FakeChannel newChannel = fakeCallContext.channel; - if (newChannel == null) { - newChannel = channel; - } - - Credentials newCallCredentials = fakeCallContext.credentials; - if (newCallCredentials == null) { - newCallCredentials = credentials; - } - - Duration newTimeout = fakeCallContext.timeout; - if (newTimeout == null) { - newTimeout = timeout; - } - - Duration newStreamWaitTimeout = fakeCallContext.streamWaitTimeout; - if (newStreamWaitTimeout == null) { - newStreamWaitTimeout = streamWaitTimeout; - } - - Duration newStreamIdleTimeout = fakeCallContext.streamIdleTimeout; - if (newStreamIdleTimeout == null) { - newStreamIdleTimeout = streamIdleTimeout; - } - - ApiTracer newTracer = fakeCallContext.tracer; - if (newTracer == null) { - newTracer = this.tracer; - } - - RetrySettings newRetrySettings = fakeCallContext.retrySettings; - if (newRetrySettings == null) { - newRetrySettings = this.retrySettings; - } - - Set newRetryableCodes = fakeCallContext.retryableCodes; - if (newRetryableCodes == null) { - newRetryableCodes = this.retryableCodes; - } - - ImmutableMap> newExtraHeaders = - Headers.mergeHeaders(extraHeaders, fakeCallContext.extraHeaders); - - ApiCallContextOptions newOptions = options.merge(fakeCallContext.options); - - return new FakeCallContext( - newCallCredentials, - newChannel, - newTimeout, - newStreamWaitTimeout, - newStreamIdleTimeout, - newExtraHeaders, - newOptions, - newTracer, - newRetrySettings, - newRetryableCodes); - } - - public RetrySettings getRetrySettings() { - return retrySettings; - } - - public FakeCallContext withRetrySettings(RetrySettings retrySettings) { - return new FakeCallContext( - this.credentials, - this.channel, - this.timeout, - this.streamWaitTimeout, - this.streamIdleTimeout, - this.extraHeaders, - this.options, - this.tracer, - retrySettings, - this.retryableCodes); - } - - public Set getRetryableCodes() { - return retryableCodes; - } - - public FakeCallContext withRetryableCodes(Set retryableCodes) { - return new FakeCallContext( - this.credentials, - this.channel, - this.timeout, - this.streamWaitTimeout, - this.streamIdleTimeout, - this.extraHeaders, - this.options, - this.tracer, - this.retrySettings, - retryableCodes); - } - - public Credentials getCredentials() { - return credentials; - } - - public FakeChannel getChannel() { - return channel; - } - - @Override - public Duration getTimeout() { - return timeout; - } - - @Nullable - @Override - public Duration getStreamWaitTimeout() { - return streamWaitTimeout; - } - - @Nullable - @Override - public Duration getStreamIdleTimeout() { - return streamIdleTimeout; - } - - @Override - public FakeCallContext withCredentials(Credentials credentials) { - return new FakeCallContext( - credentials, - this.channel, - this.timeout, - this.streamWaitTimeout, - this.streamIdleTimeout, - this.extraHeaders, - this.options, - this.tracer, - this.retrySettings, - this.retryableCodes); - } - - @Override - public FakeCallContext withTransportChannel(TransportChannel inputChannel) { - Preconditions.checkNotNull(inputChannel); - if (!(inputChannel instanceof FakeTransportChannel)) { - throw new IllegalArgumentException( - "Expected FakeTransportChannel, got " + inputChannel.getClass().getName()); - } - FakeTransportChannel transportChannel = (FakeTransportChannel) inputChannel; - return withChannel(transportChannel.getChannel()); - } - - public FakeCallContext withChannel(FakeChannel channel) { - return new FakeCallContext( - this.credentials, - channel, - this.timeout, - this.streamWaitTimeout, - this.streamIdleTimeout, - this.extraHeaders, - this.options, - this.tracer, - this.retrySettings, - this.retryableCodes); - } - - @Override - public FakeCallContext withTimeout(Duration timeout) { - // Default RetrySettings use 0 for RPC timeout. Treat that as disabled timeouts. - if (timeout != null && (timeout.isZero() || timeout.isNegative())) { - timeout = null; - } - - // Prevent expanding timeouts - if (timeout != null && this.timeout != null && this.timeout.compareTo(timeout) <= 0) { - return this; - } - - return new FakeCallContext( - this.credentials, - this.channel, - timeout, - this.streamWaitTimeout, - this.streamIdleTimeout, - this.extraHeaders, - this.options, - this.tracer, - this.retrySettings, - this.retryableCodes); - } - - @Override - public ApiCallContext withStreamWaitTimeout(@Nullable Duration streamWaitTimeout) { - return new FakeCallContext( - this.credentials, - this.channel, - this.timeout, - streamWaitTimeout, - this.streamIdleTimeout, - this.extraHeaders, - this.options, - this.tracer, - this.retrySettings, - this.retryableCodes); - } - - @Override - public ApiCallContext withStreamIdleTimeout(@Nullable Duration streamIdleTimeout) { - Preconditions.checkNotNull(streamIdleTimeout); - return new FakeCallContext( - this.credentials, - this.channel, - this.timeout, - this.streamWaitTimeout, - streamIdleTimeout, - this.extraHeaders, - this.options, - this.tracer, - this.retrySettings, - this.retryableCodes); - } - - @Override - public ApiCallContext withExtraHeaders(Map> extraHeaders) { - Preconditions.checkNotNull(extraHeaders); - ImmutableMap> newExtraHeaders = - Headers.mergeHeaders(this.extraHeaders, extraHeaders); - return new FakeCallContext( - credentials, - channel, - timeout, - streamWaitTimeout, - streamIdleTimeout, - newExtraHeaders, - this.options, - this.tracer, - this.retrySettings, - this.retryableCodes); - } - - @Override - public Map> getExtraHeaders() { - return this.extraHeaders; - } - - @Override - public ApiCallContext withOption(Key key, T value) { - Preconditions.checkNotNull(key); - ApiCallContextOptions newOptions = options.withOption(key, value); - return new FakeCallContext( - credentials, - channel, - timeout, - streamWaitTimeout, - streamIdleTimeout, - extraHeaders, - newOptions, - tracer, - retrySettings, - retryableCodes); - } - - @Override - public T getOption(Key key) { - Preconditions.checkNotNull(key); - return options.getOption(key); - } - - /** {@inheritDoc} */ - @Override - @Nonnull - public ApiTracer getTracer() { - if (tracer == null) { - return BaseApiTracer.getInstance(); - } - return tracer; - } - - /** {@inheritDoc} */ - @Override - public ApiCallContext withTracer(@Nonnull ApiTracer tracer) { - Preconditions.checkNotNull(tracer); - - return new FakeCallContext( - this.credentials, - this.channel, - this.timeout, - this.streamWaitTimeout, - this.streamIdleTimeout, - this.extraHeaders, - this.options, - tracer, - this.retrySettings, - this.retryableCodes); - } - - public static FakeCallContext create(ClientContext clientContext) { - return FakeCallContext.createDefault() - .withTransportChannel(clientContext.getTransportChannel()) - .withCredentials(clientContext.getCredentials()); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeCallableFactory.java b/gax/src/test/java/com/google/api/gax/rpc/testing/FakeCallableFactory.java deleted file mode 100644 index 017ffa561..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeCallableFactory.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc.testing; - -import com.google.api.core.InternalApi; -import com.google.api.gax.longrunning.OperationSnapshot; -import com.google.api.gax.rpc.BatchingCallSettings; -import com.google.api.gax.rpc.BidiStreamingCallable; -import com.google.api.gax.rpc.Callables; -import com.google.api.gax.rpc.ClientContext; -import com.google.api.gax.rpc.ClientStreamingCallable; -import com.google.api.gax.rpc.LongRunningClient; -import com.google.api.gax.rpc.OperationCallSettings; -import com.google.api.gax.rpc.OperationCallable; -import com.google.api.gax.rpc.PagedCallSettings; -import com.google.api.gax.rpc.ServerStreamingCallable; -import com.google.api.gax.rpc.StreamingCallSettings; -import com.google.api.gax.rpc.UnaryCallSettings; -import com.google.api.gax.rpc.UnaryCallable; - -@InternalApi("for testing") -public class FakeCallableFactory { - private FakeCallableFactory() {} - - private static UnaryCallable createBaseUnaryCallable( - UnaryCallable innerCallable, - UnaryCallSettings callSettings, - ClientContext clientContext) { - UnaryCallable callable = - new FakeExceptionCallable<>(innerCallable, callSettings.getRetryableCodes()); - callable = Callables.retrying(callable, callSettings, clientContext); - return callable; - } - - /** - * Create a callable object with grpc-specific functionality. Designed for use by generated code. - * - * @param innerCallable the callable that performs the work - * @param callSettings {@link UnaryCallSettings} to configure the method-level settings with. - * @param clientContext {@link ClientContext} to use to connect to the service. - * @return {@link UnaryCallable} callable object. - */ - public static UnaryCallable createUnaryCallable( - UnaryCallable innerCallable, - UnaryCallSettings callSettings, - ClientContext clientContext) { - UnaryCallable callable = - createBaseUnaryCallable(innerCallable, callSettings, clientContext); - return callable.withDefaultCallContext(FakeCallContext.create(clientContext)); - } - - /** - * Create a callable object that represents a simple call to a paged API method. Designed for use - * by generated code. - * - * @param innerCallable the callable that performs the work - * @param pagedCallSettings {@link PagedCallSettings} to configure the method-level settings with. - * @param clientContext {@link ClientContext} to use to connect to the service. - * @return {@link UnaryCallable} callable object. - */ - public static - UnaryCallable createUnpagedCallable( - UnaryCallable innerCallable, - PagedCallSettings pagedCallSettings, - ClientContext clientContext) { - UnaryCallable callable = - createBaseUnaryCallable(innerCallable, pagedCallSettings, clientContext); - return callable.withDefaultCallContext(FakeCallContext.create(clientContext)); - } - - /** - * Create a paged callable object that represents a paged API method. Designed for use by - * generated code. - * - * @param innerCallable the callable that performs the work - * @param pagedCallSettings {@link PagedCallSettings} to configure the paged settings with. - * @param clientContext {@link ClientContext} to use to connect to the service. - * @return {@link UnaryCallable} callable object. - */ - public static - UnaryCallable createPagedCallable( - UnaryCallable innerCallable, - PagedCallSettings pagedCallSettings, - ClientContext clientContext) { - UnaryCallable callable = - createBaseUnaryCallable(innerCallable, pagedCallSettings, clientContext); - UnaryCallable pagedCallable = - Callables.paged(callable, pagedCallSettings); - return pagedCallable.withDefaultCallContext(FakeCallContext.create(clientContext)); - } - - /** - * Create a callable object that represents a batching API method. Designed for use by generated - * code. - * - * @param innerCallable the callable that performs the work - * @param batchingCallSettings {@link BatchingCallSettings} to configure the batching related - * settings with. - * @param clientContext {@link ClientContext} to use to connect to the service. - * @return {@link UnaryCallable} callable object. - */ - public static UnaryCallable createBatchingCallable( - UnaryCallable innerCallable, - BatchingCallSettings batchingCallSettings, - ClientContext clientContext) { - UnaryCallable callable = - createBaseUnaryCallable(innerCallable, batchingCallSettings, clientContext); - callable = Callables.batching(callable, batchingCallSettings, clientContext); - return callable.withDefaultCallContext(FakeCallContext.create(clientContext)); - } - - /** - * Creates a callable object that represents a long-running operation. Designed for use by - * generated code. - * - * @param innerCallable the callable that starts the operation - * @param operationCallSettings {@link OperationCallSettings} to configure the method-level - * settings with. - * @param clientContext {@link ClientContext} to use to connect to the service. - * @param longRunningClient {@link LongRunningClient} to use to poll for updates on the Operation. - * @return {@link com.google.api.gax.rpc.OperationCallable} callable object. - */ - public static - OperationCallable createOperationCallable( - UnaryCallable innerCallable, - OperationCallSettings operationCallSettings, - ClientContext clientContext, - LongRunningClient longRunningClient) { - UnaryCallable initialCallable = - createBaseUnaryCallable( - innerCallable, operationCallSettings.getInitialCallSettings(), clientContext); - OperationCallable operationCallable = - Callables.longRunningOperation( - initialCallable, operationCallSettings, clientContext, longRunningClient); - return operationCallable.withDefaultCallContext(FakeCallContext.create(clientContext)); - } - - /** - * Create a bidirectional streaming callable object with grpc-specific functionality. Designed for - * use by generated code. - * - * @param innerCallable the callable that performs the work - * @param streamingCallSettings {@link StreamingCallSettings} to configure the method-level - * settings with. - * @param clientContext {@link ClientContext} to use to connect to the service. - * @return {@link BidiStreamingCallable} callable object. - */ - public static - BidiStreamingCallable createBidiStreamingCallable( - BidiStreamingCallable innerCallable, - StreamingCallSettings streamingCallSettings, - ClientContext clientContext) { - return innerCallable.withDefaultCallContext(FakeCallContext.create(clientContext)); - } - - /** - * Create a server-streaming callable with grpc-specific functionality. Designed for use by - * generated code. - * - * @param innerCallable the callable that performs the work - * @param streamingCallSettings {@link StreamingCallSettings} to configure the method-level - * settings with. - * @param clientContext {@link ClientContext} to use to connect to the service. - * @return {@link ServerStreamingCallable} callable object. - */ - public static - ServerStreamingCallable createServerStreamingCallable( - ServerStreamingCallable innerCallable, - StreamingCallSettings streamingCallSettings, - ClientContext clientContext) { - return innerCallable.withDefaultCallContext(FakeCallContext.create(clientContext)); - } - - /** - * Create a client-streaming callable object with grpc-specific functionality. Designed for use by - * generated code. - * - * @param innerCallable the callable that performs the work - * @param streamingCallSettings {@link StreamingCallSettings} to configure the method-level - * settings with. - * @param clientContext {@link ClientContext} to use to connect to the service. - * @return {@link ClientStreamingCallable} callable object. - */ - public static - ClientStreamingCallable createClientStreamingCallable( - ClientStreamingCallable innerCallable, - StreamingCallSettings streamingCallSettings, - ClientContext clientContext) { - return innerCallable.withDefaultCallContext(FakeCallContext.create(clientContext)); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeChannel.java b/gax/src/test/java/com/google/api/gax/rpc/testing/FakeChannel.java deleted file mode 100644 index b725da363..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeChannel.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc.testing; - -import com.google.api.core.InternalApi; - -@InternalApi("for testing") -public class FakeChannel {} diff --git a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeClientSettings.java b/gax/src/test/java/com/google/api/gax/rpc/testing/FakeClientSettings.java deleted file mode 100644 index 7bd913993..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeClientSettings.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc.testing; - -import com.google.api.core.InternalApi; -import com.google.api.gax.rpc.ClientContext; -import com.google.api.gax.rpc.ClientSettings; -import com.google.api.gax.rpc.StubSettings; -import java.io.IOException; - -@InternalApi("for testing") -public class FakeClientSettings extends ClientSettings { - - private FakeClientSettings(Builder builder) throws IOException { - super(builder); - } - - @Override - public ClientSettings.Builder toBuilder() { - return new Builder(this); - } - - public static class Builder extends ClientSettings.Builder { - - public Builder(ClientSettings settings) { - super(settings); - } - - public Builder(ClientContext clientContext) { - super(new FakeStubSettings.Builder(clientContext)); - } - - public Builder(StubSettings stubSettings) { - super(stubSettings.toBuilder()); - } - - public Builder() { - super(new FakeStubSettings.Builder()); - } - - @Override - public FakeClientSettings build() throws IOException { - return new FakeClientSettings(this); - } - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeExceptionCallable.java b/gax/src/test/java/com/google/api/gax/rpc/testing/FakeExceptionCallable.java deleted file mode 100644 index 89a8c9128..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeExceptionCallable.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc.testing; - -import static com.google.common.util.concurrent.MoreExecutors.directExecutor; - -import com.google.api.core.AbstractApiFuture; -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutureCallback; -import com.google.api.core.ApiFutures; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.ApiException; -import com.google.api.gax.rpc.ApiExceptionFactory; -import com.google.api.gax.rpc.StatusCode; -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableSet; -import java.util.Set; -import java.util.concurrent.CancellationException; - -/** - * Transforms all {@code Throwable}s thrown during a call into an instance of {@link ApiException}. - * - *

Package-private for internal use. - */ -class FakeExceptionCallable extends UnaryCallable { - private final UnaryCallable callable; - private final ImmutableSet retryableCodes; - - FakeExceptionCallable(UnaryCallable callable, Set retryableCodes) { - this.callable = Preconditions.checkNotNull(callable); - this.retryableCodes = ImmutableSet.copyOf(retryableCodes); - } - - @Override - public ApiFuture futureCall(RequestT request, ApiCallContext inputContext) { - FakeCallContext context = FakeCallContext.createDefault().nullToSelf(inputContext); - ApiFuture innerCallFuture = callable.futureCall(request, context); - ExceptionTransformingFuture transformingFuture = - new ExceptionTransformingFuture(innerCallFuture); - ApiFutures.addCallback(innerCallFuture, transformingFuture, directExecutor()); - return transformingFuture; - } - - private class ExceptionTransformingFuture extends AbstractApiFuture - implements ApiFutureCallback { - private ApiFuture innerCallFuture; - private volatile boolean cancelled = false; - - public ExceptionTransformingFuture(ApiFuture innerCallFuture) { - this.innerCallFuture = innerCallFuture; - } - - @Override - protected void interruptTask() { - cancelled = true; - innerCallFuture.cancel(true); - } - - @Override - public void onSuccess(ResponseT r) { - super.set(r); - } - - @Override - public void onFailure(Throwable throwable) { - StatusCode.Code statusCode = StatusCode.Code.UNKNOWN; - boolean canRetry = false; - boolean rethrow = false; - if (throwable instanceof FakeStatusException) { - FakeStatusException e = (FakeStatusException) throwable; - statusCode = e.getStatusCode().getCode(); - canRetry = retryableCodes.contains(e.getStatusCode().getCode()); - } else if (throwable instanceof CancellationException && cancelled) { - // this just circled around, so ignore. - return; - } else if (throwable instanceof ApiException) { - rethrow = true; - } else { - // Do not retry on unknown throwable, even when UNKNOWN is in retryableCodes - statusCode = StatusCode.Code.UNKNOWN; - canRetry = false; - } - if (rethrow) { - super.setException(throwable); - } else { - super.setException( - ApiExceptionFactory.createException( - throwable, FakeStatusCode.of(statusCode), canRetry)); - } - } - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeMtlsProvider.java b/gax/src/test/java/com/google/api/gax/rpc/testing/FakeMtlsProvider.java deleted file mode 100644 index e5f5c3a91..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeMtlsProvider.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.gax.rpc.testing; - -import com.google.api.client.util.SecurityUtils; -import com.google.api.core.InternalApi; -import com.google.api.gax.rpc.mtls.MtlsProvider; -import java.io.IOException; -import java.io.InputStream; -import java.security.GeneralSecurityException; -import java.security.KeyStore; - -@InternalApi("for testing") -public class FakeMtlsProvider extends MtlsProvider { - private boolean useClientCertificate; - private MtlsEndpointUsagePolicy mtlsEndpointUsagePolicy; - private KeyStore keyStore; - private boolean throwExceptionForGetKeyStore; - - public FakeMtlsProvider( - boolean useClientCertificate, - MtlsEndpointUsagePolicy mtlsEndpointUsagePolicy, - KeyStore keystore, - String keyStorePassword, - boolean throwExceptionForGetKeyStore) { - super(); - this.useClientCertificate = useClientCertificate; - this.mtlsEndpointUsagePolicy = mtlsEndpointUsagePolicy; - this.keyStore = keystore; - this.throwExceptionForGetKeyStore = throwExceptionForGetKeyStore; - } - - @Override - public boolean useMtlsClientCertificate() { - return useClientCertificate; - } - - @Override - public MtlsEndpointUsagePolicy getMtlsEndpointUsagePolicy() { - return mtlsEndpointUsagePolicy; - } - - @Override - public KeyStore getKeyStore() throws IOException { - if (throwExceptionForGetKeyStore) { - throw new IOException("getKeyStore throws exception"); - } - return keyStore; - } - - public static KeyStore createTestMtlsKeyStore() throws IOException { - try { - InputStream certAndKey = - FakeMtlsProvider.class - .getClassLoader() - .getResourceAsStream("com/google/api/gax/rpc/mtls/mtlsCertAndKey.pem"); - return SecurityUtils.createMtlsKeyStore(certAndKey); - } catch (GeneralSecurityException e) { - throw new IOException("Failed to create key store", e); - } - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeOperationApi.java b/gax/src/test/java/com/google/api/gax/rpc/testing/FakeOperationApi.java deleted file mode 100644 index 7cfb80b12..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeOperationApi.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc.testing; - -import com.google.api.core.AbstractApiFuture; -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.api.core.InternalApi; -import com.google.api.gax.longrunning.OperationFuture; -import com.google.api.gax.longrunning.OperationSnapshot; -import com.google.api.gax.retrying.RetryingFuture; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.OperationCallable; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ExecutionException; - -@InternalApi("for testing") -public class FakeOperationApi { - public static class OperationStashCallable extends OperationCallable { - - private ApiCallContext context; - private Integer request; - private Map operations = new HashMap<>(); - private ApiCallContext resumeContext; - private ApiCallContext cancelContext; - private boolean wasCancelCalled = false; - - @Override - public OperationFuture futureCall(Integer request, ApiCallContext context) { - this.request = request; - this.context = context; - String opName = "opName-" + request; - FakeOperationFuture opFuture = new FakeOperationFuture(request.toString(), opName); - operations.put(opName, opFuture); - return opFuture; - } - - @Override - public OperationFuture resumeFutureCall( - String operationName, ApiCallContext context) { - if (!operations.containsKey(operationName)) { - throw new IllegalArgumentException("Operation not found: " + operationName); - } - resumeContext = context; - return operations.get(operationName); - } - - @Override - public ApiFuture cancel(String operationName, ApiCallContext context) { - wasCancelCalled = true; - cancelContext = context; - return ApiFutures.immediateFuture(null); - } - - public ApiCallContext getContext() { - return context; - } - - public Integer getRequest() { - return request; - } - - public ApiCallContext getResumeContext() { - return resumeContext; - } - - public boolean wasCancelCalled() { - return wasCancelCalled; - } - - public ApiCallContext getCancelContext() { - return cancelContext; - } - } - - public static class FakeOperationFuture extends AbstractApiFuture - implements OperationFuture { - - private final String result; - private final String operationName; - - public FakeOperationFuture(String result, String operationName) { - this.result = result; - this.operationName = operationName; - } - - @Override - public String get() { - return result; - } - - @Override - public String getName() throws InterruptedException, ExecutionException { - return operationName; - } - - @Override - public ApiFuture getInitialFuture() { - throw new UnsupportedOperationException("getInitialFuture() not implemented"); - } - - @Override - public RetryingFuture getPollingFuture() { - throw new UnsupportedOperationException("getPollingFuture() not implemented"); - } - - @Override - public ApiFuture peekMetadata() { - return null; - } - - @Override - public ApiFuture getMetadata() { - return null; - } - } - - public static class FakeOperation {} -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeOperationSnapshot.java b/gax/src/test/java/com/google/api/gax/rpc/testing/FakeOperationSnapshot.java deleted file mode 100644 index 59db2a800..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeOperationSnapshot.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc.testing; - -import com.google.api.core.InternalApi; -import com.google.api.gax.longrunning.OperationSnapshot; -import com.google.api.gax.rpc.StatusCode; -import com.google.auto.value.AutoValue; -import javax.annotation.Nullable; - -@InternalApi("for testing") -@AutoValue -public abstract class FakeOperationSnapshot implements OperationSnapshot { - - @Override - public abstract String getName(); - - @Override - @Nullable - public abstract Object getMetadata(); - - @Override - public abstract boolean isDone(); - - @Override - @Nullable - public abstract Object getResponse(); - - @Override - public abstract StatusCode getErrorCode(); - - @Override - @Nullable - public abstract String getErrorMessage(); - - public static Builder newBuilder() { - return new AutoValue_FakeOperationSnapshot.Builder(); - } - - @AutoValue.Builder - public abstract static class Builder { - public abstract Builder setName(String value); - - public abstract Builder setMetadata(Object value); - - public abstract Builder setDone(boolean value); - - public abstract Builder setResponse(Object value); - - public abstract Builder setErrorCode(StatusCode value); - - public abstract Builder setErrorMessage(String value); - - public abstract FakeOperationSnapshot build(); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/testing/FakePagedApi.java b/gax/src/test/java/com/google/api/gax/rpc/testing/FakePagedApi.java deleted file mode 100644 index 6d4589d18..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/testing/FakePagedApi.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc.testing; - -import static com.google.common.util.concurrent.MoreExecutors.directExecutor; - -import com.google.api.core.ApiFunction; -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.api.core.InternalApi; -import com.google.api.gax.paging.AbstractFixedSizeCollection; -import com.google.api.gax.paging.AbstractPage; -import com.google.api.gax.paging.AbstractPagedListResponse; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.PageContext; -import com.google.api.gax.rpc.PagedListDescriptor; -import com.google.api.gax.rpc.PagedListResponseFactory; -import com.google.api.gax.rpc.UnaryCallable; -import java.util.List; - -@InternalApi("for testing") -public class FakePagedApi { - public static class PagedStashCallable extends UnaryCallable> { - - ApiCallContext context; - Integer request; - List> results; - int currentResultToReturn = 0; - - public PagedStashCallable(List> results) { - this.results = results; - } - - @Override - public ApiFuture> futureCall(Integer request, ApiCallContext context) { - this.request = request; - this.context = context; - List result = results.get(currentResultToReturn); - currentResultToReturn += 1; - return ApiFutures.immediateFuture(result); - } - } - - private static class StashPagedListDescriptor - implements PagedListDescriptor, Integer> { - @Override - public String emptyToken() { - return ""; - } - - @Override - public Integer injectToken(Integer payload, String token) { - return Integer.parseInt(token); - } - - @Override - public String extractNextToken(List payload) { - int size = payload.size(); - return size == 0 ? emptyToken() : payload.get(size - 1).toString(); - } - - @Override - public Iterable extractResources(List payload) { - return payload; - } - - @Override - public Integer injectPageSize(Integer payload, int pageSize) { - return payload; - } - - @Override - public Integer extractPageSize(Integer payload) { - return 3; - } - } - - public static class ListIntegersPagedResponse - extends AbstractPagedListResponse< - Integer, List, Integer, ListIntegersPage, ListIntegersSizedPage> { - - protected ListIntegersPagedResponse(ListIntegersPage page) { - super(page, ListIntegersSizedPage.createEmptyCollection()); - } - - public static ListIntegersPagedResponse create( - PageContext, Integer> context, List response) { - ListIntegersPage page = new ListIntegersPage(context, response); - return new ListIntegersPagedResponse(page); - } - - public static ApiFuture create( - PageContext, Integer> context, - ApiFuture> futureResponse) { - ApiFuture futurePage = - new ListIntegersPage(null, null).createPageAsync(context, futureResponse); - return ApiFutures.transform( - futurePage, - new ApiFunction() { - @Override - public ListIntegersPagedResponse apply(ListIntegersPage input) { - return new ListIntegersPagedResponse(input); - } - }, - directExecutor()); - } - } - - private static class ListIntegersPage - extends AbstractPage, Integer, ListIntegersPage> { - - public ListIntegersPage( - PageContext, Integer> context, List response) { - super(context, response); - } - - @Override - protected ListIntegersPage createPage( - PageContext, Integer> context, List response) { - return new ListIntegersPage(context, response); - } - } - - private static class ListIntegersSizedPage - extends AbstractFixedSizeCollection< - Integer, List, Integer, ListIntegersPage, ListIntegersSizedPage> { - - private ListIntegersSizedPage(List pages, int collectionSize) { - super(pages, collectionSize); - } - - private static ListIntegersSizedPage createEmptyCollection() { - return new ListIntegersSizedPage(null, 0); - } - - @Override - protected ListIntegersSizedPage createCollection( - List pages, int collectionSize) { - return new ListIntegersSizedPage(pages, collectionSize); - } - } - - public static class ListIntegersPagedResponseFactory - implements PagedListResponseFactory, ListIntegersPagedResponse> { - - private final StashPagedListDescriptor streamingDescriptor = new StashPagedListDescriptor(); - - @Override - public ApiFuture getFuturePagedResponse( - UnaryCallable> callable, - Integer request, - ApiCallContext context, - ApiFuture> futureResponse) { - PageContext, Integer> pageContext = - PageContext.create(callable, streamingDescriptor, request, context); - return ListIntegersPagedResponse.create(pageContext, futureResponse); - } - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeSimpleApi.java b/gax/src/test/java/com/google/api/gax/rpc/testing/FakeSimpleApi.java deleted file mode 100644 index fce6002b6..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeSimpleApi.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc.testing; - -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.api.core.InternalApi; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.UnaryCallable; - -@InternalApi("for testing") -public class FakeSimpleApi { - public static class StashCallable - extends UnaryCallable { - - private ApiCallContext context; - private RequestT request; - private ResponseT result; - - public StashCallable(ResponseT result) { - this.result = result; - } - - @Override - public ApiFuture futureCall(RequestT request, ApiCallContext context) { - this.request = request; - this.context = context; - return ApiFutures.immediateFuture(result); - } - - public ApiCallContext getContext() { - return context; - } - - public RequestT getRequest() { - return request; - } - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeStatusCode.java b/gax/src/test/java/com/google/api/gax/rpc/testing/FakeStatusCode.java deleted file mode 100644 index 5deb20826..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeStatusCode.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc.testing; - -import com.google.api.core.InternalApi; -import com.google.api.gax.rpc.StatusCode; - -@InternalApi("for testing") -public class FakeStatusCode implements StatusCode { - private final Code code; - - public FakeStatusCode(Code code) { - this.code = code; - } - - @Override - public Code getCode() { - return code; - } - - @Override - public Code getTransportCode() { - return getCode(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - FakeStatusCode that = (FakeStatusCode) o; - - return code == that.code; - } - - @Override - public int hashCode() { - return code != null ? code.hashCode() : 0; - } - - public static FakeStatusCode of(Code code) { - return new FakeStatusCode(code); - } - - @Override - public String toString() { - return code.toString(); - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeStatusException.java b/gax/src/test/java/com/google/api/gax/rpc/testing/FakeStatusException.java deleted file mode 100644 index 4846b299a..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeStatusException.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc.testing; - -import com.google.api.core.InternalApi; - -@InternalApi("for testing") -public class FakeStatusException extends Exception { - private final FakeStatusCode fakeStatusCode; - - public static String formatCode(FakeStatusCode.Code code) { - if (code == null) { - return ""; - } else { - return code.toString(); - } - } - - public static String formatCodeAsPrefix(FakeStatusCode.Code code) { - if (code == null) { - return ""; - } else { - return code + ": "; - } - } - - public FakeStatusException(FakeStatusCode.Code statusCode) { - super(formatCode(statusCode)); - fakeStatusCode = FakeStatusCode.of(statusCode); - } - - public FakeStatusException(Throwable cause, FakeStatusCode.Code statusCode) { - super(formatCode(statusCode), cause); - fakeStatusCode = FakeStatusCode.of(statusCode); - } - - public FakeStatusException(String message, Throwable cause, FakeStatusCode.Code statusCode) { - super(formatCodeAsPrefix(statusCode) + message, cause); - fakeStatusCode = FakeStatusCode.of(statusCode); - } - - /** - * Returns the status code of the underlying grpc exception. In cases where the underlying - * exception is not of type StatusException or StatusRuntimeException, the status code will be - * Status.Code.UNKNOWN. For more information about status codes see - * https://github.com/grpc/grpc-java/blob/master/api/src/main/java/io/grpc/Status.java - */ - public FakeStatusCode getStatusCode() { - return fakeStatusCode; - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeStreamingApi.java b/gax/src/test/java/com/google/api/gax/rpc/testing/FakeStreamingApi.java deleted file mode 100644 index b438c641b..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeStreamingApi.java +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc.testing; - -import com.google.api.core.InternalApi; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.ApiExceptionFactory; -import com.google.api.gax.rpc.ApiStreamObserver; -import com.google.api.gax.rpc.BidiStreamingCallable; -import com.google.api.gax.rpc.ClientStream; -import com.google.api.gax.rpc.ClientStreamReadyObserver; -import com.google.api.gax.rpc.ClientStreamingCallable; -import com.google.api.gax.rpc.ResponseObserver; -import com.google.api.gax.rpc.ServerStreamingCallable; -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.api.gax.rpc.StreamController; -import com.google.common.base.Preconditions; -import com.google.common.collect.Queues; -import java.util.ArrayList; -import java.util.List; -import java.util.Queue; -import java.util.concurrent.CancellationException; - -@InternalApi("for testing") -public class FakeStreamingApi { - - public static class BidiStreamingStashCallable - extends BidiStreamingCallable { - private ApiCallContext context; - private ResponseObserver responseObserver; - private AccumulatingClientStream clientStream; - private List responseList; - - public BidiStreamingStashCallable() { - responseList = new ArrayList<>(); - } - - public BidiStreamingStashCallable(List responseList) { - this.responseList = responseList; - } - - @Override - public ClientStream internalCall( - ResponseObserver responseObserver, - ClientStreamReadyObserver onReady, - ApiCallContext context) { - Preconditions.checkNotNull(responseObserver); - this.responseObserver = responseObserver; - this.context = context; - this.clientStream = new AccumulatingClientStream<>(); - - StreamControllerStash controller = - new StreamControllerStash<>(responseList, responseObserver); - controller.startBidi(); - onReady.onReady(clientStream); - - return clientStream; - } - - public ApiCallContext getContext() { - return context; - } - - public ResponseObserver getActualObserver() { - return responseObserver; - } - - public List getActualRequests() { - return clientStream.getValues(); - } - - private void sendResponses() { - for (ResponseT response : responseList) { - responseObserver.onResponse(response); - } - responseObserver.onComplete(); - } - - private class AccumulatingClientStream implements ClientStream { - private List requestList = new ArrayList<>(); - private Throwable error; - private boolean completed = false; - - @Override - public void send(T value) { - requestList.add(value); - } - - @Override - public void closeSendWithError(Throwable t) { - error = t; - } - - @Override - public void closeSend() { - completed = true; - } - - @Override - public boolean isSendReady() { - return true; - } - - public List getValues() { - if (!completed) { - throw new IllegalStateException("Stream not completed."); - } - if (error != null) { - throw ApiExceptionFactory.createException(error, FakeStatusCode.of(Code.UNKNOWN), false); - } - return requestList; - } - } - } - - public static class ServerStreamingStashCallable - extends ServerStreamingCallable { - private ApiCallContext context; - private ResponseObserver actualObserver; - private RequestT actualRequest; - private List responseList; - - public ServerStreamingStashCallable() { - responseList = new ArrayList<>(); - } - - public ServerStreamingStashCallable(List responseList) { - this.responseList = responseList; - } - - @Override - public void call( - RequestT request, ResponseObserver responseObserver, ApiCallContext context) { - Preconditions.checkNotNull(request); - Preconditions.checkNotNull(responseObserver); - this.actualRequest = request; - this.actualObserver = responseObserver; - this.context = context; - - StreamControllerStash controller = - new StreamControllerStash<>(responseList, responseObserver); - controller.start(); - } - - public ApiCallContext getContext() { - return context; - } - - public ResponseObserver getActualObserver() { - return actualObserver; - } - - public RequestT getActualRequest() { - return actualRequest; - } - } - - // Minimal implementation of back pressure aware stream controller. Not threadsafe - private static class StreamControllerStash implements StreamController { - final ResponseObserver observer; - final Queue queue; - boolean autoFlowControl = true; - long numPending; - Throwable error; - boolean delivering, closed; - - public StreamControllerStash( - List responseList, ResponseObserver observer) { - this.observer = observer; - this.queue = Queues.newArrayDeque(responseList); - } - - public void start() { - observer.onStart(this); - if (autoFlowControl) { - numPending = Integer.MAX_VALUE; - } - deliver(); - } - - public void startBidi() { - start(); - } - - @Override - public void disableAutoInboundFlowControl() { - autoFlowControl = false; - } - - @Override - public void request(int count) { - numPending += count; - deliver(); - } - - @Override - public void cancel() { - error = new CancellationException("User cancelled stream"); - deliver(); - } - - private void deliver() { - if (delivering || closed) return; - delivering = true; - - try { - while (error == null && numPending > 0 && !queue.isEmpty()) { - numPending--; - observer.onResponse(queue.poll()); - } - - if (error != null || queue.isEmpty()) { - if (error != null) { - observer.onError(error); - } else { - observer.onComplete(); - } - closed = true; - } - } finally { - delivering = false; - } - } - } - - public static class ClientStreamingStashCallable - extends ClientStreamingCallable { - private ApiCallContext context; - private ApiStreamObserver responseObserver; - private AccumulatingStreamObserver requestObserver; - private ResponseT response; - - public ClientStreamingStashCallable() {} - - public ClientStreamingStashCallable(ResponseT response) { - this.response = response; - } - - @Override - public ApiStreamObserver clientStreamingCall( - ApiStreamObserver responseObserver, ApiCallContext context) { - Preconditions.checkNotNull(responseObserver); - this.responseObserver = responseObserver; - this.context = context; - this.requestObserver = new AccumulatingStreamObserver<>(); - return requestObserver; - } - - public ApiCallContext getContext() { - return context; - } - - public ApiStreamObserver getActualObserver() { - return responseObserver; - } - - public List getActualRequests() { - return requestObserver.getValues(); - } - - private void sendResponses() { - responseObserver.onNext(response); - responseObserver.onCompleted(); - } - - private class AccumulatingStreamObserver implements ApiStreamObserver { - private List requestList = new ArrayList<>(); - private Throwable error; - private boolean completed = false; - - @Override - public void onNext(T value) { - requestList.add(value); - } - - @Override - public void onError(Throwable t) { - error = t; - } - - @Override - public void onCompleted() { - completed = true; - ClientStreamingStashCallable.this.sendResponses(); - } - - public List getValues() { - if (!completed) { - throw new IllegalStateException("Stream not completed."); - } - if (error != null) { - throw ApiExceptionFactory.createException(error, FakeStatusCode.of(Code.UNKNOWN), false); - } - return requestList; - } - } - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeStubSettings.java b/gax/src/test/java/com/google/api/gax/rpc/testing/FakeStubSettings.java deleted file mode 100644 index 2c41d75a4..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeStubSettings.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc.testing; - -import com.google.api.core.InternalApi; -import com.google.api.gax.rpc.ClientContext; -import com.google.api.gax.rpc.StubSettings; -import java.io.IOException; - -@InternalApi("for testing") -public class FakeStubSettings extends StubSettings { - - private FakeStubSettings(Builder builder) throws IOException { - super(builder); - } - - @Override - public StubSettings.Builder toBuilder() { - return new Builder(this); - } - - public static class Builder extends StubSettings.Builder { - - public Builder(ClientContext clientContext) { - super(clientContext); - } - - public Builder(StubSettings stubSettings) { - super(stubSettings); - } - - public Builder() { - super((ClientContext) null); - } - - @Override - public com.google.api.gax.rpc.testing.FakeStubSettings build() throws IOException { - return new com.google.api.gax.rpc.testing.FakeStubSettings(this); - } - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeTransportChannel.java b/gax/src/test/java/com/google/api/gax/rpc/testing/FakeTransportChannel.java deleted file mode 100644 index 0d4abac8f..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/testing/FakeTransportChannel.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc.testing; - -import com.google.api.core.InternalApi; -import com.google.api.gax.rpc.TransportChannel; -import java.util.Map; -import java.util.concurrent.Executor; -import java.util.concurrent.TimeUnit; - -@InternalApi("for testing") -public class FakeTransportChannel implements TransportChannel { - private final FakeChannel channel; - private volatile boolean isShutdown = false; - private volatile Map headers; - private volatile Executor executor; - - private FakeTransportChannel(FakeChannel channel) { - this.channel = channel; - } - - public static FakeTransportChannel create(FakeChannel channel) { - return new FakeTransportChannel(channel); - } - - /** The name of the Fake transport. */ - public static String getFakeTransportName() { - return "fake"; - } - - @Override - public String getTransportName() { - return getFakeTransportName(); - } - - @Override - public FakeCallContext getEmptyCallContext() { - return FakeCallContext.createDefault(); - } - - @Override - public void shutdown() { - isShutdown = true; - } - - @Override - public boolean isShutdown() { - return isShutdown; - } - - @Override - public boolean isTerminated() { - return isShutdown; - } - - @Override - public void shutdownNow() { - isShutdown = true; - } - - @Override - public boolean awaitTermination(long duration, TimeUnit unit) throws InterruptedException { - return false; - } - - @Override - public void close() {} - - public FakeChannel getChannel() { - return channel; - } - - public void setHeaders(Map headers) { - this.headers = headers; - } - - public Map getHeaders() { - return this.headers; - } - - public void setExecutor(Executor executor) { - this.executor = executor; - } - - public Executor getExecutor() { - return executor; - } -} diff --git a/gax/src/test/java/com/google/api/gax/rpc/testing/MockStreamingApi.java b/gax/src/test/java/com/google/api/gax/rpc/testing/MockStreamingApi.java deleted file mode 100644 index 4daab63e9..000000000 --- a/gax/src/test/java/com/google/api/gax/rpc/testing/MockStreamingApi.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.rpc.testing; - -import com.google.api.core.SettableApiFuture; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.ResponseObserver; -import com.google.api.gax.rpc.ServerStreamingCallable; -import com.google.api.gax.rpc.StateCheckingResponseObserver; -import com.google.api.gax.rpc.StreamController; -import com.google.common.collect.Queues; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; - -public class MockStreamingApi { - public static class MockServerStreamingCallable - extends ServerStreamingCallable { - private final BlockingQueue> calls = - Queues.newLinkedBlockingDeque(); - - @Override - public void call( - RequestT request, ResponseObserver responseObserver, ApiCallContext context) { - MockStreamController controller = new MockStreamController<>(responseObserver); - calls.add(new MockServerStreamingCall<>(request, controller)); - responseObserver.onStart(controller); - } - - public MockServerStreamingCall popLastCall() { - try { - return calls.poll(1, TimeUnit.SECONDS); - } catch (Throwable e) { - return null; - } - } - } - - public static class MockServerStreamingCall { - private final RequestT request; - private final MockStreamController controller; - - public MockServerStreamingCall(RequestT request, MockStreamController controller) { - this.request = request; - this.controller = controller; - } - - public RequestT getRequest() { - return request; - } - - public MockStreamController getController() { - return controller; - } - } - - public static class MockStreamController implements StreamController { - private final ResponseObserver downstreamObserver; - private final BlockingQueue pulls = Queues.newLinkedBlockingQueue(); - private SettableApiFuture cancelFuture = SettableApiFuture.create(); - private boolean autoFlowControl = true; - - public MockStreamController(ResponseObserver downstreamObserver) { - this.downstreamObserver = downstreamObserver; - } - - @Override - public void disableAutoInboundFlowControl() { - autoFlowControl = false; - } - - @Override - public void request(int count) { - pulls.add(count); - } - - @Override - public void cancel() { - cancelFuture.set(true); - } - - public ResponseObserver getObserver() { - return downstreamObserver; - } - - public boolean isAutoFlowControlEnabled() { - return autoFlowControl; - } - - public boolean isCancelled() { - return cancelFuture.isDone(); - } - - public void waitForCancel() { - try { - cancelFuture.get(1, TimeUnit.SECONDS); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - public int popLastPull() { - Integer results; - - try { - results = pulls.poll(1, TimeUnit.SECONDS); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new RuntimeException(e); - } - - if (results == null) { - return 0; - } else { - return results; - } - } - } - - public static class MockResponseObserver extends StateCheckingResponseObserver { - private final boolean autoFlowControl; - private StreamController controller; - private final BlockingQueue responses = Queues.newLinkedBlockingDeque(); - private final SettableApiFuture done = SettableApiFuture.create(); - - public MockResponseObserver(boolean autoFlowControl) { - this.autoFlowControl = autoFlowControl; - } - - @Override - protected void onStartImpl(StreamController controller) { - this.controller = controller; - if (!autoFlowControl) { - controller.disableAutoInboundFlowControl(); - } - } - - @Override - protected void onResponseImpl(T response) { - responses.add(response); - } - - @Override - protected void onErrorImpl(Throwable t) { - done.setException(t); - } - - @Override - protected void onCompleteImpl() { - done.set(null); - } - - public StreamController getController() { - return controller; - } - - public T popNextResponse() { - try { - return responses.poll(1, TimeUnit.SECONDS); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new RuntimeException(e); - } - } - - public Throwable getFinalError() { - try { - done.get(1, TimeUnit.SECONDS); - return null; - } catch (ExecutionException e) { - return e.getCause(); - } catch (Throwable t) { - return t; - } - } - - public boolean isDone() { - return done.isDone(); - } - } -} diff --git a/gax/src/test/java/com/google/api/gax/tracing/OpencensusTracerFactoryTest.java b/gax/src/test/java/com/google/api/gax/tracing/OpencensusTracerFactoryTest.java deleted file mode 100644 index 457492acf..000000000 --- a/gax/src/test/java/com/google/api/gax/tracing/OpencensusTracerFactoryTest.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.tracing; - -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.nullable; -import static org.mockito.ArgumentMatchers.same; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.api.gax.tracing.ApiTracerFactory.OperationType; -import com.google.common.collect.ImmutableMap; -import io.grpc.Context; -import io.opencensus.trace.AttributeValue; -import io.opencensus.trace.Span; -import io.opencensus.trace.SpanBuilder; -import io.opencensus.trace.Tracer; -import io.opencensus.trace.unsafe.ContextUtils; -import java.util.Map; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; - -@RunWith(JUnit4.class) -public class OpencensusTracerFactoryTest { - @Rule public final MockitoRule mockitoRule = MockitoJUnit.rule(); - @Mock private Tracer internalTracer; - @Mock private SpanBuilder spanBuilder; - @Mock private Span span; - private final Map defaultSpanAttributes = ImmutableMap.of(); - - @Before - public void setUp() { - when(internalTracer.spanBuilderWithExplicitParent(anyString(), nullable(Span.class))) - .thenReturn(spanBuilder); - - when(spanBuilder.setRecordEvents(true)).thenReturn(spanBuilder); - - when(spanBuilder.startSpan()).thenReturn(span); - } - - @Test - public void testSpanNamePassthrough() { - OpencensusTracerFactory factory = - new OpencensusTracerFactory(internalTracer, ImmutableMap.of()); - - factory.newTracer( - BaseApiTracer.getInstance(), SpanName.of("FakeClient", "FakeMethod"), OperationType.Unary); - - verify(internalTracer) - .spanBuilderWithExplicitParent(eq("FakeClient.FakeMethod"), nullable(Span.class)); - } - - @Test - public void testImplicitParentSpan() { - OpencensusTracerFactory factory = - new OpencensusTracerFactory(internalTracer, defaultSpanAttributes); - - Span parentSpan = mock(Span.class); - Context origContext = ContextUtils.withValue(Context.current(), parentSpan).attach(); - - try { - factory.newTracer( - BaseApiTracer.getInstance(), - SpanName.of("FakeClient", "FakeMethod"), - OperationType.Unary); - } finally { - Context.current().detach(origContext); - } - - verify(internalTracer).spanBuilderWithExplicitParent(anyString(), same(parentSpan)); - } - - @Test - public void testExplicitParent() { - OpencensusTracerFactory factory = - new OpencensusTracerFactory(internalTracer, defaultSpanAttributes); - - Span parentSpan = mock(Span.class); - OpencensusTracer parentTracer = - new OpencensusTracer(internalTracer, parentSpan, OperationType.Unary); - - factory.newTracer(parentTracer, SpanName.of("FakeClient", "FakeMethod"), OperationType.Unary); - - verify(internalTracer).spanBuilderWithExplicitParent(anyString(), same(parentSpan)); - } - - @Test - public void testExplicitParentOverridesImplicit() { - OpencensusTracerFactory factory = - new OpencensusTracerFactory(internalTracer, defaultSpanAttributes); - - Span parentSpan = mock(Span.class); - OpencensusTracer parentTracer = - new OpencensusTracer(internalTracer, parentSpan, OperationType.Unary); - - Context origContext = ContextUtils.withValue(Context.current(), parentSpan).attach(); - - try { - factory.newTracer(parentTracer, SpanName.of("FakeClient", "FakeMethod"), OperationType.Unary); - } finally { - Context.current().detach(origContext); - } - - verify(internalTracer).spanBuilderWithExplicitParent(anyString(), same(parentSpan)); - } - - @Test - public void testSpanAttributes() { - OpencensusTracerFactory factory = - new OpencensusTracerFactory(internalTracer, ImmutableMap.of("gax.version", "1.2.3")); - - factory.newTracer( - BaseApiTracer.getInstance(), SpanName.of("FakeClient", "FakeMethod"), OperationType.Unary); - - verify(span, times(1)) - .putAttributes( - ImmutableMap.of("gax.version", AttributeValue.stringAttributeValue("1.2.3"))); - } -} diff --git a/gax/src/test/java/com/google/api/gax/tracing/OpencensusTracerTest.java b/gax/src/test/java/com/google/api/gax/tracing/OpencensusTracerTest.java deleted file mode 100644 index 8cf6f82fa..000000000 --- a/gax/src/test/java/com/google/api/gax/tracing/OpencensusTracerTest.java +++ /dev/null @@ -1,383 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.tracing; - -import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; - -import com.google.api.gax.retrying.ServerStreamingAttemptException; -import com.google.api.gax.rpc.ApiException; -import com.google.api.gax.rpc.DeadlineExceededException; -import com.google.api.gax.rpc.NotFoundException; -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.api.gax.rpc.testing.FakeStatusCode; -import com.google.api.gax.tracing.ApiTracerFactory.OperationType; -import com.google.common.collect.ImmutableMap; -import io.opencensus.trace.AttributeValue; -import io.opencensus.trace.EndSpanOptions; -import io.opencensus.trace.Span; -import io.opencensus.trace.Status; -import io.opencensus.trace.Status.CanonicalCode; -import io.opencensus.trace.Tracer; -import java.util.Map; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.mockito.quality.Strictness; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class OpencensusTracerTest { - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS); - - @Mock private Tracer internalTracer; - @Mock private Span span; - @Captor private ArgumentCaptor> attributeCaptor; - - private OpencensusTracer tracer; - - @Before - public void setUp() { - tracer = new OpencensusTracer(internalTracer, span, OperationType.Unary); - } - - @Test - public void testUnarySuccessExample() { - tracer.attemptStarted(0); - tracer.connectionSelected("1"); - ApiException error0 = - new DeadlineExceededException( - "deadline exceeded", null, new FakeStatusCode(Code.DEADLINE_EXCEEDED), true); - tracer.attemptFailed(error0, Duration.ofMillis(5)); - - tracer.attemptStarted(1); - tracer.connectionSelected("2"); - tracer.attemptSucceeded(); - tracer.operationSucceeded(); - - // Attempt 0 - verify(span) - .addAnnotation( - "Attempt failed, scheduling next attempt", - ImmutableMap.of( - "attempt", AttributeValue.longAttributeValue(0), - "delay ms", AttributeValue.longAttributeValue(5), - "status", AttributeValue.stringAttributeValue("DEADLINE_EXCEEDED"), - "status message", AttributeValue.stringAttributeValue("deadline exceeded"), - "connection", AttributeValue.stringAttributeValue("1"))); - - // Attempt 1 - verify(span) - .addAnnotation( - "Attempt succeeded", - ImmutableMap.of( - "attempt", AttributeValue.longAttributeValue(1), - "connection", AttributeValue.stringAttributeValue("2"))); - - verify(span) - .putAttributes(ImmutableMap.of("attempt count", AttributeValue.longAttributeValue(2))); - verify(span).end(); - - verifyNoMoreInteractions(span); - } - - @Test - public void testBatchExample() { - tracer.batchRequestSent(100, 1000); - tracer.attemptStarted(0); - tracer.connectionSelected("1"); - tracer.attemptSucceeded(); - tracer.operationSucceeded(); - - verify(span).putAttribute("batch count", AttributeValue.longAttributeValue(100)); - verify(span).putAttribute("batch size", AttributeValue.longAttributeValue(1000)); - } - - @Test - public void testLongRunningExample() { - tracer = new OpencensusTracer(internalTracer, span, OperationType.LongRunning); - - // Initial poll of the initial rpc - tracer.attemptStarted(0); - tracer.attemptFailed(null, Duration.ofMillis(5)); - - // Initial rpc finished - tracer.lroStartSucceeded(); - - // First real poll - tracer.attemptStarted(1); - tracer.attemptSucceeded(); - tracer.operationSucceeded(); - - // Attempt 0 - initial poll of the initial rpc - verify(span) - .addAnnotation( - "Scheduling next poll", - ImmutableMap.of( - "attempt", AttributeValue.longAttributeValue(0), - "delay ms", AttributeValue.longAttributeValue(5), - "status", AttributeValue.stringAttributeValue("OK"))); - - verify(span).addAnnotation("Operation started", ImmutableMap.of()); - - // Attempt 1 - first real poll - verify(span) - .addAnnotation( - "Polling completed", ImmutableMap.of("attempt", AttributeValue.longAttributeValue(1))); - - verify(span) - .putAttributes(ImmutableMap.of("attempt count", AttributeValue.longAttributeValue(2))); - verify(span).end(); - - verifyNoMoreInteractions(span); - } - - @Test - public void testRetriesExhaustedExample() { - tracer.attemptStarted(0); - tracer.connectionSelected("1"); - ApiException error0 = - new DeadlineExceededException( - "deadline exceeded", null, new FakeStatusCode(Code.DEADLINE_EXCEEDED), false); - tracer.attemptFailedRetriesExhausted(error0); - tracer.operationFailed(error0); - - verify(span) - .addAnnotation( - "Attempts exhausted", - ImmutableMap.of( - "attempt", AttributeValue.longAttributeValue(0), - "status", AttributeValue.stringAttributeValue("DEADLINE_EXCEEDED"), - "status message", AttributeValue.stringAttributeValue("deadline exceeded"), - "connection", AttributeValue.stringAttributeValue("1"))); - - verify(span) - .putAttributes(ImmutableMap.of("attempt count", AttributeValue.longAttributeValue(1))); - - verify(span) - .end( - EndSpanOptions.builder() - .setStatus(Status.DEADLINE_EXCEEDED.withDescription("deadline exceeded")) - .build()); - - verifyNoMoreInteractions(span); - } - - @Test - public void testCancellationExample() { - tracer.attemptStarted(0); - tracer.connectionSelected("1"); - tracer.attemptCancelled(); - tracer.operationCancelled(); - - verify(span) - .addAnnotation( - "Attempt cancelled", - ImmutableMap.of( - "attempt", AttributeValue.longAttributeValue(0), - "connection", AttributeValue.stringAttributeValue("1"))); - - verify(span) - .putAttributes(ImmutableMap.of("attempt count", AttributeValue.longAttributeValue(1))); - - verify(span) - .end( - EndSpanOptions.builder() - .setStatus(Status.CANCELLED.withDescription("Cancelled by caller")) - .build()); - verifyNoMoreInteractions(span); - } - - @Test - public void testFailureExample() { - tracer.attemptStarted(0); - tracer.connectionSelected("1"); - ApiException error0 = - new NotFoundException("not found", null, new FakeStatusCode(Code.NOT_FOUND), false); - tracer.attemptPermanentFailure(error0); - tracer.operationFailed(error0); - - verify(span) - .addAnnotation( - "Attempt failed, error not retryable", - ImmutableMap.of( - "attempt", AttributeValue.longAttributeValue(0), - "status", AttributeValue.stringAttributeValue("NOT_FOUND"), - "status message", AttributeValue.stringAttributeValue("not found"), - "connection", AttributeValue.stringAttributeValue("1"))); - - verify(span) - .putAttributes(ImmutableMap.of("attempt count", AttributeValue.longAttributeValue(1))); - - verify(span) - .end( - EndSpanOptions.builder() - .setStatus(Status.NOT_FOUND.withDescription("not found")) - .build()); - verifyNoMoreInteractions(span); - } - - @Test - public void testResponseCount() { - // Initial attempt got 2 messages, then failed - tracer.attemptStarted(0); - tracer.responseReceived(); - tracer.responseReceived(); - tracer.attemptFailed(new RuntimeException(), Duration.ofMillis(1)); - - // Next attempt got 1 message, then successfully finished the attempt and the logical operation. - tracer.attemptStarted(1); - tracer.responseReceived(); - tracer.attemptSucceeded(); - tracer.operationSucceeded(); - - verify(span) - .addAnnotation(eq("Attempt failed, scheduling next attempt"), attributeCaptor.capture()); - assertThat(attributeCaptor.getValue()) - .containsEntry("attempt response count", AttributeValue.longAttributeValue(2)); - - verify(span).addAnnotation(eq("Attempt succeeded"), attributeCaptor.capture()); - assertThat(attributeCaptor.getValue()) - .containsEntry("attempt response count", AttributeValue.longAttributeValue(1)); - - verify(span).putAttributes(attributeCaptor.capture()); - assertThat(attributeCaptor.getValue()) - .containsEntry("total response count", AttributeValue.longAttributeValue(3)); - } - - @Test - public void testRequestCount() { - // Initial attempt sent 2 messages, then failed - tracer.attemptStarted(0); - tracer.requestSent(); - tracer.requestSent(); - tracer.attemptFailed(new RuntimeException(), Duration.ofMillis(1)); - - // Next attempt sent 1 message, then successfully finished the attempt and the logical - // operation. - tracer.attemptStarted(1); - tracer.requestSent(); - tracer.attemptSucceeded(); - tracer.operationSucceeded(); - - verify(span) - .addAnnotation(eq("Attempt failed, scheduling next attempt"), attributeCaptor.capture()); - assertThat(attributeCaptor.getValue()) - .containsEntry("attempt request count", AttributeValue.longAttributeValue(2)); - - verify(span).addAnnotation(eq("Attempt succeeded"), attributeCaptor.capture()); - assertThat(attributeCaptor.getValue()) - .containsEntry("attempt request count", AttributeValue.longAttributeValue(1)); - - verify(span).putAttributes(attributeCaptor.capture()); - assertThat(attributeCaptor.getValue()) - .containsEntry("total request count", AttributeValue.longAttributeValue(3)); - } - - @Test - public void testAttemptNumber() { - tracer.attemptStarted(0); - tracer.attemptFailed(new RuntimeException(), Duration.ofMillis(1)); - tracer.attemptStarted(1); - tracer.attemptSucceeded(); - tracer.operationSucceeded(); - - verify(span) - .addAnnotation(eq("Attempt failed, scheduling next attempt"), attributeCaptor.capture()); - assertThat(attributeCaptor.getValue()) - .containsEntry("attempt", AttributeValue.longAttributeValue(0)); - - verify(span).addAnnotation(eq("Attempt succeeded"), attributeCaptor.capture()); - assertThat(attributeCaptor.getValue()) - .containsEntry("attempt", AttributeValue.longAttributeValue(1)); - - verify(span).putAttributes(attributeCaptor.capture()); - assertThat(attributeCaptor.getValue()) - .containsEntry("attempt count", AttributeValue.longAttributeValue(2)); - } - - @Test - public void testStatusCode() { - tracer.attemptStarted(0); - tracer.attemptFailed( - new DeadlineExceededException( - "deadline exceeded", null, new FakeStatusCode(Code.DEADLINE_EXCEEDED), true), - Duration.ofMillis(1)); - - tracer.attemptStarted(1); - ApiException permanentError = - new NotFoundException("not found", null, new FakeStatusCode(Code.NOT_FOUND), false); - tracer.attemptPermanentFailure(permanentError); - tracer.operationFailed(permanentError); - - verify(span) - .addAnnotation(eq("Attempt failed, scheduling next attempt"), attributeCaptor.capture()); - assertThat(attributeCaptor.getValue()) - .containsEntry("status", AttributeValue.stringAttributeValue("DEADLINE_EXCEEDED")); - - verify(span) - .addAnnotation(eq("Attempt failed, error not retryable"), attributeCaptor.capture()); - assertThat(attributeCaptor.getValue()) - .containsEntry("status", AttributeValue.stringAttributeValue("NOT_FOUND")); - } - - @Test - public void testErrorConversion() { - for (Code code : Code.values()) { - ApiException error = new ApiException("fake message", null, new FakeStatusCode(code), false); - Status opencensusStatus = OpencensusTracer.convertErrorToStatus(error); - assertThat(opencensusStatus.getDescription()).isEqualTo("fake message"); - assertThat(opencensusStatus.getCanonicalCode().toString()).isEqualTo(code.toString()); - } - } - - @Test - public void testStreamingErrorConversion() { - ServerStreamingAttemptException error = - new ServerStreamingAttemptException( - new DeadlineExceededException( - "timeout", null, new FakeStatusCode(Code.DEADLINE_EXCEEDED), true), - true, - true); - Status opencensusStatus = OpencensusTracer.convertErrorToStatus(error); - assertThat(opencensusStatus.getDescription()).isEqualTo("timeout"); - assertThat(opencensusStatus.getCanonicalCode()).isEqualTo(CanonicalCode.DEADLINE_EXCEEDED); - } -} diff --git a/gax/src/test/java/com/google/api/gax/tracing/TraceFinisherTest.java b/gax/src/test/java/com/google/api/gax/tracing/TraceFinisherTest.java deleted file mode 100644 index 5aa94f651..000000000 --- a/gax/src/test/java/com/google/api/gax/tracing/TraceFinisherTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.tracing; - -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.common.util.concurrent.MoreExecutors; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.mockito.quality.Strictness; - -@RunWith(JUnit4.class) -public class TraceFinisherTest { - @Rule public MockitoRule mockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS); - @Mock private ApiTracer mockTracer; - - @Test - public void testSuccess() { - ApiFuture future = ApiFutures.immediateFuture("result"); - ApiFutures.addCallback( - future, new TraceFinisher(mockTracer), MoreExecutors.directExecutor()); - - verify(mockTracer, times(1)).operationSucceeded(); - } - - @Test - public void testCancellation() { - ApiFuture future = ApiFutures.immediateCancelledFuture(); - ApiFutures.addCallback( - future, new TraceFinisher(mockTracer), MoreExecutors.directExecutor()); - - verify(mockTracer, times(1)).operationCancelled(); - } - - @Test - public void testFailure() { - RuntimeException expectedError = new RuntimeException("fake"); - ApiFuture future = ApiFutures.immediateFailedFuture(expectedError); - ApiFutures.addCallback( - future, new TraceFinisher(mockTracer), MoreExecutors.directExecutor()); - - verify(mockTracer, times(1)).operationFailed(expectedError); - } -} diff --git a/gax/src/test/java/com/google/api/gax/tracing/TracedBatchingCallableTest.java b/gax/src/test/java/com/google/api/gax/tracing/TracedBatchingCallableTest.java deleted file mode 100644 index 6488dde28..000000000 --- a/gax/src/test/java/com/google/api/gax/tracing/TracedBatchingCallableTest.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.gax.tracing; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.api.core.SettableApiFuture; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.BatchingDescriptor; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.api.gax.rpc.testing.FakeCallContext; -import com.google.api.gax.tracing.ApiTracerFactory.OperationType; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.mockito.quality.Strictness; - -public class TracedBatchingCallableTest { - private static final SpanName SPAN_NAME = SpanName.of("FakeClient", "FakeRpc"); - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS); - - @Mock private ApiTracerFactory tracerFactory; - @Mock private ApiTracer tracer; - @Mock private BatchingDescriptor batchingDescriptor; - @Mock private UnaryCallable innerCallable; - private SettableApiFuture innerResult; - - private TracedBatchingCallable tracedBatchingCallable; - private FakeCallContext callContext; - - @Before - public void setUp() { - // Wire the mock tracer factory - when(tracerFactory.newTracer( - any(ApiTracer.class), any(SpanName.class), eq(OperationType.Batching))) - .thenReturn(tracer); - - // Wire the mock inner callable - // This is a very hacky mock, the actual batching infrastructure is completely omitted here. - innerResult = SettableApiFuture.create(); - when(innerCallable.futureCall(anyString(), any(ApiCallContext.class))).thenReturn(innerResult); - - // Build the system under test - tracedBatchingCallable = - new TracedBatchingCallable<>(innerCallable, tracerFactory, SPAN_NAME, batchingDescriptor); - callContext = FakeCallContext.createDefault(); - } - - @Test - public void testRootTracerCreated() { - tracedBatchingCallable.futureCall("test", callContext); - verify(tracerFactory, times(1)) - .newTracer(callContext.getTracer(), SPAN_NAME, OperationType.Batching); - } - - @Test - public void testBatchAttributesStamped() { - when(batchingDescriptor.countElements(anyString())).thenReturn(10L); - when(batchingDescriptor.countBytes(anyString())).thenReturn(20L); - - tracedBatchingCallable.futureCall("test", callContext); - verify(tracer).batchRequestSent(10, 20); - } - - @Test - public void testOperationFinish() { - innerResult.set("successful result"); - tracedBatchingCallable.futureCall("test", callContext); - - verify(tracer, times(1)).operationSucceeded(); - } - - @Test - public void testOperationFailed() { - RuntimeException fakeError = new RuntimeException("fake error"); - innerResult.setException(fakeError); - tracedBatchingCallable.futureCall("test", callContext); - - verify(tracer, times(1)).operationFailed(fakeError); - } - - @Test - public void testSyncError() { - RuntimeException fakeError = new RuntimeException("fake error"); - - // Reset the irrelevant expectations from setup. (only needed to silence the warnings). - @SuppressWarnings("unchecked") - UnaryCallable[] innerCallableWrapper = new UnaryCallable[] {innerCallable}; - reset(innerCallableWrapper); - - when(innerCallable.futureCall(eq("failing test"), any(ApiCallContext.class))) - .thenThrow(fakeError); - - try { - tracedBatchingCallable.futureCall("failing test", callContext); - } catch (RuntimeException e) { - // ignored - } - - verify(tracer, times(1)).operationFailed(fakeError); - } -} diff --git a/gax/src/test/java/com/google/api/gax/tracing/TracedBidiCallableTest.java b/gax/src/test/java/com/google/api/gax/tracing/TracedBidiCallableTest.java deleted file mode 100644 index 93a007f73..000000000 --- a/gax/src/test/java/com/google/api/gax/tracing/TracedBidiCallableTest.java +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.tracing; - -import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.BidiStream; -import com.google.api.gax.rpc.BidiStreamObserver; -import com.google.api.gax.rpc.BidiStreamingCallable; -import com.google.api.gax.rpc.ClientStream; -import com.google.api.gax.rpc.ClientStreamReadyObserver; -import com.google.api.gax.rpc.ResponseObserver; -import com.google.api.gax.rpc.StreamController; -import com.google.api.gax.rpc.testing.FakeCallContext; -import com.google.api.gax.tracing.ApiTracerFactory.OperationType; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CancellationException; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; - -@RunWith(JUnit4.class) -public class TracedBidiCallableTest { - private static final SpanName SPAN_NAME = SpanName.of("fake-client", "fake-method"); - public @Rule MockitoRule mockitoRule = MockitoJUnit.rule(); - - private FakeBidiObserver outerObserver; - private FakeCallContext outerCallContext; - - @Mock private ApiTracerFactory tracerFactory; - private ApiTracer parentTracer = BaseApiTracer.getInstance(); - @Mock private ApiTracer tracer; - - private TracedBidiCallable tracedCallable; - - private FakeBidiCallable innerCallable; - private FakeStreamController innerController; - - @Before - public void setUp() { - outerObserver = new FakeBidiObserver(); - outerCallContext = FakeCallContext.createDefault(); - - when(tracerFactory.newTracer(parentTracer, SPAN_NAME, OperationType.BidiStreaming)) - .thenReturn(tracer); - - innerCallable = new FakeBidiCallable(); - innerController = new FakeStreamController(); - tracedCallable = new TracedBidiCallable<>(innerCallable, tracerFactory, SPAN_NAME); - } - - @Test - public void testTracerCreated() { - tracedCallable.call(outerObserver, outerCallContext); - - verify(tracerFactory, times(1)).newTracer(parentTracer, SPAN_NAME, OperationType.BidiStreaming); - } - - @Test - public void testOperationCancelled() { - tracedCallable.call(outerObserver, outerCallContext); - outerObserver.clientStream.closeSendWithError(new CancellationException()); - innerCallable.responseObserver.onError( - new RuntimeException("server generated result from cancelling")); - - verify(tracer, times(1)).operationCancelled(); - assertThat(outerObserver.complete).isTrue(); - } - - @Test - public void testOperationCancelled2() { - BidiStream stream = tracedCallable.call(outerCallContext); - - stream.cancel(); - innerCallable.responseObserver.onError( - new RuntimeException("server generated result from cancelling")); - - verify(tracer, times(1)).operationCancelled(); - } - - @Test - public void testOperationFinished() { - tracedCallable.call(outerObserver, outerCallContext); - innerCallable.responseObserver.onComplete(); - - verify(tracer, times(1)).operationSucceeded(); - assertThat(outerObserver.complete).isTrue(); - } - - @Test - public void testOperationFailed() { - RuntimeException expectedException = new RuntimeException("fake"); - - tracedCallable.call(outerObserver, outerCallContext); - innerCallable.responseObserver.onError(expectedException); - - verify(tracer, times(1)).operationFailed(expectedException); - assertThat(outerObserver.complete).isTrue(); - assertThat(outerObserver.error).isEqualTo(expectedException); - } - - @Test - public void testSyncError() { - RuntimeException expectedException = new RuntimeException("fake"); - innerCallable.syncError = expectedException; - - try { - tracedCallable.call(outerObserver, outerCallContext); - } catch (RuntimeException e) { - // noop - } - - verify(tracer, times(1)).operationFailed(expectedException); - } - - @Test - public void testRequestNotify() { - tracedCallable.call(outerObserver, outerCallContext); - outerObserver.clientStream.send("request1"); - outerObserver.clientStream.send("request2"); - - verify(tracer, times(2)).requestSent(); - assertThat(innerCallable.clientStream.sent).containsExactly("request1", "request2"); - } - - @Test - public void testRequestNotify2() { - BidiStream stream = tracedCallable.call(outerCallContext); - stream.send("request1"); - stream.send("request2"); - - verify(tracer, times(2)).requestSent(); - assertThat(innerCallable.clientStream.sent).containsExactly("request1", "request2"); - } - - @Test - public void testResponseNotify() { - tracedCallable.call(outerObserver, outerCallContext); - - innerCallable.responseObserver.onResponse("response1"); - innerCallable.responseObserver.onResponse("response2"); - - verify(tracer, times(2)).responseReceived(); - assertThat(outerObserver.responses).containsExactly("response1", "response2"); - } - - private static class FakeBidiCallable extends BidiStreamingCallable { - RuntimeException syncError; - - FakeStreamController responseController; - ResponseObserver responseObserver; - ClientStreamReadyObserver onReady; - ApiCallContext callContext; - FakeClientStream clientStream; - - @Override - public ClientStream internalCall( - ResponseObserver responseObserver, - ClientStreamReadyObserver onReady, - ApiCallContext context) { - - if (syncError != null) { - throw syncError; - } - - this.responseController = new FakeStreamController(); - - this.responseObserver = responseObserver; - this.onReady = onReady; - this.callContext = context; - this.clientStream = new FakeClientStream(); - - onReady.onReady(clientStream); - responseObserver.onStart(responseController); - - return clientStream; - } - } - - private static class FakeClientStream implements ClientStream { - private List sent = new ArrayList<>(); - private Throwable closeError; - private boolean closed; - - @Override - public void send(String request) { - sent.add(request); - } - - @Override - public void closeSendWithError(Throwable t) { - closed = true; - closeError = t; - } - - @Override - public void closeSend() { - closed = true; - } - - @Override - public boolean isSendReady() { - return true; - } - } - - private static class FakeBidiObserver implements BidiStreamObserver { - private ClientStream clientStream; - private StreamController streamController; - private List responses = new ArrayList<>(); - private Throwable error; - private boolean complete; - - @Override - public void onReady(ClientStream stream) { - this.clientStream = stream; - } - - @Override - public void onStart(StreamController controller) { - this.streamController = controller; - } - - @Override - public void onResponse(String response) { - responses.add(response); - } - - @Override - public void onError(Throwable t) { - this.error = t; - this.complete = true; - } - - @Override - public void onComplete() { - this.complete = true; - } - } - - private static class FakeStreamController implements StreamController { - private boolean wasCancelled; - - @Override - public void cancel() { - this.wasCancelled = true; - } - - @Override - public void disableAutoInboundFlowControl() {} - - @Override - public void request(int count) {} - } -} diff --git a/gax/src/test/java/com/google/api/gax/tracing/TracedCallableTest.java b/gax/src/test/java/com/google/api/gax/tracing/TracedCallableTest.java deleted file mode 100644 index 834b357e4..000000000 --- a/gax/src/test/java/com/google/api/gax/tracing/TracedCallableTest.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.tracing; - -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import com.google.api.core.ApiFuture; -import com.google.api.core.SettableApiFuture; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.Callables; -import com.google.api.gax.rpc.ClientContext; -import com.google.api.gax.rpc.UnaryCallSettings; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.api.gax.rpc.testing.FakeCallContext; -import com.google.api.gax.tracing.ApiTracerFactory.OperationType; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.mockito.quality.Strictness; -import org.threeten.bp.Duration; - -@RunWith(JUnit4.class) -public class TracedCallableTest { - private static final SpanName SPAN_NAME = SpanName.of("FakeClient", "FakeRpc"); - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS); - - @Mock private ApiTracerFactory tracerFactory; - private ApiTracer parentTracer; - @Mock private ApiTracer tracer; - @Mock private UnaryCallable innerCallable; - private SettableApiFuture innerResult; - - private ApiCallContext callContext; - private ClientContext clientContext; - - @Before - public void setUp() { - parentTracer = BaseApiTracer.getInstance(); - - // Wire the mock tracer factory - when(tracerFactory.newTracer( - any(ApiTracer.class), any(SpanName.class), eq(OperationType.Unary))) - .thenReturn(tracer); - - // Wire the mock inner callable - innerResult = SettableApiFuture.create(); - when(innerCallable.futureCall(anyString(), any(ApiCallContext.class))).thenReturn(innerResult); - - callContext = FakeCallContext.createDefault(); - clientContext = ClientContext.newBuilder().setDefaultCallContext(callContext).build(); - } - - public UnaryCallable setupTracedUnaryCallable( - UnaryCallSettings callSettings) { - UnaryCallable callable = - Callables.retrying(innerCallable, callSettings, clientContext); - return new TracedUnaryCallable<>(callable, tracerFactory, SPAN_NAME); - } - - @Test - public void testNonRetriedCallable() throws Exception { - // Verify that callables configured to not retry have the appropriate tracer interactions. - UnaryCallSettings callSettings = - UnaryCallSettings.newUnaryCallSettingsBuilder() - .setSimpleTimeoutNoRetries(Duration.ofMillis(5L)) - .build(); - UnaryCallable callable = setupTracedUnaryCallable(callSettings); - innerResult.set("No, my refrigerator is not running!"); - - ApiFuture future = callable.futureCall("Is your refrigerator running?", callContext); - - verify(tracerFactory, times(1)).newTracer(parentTracer, SPAN_NAME, OperationType.Unary); - verify(tracer, times(1)).attemptStarted(anyString(), anyInt()); - verify(tracer, times(1)).attemptSucceeded(); - verify(tracer, times(1)).operationSucceeded(); - verifyNoMoreInteractions(tracer); - } -} diff --git a/gax/src/test/java/com/google/api/gax/tracing/TracedClientStreamingCallableTest.java b/gax/src/test/java/com/google/api/gax/tracing/TracedClientStreamingCallableTest.java deleted file mode 100644 index cfee1c2a7..000000000 --- a/gax/src/test/java/com/google/api/gax/tracing/TracedClientStreamingCallableTest.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.tracing; - -import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.ApiStreamObserver; -import com.google.api.gax.rpc.CancelledException; -import com.google.api.gax.rpc.ClientStreamingCallable; -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.api.gax.rpc.testing.FakeCallContext; -import com.google.api.gax.rpc.testing.FakeStatusCode; -import com.google.api.gax.tracing.ApiTracerFactory.OperationType; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Lists; -import java.util.List; -import java.util.concurrent.CancellationException; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.mockito.quality.Strictness; - -@RunWith(JUnit4.class) -public class TracedClientStreamingCallableTest { - private static final SpanName SPAN_NAME = SpanName.of("fake-client", "fake-method"); - public @Rule MockitoRule mockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS); - - @Mock private ApiTracerFactory tracerFactory; - private ApiTracer parentTracer = BaseApiTracer.getInstance(); - @Mock private ApiTracer tracer; - - private FakeClientCallable innerCallable; - private TracedClientStreamingCallable tracedCallable; - private FakeStreamObserver outerResponseObsever; - private FakeCallContext callContext; - - @Before - public void setUp() { - when(tracerFactory.newTracer(parentTracer, SPAN_NAME, OperationType.ClientStreaming)) - .thenReturn(tracer); - innerCallable = new FakeClientCallable(); - tracedCallable = new TracedClientStreamingCallable<>(innerCallable, tracerFactory, SPAN_NAME); - outerResponseObsever = new FakeStreamObserver(); - callContext = FakeCallContext.createDefault(); - } - - @Test - public void testTracerCreated() { - tracedCallable.clientStreamingCall(outerResponseObsever, callContext); - - verify(tracerFactory, times(1)) - .newTracer(parentTracer, SPAN_NAME, OperationType.ClientStreaming); - } - - @Test - public void testCallContextPropagated() { - ImmutableMap> extraHeaders = - ImmutableMap.>of("header1", ImmutableList.of("value1")); - - ApiCallContext newCallContext = callContext.withExtraHeaders(extraHeaders); - tracedCallable.clientStreamingCall(outerResponseObsever, newCallContext); - - assertThat(innerCallable.callContext.getExtraHeaders()).isEqualTo(extraHeaders); - } - - @Test - public void testOperationCancelled() { - ApiStreamObserver clientStream = - tracedCallable.clientStreamingCall(outerResponseObsever, callContext); - - clientStream.onError(new CancellationException("explicitly cancelled")); - innerCallable.responseObserver.onError( - new CancelledException( - "fake exception that would be generated by a client cancelling the rpc", - null, - FakeStatusCode.of(Code.CANCELLED), - false)); - - verify(tracer, times(1)).operationCancelled(); - } - - @Test - public void testOperationFinished() { - tracedCallable.clientStreamingCall(outerResponseObsever, callContext); - innerCallable.responseObserver.onNext("ignored"); - innerCallable.responseObserver.onCompleted(); - - verify(tracer, times(1)).operationSucceeded(); - } - - @Test - public void testOperationFailed() { - RuntimeException expectedError = new RuntimeException("fake error"); - tracedCallable.clientStreamingCall(outerResponseObsever, callContext); - innerCallable.responseObserver.onError(expectedError); - - verify(tracer, times(1)).operationFailed(expectedError); - } - - @Test - public void testSyncError() { - RuntimeException expectedError = new RuntimeException("fake error"); - innerCallable.syncError = expectedError; - - try { - tracedCallable.clientStreamingCall(outerResponseObsever, callContext); - } catch (RuntimeException e) { - // noop - } - - verify(tracer, times(1)).operationFailed(expectedError); - } - - @Test - public void testRequestNotify() { - ApiStreamObserver requestStream = - tracedCallable.clientStreamingCall(outerResponseObsever, callContext); - - requestStream.onNext("request1"); - requestStream.onNext("request2"); - innerCallable.responseObserver.onNext("response"); - innerCallable.responseObserver.onCompleted(); - - verify(tracer, times(2)).requestSent(); - assertThat(outerResponseObsever.completed).isTrue(); - assertThat(innerCallable.requestObserver.messages).containsExactly("request1", "request2"); - } - - private static class FakeClientCallable extends ClientStreamingCallable { - private RuntimeException syncError; - private ApiStreamObserver responseObserver; - // TODO: https://github.com/googleapis/gax-java/issues/687 - private ApiCallContext callContext; - private FakeStreamObserver requestObserver; - - @Override - public ApiStreamObserver clientStreamingCall( - ApiStreamObserver responseObserver, ApiCallContext context) { - - if (syncError != null) { - throw syncError; - } - - this.responseObserver = responseObserver; - this.callContext = context; - this.requestObserver = new FakeStreamObserver(); - - return this.requestObserver; - } - } - - private static class FakeStreamObserver implements ApiStreamObserver { - private List messages = Lists.newArrayList(); - private Throwable error; - private boolean completed; - - @Override - public void onNext(String value) { - messages.add(value); - } - - @Override - public void onError(Throwable t) { - error = t; - completed = true; - } - - @Override - public void onCompleted() { - completed = true; - } - } -} diff --git a/gax/src/test/java/com/google/api/gax/tracing/TracedOperationCallableTest.java b/gax/src/test/java/com/google/api/gax/tracing/TracedOperationCallableTest.java deleted file mode 100644 index 80efd1f47..000000000 --- a/gax/src/test/java/com/google/api/gax/tracing/TracedOperationCallableTest.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.tracing; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.api.core.AbstractApiFuture; -import com.google.api.core.ApiFuture; -import com.google.api.core.SettableApiFuture; -import com.google.api.gax.longrunning.OperationFuture; -import com.google.api.gax.longrunning.OperationSnapshot; -import com.google.api.gax.retrying.RetryingFuture; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.OperationCallable; -import com.google.api.gax.rpc.testing.FakeCallContext; -import com.google.api.gax.tracing.ApiTracerFactory.OperationType; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.mockito.quality.Strictness; - -@RunWith(JUnit4.class) -public class TracedOperationCallableTest { - private static final SpanName SPAN_NAME = SpanName.of("FakeClient", "FakeOperation"); - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS); - - @Mock private ApiTracerFactory tracerFactory; - private ApiTracer parentTracer; - @Mock private ApiTracer tracer; - @Mock private OperationCallable innerCallable; - private FakeOperationFuture innerResult; - - private TracedOperationCallable tracedOperationCallable; - private FakeCallContext callContext; - - @Before - public void setUp() { - parentTracer = BaseApiTracer.getInstance(); - - // Wire the mock tracer factory - when(tracerFactory.newTracer( - any(ApiTracer.class), any(SpanName.class), eq(OperationType.LongRunning))) - .thenReturn(tracer); - - // Wire the mock inner callable - innerResult = new FakeOperationFuture(); - when(innerCallable.futureCall(anyString(), any(ApiCallContext.class))).thenReturn(innerResult); - - // Build the system under test - tracedOperationCallable = - new TracedOperationCallable<>(innerCallable, tracerFactory, SPAN_NAME); - callContext = FakeCallContext.createDefault(); - } - - @Test - public void testTracerCreated() { - tracedOperationCallable.futureCall("test", callContext); - verify(tracerFactory, times(1)).newTracer(parentTracer, SPAN_NAME, OperationType.LongRunning); - } - - @Test - public void testOperationFinish() { - innerResult.set("successful result"); - tracedOperationCallable.futureCall("test", callContext); - - verify(tracer, times(1)).operationSucceeded(); - } - - @Test - public void testOperationCancelled() { - innerResult.cancel(true); - tracedOperationCallable.futureCall("test", callContext); - verify(tracer, times(1)).operationCancelled(); - } - - @Test - public void testExternalOperationCancel() { - Mockito.reset(innerCallable, tracerFactory); - - when(tracerFactory.newTracer( - any(ApiTracer.class), any(SpanName.class), eq(OperationType.Unary))) - .thenReturn(tracer); - - SettableApiFuture innerCancelResult = SettableApiFuture.create(); - when(innerCallable.cancel(anyString(), any(ApiCallContext.class))) - .thenReturn(innerCancelResult); - - tracedOperationCallable.cancel("some external operation", callContext); - - verify(tracerFactory, times(1)) - .newTracer( - parentTracer, - SpanName.of(SPAN_NAME.getClientName(), SPAN_NAME.getMethodName() + ".Cancel"), - OperationType.Unary); - } - - @Test - public void testOperationFailed() { - RuntimeException fakeError = new RuntimeException("fake error"); - innerResult.setException(fakeError); - tracedOperationCallable.futureCall("test", callContext); - - verify(tracer, times(1)).operationFailed(fakeError); - } - - @Test - public void testSyncError() { - RuntimeException fakeError = new RuntimeException("fake error"); - - // Reset the irrelevant expectations from setup. (only needed to silence the warnings). - @SuppressWarnings("unchecked") - OperationCallable[] innerCallableWrapper = - new OperationCallable[] {innerCallable}; - reset(innerCallableWrapper); - - when(innerCallable.futureCall(eq("failing test"), any(ApiCallContext.class))) - .thenThrow(fakeError); - - try { - tracedOperationCallable.futureCall("failing test", callContext); - } catch (RuntimeException e) { - // ignored - } - - verify(tracer, times(1)).operationFailed(fakeError); - } - - static class FakeOperationFuture extends AbstractApiFuture - implements OperationFuture { - @Override - public boolean set(String value) { - return super.set(value); - } - - @Override - public boolean setException(Throwable throwable) { - return super.setException(throwable); - } - - @Override - public String getName() { - throw new UnsupportedOperationException("getInitialFuture() not implemented"); - } - - @Override - public ApiFuture getInitialFuture() { - throw new UnsupportedOperationException("getInitialFuture() not implemented"); - } - - @Override - public RetryingFuture getPollingFuture() { - throw new UnsupportedOperationException("getPollingFuture() not implemented"); - } - - @Override - public ApiFuture peekMetadata() { - throw new UnsupportedOperationException("getInitialFuture() not implemented"); - } - - @Override - public ApiFuture getMetadata() { - throw new UnsupportedOperationException("getInitialFuture() not implemented"); - } - } -} diff --git a/gax/src/test/java/com/google/api/gax/tracing/TracedServerStreamingCallableTest.java b/gax/src/test/java/com/google/api/gax/tracing/TracedServerStreamingCallableTest.java deleted file mode 100644 index 660e525b5..000000000 --- a/gax/src/test/java/com/google/api/gax/tracing/TracedServerStreamingCallableTest.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.tracing; - -import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.CancelledException; -import com.google.api.gax.rpc.ResponseObserver; -import com.google.api.gax.rpc.ServerStreamingCallable; -import com.google.api.gax.rpc.StatusCode.Code; -import com.google.api.gax.rpc.testing.FakeCallContext; -import com.google.api.gax.rpc.testing.FakeStatusCode; -import com.google.api.gax.rpc.testing.MockStreamingApi.MockResponseObserver; -import com.google.api.gax.rpc.testing.MockStreamingApi.MockServerStreamingCall; -import com.google.api.gax.rpc.testing.MockStreamingApi.MockServerStreamingCallable; -import com.google.api.gax.tracing.ApiTracerFactory.OperationType; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.mockito.quality.Strictness; - -@RunWith(JUnit4.class) -public class TracedServerStreamingCallableTest { - private static final SpanName SPAN_NAME = SpanName.of("FakeClient", "FakeRpc"); - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS); - - @Mock private ApiTracerFactory tracerFactory; - @Mock private ApiTracer tracer; - - private MockServerStreamingCallable innerCallable; - private TracedServerStreamingCallable tracedCallable; - private MockResponseObserver responseObserver; - private ApiCallContext callContext; - @Mock private ApiTracer parentTracer; - - @Before - public void setUp() { - // Wire the mock tracer factory - when(tracerFactory.newTracer( - any(ApiTracer.class), any(SpanName.class), eq(OperationType.ServerStreaming))) - .thenReturn(tracer); - innerCallable = new MockServerStreamingCallable<>(); - - responseObserver = new MockResponseObserver<>(true); - callContext = FakeCallContext.createDefault().withTracer(parentTracer); - - // Build the system under test - tracedCallable = new TracedServerStreamingCallable<>(innerCallable, tracerFactory, SPAN_NAME); - } - - @Test - public void testTracerCreated() { - tracedCallable.call("test", responseObserver, callContext); - verify(tracerFactory, times(1)) - .newTracer(parentTracer, SPAN_NAME, OperationType.ServerStreaming); - } - - @Test - public void testResponseNotify() { - tracedCallable.call("test", responseObserver, callContext); - - MockServerStreamingCall innerCall = innerCallable.popLastCall(); - innerCall.getController().getObserver().onResponse("response1"); - innerCall.getController().getObserver().onResponse("response2"); - - assertThat(responseObserver.popNextResponse()).isEqualTo("response1"); - assertThat(responseObserver.popNextResponse()).isEqualTo("response2"); - verify(tracer, times(2)).responseReceived(); - } - - @Test - public void testOperationCancelled() { - tracedCallable.call("test", responseObserver, callContext); - responseObserver.getController().cancel(); - - MockServerStreamingCall innerCall = innerCallable.popLastCall(); - innerCall - .getController() - .getObserver() - .onError( - new CancelledException("fake cancel", null, new FakeStatusCode(Code.CANCELLED), false)); - - assertThat(responseObserver.isDone()).isTrue(); - verify(tracer, times(1)).operationCancelled(); - } - - @Test - public void testOperationFinish() { - tracedCallable.call("test", responseObserver, callContext); - - MockServerStreamingCall innerCall = innerCallable.popLastCall(); - innerCall.getController().getObserver().onComplete(); - - assertThat(responseObserver.isDone()).isTrue(); - verify(tracer, times(1)).operationSucceeded(); - } - - @Test - public void testOperationFail() { - RuntimeException expectedError = new RuntimeException("expected error"); - - tracedCallable.call("test", responseObserver, callContext); - - MockServerStreamingCall innerCall = innerCallable.popLastCall(); - innerCall.getController().getObserver().onError(expectedError); - - assertThat(responseObserver.getFinalError()).isEqualTo(expectedError); - verify(tracer, times(1)).operationFailed(expectedError); - } - - @Test - @SuppressWarnings("unchecked") - public void testSyncError() { - RuntimeException expectedError = new RuntimeException("expected error"); - - // Create a broken inner callable - ServerStreamingCallable innerCallable = mock(ServerStreamingCallable.class); - doThrow(expectedError) - .when(innerCallable) - .call( - eq("test"), - (ResponseObserver) any(ResponseObserver.class), - any(ApiCallContext.class)); - - // Recreate the tracedCallable using the new inner callable - tracedCallable = new TracedServerStreamingCallable<>(innerCallable, tracerFactory, SPAN_NAME); - - try { - tracedCallable.call("test", responseObserver, callContext); - } catch (RuntimeException e) { - // noop - } - - verify(tracer, times(1)).operationFailed(expectedError); - } -} diff --git a/gax/src/test/java/com/google/api/gax/tracing/TracedUnaryCallableTest.java b/gax/src/test/java/com/google/api/gax/tracing/TracedUnaryCallableTest.java deleted file mode 100644 index 9d066bdb4..000000000 --- a/gax/src/test/java/com/google/api/gax/tracing/TracedUnaryCallableTest.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2018 Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.gax.tracing; - -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.api.core.SettableApiFuture; -import com.google.api.gax.rpc.ApiCallContext; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.api.gax.rpc.testing.FakeCallContext; -import com.google.api.gax.tracing.ApiTracerFactory.OperationType; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.mockito.quality.Strictness; - -@RunWith(JUnit4.class) -public class TracedUnaryCallableTest { - private static final SpanName SPAN_NAME = SpanName.of("FakeClient", "FakeRpc"); - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS); - - @Mock private ApiTracerFactory tracerFactory; - private ApiTracer parentTracer; - @Mock private ApiTracer tracer; - @Mock private UnaryCallable innerCallable; - private SettableApiFuture innerResult; - - private TracedUnaryCallable tracedUnaryCallable; - private FakeCallContext callContext; - - @Before - public void setUp() { - parentTracer = BaseApiTracer.getInstance(); - - // Wire the mock tracer factory - when(tracerFactory.newTracer( - any(ApiTracer.class), any(SpanName.class), eq(OperationType.Unary))) - .thenReturn(tracer); - - // Wire the mock inner callable - innerResult = SettableApiFuture.create(); - when(innerCallable.futureCall(anyString(), any(ApiCallContext.class))).thenReturn(innerResult); - - // Build the system under test - tracedUnaryCallable = new TracedUnaryCallable<>(innerCallable, tracerFactory, SPAN_NAME); - callContext = FakeCallContext.createDefault(); - } - - @Test - public void testTracerCreated() { - tracedUnaryCallable.futureCall("test", callContext); - verify(tracerFactory, times(1)).newTracer(parentTracer, SPAN_NAME, OperationType.Unary); - } - - @Test - public void testOperationFinish() { - innerResult.set("successful result"); - tracedUnaryCallable.futureCall("test", callContext); - - verify(tracer, times(1)).operationSucceeded(); - } - - @Test - public void testOperationCancelled() { - innerResult.cancel(true); - tracedUnaryCallable.futureCall("test", callContext); - verify(tracer, times(1)).operationCancelled(); - } - - @Test - public void testOperationFailed() { - RuntimeException fakeError = new RuntimeException("fake error"); - innerResult.setException(fakeError); - tracedUnaryCallable.futureCall("test", callContext); - - verify(tracer, times(1)).operationFailed(fakeError); - } - - @Test - public void testSyncError() { - RuntimeException fakeError = new RuntimeException("fake error"); - - // Reset the irrelevant expectations from setup. (only needed to silence the warnings). - @SuppressWarnings("unchecked") - UnaryCallable[] innerCallableWrapper = new UnaryCallable[] {innerCallable}; - reset(innerCallableWrapper); - - when(innerCallable.futureCall(eq("failing test"), any(ApiCallContext.class))) - .thenThrow(fakeError); - - try { - tracedUnaryCallable.futureCall("failing test", callContext); - } catch (RuntimeException e) { - // ignored - } - - verify(tracer, times(1)).operationFailed(fakeError); - } -} diff --git a/gax/src/test/resources/com/google/api/gax/core/test.properties b/gax/src/test/resources/com/google/api/gax/core/test.properties deleted file mode 100644 index 5f233db11..000000000 --- a/gax/src/test/resources/com/google/api/gax/core/test.properties +++ /dev/null @@ -1 +0,0 @@ -version=0.0.0 \ No newline at end of file diff --git a/gax/src/test/resources/com/google/api/gax/rpc/mtls/mtlsCertAndKey.pem b/gax/src/test/resources/com/google/api/gax/rpc/mtls/mtlsCertAndKey.pem deleted file mode 100644 index f95c93bcf..000000000 --- a/gax/src/test/resources/com/google/api/gax/rpc/mtls/mtlsCertAndKey.pem +++ /dev/null @@ -1,30 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICGzCCAYSgAwIBAgIIWrt6xtmHPs4wDQYJKoZIhvcNAQEFBQAwMzExMC8GA1UE -AxMoMTAwOTEyMDcyNjg3OC5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbTAeFw0x -MjEyMDExNjEwNDRaFw0yMjExMjkxNjEwNDRaMDMxMTAvBgNVBAMTKDEwMDkxMjA3 -MjY4NzguYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20wgZ8wDQYJKoZIhvcNAQEB -BQADgY0AMIGJAoGBAL1SdY8jTUVU7O4/XrZLYTw0ON1lV6MQRGajFDFCqD2Fd9tQ -GLW8Iftx9wfXe1zuaehJSgLcyCxazfyJoN3RiONBihBqWY6d3lQKqkgsRTNZkdFJ -Wdzl/6CxhK9sojh2p0r3tydtv9iwq5fuuWIvtODtT98EgphhncQAqkKoF3zVAgMB -AAGjODA2MAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMBYGA1UdJQEB/wQM -MAoGCCsGAQUFBwMCMA0GCSqGSIb3DQEBBQUAA4GBAD8XQEqzGePa9VrvtEGpf+R4 -fkxKbcYAzqYq202nKu0kfjhIYkYSBj6gi348YaxE64yu60TVl42l5HThmswUheW4 -uQIaq36JvwvsDP5Zoj5BgiNSnDAFQp+jJFBRUA5vooJKgKgMDf/r/DCOsbO6VJF1 -kWwa9n19NFiV0z3m6isj ------END CERTIFICATE----- ------BEGIN PRIVATE KEY----- -MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAL1SdY8jTUVU7O4/ -XrZLYTw0ON1lV6MQRGajFDFCqD2Fd9tQGLW8Iftx9wfXe1zuaehJSgLcyCxazfyJ -oN3RiONBihBqWY6d3lQKqkgsRTNZkdFJWdzl/6CxhK9sojh2p0r3tydtv9iwq5fu -uWIvtODtT98EgphhncQAqkKoF3zVAgMBAAECgYB51B9cXe4yiGTzJ4pOKpHGySAy -sC1F/IjXt2eeD3PuKv4m/hL4l7kScpLx0+NJuQ4j8U2UK/kQOdrGANapB1ZbMZAK -/q0xmIUzdNIDiGSoTXGN2mEfdsEpQ/Xiv0lyhYBBPC/K4sYIpHccnhSRQUZlWLLY -lE5cFNKC9b7226mNvQJBAPt0hfCNIN0kUYOA9jdLtx7CE4ySGMPf5KPBuzPd8ty1 -fxaFm9PB7B76VZQYmHcWy8rT5XjoLJHrmGW1ZvP+iDsCQQDAvnKoarPOGb5iJfkq -RrA4flf1TOlf+1+uqIOJ94959jkkJeb0gv/TshDnm6/bWn+1kJylQaKygCizwPwB -Z84vAkA0Duur4YvsPJijoQ9YY1SGCagCcjyuUKwFOxaGpmyhRPIKt56LOJqpzyno -fy8ReKa4VyYq4eZYT249oFCwMwIBAkAROPNF2UL3x5UbcAkznd1hLujtIlI4IV4L -XUNjsJtBap7we/KHJq11XRPlniO4lf2TW7iji5neGVWJulTKS1xBAkAerktk4Hsw -ErUaUG1s/d+Sgc8e/KMeBElV+NxGhcWEeZtfHMn/6VOlbzY82JyvC9OKC80A5CAE -VUV6b25kqrcu ------END PRIVATE KEY----- diff --git a/gax/src/test/resources/com/google/api/gax/rpc/mtls/mtls_context_aware_metadata.json b/gax/src/test/resources/com/google/api/gax/rpc/mtls/mtls_context_aware_metadata.json deleted file mode 100644 index 62f10dd25..000000000 --- a/gax/src/test/resources/com/google/api/gax/rpc/mtls/mtls_context_aware_metadata.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "cert_provider_command": [ - "some_binary", - "some_argument" - ], - "device_resource_ids": [ - "123" - ] -} diff --git a/gax_java.bzl b/gax_java.bzl deleted file mode 100644 index 83e11815c..000000000 --- a/gax_java.bzl +++ /dev/null @@ -1,85 +0,0 @@ -# Copyright 2019 Google LLC -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google LLC nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -def java_tests(name, srcs, runtime_deps, size): - classNames = [] - for src in srcs: - # convert .java file path to fully qualified class name - className = src[(src.index("/com/") + 1):-5].replace("/", ".") - classNames.append(className) - native.java_test( - name = className, - test_class = className, - runtime_deps = runtime_deps, - size = size, - ) - if classNames: - native.test_suite( - name = name, - tests = classNames, - ) - -def google_java_format(name, srcs, formatter): - native.genrule( - name = name, - outs = ["%s.sh" % name], - srcs = srcs, - # TODO: this may fail if list of files is too long (exceeds max command line limit in shell). - # Split the command into multiple executions if this ever fails (good enough for now) - cmd = "echo ' $(location %s) --replace $(SRCS)' > $@" % formatter, - executable = True, - tools = [formatter], - local = 1, - ) - -def _google_java_format_verification_impl(ctx): - src_files = [src.path for src in ctx.files.srcs] - output_file = ctx.outputs.output_file - formatter = ctx.executable.formatter - - ctx.actions.run_shell( - inputs = ctx.files.srcs, - arguments = ["--dry-run", "--set-exit-if-changed"] + src_files, - tools = [formatter], - command = "%s $@ > %s" % (formatter.path, output_file.path), - outputs = [output_file], - progress_message = - "If this target fails check the list of files that must be formatted in %s" % output_file.path, - ) - -google_java_format_verification = rule( - attrs = { - "srcs": attr.label_list(allow_files = True), - "formatter": attr.label( - executable = True, - cfg = "host", - ), - }, - outputs = {"output_file": "%{name}.txt"}, - implementation = _google_java_format_verification_impl, -) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 943f0cbfa..000000000 Binary files a/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index f398c33c4..000000000 --- a/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip -networkTimeout=10000 -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew deleted file mode 100755 index 65dcd68d6..000000000 --- a/gradlew +++ /dev/null @@ -1,244 +0,0 @@ -#!/bin/sh - -# -# Copyright © 2015-2021 the original 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 -# -# 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. -# - -############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -# This is normally unused -# shellcheck disable=SC2034 -APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat deleted file mode 100644 index 6689b85be..000000000 --- a/gradlew.bat +++ /dev/null @@ -1,92 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/java.header b/java.header deleted file mode 100644 index 0ae9545db..000000000 --- a/java.header +++ /dev/null @@ -1,29 +0,0 @@ -^/\*$ -^ \* Copyright 20\d\d Google LLC$ -^ \*$ -^ \* Redistribution and use in source and binary forms, with or without$ -^ \* modification, are permitted provided that the following conditions are$ -^ \* met:$ -^ \*$ -^ \* \* Redistributions of source code must retain the above copyright$ -^ \* notice, this list of conditions and the following disclaimer.$ -^ \* \* Redistributions in binary form must reproduce the above$ -^ \* copyright notice, this list of conditions and the following disclaimer$ -^ \* in the documentation and/or other materials provided with the$ -^ \* distribution.$ -^ \* \* Neither the name of Google LLC nor the names of its$ -^ \* contributors may be used to endorse or promote products derived from$ -^ \* this software without specific prior written permission.$ -^ \*$ -^ \* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS$ -^ \* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT$ -^ \* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR$ -^ \* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT$ -^ \* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,$ -^ \* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES \(INCLUDING, BUT NOT$ -^ \* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,$ -^ \* DATA, OR PROFITS; OR BUSINESS INTERRUPTION\) HOWEVER CAUSED AND ON ANY$ -^ \* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT$ -^ \* \(INCLUDING NEGLIGENCE OR OTHERWISE\) ARISING IN ANY WAY OUT OF THE USE$ -^ \* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.$ -^ \*/$ \ No newline at end of file diff --git a/license-checks.xml b/license-checks.xml deleted file mode 100644 index 362833222..000000000 --- a/license-checks.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/license-header-javadoc.txt b/license-header-javadoc.txt deleted file mode 100644 index d31410dc3..000000000 --- a/license-header-javadoc.txt +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 20xx Google LLC - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/pom.xml b/pom.xml deleted file mode 100644 index 45cb918c6..000000000 --- a/pom.xml +++ /dev/null @@ -1,285 +0,0 @@ - - - 4.0.0 - com.google.api - gax-parent - pom - 2.20.1 - GAX (Google Api eXtensions) for Java (Parent) - https://github.com/googleapis/gax-java - Google Api eXtensions for Java (Parent) - - - com.google.cloud - google-cloud-shared-config - 1.5.5 - - - - - GoogleAPIs - GoogleAPIs - googleapis@googlegroups.com - Google LLC - https://www.google.com - - - - - scm:git:https://github.com/googleapis/gax-java.git - https://github.com/googleapis/gax-java - - - - - BSD - https://github.com/googleapis/gax-java/blob/master/LICENSE - - - - - UTF-8 - 1.8 - 1.8 - 1.10.1 - - - - gax - gax-grpc - gax-httpjson - gax-bom - - - - - - com.google.api - api-common - 2.3.1 - - - com.google.auth - google-auth-library-credentials - 1.14.0 - - - org.threeten - threetenbp - 1.6.5 - - - com.google.auth - google-auth-library-oauth2-http - 1.14.0 - - - com.google.errorprone - error_prone_annotations - - - - - com.google.code.findbugs - jsr305 - 3.0.2 - - - com.google.guava - guava - 31.1-jre - - - com.google.errorprone - error_prone_annotations - - - - - io.opencensus - opencensus-api - 0.31.1 - - - com.google.auto.value - auto-value-annotations - ${auto-value.version} - - - com.google.auto.value - auto-value - ${auto-value.version} - - - junit - junit - 4.13.2 - - - org.mockito - mockito-core - 4.11.0 - - - com.google.api - gax - 2.20.1 - - - com.google.api - gax - 2.20.1 - test-jar - testlib - - - com.google.api.grpc - proto-google-common-protos - 2.11.0 - - - com.google.api.grpc - grpc-google-common-protos - 2.11.0 - - - io.grpc - grpc-bom - 1.51.1 - pom - import - - - com.google.code.gson - gson - 2.10 - - - org.graalvm.sdk - graal-sdk - 22.3.0 - - - com.google.http-client - google-http-client-bom - 1.42.3 - pom - import - - - com.google.protobuf - protobuf-bom - 3.21.12 - pom - import - - - - - - - - junit - junit - test - - - org.mockito - mockito-core - test - - - com.google.truth - truth - 1.1.3 - - - org.checkerframework - checker-qual - - - com.google.errorprone - error_prone_annotations - - - test - - - - - - - src/main/resources - true - - - - - maven-compiler-plugin - - - - com.google.auto.value - auto-value - ${auto-value.version} - - - 8 - - -Xlint:unchecked - -Xlint:deprecation - - - - - org.apache.maven.plugins - maven-jar-plugin - - - - test-jar - - - true - - - - - - com.coveo - fmt-maven-plugin - - - validate - - check - - - - - - - - - - - release-staging-repository - - - - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.13 - true - - sonatype-nexus-staging - https://google.oss.sonatype.org/ - false - - - - - - - \ No newline at end of file diff --git a/renovate.json b/renovate.json deleted file mode 100644 index 930f87aab..000000000 --- a/renovate.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "enabled": false, - "extends": [ - "config:base" - ], - "ignorePaths": [".kokoro/requirements.txt"], - "regexManagers": [ - { - "fileMatch": ["^dependencies\\.properties$"], - "matchStrings": ["=(?.*?):(?.*?)\\n"], - "datasourceTemplate": "maven" - }, - { - "fileMatch": ["^dependencies\\.properties$"], - "matchStrings": ["version\\.com_google_protobuf=(?.*?)\\n"], - "depNameTemplate": "com.google.protobuf:protobuf-java", - "datasourceTemplate": "maven" - }, - { - "fileMatch": ["^dependencies\\.properties$"], - "matchStrings": ["version\\.google_java_format=(?.*?)\\n"], - "depNameTemplate": "com.google.googlejavaformat:google-java-format", - "datasourceTemplate": "maven" - }, - { - "fileMatch": ["^dependencies\\.properties$"], - "matchStrings": ["version\\.io_grpc=(?.*?)\\n"], - "depNameTemplate": "io.grpc:grpc-core", - "datasourceTemplate": "maven" - } - ] -} diff --git a/repositories.bzl b/repositories.bzl deleted file mode 100644 index 4231c5790..000000000 --- a/repositories.bzl +++ /dev/null @@ -1,149 +0,0 @@ -# Copyright 2019 Google LLC -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google LLC nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") -load("@bazel_tools//tools/build_defs/repo:jvm.bzl", "jvm_maven_import_external") -load("@com_google_api_gax_java_properties//:dependencies.properties.bzl", "PROPERTIES") - -def com_google_api_gax_java_repositories(): - # Import dependencies shared between Gradle and Bazel (i.e. maven dependencies) - for name, artifact in PROPERTIES.items(): - _maybe( - jvm_maven_import_external, - name = name, - strip_repo_prefix = "maven.", - artifact = _fix_bazel_artifact_format(artifact), - server_urls = ["https://repo.maven.apache.org/maven2/", "http://repo1.maven.org/maven2/"], - licenses = ["notice", "reciprocal"], - ) - - # Import Bazel-only dependencies (Gradle version will import maven artifacts of same - # version, while Bazel will depend on Bazel workspaces). The versions are shared in the - # properties file. - - _protobuf_version = PROPERTIES["version.com_google_protobuf"] - _protobuf_version_in_link = "v%s" % _protobuf_version - _maybe( - http_archive, - name = "com_google_protobuf", - urls = ["https://github.com/protocolbuffers/protobuf/archive/%s.zip" % _protobuf_version_in_link], - strip_prefix = "protobuf-%s" % _protobuf_version, - ) - - _grpc_version = PROPERTIES["version.io_grpc"] - _grpc_version_in_link = "v%s" % _grpc_version - _maybe( - http_archive, - name = "io_grpc_grpc_java", - urls = ["https://github.com/grpc/grpc-java/archive/%s.zip" % _grpc_version_in_link], - strip_prefix = "grpc-java-%s" % _grpc_version, - ) - - _bazel_skylib_version = "1.0.3" - _maybe( - http_archive, - name = "bazel_skylib", - strip_prefix = "bazel-skylib-%s" % _bazel_skylib_version, - urls = ["https://github.com/bazelbuild/bazel-skylib/archive/%s.zip" % _bazel_skylib_version], - ) - - _maybe( - jvm_maven_import_external, - name = "com_google_protobuf_java_util", - artifact = "com.google.protobuf:protobuf-java-util:%s" % PROPERTIES["version.com_google_protobuf"], - server_urls = ["https://repo.maven.apache.org/maven2/", "http://repo1.maven.org/maven2/"], - licenses = ["notice", "reciprocal"], - ) - - _maybe( - jvm_maven_import_external, - name = "com_google_protobuf_java", - artifact = "com.google.protobuf:protobuf-java:%s" % PROPERTIES["version.com_google_protobuf"], - server_urls = ["https://repo.maven.apache.org/maven2/", "http://repo1.maven.org/maven2/"], - licenses = ["notice", "reciprocal"], - ) - - _maybe( - jvm_maven_import_external, - name = "io_grpc_grpc_netty_shaded", - artifact = "io.grpc:grpc-netty-shaded:%s" % PROPERTIES["version.io_grpc"], - server_urls = ["https://repo.maven.apache.org/maven2/", "http://repo1.maven.org/maven2/"], - licenses = ["notice", "reciprocal"], - ) - - _maybe( - jvm_maven_import_external, - name = "io_grpc_grpc_grpclb", - artifact = "io.grpc:grpc-grpclb:%s" % PROPERTIES["version.io_grpc"], - server_urls = ["https://repo.maven.apache.org/maven2/", "http://repo1.maven.org/maven2/"], - licenses = ["notice", "reciprocal"], - ) - - _maybe( - jvm_maven_import_external, - name = "google_java_format_all_deps", - artifact = "com.google.googlejavaformat:google-java-format:jar:all-deps:%s" % PROPERTIES["version.google_java_format"], - server_urls = ["https://repo.maven.apache.org/maven2/", "http://repo1.maven.org/maven2/"], - licenses = ["notice", "reciprocal"], - ) - - _maybe( - native.bind, - name = "guava", - actual = "@com_google_guava_guava//jar", - ) - - _maybe( - native.bind, - name = "gson", - actual = "@com_google_code_gson_gson//jar", - ) - - _maybe( - native.bind, - name = "error_prone_annotations", - actual = "@com_google_errorprone_error_prone_annotations//jar", - ) - -def _maybe(repo_rule, name, strip_repo_prefix = "", **kwargs): - if not name.startswith(strip_repo_prefix): - return - repo_name = name[len(strip_repo_prefix):] - if repo_name in native.existing_rules(): - return - repo_rule(name = repo_name, **kwargs) - -def _fix_bazel_artifact_format(artifact_id): - # Fix the artifact id format discrepancy between Bazel & Gradle. - # This is relevant only when classifier is specified explicitly. - # Bazel format: groupId:artifactId:jar:classifier:version - # Gradle format: groupId:artifactId:version:classifier - ids = artifact_id.split(":") - if len(ids) != 4: - return artifact_id - return "%s:%s:%s:%s:%s" % (ids[0], ids[1], "jar", ids[3], ids[2]) diff --git a/repository_rules.bzl b/repository_rules.bzl deleted file mode 100644 index 5c62c23c0..000000000 --- a/repository_rules.bzl +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright 2019 Google LLC -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google LLC nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -def _com_google_api_gax_java_properties_impl(ctx): - props_path = ctx.path(ctx.attr.file) - result = ctx.execute(["cat", props_path]) - - if result.return_code != 0: - fail("Could not load dependencies from properties file, error_code %s" + str(result.return_code)) - - props = result.stdout.splitlines() - props_as_map = {} - - for prop in props: - p = prop.strip() - if len(p) <= 0 or p.startswith("#"): - continue - key_value = p.split("=", 1) - props_as_map[key_value[0]] = key_value[1] - - props_name = ctx.attr.file.name - dependencies_bzl = """ -# DO NOT EDIT. This file was generated from {properties_file}. -PROPERTIES = {props_as_map} - """.format( - properties_file = props_name, - props_as_map = str(props_as_map), - ) - ctx.file("BUILD.bazel", "") - ctx.file("%s.bzl" % props_name, dependencies_bzl) - - -com_google_api_gax_java_properties = repository_rule( - implementation = _com_google_api_gax_java_properties_impl, - attrs = { - "file": attr.label(), - }, - local = True, -) - diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index 52f23d4bf..000000000 --- a/settings.gradle +++ /dev/null @@ -1,4 +0,0 @@ -include "gax" -include "gax-bom" -include "gax-grpc" -include "gax-httpjson" diff --git a/versions.txt b/versions.txt deleted file mode 100644 index 35a770fde..000000000 --- a/versions.txt +++ /dev/null @@ -1,7 +0,0 @@ -# Format: -# module:released-version:current-version - -gax:2.20.1:2.20.1 -gax-bom:2.20.1:2.20.1 -gax-grpc:2.20.1:2.20.1 -gax-httpjson:0.105.1:0.105.1