diff --git a/doc/environment_variables.md b/doc/environment_variables.md index 0237dff7..70b32e71 100644 --- a/doc/environment_variables.md +++ b/doc/environment_variables.md @@ -29,6 +29,7 @@ can be set. - `channel` - Traces channel events - `connectivity_state` - Traces channel connectivity state changes - `dns_resolver` - Traces DNS resolution + - `ip_resolver` - Traces IPv4/v6 resolution - `pick_first` - Traces the pick first load balancing policy - `proxy` - Traces proxy operations - `resolving_load_balancer` - Traces the resolving load balancer @@ -40,6 +41,9 @@ can be set. - `subchannel_flowctrl` - Traces HTTP/2 flow control. Includes per-call logs. - `subchannel_internals` - Traces HTTP/2 session state. Includes per-call logs. - `channel_stacktrace` - Traces channel construction events with stack traces. + - `keepalive` - Traces gRPC keepalive pings + - `index` - Traces module loading + - `outlier_detection` - Traces outlier detection events The following tracers are added by the `@grpc/grpc-js-xds` library: - `cds_balancer` - Traces the CDS load balancing policy diff --git a/packages/grpc-js-xds/README.md b/packages/grpc-js-xds/README.md index 20bd924a..bbdd9886 100644 --- a/packages/grpc-js-xds/README.md +++ b/packages/grpc-js-xds/README.md @@ -28,4 +28,4 @@ const client = new MyServiceClient('xds:///example.com:123'); - [xDS Circuit Breaking](https://github.com/grpc/proposal/blob/master/A32-xds-circuit-breaking.md) - [xDS Client-Side Fault Injection](https://github.com/grpc/proposal/blob/master/A33-Fault-Injection.md) - [Client Status Discovery Service](https://github.com/grpc/proposal/blob/master/A40-csds-support.md) - - [Outlier Detection](https://github.com/grpc/proposal/blob/master/A50-xds-outlier-detection.md) (experimental, disabled by default, enabled by setting the environment variable `GRPC_EXPERIMENTAL_ENABLE_OUTLIER_DETECTION=true`) \ No newline at end of file + - [Outlier Detection](https://github.com/grpc/proposal/blob/master/A50-xds-outlier-detection.md) \ No newline at end of file diff --git a/packages/grpc-js-xds/interop/Dockerfile b/packages/grpc-js-xds/interop/Dockerfile new file mode 100644 index 00000000..b93e309d --- /dev/null +++ b/packages/grpc-js-xds/interop/Dockerfile @@ -0,0 +1,38 @@ +# Copyright 2022 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Dockerfile for building the xDS interop client. To build the image, run the +# following command from grpc-node directory: +# docker build -t -f packages/grpc-js-xds/interop/Dockerfile . + +FROM node:16-alpine as build + +# Make a grpc-node directory and copy the repo into it. +WORKDIR /node/src/grpc-node +COPY . . + +WORKDIR /node/src/grpc-node/packages/grpc-js +RUN npm install +WORKDIR /node/src/grpc-node/packages/grpc-js-xds +RUN npm install + +FROM node:16-alpine +WORKDIR /node/src/grpc-node +COPY --from=build /node/src/grpc-node/packages/grpc-js ./packages/grpc-js/ +COPY --from=build /node/src/grpc-node/packages/grpc-js-xds ./packages/grpc-js-xds/ + +ENV GRPC_VERBOSITY="DEBUG" +ENV GRPC_TRACE=xds_client,xds_resolver,cds_balancer,eds_balancer,priority,weighted_target,round_robin,resolving_load_balancer,subchannel,keepalive,dns_resolver,fault_injection,http_filter,csds,outlier_detection + +ENTRYPOINT [ "node", "/node/src/grpc-node/packages/grpc-js-xds/build/interop/xds-interop-client" ] diff --git a/packages/grpc-js-xds/package.json b/packages/grpc-js-xds/package.json index 9062403c..fcb9279f 100644 --- a/packages/grpc-js-xds/package.json +++ b/packages/grpc-js-xds/package.json @@ -1,6 +1,6 @@ { "name": "@grpc/grpc-js-xds", - "version": "1.6.1", + "version": "1.7.0", "description": "Plugin for @grpc/grpc-js. Adds the xds:// URL scheme and associated features.", "main": "build/src/index.js", "scripts": { @@ -47,7 +47,7 @@ "re2-wasm": "^1.0.1" }, "peerDependencies": { - "@grpc/grpc-js": "~1.6.0" + "@grpc/grpc-js": "~1.7.0" }, "engines": { "node": ">=10.10.0" diff --git a/packages/grpc-js-xds/scripts/xds_k8s_lb.sh b/packages/grpc-js-xds/scripts/xds_k8s_lb.sh new file mode 100755 index 00000000..ca747f7e --- /dev/null +++ b/packages/grpc-js-xds/scripts/xds_k8s_lb.sh @@ -0,0 +1,178 @@ +#!/usr/bin/env bash +# Copyright 2022 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -eo pipefail + +# Constants +readonly GITHUB_REPOSITORY_NAME="grpc-node" +readonly TEST_DRIVER_INSTALL_SCRIPT_URL="https://raw.githubusercontent.com/${TEST_DRIVER_REPO_OWNER:-grpc}/grpc/${TEST_DRIVER_BRANCH:-master}/tools/internal_ci/linux/grpc_xds_k8s_install_test_driver.sh" +## xDS test client Docker images +readonly SERVER_IMAGE_NAME="gcr.io/grpc-testing/xds-interop/java-server:v1.46.x" +readonly CLIENT_IMAGE_NAME="gcr.io/grpc-testing/xds-interop/node-client" +readonly FORCE_IMAGE_BUILD="${FORCE_IMAGE_BUILD:-0}" +readonly BUILD_APP_PATH="packages/grpc-js-xds/interop/Dockerfile" +readonly LANGUAGE_NAME="Node" + +####################################### +# Builds test app Docker images and pushes them to GCR +# Globals: +# BUILD_APP_PATH +# CLIENT_IMAGE_NAME: Test client Docker image name +# GIT_COMMIT: SHA-1 of git commit being built +# TESTING_VERSION: version branch under test, f.e. v1.42.x, master +# Arguments: +# None +# Outputs: +# Writes the output of `gcloud builds submit` to stdout, stderr +####################################### +build_test_app_docker_images() { + echo "Building ${LANGUAGE_NAME} xDS interop test app Docker images" + + pushd "${SRC_DIR}" + docker build \ + -f "${BUILD_APP_PATH}" \ + -t "${CLIENT_IMAGE_NAME}:${GIT_COMMIT}" \ + . + + gcloud -q auth configure-docker + docker push "${CLIENT_IMAGE_NAME}:${GIT_COMMIT}" + if is_version_branch "${TESTING_VERSION}"; then + tag_and_push_docker_image "${CLIENT_IMAGE_NAME}" "${GIT_COMMIT}" "${TESTING_VERSION}" + fi + popd +} + +####################################### +# Builds test app and its docker images unless they already exist +# Globals: +# CLIENT_IMAGE_NAME: Test client Docker image name +# GIT_COMMIT: SHA-1 of git commit being built +# FORCE_IMAGE_BUILD +# Arguments: +# None +# Outputs: +# Writes the output to stdout, stderr +####################################### +build_docker_images_if_needed() { + # Check if images already exist + client_tags="$(gcloud_gcr_list_image_tags "${CLIENT_IMAGE_NAME}" "${GIT_COMMIT}")" + printf "Client image: %s:%s\n" "${CLIENT_IMAGE_NAME}" "${GIT_COMMIT}" + echo "${client_tags:-Client image not found}" + + # Build if any of the images are missing, or FORCE_IMAGE_BUILD=1 + if [[ "${FORCE_IMAGE_BUILD}" == "1" || -z "${client_tags}" ]]; then + build_test_app_docker_images + else + echo "Skipping ${LANGUAGE_NAME} test app build" + fi +} + +####################################### +# Executes the test case +# Globals: +# TEST_DRIVER_FLAGFILE: Relative path to test driver flagfile +# KUBE_CONTEXT: The name of kubectl context with GKE cluster access +# SECONDARY_KUBE_CONTEXT: The name of kubectl context with secondary GKE cluster access, if any +# TEST_XML_OUTPUT_DIR: Output directory for the test xUnit XML report +# CLIENT_IMAGE_NAME: Test client Docker image name +# GIT_COMMIT: SHA-1 of git commit being built +# Arguments: +# Test case name +# Outputs: +# Writes the output of test execution to stdout, stderr +# Test xUnit report to ${TEST_XML_OUTPUT_DIR}/${test_name}/sponge_log.xml +####################################### +run_test() { + # Test driver usage: + # https://github.com/grpc/grpc/tree/master/tools/run_tests/xds_k8s_test_driver#basic-usage + local test_name="${1:?Usage: run_test test_name}" + local out_dir="${TEST_XML_OUTPUT_DIR}/${test_name}" + mkdir -pv "${out_dir}" + # testing_version is used by the framework to determine the supported PSM + # features. It's captured from Kokoro job name of the Node repo, which takes + # the form: + # grpc/node// + python3 -m "tests.${test_name}" \ + --flagfile="${TEST_DRIVER_FLAGFILE}" \ + --kube_context="${KUBE_CONTEXT}" \ + --secondary_kube_context="${SECONDARY_KUBE_CONTEXT}" \ + --client_image="${CLIENT_IMAGE_NAME}:${GIT_COMMIT}" \ + --server_image="${SERVER_IMAGE_NAME}" \ + --testing_version="${TESTING_VERSION}" \ + --force_cleanup \ + --collect_app_logs \ + --log_dir="${out_dir}" \ + --xml_output_file="${out_dir}/sponge_log.xml" \ + |& tee "${out_dir}/sponge_log.log" +} + +####################################### +# Main function: provision software necessary to execute tests, and run them +# Globals: +# KOKORO_ARTIFACTS_DIR +# GITHUB_REPOSITORY_NAME +# SRC_DIR: Populated with absolute path to the source repo +# TEST_DRIVER_REPO_DIR: Populated with the path to the repo containing +# the test driver +# TEST_DRIVER_FULL_DIR: Populated with the path to the test driver source code +# TEST_DRIVER_FLAGFILE: Populated with relative path to test driver flagfile +# TEST_XML_OUTPUT_DIR: Populated with the path to test xUnit XML report +# GIT_ORIGIN_URL: Populated with the origin URL of git repo used for the build +# GIT_COMMIT: Populated with the SHA-1 of git commit being built +# GIT_COMMIT_SHORT: Populated with the short SHA-1 of git commit being built +# KUBE_CONTEXT: Populated with name of kubectl context with GKE cluster access +# SECONDARY_KUBE_CONTEXT: Populated with name of kubectl context with secondary GKE cluster access, if any +# Arguments: +# None +# Outputs: +# Writes the output of test execution to stdout, stderr +####################################### +main() { + local script_dir + script_dir="$(dirname "$0")" + + cd "${script_dir}" + + git submodule update --init --recursive + + # Source the test driver from the master branch. + echo "Sourcing test driver install script from: ${TEST_DRIVER_INSTALL_SCRIPT_URL}" + source /dev/stdin <<< "$(curl -s "${TEST_DRIVER_INSTALL_SCRIPT_URL}")" + + activate_gke_cluster GKE_CLUSTER_PSM_LB + activate_secondary_gke_cluster GKE_CLUSTER_PSM_LB + + set -x + if [[ -n "${KOKORO_ARTIFACTS_DIR}" ]]; then + kokoro_setup_test_driver "${GITHUB_REPOSITORY_NAME}" + else + local_setup_test_driver "${script_dir}" + fi + build_docker_images_if_needed + + # Run tests + cd "${TEST_DRIVER_FULL_DIR}" + local failed_tests=0 + test_suites=("baseline_test" "api_listener_test" "change_backend_service_test" "failover_test" "remove_neg_test" "round_robin_test" "outlier_detection_test") + for test in "${test_suites[@]}"; do + run_test $test || (( failed_tests++ )) + done + echo "Failed test suites: ${failed_tests}" + if (( failed_tests > 0 )); then + exit 1 + fi +} + +main "$@" diff --git a/packages/grpc-js-xds/scripts/xds_k8s_url_map.sh b/packages/grpc-js-xds/scripts/xds_k8s_url_map.sh new file mode 100644 index 00000000..69126c72 --- /dev/null +++ b/packages/grpc-js-xds/scripts/xds_k8s_url_map.sh @@ -0,0 +1,162 @@ +#!/usr/bin/env bash +# Copyright 2022 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -eo pipefail + +# Constants +readonly GITHUB_REPOSITORY_NAME="grpc-node" +readonly TEST_DRIVER_INSTALL_SCRIPT_URL="https://raw.githubusercontent.com/${TEST_DRIVER_REPO_OWNER:-grpc}/grpc/${TEST_DRIVER_BRANCH:-master}/tools/internal_ci/linux/grpc_xds_k8s_install_test_driver.sh" +## xDS test client Docker images +readonly CLIENT_IMAGE_NAME="gcr.io/grpc-testing/xds-interop/node-client" +readonly FORCE_IMAGE_BUILD="${FORCE_IMAGE_BUILD:-0}" +readonly BUILD_APP_PATH="packages/grpc-js-xds/interop/Dockerfile" +readonly LANGUAGE_NAME="Node" + +####################################### +# Builds test app Docker images and pushes them to GCR +# Globals: +# BUILD_APP_PATH +# CLIENT_IMAGE_NAME: Test client Docker image name +# GIT_COMMIT: SHA-1 of git commit being built +# TESTING_VERSION: version branch under test, f.e. v1.42.x, master +# Arguments: +# None +# Outputs: +# Writes the output of `gcloud builds submit` to stdout, stderr +####################################### +build_test_app_docker_images() { + echo "Building ${LANGUAGE_NAME} xDS interop test app Docker images" + + pushd "${SRC_DIR}" + docker build \ + -f "${BUILD_APP_PATH}" \ + -t "${CLIENT_IMAGE_NAME}:${GIT_COMMIT}" \ + . + + gcloud -q auth configure-docker + docker push "${CLIENT_IMAGE_NAME}:${GIT_COMMIT}" + if is_version_branch "${TESTING_VERSION}"; then + tag_and_push_docker_image "${CLIENT_IMAGE_NAME}" "${GIT_COMMIT}" "${TESTING_VERSION}" + fi + popd +} + +####################################### +# Builds test app and its docker images unless they already exist +# Globals: +# CLIENT_IMAGE_NAME: Test client Docker image name +# GIT_COMMIT: SHA-1 of git commit being built +# FORCE_IMAGE_BUILD +# Arguments: +# None +# Outputs: +# Writes the output to stdout, stderr +####################################### +build_docker_images_if_needed() { + # Check if images already exist + client_tags="$(gcloud_gcr_list_image_tags "${CLIENT_IMAGE_NAME}" "${GIT_COMMIT}")" + printf "Client image: %s:%s\n" "${CLIENT_IMAGE_NAME}" "${GIT_COMMIT}" + echo "${client_tags:-Client image not found}" + + # Build if any of the images are missing, or FORCE_IMAGE_BUILD=1 + if [[ "${FORCE_IMAGE_BUILD}" == "1" || -z "${client_tags}" ]]; then + build_test_app_docker_images + else + echo "Skipping ${LANGUAGE_NAME} test app build" + fi +} + +####################################### +# Executes the test case +# Globals: +# TEST_DRIVER_FLAGFILE: Relative path to test driver flagfile +# KUBE_CONTEXT: The name of kubectl context with GKE cluster access +# TEST_XML_OUTPUT_DIR: Output directory for the test xUnit XML report +# CLIENT_IMAGE_NAME: Test client Docker image name +# GIT_COMMIT: SHA-1 of git commit being built +# TESTING_VERSION: version branch under test: used by the framework to determine the supported PSM +# features. +# Arguments: +# Test case name +# Outputs: +# Writes the output of test execution to stdout, stderr +# Test xUnit report to ${TEST_XML_OUTPUT_DIR}/${test_name}/sponge_log.xml +####################################### +run_test() { + # Test driver usage: + # https://github.com/grpc/grpc/tree/master/tools/run_tests/xds_k8s_test_driver#basic-usage + local test_name="${1:?Usage: run_test test_name}" + local out_dir="${TEST_XML_OUTPUT_DIR}/${test_name}" + mkdir -pv "${out_dir}" + set -x + python3 -m "tests.${test_name}" \ + --flagfile="${TEST_DRIVER_FLAGFILE}" \ + --flagfile="config/url-map.cfg" \ + --kube_context="${KUBE_CONTEXT}" \ + --client_image="${CLIENT_IMAGE_NAME}:${GIT_COMMIT}" \ + --testing_version="${TESTING_VERSION}" \ + --collect_app_logs \ + --log_dir="${out_dir}" \ + --xml_output_file="${out_dir}/sponge_log.xml" \ + |& tee "${out_dir}/sponge_log.log" +} + +####################################### +# Main function: provision software necessary to execute tests, and run them +# Globals: +# KOKORO_ARTIFACTS_DIR +# GITHUB_REPOSITORY_NAME +# SRC_DIR: Populated with absolute path to the source repo +# TEST_DRIVER_REPO_DIR: Populated with the path to the repo containing +# the test driver +# TEST_DRIVER_FULL_DIR: Populated with the path to the test driver source code +# TEST_DRIVER_FLAGFILE: Populated with relative path to test driver flagfile +# TEST_XML_OUTPUT_DIR: Populated with the path to test xUnit XML report +# GIT_ORIGIN_URL: Populated with the origin URL of git repo used for the build +# GIT_COMMIT: Populated with the SHA-1 of git commit being built +# GIT_COMMIT_SHORT: Populated with the short SHA-1 of git commit being built +# KUBE_CONTEXT: Populated with name of kubectl context with GKE cluster access +# Arguments: +# None +# Outputs: +# Writes the output of test execution to stdout, stderr +####################################### +main() { + local script_dir + script_dir="$(dirname "$0")" + + cd "${script_dir}" + + git submodule update --init --recursive + + # Source the test driver from the master branch. + echo "Sourcing test driver install script from: ${TEST_DRIVER_INSTALL_SCRIPT_URL}" + source /dev/stdin <<< "$(curl -s "${TEST_DRIVER_INSTALL_SCRIPT_URL}")" + + activate_gke_cluster GKE_CLUSTER_PSM_BASIC + + set -x + if [[ -n "${KOKORO_ARTIFACTS_DIR}" ]]; then + kokoro_setup_test_driver "${GITHUB_REPOSITORY_NAME}" + else + local_setup_test_driver "${script_dir}" + fi + build_docker_images_if_needed + # Run tests + cd "${TEST_DRIVER_FULL_DIR}" + run_test url_map +} + +main "$@" diff --git a/packages/grpc-js-xds/src/environment.ts b/packages/grpc-js-xds/src/environment.ts index b8b518da..250f791a 100644 --- a/packages/grpc-js-xds/src/environment.ts +++ b/packages/grpc-js-xds/src/environment.ts @@ -16,4 +16,4 @@ */ export const EXPERIMENTAL_FAULT_INJECTION = (process.env.GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION ?? 'true') === 'true'; -export const EXPERIMENTAL_OUTLIER_DETECTION = process.env.GRPC_EXPERIMENTAL_ENABLE_OUTLIER_DETECTION === 'true'; \ No newline at end of file +export const EXPERIMENTAL_OUTLIER_DETECTION = (process.env.GRPC_EXPERIMENTAL_ENABLE_OUTLIER_DETECTION ?? 'true') === 'true'; \ No newline at end of file diff --git a/packages/grpc-js-xds/src/load-balancer-cds.ts b/packages/grpc-js-xds/src/load-balancer-cds.ts index a6dbf42f..4d47b254 100644 --- a/packages/grpc-js-xds/src/load-balancer-cds.ts +++ b/packages/grpc-js-xds/src/load-balancer-cds.ts @@ -79,9 +79,8 @@ function translateOutlierDetectionConfig(outlierDetection: OutlierDetection__Out return undefined; } if (!outlierDetection) { - /* No-op outlier detection config, with max possible interval and no - * ejection criteria configured. */ - return new OutlierDetectionLoadBalancingConfig(~(1<<31), null, null, null, null, null, []); + /* No-op outlier detection config, with all fields unset. */ + return new OutlierDetectionLoadBalancingConfig(null, null, null, null, null, null, []); } let successRateConfig: Partial | null = null; /* Success rate ejection is enabled by default, so we only disable it if diff --git a/packages/grpc-js-xds/src/load-balancer-priority.ts b/packages/grpc-js-xds/src/load-balancer-priority.ts index b05e459a..12037a77 100644 --- a/packages/grpc-js-xds/src/load-balancer-priority.ts +++ b/packages/grpc-js-xds/src/load-balancer-priority.ts @@ -115,7 +115,6 @@ interface PriorityChildBalancer { resetBackoff(): void; deactivate(): void; maybeReactivate(): void; - cancelFailoverTimer(): void; isFailoverTimerPending(): boolean; getConnectivityState(): ConnectivityState; getPicker(): Picker; @@ -138,6 +137,7 @@ export class PriorityLoadBalancer implements LoadBalancer { private childBalancer: ChildLoadBalancerHandler; private failoverTimer: NodeJS.Timer | null = null; private deactivationTimer: NodeJS.Timer | null = null; + private seenReadyOrIdleSinceTransientFailure = false; constructor(private parent: PriorityLoadBalancer, private name: string) { this.childBalancer = new ChildLoadBalancerHandler(experimental.createChildChannelControlHelper(this.parent.channelControlHelper, { updateState: (connectivityState: ConnectivityState, picker: Picker) => { @@ -145,12 +145,24 @@ export class PriorityLoadBalancer implements LoadBalancer { }, })); this.picker = new QueuePicker(this.childBalancer); + this.startFailoverTimer(); } private updateState(connectivityState: ConnectivityState, picker: Picker) { trace('Child ' + this.name + ' ' + ConnectivityState[this.connectivityState] + ' -> ' + ConnectivityState[connectivityState]); this.connectivityState = connectivityState; this.picker = picker; + if (connectivityState === ConnectivityState.CONNECTING) { + if (this.seenReadyOrIdleSinceTransientFailure && this.failoverTimer === null) { + this.startFailoverTimer(); + } + } else if (connectivityState === ConnectivityState.READY || connectivityState === ConnectivityState.IDLE) { + this.seenReadyOrIdleSinceTransientFailure = true; + this.cancelFailoverTimer(); + } else if (connectivityState === ConnectivityState.TRANSIENT_FAILURE) { + this.seenReadyOrIdleSinceTransientFailure = false; + this.cancelFailoverTimer(); + } this.parent.onChildStateChange(this); } @@ -174,13 +186,9 @@ export class PriorityLoadBalancer implements LoadBalancer { attributes: { [key: string]: unknown } ): void { this.childBalancer.updateAddressList(addressList, lbConfig, attributes); - this.startFailoverTimer(); } exitIdle() { - if (this.connectivityState === ConnectivityState.IDLE) { - this.startFailoverTimer(); - } this.childBalancer.exitIdle(); } @@ -204,7 +212,7 @@ export class PriorityLoadBalancer implements LoadBalancer { } } - cancelFailoverTimer() { + private cancelFailoverTimer() { if (this.failoverTimer !== null) { clearTimeout(this.failoverTimer); this.failoverTimer = null; @@ -258,14 +266,8 @@ export class PriorityLoadBalancer implements LoadBalancer { * Current chosen priority that requests are sent to */ private currentPriority: number | null = null; - /** - * After an update, this preserves the currently selected child from before - * the update. We continue to use that child until it disconnects, or - * another higher-priority child connects, or it is deleted because it is not - * in the new priority list at all and its retention interval has expired, or - * we try and fail to connect to every child in the new priority list. - */ - private currentChildFromBeforeUpdate: PriorityChildBalancer | null = null; + + private updatesPaused = false; constructor(private channelControlHelper: ChannelControlHelper) {} @@ -286,57 +288,14 @@ export class PriorityLoadBalancer implements LoadBalancer { private onChildStateChange(child: PriorityChildBalancer) { const childState = child.getConnectivityState(); trace('Child ' + child.getName() + ' transitioning to ' + ConnectivityState[childState]); - if (child === this.currentChildFromBeforeUpdate) { - if ( - childState === ConnectivityState.READY || - childState === ConnectivityState.IDLE - ) { - this.updateState(childState, child.getPicker()); - } else { - this.currentChildFromBeforeUpdate = null; - this.tryNextPriority(true); - } + if (this.updatesPaused) { return; } - const childPriority = this.priorities.indexOf(child.getName()); - if (childPriority < 0) { - // child is not in the priority list, ignore updates - return; - } - if (this.currentPriority !== null && childPriority > this.currentPriority) { - // child is lower priority than the currently selected child, ignore updates - return; - } - if (childState === ConnectivityState.TRANSIENT_FAILURE) { - /* Report connecting if and only if the currently selected child is the - * one entering TRANSIENT_FAILURE */ - this.tryNextPriority(childPriority === this.currentPriority); - return; - } - if (this.currentPriority === null || childPriority < this.currentPriority) { - /* In this case, either there is no currently selected child or this - * child is higher priority than the currently selected child, so we want - * to switch to it if it is READY or IDLE. */ - if ( - childState === ConnectivityState.READY || - childState === ConnectivityState.IDLE - ) { - this.selectPriority(childPriority); - } - return; - } - /* The currently selected child has updated state to something other than - * TRANSIENT_FAILURE, so we pass that update along */ - this.updateState(childState, child.getPicker()); + this.choosePriority(); } private deleteChild(child: PriorityChildBalancer) { - if (child === this.currentChildFromBeforeUpdate) { - this.currentChildFromBeforeUpdate = null; - /* If we get to this point, the currentChildFromBeforeUpdate was still in - * use, so we are still trying to connect to the specified priorities */ - this.tryNextPriority(true); - } + this.children.delete(child.getName()); } /** @@ -345,35 +304,31 @@ export class PriorityLoadBalancer implements LoadBalancer { * child connects. * @param priority */ - private selectPriority(priority: number) { + private selectPriority(priority: number, deactivateLowerPriorities: boolean) { this.currentPriority = priority; const chosenChild = this.children.get(this.priorities[priority])!; - chosenChild.cancelFailoverTimer(); this.updateState( chosenChild.getConnectivityState(), chosenChild.getPicker() ); - this.currentChildFromBeforeUpdate = null; - // Deactivate each child of lower priority than the chosen child - for (let i = priority + 1; i < this.priorities.length; i++) { - this.children.get(this.priorities[i])?.deactivate(); + if (deactivateLowerPriorities) { + for (let i = priority + 1; i < this.priorities.length; i++) { + this.children.get(this.priorities[i])?.deactivate(); + } } } - /** - * Check each child in priority order until we find one to use - * @param reportConnecting Whether we should report a CONNECTING state if we - * stop before picking a specific child. This should be true when we have - * not already selected a child. - */ - private tryNextPriority(reportConnecting: boolean) { - for (const [index, childName] of this.priorities.entries()) { + private choosePriority() { + if (this.priorities.length === 0) { + this.updateState(ConnectivityState.TRANSIENT_FAILURE, new UnavailablePicker({code: Status.UNAVAILABLE, details: 'priority policy has empty priority list', metadata: new Metadata()})); + return; + } + + for (const [priority, childName] of this.priorities.entries()) { + trace('Trying priority ' + priority + ' child ' + childName); let child = this.children.get(childName); /* If the child doesn't already exist, create it and update it. */ if (child === undefined) { - if (reportConnecting) { - this.updateState(ConnectivityState.CONNECTING, new QueuePicker(this)); - } child = new this.PriorityChildImpl(this, childName); this.children.set(childName, child); const childUpdate = this.latestUpdates.get(childName); @@ -384,36 +339,38 @@ export class PriorityLoadBalancer implements LoadBalancer { this.latestAttributes ); } + } else { + /* We're going to try to use this child, so reactivate it if it has been + * deactivated */ + child.maybeReactivate(); } - /* We're going to try to use this child, so reactivate it if it has been - * deactivated */ - child.maybeReactivate(); if ( child.getConnectivityState() === ConnectivityState.READY || child.getConnectivityState() === ConnectivityState.IDLE ) { - this.selectPriority(index); + this.selectPriority(priority, true); return; } if (child.isFailoverTimerPending()) { + this.selectPriority(priority, false); /* This child is still trying to connect. Wait until its failover timer - * has ended to continue to the next one */ - if (reportConnecting) { - this.updateState(ConnectivityState.CONNECTING, new QueuePicker(this)); - } + * has ended to continue to the next one */ return; } } - this.currentPriority = null; - this.currentChildFromBeforeUpdate = null; - this.updateState( - ConnectivityState.TRANSIENT_FAILURE, - new UnavailablePicker({ - code: Status.UNAVAILABLE, - details: 'No ready priority', - metadata: new Metadata(), - }) - ); + + /* If we didn't find any priority to try, pick the first one in the state + * CONNECTING */ + for (const [priority, childName] of this.priorities.entries()) { + let child = this.children.get(childName)!; + if (child.getConnectivityState() === ConnectivityState.CONNECTING) { + this.selectPriority(priority, false); + return; + } + } + + // Did not find any child in CONNECTING, delegate to last child + this.selectPriority(this.priorities.length - 1, false); } updateAddressList( @@ -455,15 +412,10 @@ export class PriorityLoadBalancer implements LoadBalancer { } childAddressList.push(childAddress); } - if (this.currentPriority !== null) { - this.currentChildFromBeforeUpdate = this.children.get( - this.priorities[this.currentPriority] - )!; - this.currentPriority = null; - } this.latestAttributes = attributes; this.latestUpdates.clear(); this.priorities = lbConfig.getPriorities(); + this.updatesPaused = true; /* Pair up the new child configs with the corresponding address lists, and * update all existing children with their new configs */ for (const [childName, childConfig] of lbConfig.getChildren()) { @@ -492,8 +444,8 @@ export class PriorityLoadBalancer implements LoadBalancer { child.deactivate(); } } - // Only report connecting if there are no existing children - this.tryNextPriority(this.children.size === 0); + this.updatesPaused = false; + this.choosePriority(); } exitIdle(): void { if (this.currentPriority !== null) { @@ -510,8 +462,6 @@ export class PriorityLoadBalancer implements LoadBalancer { child.destroy(); } this.children.clear(); - this.currentChildFromBeforeUpdate?.destroy(); - this.currentChildFromBeforeUpdate = null; } getTypeName(): string { return TYPE_NAME; diff --git a/packages/grpc-js-xds/src/load-balancer-weighted-target.ts b/packages/grpc-js-xds/src/load-balancer-weighted-target.ts index a7a28c66..5d7cfa04 100644 --- a/packages/grpc-js-xds/src/load-balancer-weighted-target.ts +++ b/packages/grpc-js-xds/src/load-balancer-weighted-target.ts @@ -181,7 +181,7 @@ export class WeightedTargetLoadBalancer implements LoadBalancer { trace('Target ' + this.name + ' ' + ConnectivityState[this.connectivityState] + ' -> ' + ConnectivityState[connectivityState]); this.connectivityState = connectivityState; this.picker = picker; - this.parent.updateState(); + this.parent.maybeUpdateState(); } updateAddressList(addressList: SubchannelAddress[], lbConfig: WeightedTarget, attributes: { [key: string]: unknown; }): void { @@ -238,9 +238,16 @@ export class WeightedTargetLoadBalancer implements LoadBalancer { * List of current target names. */ private targetList: string[] = []; + private updatesPaused = false; constructor(private channelControlHelper: ChannelControlHelper) {} + private maybeUpdateState() { + if (!this.updatesPaused) { + this.updateState() + } + } + private updateState() { const pickerList: WeightedPicker[] = []; let end = 0; @@ -343,6 +350,7 @@ export class WeightedTargetLoadBalancer implements LoadBalancer { childAddressList.push(childAddress); } + this.updatesPaused = true; this.targetList = Array.from(lbConfig.getTargets().keys()); for (const [targetName, targetConfig] of lbConfig.getTargets()) { let target = this.targets.get(targetName); @@ -364,6 +372,7 @@ export class WeightedTargetLoadBalancer implements LoadBalancer { target.deactivate(); } } + this.updatesPaused = false; this.updateState(); } diff --git a/packages/grpc-js-xds/src/load-balancer-xds-cluster-manager.ts b/packages/grpc-js-xds/src/load-balancer-xds-cluster-manager.ts index 6210ea84..bfc55c80 100644 --- a/packages/grpc-js-xds/src/load-balancer-xds-cluster-manager.ts +++ b/packages/grpc-js-xds/src/load-balancer-xds-cluster-manager.ts @@ -144,7 +144,7 @@ class XdsClusterManager implements LoadBalancer { trace('Child ' + this.name + ' ' + ConnectivityState[this.connectivityState] + ' -> ' + ConnectivityState[connectivityState]); this.connectivityState = connectivityState; this.picker = picker; - this.parent.updateState(); + this.parent.maybeUpdateState(); } updateAddressList(addressList: SubchannelAddress[], lbConfig: ClusterManagerChild, attributes: { [key: string]: unknown; }): void { const childConfig = getFirstUsableConfig(lbConfig.child_policy); @@ -173,8 +173,15 @@ class XdsClusterManager implements LoadBalancer { private children: Map = new Map(); // Shutdown is a placeholder value that will never appear in normal operation. private currentState: ConnectivityState = ConnectivityState.SHUTDOWN; + private updatesPaused = false; constructor(private channelControlHelper: ChannelControlHelper) {} + private maybeUpdateState() { + if (!this.updatesPaused) { + this.updateState(); + } + } + private updateState() { const pickerMap: Map = new Map(); let anyReady = false; @@ -250,6 +257,7 @@ class XdsClusterManager implements LoadBalancer { namesToRemove.push(name); } } + this.updatesPaused = true; for (const name of namesToRemove) { this.children.get(name)!.destroy(); this.children.delete(name); @@ -262,6 +270,7 @@ class XdsClusterManager implements LoadBalancer { this.children.set(name, newChild); } } + this.updatesPaused = false; this.updateState(); } exitIdle(): void { diff --git a/packages/grpc-js-xds/src/resolver-xds.ts b/packages/grpc-js-xds/src/resolver-xds.ts index f6e2ad40..8c447931 100644 --- a/packages/grpc-js-xds/src/resolver-xds.ts +++ b/packages/grpc-js-xds/src/resolver-xds.ts @@ -319,9 +319,12 @@ class XdsResolver implements Resolver { private handleRouteConfig(routeConfig: RouteConfiguration__Output, isV2: boolean) { this.latestRouteConfig = routeConfig; this.latestRouteConfigIsV2 = isV2; - const virtualHost = findVirtualHostForDomain(routeConfig.virtual_hosts, this.target.path); + /* Select the virtual host using the default authority override if it + * exists, and the channel target otherwise. */ + const hostDomain = this.channelOptions['grpc.default_authority'] ?? this.target.path; + const virtualHost = findVirtualHostForDomain(routeConfig.virtual_hosts, hostDomain); if (virtualHost === null) { - this.reportResolutionError('No matching route found'); + this.reportResolutionError('No matching route found for ' + hostDomain); return; } const virtualHostHttpFilterOverrides = new Map(); diff --git a/packages/grpc-js-xds/src/xds-client.ts b/packages/grpc-js-xds/src/xds-client.ts index 7a12af1f..0c8126cb 100644 --- a/packages/grpc-js-xds/src/xds-client.ts +++ b/packages/grpc-js-xds/src/xds-client.ts @@ -309,7 +309,7 @@ export class XdsClient { const edsState = new EdsState(() => { this.updateNames('eds'); }); - const cdsState = new CdsState(edsState, () => { + const cdsState = new CdsState(() => { this.updateNames('cds'); }); const rdsState = new RdsState(() => { @@ -360,6 +360,10 @@ export class XdsClient { } else { this.apiVersion = XdsApiVersion.V2; } + if (bootstrapInfo.xdsServers[0].serverFeatures.indexOf('ignore_resource_deletion') >= 0) { + this.adsState.lds.enableIgnoreResourceDeletion(); + this.adsState.cds.enableIgnoreResourceDeletion(); + } const nodeV2: NodeV2 = { ...bootstrapInfo.node, build_version: `gRPC Node Pure JS ${clientVersion}`, @@ -630,6 +634,7 @@ export class XdsClient { this.updateNames(service); } } + this.reportAdsStreamStarted(); } } @@ -726,7 +731,7 @@ export class XdsClient { if (serviceKind) { this.adsState[serviceKind].reportStreamError({ code: status.UNAVAILABLE, - details: message, + details: message + ' Node ID=' + this.adsNodeV3!.id, metadata: new Metadata() }); resourceNames = this.adsState[serviceKind].getResourceNames(); @@ -771,17 +776,24 @@ export class XdsClient { } private reportStreamError(status: StatusObject) { + status = {...status, details: status.details + ' Node ID=' + this.adsNodeV3!.id}; this.adsState.eds.reportStreamError(status); this.adsState.cds.reportStreamError(status); this.adsState.rds.reportStreamError(status); this.adsState.lds.reportStreamError(status); } + private reportAdsStreamStarted() { + this.adsState.eds.reportAdsStreamStart(); + this.adsState.cds.reportAdsStreamStart(); + this.adsState.rds.reportAdsStreamStart(); + this.adsState.lds.reportAdsStreamStart(); + } + private handleLrsResponse(message: LoadStatsResponse__Output) { trace('Received LRS response'); /* Once we get any response from the server, we assume that the stream is * in a good state, so we can reset the backoff timer. */ - this.lrsBackoff.stop(); this.lrsBackoff.reset(); if ( !this.receivedLrsSettingsForCurrentStream || diff --git a/packages/grpc-js-xds/src/xds-stream-state/cds-state.ts b/packages/grpc-js-xds/src/xds-stream-state/cds-state.ts index 8c3c4d73..9fd12d6e 100644 --- a/packages/grpc-js-xds/src/xds-stream-state/cds-state.ts +++ b/packages/grpc-js-xds/src/xds-stream-state/cds-state.ts @@ -15,94 +15,21 @@ * */ -import { experimental, logVerbosity, StatusObject } from "@grpc/grpc-js"; import { EXPERIMENTAL_OUTLIER_DETECTION } from "../environment"; import { Cluster__Output } from "../generated/envoy/config/cluster/v3/Cluster"; -import { Any__Output } from "../generated/google/protobuf/Any"; import { Duration__Output } from "../generated/google/protobuf/Duration"; import { UInt32Value__Output } from "../generated/google/protobuf/UInt32Value"; -import { EdsState } from "./eds-state"; -import { HandleResponseResult, RejectedResourceEntry, ResourcePair, Watcher, XdsStreamState } from "./xds-stream-state"; +import { BaseXdsStreamState, XdsStreamState } from "./xds-stream-state"; -const TRACER_NAME = 'xds_client'; - -function trace(text: string): void { - experimental.trace(logVerbosity.DEBUG, TRACER_NAME, text); -} - -export class CdsState implements XdsStreamState { - versionInfo = ''; - nonce = ''; - - private watchers: Map[]> = new Map< - string, - Watcher[] - >(); - - private latestResponses: Cluster__Output[] = []; - private latestIsV2 = false; - - constructor( - private edsState: EdsState, - private updateResourceNames: () => void - ) {} - - /** - * Add the watcher to the watcher list. Returns true if the list of resource - * names has changed, and false otherwise. - * @param clusterName - * @param watcher - */ - addWatcher(clusterName: string, watcher: Watcher): void { - trace('Adding CDS watcher for clusterName ' + clusterName); - let watchersEntry = this.watchers.get(clusterName); - let addedServiceName = false; - if (watchersEntry === undefined) { - addedServiceName = true; - watchersEntry = []; - this.watchers.set(clusterName, watchersEntry); - } - watchersEntry.push(watcher); - - /* If we have already received an update for the requested edsServiceName, - * immediately pass that update along to the watcher */ - const isV2 = this.latestIsV2; - for (const message of this.latestResponses) { - if (message.name === clusterName) { - /* These updates normally occur asynchronously, so we ensure that - * the same happens here */ - process.nextTick(() => { - trace('Reporting existing CDS update for new watcher for clusterName ' + clusterName); - watcher.onValidUpdate(message, isV2); - }); - } - } - if (addedServiceName) { - this.updateResourceNames(); - } +export class CdsState extends BaseXdsStreamState implements XdsStreamState { + protected isStateOfTheWorld(): boolean { + return true; } - - removeWatcher(clusterName: string, watcher: Watcher): void { - trace('Removing CDS watcher for clusterName ' + clusterName); - const watchersEntry = this.watchers.get(clusterName); - let removedServiceName = false; - if (watchersEntry !== undefined) { - const entryIndex = watchersEntry.indexOf(watcher); - if (entryIndex >= 0) { - watchersEntry.splice(entryIndex, 1); - } - if (watchersEntry.length === 0) { - removedServiceName = true; - this.watchers.delete(clusterName); - } - } - if (removedServiceName) { - this.updateResourceNames(); - } + protected getResourceName(resource: Cluster__Output): string { + return resource.name; } - - getResourceNames(): string[] { - return Array.from(this.watchers.keys()); + protected getProtocolName(): string { + return 'CDS'; } private validateNonnegativeDuration(duration: Duration__Output | null): boolean { @@ -125,7 +52,7 @@ export class CdsState implements XdsStreamState { return percentage.value >=0 && percentage.value <= 100; } - private validateResponse(message: Cluster__Output): boolean { + public validateResponse(message: Cluster__Output): boolean { if (message.type !== 'EDS') { return false; } @@ -167,69 +94,4 @@ export class CdsState implements XdsStreamState { } return true; } - - /** - * Given a list of clusterNames (which may actually be the cluster name), - * for each watcher watching a name not on the list, call that watcher's - * onResourceDoesNotExist method. - * @param allClusterNames - */ - private handleMissingNames(allClusterNames: Set): string[] { - const missingNames: string[] = []; - for (const [clusterName, watcherList] of this.watchers.entries()) { - if (!allClusterNames.has(clusterName)) { - trace('Reporting CDS resource does not exist for clusterName ' + clusterName); - missingNames.push(clusterName); - for (const watcher of watcherList) { - watcher.onResourceDoesNotExist(); - } - } - } - return missingNames; - } - - handleResponses(responses: ResourcePair[], isV2: boolean): HandleResponseResult { - const validResponses: Cluster__Output[] = []; - const result: HandleResponseResult = { - accepted: [], - rejected: [], - missing: [] - } - for (const {resource, raw} of responses) { - if (this.validateResponse(resource)) { - validResponses.push(resource); - result.accepted.push({ - name: resource.name, - raw: raw}); - } else { - trace('CDS validation failed for message ' + JSON.stringify(resource)); - result.rejected.push({ - name: resource.name, - raw: raw, - error: `Cluster validation failed for resource ${resource.name}` - }); - } - } - this.latestResponses = validResponses; - this.latestIsV2 = isV2; - const allClusterNames: Set = new Set(); - for (const message of validResponses) { - allClusterNames.add(message.name); - const watchers = this.watchers.get(message.name) ?? []; - for (const watcher of watchers) { - watcher.onValidUpdate(message, isV2); - } - } - trace('Received CDS updates for cluster names [' + Array.from(allClusterNames) + ']'); - result.missing = this.handleMissingNames(allClusterNames); - return result; - } - - reportStreamError(status: StatusObject): void { - for (const watcherList of this.watchers.values()) { - for (const watcher of watcherList) { - watcher.onTransientError(status); - } - } - } } \ No newline at end of file diff --git a/packages/grpc-js-xds/src/xds-stream-state/eds-state.ts b/packages/grpc-js-xds/src/xds-stream-state/eds-state.ts index fe9f3c62..9b7b9cd5 100644 --- a/packages/grpc-js-xds/src/xds-stream-state/eds-state.ts +++ b/packages/grpc-js-xds/src/xds-stream-state/eds-state.ts @@ -17,9 +17,11 @@ import { experimental, logVerbosity, StatusObject } from "@grpc/grpc-js"; import { isIPv4, isIPv6 } from "net"; +import { Locality__Output } from "../generated/envoy/config/core/v3/Locality"; +import { SocketAddress__Output } from "../generated/envoy/config/core/v3/SocketAddress"; import { ClusterLoadAssignment__Output } from "../generated/envoy/config/endpoint/v3/ClusterLoadAssignment"; import { Any__Output } from "../generated/google/protobuf/Any"; -import { HandleResponseResult, RejectedResourceEntry, ResourcePair, Watcher, XdsStreamState } from "./xds-stream-state"; +import { BaseXdsStreamState, HandleResponseResult, RejectedResourceEntry, ResourcePair, Watcher, XdsStreamState } from "./xds-stream-state"; const TRACER_NAME = 'xds_client'; @@ -27,83 +29,23 @@ function trace(text: string): void { experimental.trace(logVerbosity.DEBUG, TRACER_NAME, text); } -export class EdsState implements XdsStreamState { - public versionInfo = ''; - public nonce = ''; +function localitiesEqual(a: Locality__Output, b: Locality__Output) { + return a.region === b.region && a.sub_zone === b.sub_zone && a.zone === b.zone; +} - private watchers: Map< - string, - Watcher[] - > = new Map[]>(); +function addressesEqual(a: SocketAddress__Output, b: SocketAddress__Output) { + return a.address === b.address && a.port_value === b.port_value; +} - private latestResponses: ClusterLoadAssignment__Output[] = []; - private latestIsV2 = false; - - constructor(private updateResourceNames: () => void) {} - - /** - * Add the watcher to the watcher list. Returns true if the list of resource - * names has changed, and false otherwise. - * @param edsServiceName - * @param watcher - */ - addWatcher( - edsServiceName: string, - watcher: Watcher - ): void { - let watchersEntry = this.watchers.get(edsServiceName); - let addedServiceName = false; - if (watchersEntry === undefined) { - addedServiceName = true; - watchersEntry = []; - this.watchers.set(edsServiceName, watchersEntry); - } - trace('Adding EDS watcher (' + watchersEntry.length + ' ->' + (watchersEntry.length + 1) + ') for edsServiceName ' + edsServiceName); - watchersEntry.push(watcher); - - /* If we have already received an update for the requested edsServiceName, - * immediately pass that update along to the watcher */ - const isV2 = this.latestIsV2; - for (const message of this.latestResponses) { - if (message.cluster_name === edsServiceName) { - /* These updates normally occur asynchronously, so we ensure that - * the same happens here */ - process.nextTick(() => { - trace('Reporting existing EDS update for new watcher for edsServiceName ' + edsServiceName); - watcher.onValidUpdate(message, isV2); - }); - } - } - if (addedServiceName) { - this.updateResourceNames(); - } +export class EdsState extends BaseXdsStreamState implements XdsStreamState { + protected getResourceName(resource: ClusterLoadAssignment__Output): string { + return resource.cluster_name; } - - removeWatcher( - edsServiceName: string, - watcher: Watcher - ): void { - trace('Removing EDS watcher for edsServiceName ' + edsServiceName); - const watchersEntry = this.watchers.get(edsServiceName); - let removedServiceName = false; - if (watchersEntry !== undefined) { - const entryIndex = watchersEntry.indexOf(watcher); - if (entryIndex >= 0) { - trace('Removed EDS watcher (' + watchersEntry.length + ' -> ' + (watchersEntry.length - 1) + ') for edsServiceName ' + edsServiceName); - watchersEntry.splice(entryIndex, 1); - } - if (watchersEntry.length === 0) { - removedServiceName = true; - this.watchers.delete(edsServiceName); - } - } - if (removedServiceName) { - this.updateResourceNames(); - } + protected getProtocolName(): string { + return 'EDS'; } - - getResourceNames(): string[] { - return Array.from(this.watchers.keys()); + protected isStateOfTheWorld(): boolean { + return false; } /** @@ -111,8 +53,20 @@ export class EdsState implements XdsStreamState { * https://github.com/grpc/proposal/blob/master/A27-xds-global-load-balancing.md#clusterloadassignment-proto * @param message */ - private validateResponse(message: ClusterLoadAssignment__Output) { + public validateResponse(message: ClusterLoadAssignment__Output) { + const seenLocalities: {locality: Locality__Output, priority: number}[] = []; + const seenAddresses: SocketAddress__Output[] = []; + const priorityTotalWeights: Map = new Map(); for (const endpoint of message.endpoints) { + if (!endpoint.locality) { + return false; + } + for (const {locality, priority} of seenLocalities) { + if (localitiesEqual(endpoint.locality, locality) && endpoint.priority === priority) { + return false; + } + } + seenLocalities.push({locality: endpoint.locality, priority: endpoint.priority}); for (const lb of endpoint.lb_endpoints) { const socketAddress = lb.endpoint?.address?.socket_address; if (!socketAddress) { @@ -124,52 +78,25 @@ export class EdsState implements XdsStreamState { if (!(isIPv4(socketAddress.address) || isIPv6(socketAddress.address))) { return false; } + for (const address of seenAddresses) { + if (addressesEqual(socketAddress, address)) { + return false; + } + } + seenAddresses.push(socketAddress); + } + priorityTotalWeights.set(endpoint.priority, (priorityTotalWeights.get(endpoint.priority) ?? 0) + (endpoint.load_balancing_weight?.value ?? 0)); + } + for (const totalWeight of priorityTotalWeights.values()) { + if (totalWeight >= 1<<32) { + return false; + } + } + for (const priority of priorityTotalWeights.keys()) { + if (priority > 0 && !priorityTotalWeights.has(priority - 1)) { + return false; } } return true; } - - handleResponses(responses: ResourcePair[], isV2: boolean): HandleResponseResult { - const validResponses: ClusterLoadAssignment__Output[] = []; - let result: HandleResponseResult = { - accepted: [], - rejected: [], - missing: [] - } - for (const {resource, raw} of responses) { - if (this.validateResponse(resource)) { - validResponses.push(resource); - result.accepted.push({ - name: resource.cluster_name, - raw: raw}); - } else { - trace('EDS validation failed for message ' + JSON.stringify(resource)); - result.rejected.push({ - name: resource.cluster_name, - raw: raw, - error: `ClusterLoadAssignment validation failed for resource ${resource.cluster_name}` - }); - } - } - this.latestResponses = validResponses; - this.latestIsV2 = isV2; - const allClusterNames: Set = new Set(); - for (const message of validResponses) { - allClusterNames.add(message.cluster_name); - const watchers = this.watchers.get(message.cluster_name) ?? []; - for (const watcher of watchers) { - watcher.onValidUpdate(message, isV2); - } - } - trace('Received EDS updates for cluster names [' + Array.from(allClusterNames) + ']'); - return result; - } - - reportStreamError(status: StatusObject): void { - for (const watcherList of this.watchers.values()) { - for (const watcher of watcherList) { - watcher.onTransientError(status); - } - } - } } \ No newline at end of file diff --git a/packages/grpc-js-xds/src/xds-stream-state/lds-state.ts b/packages/grpc-js-xds/src/xds-stream-state/lds-state.ts index 7c27c948..bd5b6423 100644 --- a/packages/grpc-js-xds/src/xds-stream-state/lds-state.ts +++ b/packages/grpc-js-xds/src/xds-stream-state/lds-state.ts @@ -15,16 +15,13 @@ * */ -import * as protoLoader from '@grpc/proto-loader'; -import { experimental, logVerbosity, StatusObject } from "@grpc/grpc-js"; +import { experimental, logVerbosity } from "@grpc/grpc-js"; import { Listener__Output } from '../generated/envoy/config/listener/v3/Listener'; import { RdsState } from "./rds-state"; -import { HandleResponseResult, RejectedResourceEntry, ResourcePair, Watcher, XdsStreamState } from "./xds-stream-state"; -import { HttpConnectionManager__Output } from '../generated/envoy/extensions/filters/network/http_connection_manager/v3/HttpConnectionManager'; +import { BaseXdsStreamState, XdsStreamState } from "./xds-stream-state"; import { decodeSingleResource, HTTP_CONNECTION_MANGER_TYPE_URL_V2, HTTP_CONNECTION_MANGER_TYPE_URL_V3 } from '../resources'; import { getTopLevelFilterUrl, validateTopLevelFilter } from '../http-filter'; import { EXPERIMENTAL_FAULT_INJECTION } from '../environment'; -import { Any__Output } from '../generated/google/protobuf/Any'; const TRACER_NAME = 'xds_client'; @@ -34,69 +31,22 @@ function trace(text: string): void { const ROUTER_FILTER_URL = 'type.googleapis.com/envoy.extensions.filters.http.router.v3.Router'; -export class LdsState implements XdsStreamState { - versionInfo = ''; - nonce = ''; - - private watchers: Map[]> = new Map[]>(); - private latestResponses: Listener__Output[] = []; - private latestIsV2 = false; - - constructor(private rdsState: RdsState, private updateResourceNames: () => void) {} - - addWatcher(targetName: string, watcher: Watcher) { - trace('Adding RDS watcher for targetName ' + targetName); - let watchersEntry = this.watchers.get(targetName); - let addedServiceName = false; - if (watchersEntry === undefined) { - addedServiceName = true; - watchersEntry = []; - this.watchers.set(targetName, watchersEntry); - } - watchersEntry.push(watcher); - - /* If we have already received an update for the requested edsServiceName, - * immediately pass that update along to the watcher */ - const isV2 = this.latestIsV2; - for (const message of this.latestResponses) { - if (message.name === targetName) { - /* These updates normally occur asynchronously, so we ensure that - * the same happens here */ - process.nextTick(() => { - trace('Reporting existing RDS update for new watcher for targetName ' + targetName); - watcher.onValidUpdate(message, isV2); - }); - } - } - if (addedServiceName) { - this.updateResourceNames(); - } +export class LdsState extends BaseXdsStreamState implements XdsStreamState { + protected getResourceName(resource: Listener__Output): string { + return resource.name; + } + protected getProtocolName(): string { + return 'LDS'; + } + protected isStateOfTheWorld(): boolean { + return true; } - removeWatcher(targetName: string, watcher: Watcher): void { - trace('Removing RDS watcher for targetName ' + targetName); - const watchersEntry = this.watchers.get(targetName); - let removedServiceName = false; - if (watchersEntry !== undefined) { - const entryIndex = watchersEntry.indexOf(watcher); - if (entryIndex >= 0) { - watchersEntry.splice(entryIndex, 1); - } - if (watchersEntry.length === 0) { - removedServiceName = true; - this.watchers.delete(targetName); - } - } - if (removedServiceName) { - this.updateResourceNames(); - } + constructor(private rdsState: RdsState, updateResourceNames: () => void) { + super(updateResourceNames); } - getResourceNames(): string[] { - return Array.from(this.watchers.keys()); - } - - private validateResponse(message: Listener__Output, isV2: boolean): boolean { + public validateResponse(message: Listener__Output, isV2: boolean): boolean { if ( !( message.api_listener?.api_listener && @@ -143,63 +93,4 @@ export class LdsState implements XdsStreamState { } return false; } - - private handleMissingNames(allTargetNames: Set): string[] { - const missingNames: string[] = []; - for (const [targetName, watcherList] of this.watchers.entries()) { - if (!allTargetNames.has(targetName)) { - missingNames.push(targetName); - for (const watcher of watcherList) { - watcher.onResourceDoesNotExist(); - } - } - } - return missingNames; - } - - handleResponses(responses: ResourcePair[], isV2: boolean): HandleResponseResult { - const validResponses: Listener__Output[] = []; - let result: HandleResponseResult = { - accepted: [], - rejected: [], - missing: [] - } - for (const {resource, raw} of responses) { - if (this.validateResponse(resource, isV2)) { - validResponses.push(resource); - result.accepted.push({ - name: resource.name, - raw: raw - }); - } else { - trace('LDS validation failed for message ' + JSON.stringify(resource)); - result.rejected.push({ - name: resource.name, - raw: raw, - error: `Listener validation failed for resource ${resource.name}` - }); - } - } - this.latestResponses = validResponses; - this.latestIsV2 = isV2; - const allTargetNames = new Set(); - for (const message of validResponses) { - allTargetNames.add(message.name); - const watchers = this.watchers.get(message.name) ?? []; - for (const watcher of watchers) { - watcher.onValidUpdate(message, isV2); - } - } - trace('Received LDS response with listener names [' + Array.from(allTargetNames) + ']'); - result.missing = this.handleMissingNames(allTargetNames); - return result; - } - - reportStreamError(status: StatusObject): void { - for (const watcherList of this.watchers.values()) { - for (const watcher of watcherList) { - watcher.onTransientError(status); - } - } - } } \ No newline at end of file diff --git a/packages/grpc-js-xds/src/xds-stream-state/rds-state.ts b/packages/grpc-js-xds/src/xds-stream-state/rds-state.ts index bc1c4a81..a5d3c47c 100644 --- a/packages/grpc-js-xds/src/xds-stream-state/rds-state.ts +++ b/packages/grpc-js-xds/src/xds-stream-state/rds-state.ts @@ -15,20 +15,10 @@ * */ -import { experimental, logVerbosity, StatusObject } from "@grpc/grpc-js"; import { EXPERIMENTAL_FAULT_INJECTION } from "../environment"; import { RouteConfiguration__Output } from "../generated/envoy/config/route/v3/RouteConfiguration"; -import { Any__Output } from "../generated/google/protobuf/Any"; import { validateOverrideFilter } from "../http-filter"; -import { CdsLoadBalancingConfig } from "../load-balancer-cds"; -import { HandleResponseResult, RejectedResourceEntry, ResourcePair, Watcher, XdsStreamState } from "./xds-stream-state"; -import ServiceConfig = experimental.ServiceConfig; - -const TRACER_NAME = 'xds_client'; - -function trace(text: string): void { - experimental.trace(logVerbosity.DEBUG, TRACER_NAME, text); -} +import { BaseXdsStreamState, XdsStreamState } from "./xds-stream-state"; const SUPPORTED_PATH_SPECIFIERS = ['prefix', 'path', 'safe_regex']; const SUPPPORTED_HEADER_MATCH_SPECIFIERS = [ @@ -40,68 +30,16 @@ const SUPPPORTED_HEADER_MATCH_SPECIFIERS = [ 'suffix_match']; const SUPPORTED_CLUSTER_SPECIFIERS = ['cluster', 'weighted_clusters', 'cluster_header']; -export class RdsState implements XdsStreamState { - versionInfo = ''; - nonce = ''; - - private watchers: Map[]> = new Map[]>(); - private latestResponses: RouteConfiguration__Output[] = []; - private latestIsV2 = false; - - constructor(private updateResourceNames: () => void) {} - - addWatcher(routeConfigName: string, watcher: Watcher) { - trace('Adding RDS watcher for routeConfigName ' + routeConfigName); - let watchersEntry = this.watchers.get(routeConfigName); - let addedServiceName = false; - if (watchersEntry === undefined) { - addedServiceName = true; - watchersEntry = []; - this.watchers.set(routeConfigName, watchersEntry); - } - watchersEntry.push(watcher); - - /* If we have already received an update for the requested edsServiceName, - * immediately pass that update along to the watcher */ - const isV2 = this.latestIsV2; - for (const message of this.latestResponses) { - if (message.name === routeConfigName) { - /* These updates normally occur asynchronously, so we ensure that - * the same happens here */ - process.nextTick(() => { - trace('Reporting existing RDS update for new watcher for routeConfigName ' + routeConfigName); - watcher.onValidUpdate(message, isV2); - }); - } - } - if (addedServiceName) { - this.updateResourceNames(); - } +export class RdsState extends BaseXdsStreamState implements XdsStreamState { + protected isStateOfTheWorld(): boolean { + return false; } - - removeWatcher(routeConfigName: string, watcher: Watcher): void { - trace('Removing RDS watcher for routeConfigName ' + routeConfigName); - const watchersEntry = this.watchers.get(routeConfigName); - let removedServiceName = false; - if (watchersEntry !== undefined) { - const entryIndex = watchersEntry.indexOf(watcher); - if (entryIndex >= 0) { - watchersEntry.splice(entryIndex, 1); - } - if (watchersEntry.length === 0) { - removedServiceName = true; - this.watchers.delete(routeConfigName); - } - } - if (removedServiceName) { - this.updateResourceNames(); - } + protected getResourceName(resource: RouteConfiguration__Output): string { + return resource.name; } - - getResourceNames(): string[] { - return Array.from(this.watchers.keys()); + protected getProtocolName(): string { + return 'RDS'; } - validateResponse(message: RouteConfiguration__Output, isV2: boolean): boolean { // https://github.com/grpc/proposal/blob/master/A28-xds-traffic-splitting-and-routing.md#response-validation for (const virtualHost of message.virtual_hosts) { @@ -151,6 +89,9 @@ export class RdsState implements XdsStreamState { } } if (route.route!.cluster_specifier === 'weighted_clusters') { + if (route.route.weighted_clusters!.total_weight?.value === 0) { + return false; + } let weightSum = 0; for (const clusterWeight of route.route.weighted_clusters!.clusters) { weightSum += clusterWeight.weight?.value ?? 0; @@ -172,48 +113,4 @@ export class RdsState implements XdsStreamState { } return true; } - - handleResponses(responses: ResourcePair[], isV2: boolean): HandleResponseResult { - const validResponses: RouteConfiguration__Output[] = []; - let result: HandleResponseResult = { - accepted: [], - rejected: [], - missing: [] - } - for (const {resource, raw} of responses) { - if (this.validateResponse(resource, isV2)) { - validResponses.push(resource); - result.accepted.push({ - name: resource.name, - raw: raw}); - } else { - trace('RDS validation failed for message ' + JSON.stringify(resource)); - result.rejected.push({ - name: resource.name, - raw: raw, - error: `Route validation failed for resource ${resource.name}` - }); - } - } - this.latestResponses = validResponses; - this.latestIsV2 = isV2; - const allRouteConfigNames = new Set(); - for (const message of validResponses) { - allRouteConfigNames.add(message.name); - const watchers = this.watchers.get(message.name) ?? []; - for (const watcher of watchers) { - watcher.onValidUpdate(message, isV2); - } - } - trace('Received RDS response with route config names [' + Array.from(allRouteConfigNames) + ']'); - return result; - } - - reportStreamError(status: StatusObject): void { - for (const watcherList of this.watchers.values()) { - for (const watcher of watcherList) { - watcher.onTransientError(status); - } - } - } } \ No newline at end of file diff --git a/packages/grpc-js-xds/src/xds-stream-state/xds-stream-state.ts b/packages/grpc-js-xds/src/xds-stream-state/xds-stream-state.ts index c8cbc41c..7b3bc018 100644 --- a/packages/grpc-js-xds/src/xds-stream-state/xds-stream-state.ts +++ b/packages/grpc-js-xds/src/xds-stream-state/xds-stream-state.ts @@ -15,9 +15,11 @@ * */ -import { StatusObject } from "@grpc/grpc-js"; +import { experimental, logVerbosity, StatusObject } from "@grpc/grpc-js"; import { Any__Output } from "../generated/google/protobuf/Any"; +const TRACER_NAME = 'xds_client'; + export interface Watcher { /* Including the isV2 flag here is a bit of a kludge. It would probably be * better for XdsStreamState#handleResponses to transform the protobuf @@ -63,4 +65,214 @@ export interface XdsStreamState { handleResponses(responses: ResourcePair[], isV2: boolean): HandleResponseResult; reportStreamError(status: StatusObject): void; + reportAdsStreamStart(): void; + + addWatcher(name: string, watcher: Watcher): void; + removeWatcher(resourceName: string, watcher: Watcher): void; +} + +interface SubscriptionEntry { + watchers: Watcher[]; + cachedResponse: ResponseType | null; + resourceTimer: NodeJS.Timer; + deletionIgnored: boolean; +} + +const RESOURCE_TIMEOUT_MS = 15_000; + +export abstract class BaseXdsStreamState implements XdsStreamState { + versionInfo = ''; + nonce = ''; + + private subscriptions: Map> = new Map>(); + private latestIsV2 = false; + private isAdsStreamRunning = false; + private ignoreResourceDeletion = false; + + constructor(private updateResourceNames: () => void) {} + + protected trace(text: string) { + experimental.trace(logVerbosity.DEBUG, TRACER_NAME, this.getProtocolName() + ' | ' + text); + } + + private startResourceTimer(subscriptionEntry: SubscriptionEntry) { + clearTimeout(subscriptionEntry.resourceTimer); + subscriptionEntry.resourceTimer = setTimeout(() => { + for (const watcher of subscriptionEntry.watchers) { + watcher.onResourceDoesNotExist(); + } + }, RESOURCE_TIMEOUT_MS); + } + + addWatcher(name: string, watcher: Watcher): void { + this.trace('Adding watcher for name ' + name); + let subscriptionEntry = this.subscriptions.get(name); + let addedName = false; + if (subscriptionEntry === undefined) { + addedName = true; + subscriptionEntry = { + watchers: [], + cachedResponse: null, + resourceTimer: setTimeout(() => {}, 0), + deletionIgnored: false + }; + if (this.isAdsStreamRunning) { + this.startResourceTimer(subscriptionEntry); + } + this.subscriptions.set(name, subscriptionEntry); + } + subscriptionEntry.watchers.push(watcher); + if (subscriptionEntry.cachedResponse !== null) { + const cachedResponse = subscriptionEntry.cachedResponse; + /* These updates normally occur asynchronously, so we ensure that + * the same happens here */ + process.nextTick(() => { + this.trace('Reporting existing update for new watcher for name ' + name); + watcher.onValidUpdate(cachedResponse, this.latestIsV2); + }); + } + if (addedName) { + this.updateResourceNames(); + } + } + removeWatcher(resourceName: string, watcher: Watcher): void { + this.trace('Removing watcher for name ' + resourceName); + const subscriptionEntry = this.subscriptions.get(resourceName); + if (subscriptionEntry !== undefined) { + const entryIndex = subscriptionEntry.watchers.indexOf(watcher); + if (entryIndex >= 0) { + subscriptionEntry.watchers.splice(entryIndex, 1); + } + if (subscriptionEntry.watchers.length === 0) { + clearTimeout(subscriptionEntry.resourceTimer); + if (subscriptionEntry.deletionIgnored) { + experimental.log(logVerbosity.INFO, 'Unsubscribing from resource with previously ignored deletion: ' + resourceName); + } + this.subscriptions.delete(resourceName); + this.updateResourceNames(); + } + } + } + + getResourceNames(): string[] { + return Array.from(this.subscriptions.keys()); + } + handleResponses(responses: ResourcePair[], isV2: boolean): HandleResponseResult { + const validResponses: ResponseType[] = []; + let result: HandleResponseResult = { + accepted: [], + rejected: [], + missing: [] + } + for (const {resource, raw} of responses) { + const resourceName = this.getResourceName(resource); + if (this.validateResponse(resource, isV2)) { + validResponses.push(resource); + result.accepted.push({ + name: resourceName, + raw: raw}); + } else { + this.trace('Validation failed for message ' + JSON.stringify(resource)); + result.rejected.push({ + name: resourceName, + raw: raw, + error: `Validation failed for resource ${resourceName}` + }); + } + } + this.latestIsV2 = isV2; + const allResourceNames = new Set(); + for (const resource of validResponses) { + const resourceName = this.getResourceName(resource); + allResourceNames.add(resourceName); + const subscriptionEntry = this.subscriptions.get(resourceName); + if (subscriptionEntry) { + const watchers = subscriptionEntry.watchers; + for (const watcher of watchers) { + watcher.onValidUpdate(resource, isV2); + } + clearTimeout(subscriptionEntry.resourceTimer); + subscriptionEntry.cachedResponse = resource; + if (subscriptionEntry.deletionIgnored) { + experimental.log(logVerbosity.INFO, 'Received resource with previously ignored deletion: ' + resourceName); + subscriptionEntry.deletionIgnored = false; + } + } + } + result.missing = this.handleMissingNames(allResourceNames); + this.trace('Received response with resource names [' + Array.from(allResourceNames) + ']'); + return result; + } + reportStreamError(status: StatusObject): void { + for (const subscriptionEntry of this.subscriptions.values()) { + for (const watcher of subscriptionEntry.watchers) { + watcher.onTransientError(status); + } + clearTimeout(subscriptionEntry.resourceTimer); + } + this.isAdsStreamRunning = false; + this.nonce = ''; + } + + reportAdsStreamStart() { + this.isAdsStreamRunning = true; + for (const subscriptionEntry of this.subscriptions.values()) { + if (subscriptionEntry.cachedResponse === null) { + this.startResourceTimer(subscriptionEntry); + } + } + } + + private handleMissingNames(allResponseNames: Set): string[] { + if (this.isStateOfTheWorld()) { + const missingNames: string[] = []; + for (const [resourceName, subscriptionEntry] of this.subscriptions.entries()) { + if (!allResponseNames.has(resourceName) && subscriptionEntry.cachedResponse !== null) { + if (this.ignoreResourceDeletion) { + if (!subscriptionEntry.deletionIgnored) { + experimental.log(logVerbosity.ERROR, 'Ignoring nonexistent resource ' + resourceName); + subscriptionEntry.deletionIgnored = true; + } + } else { + this.trace('Reporting resource does not exist named ' + resourceName); + missingNames.push(resourceName); + for (const watcher of subscriptionEntry.watchers) { + watcher.onResourceDoesNotExist(); + } + subscriptionEntry.cachedResponse = null; + } + } + } + return missingNames; + } else { + return []; + } + } + + enableIgnoreResourceDeletion() { + this.ignoreResourceDeletion = true; + } + + /** + * Apply the validation rules for this resource type to this resource + * instance. + * This function is public so that the LDS validateResponse can call into + * the RDS validateResponse. + * @param resource The resource object sent by the xDS server + * @param isV2 If true, the resource is an xDS V2 resource instead of xDS V3 + */ + public abstract validateResponse(resource: ResponseType, isV2: boolean): boolean; + /** + * Get the name of a resource object. The name is some field of the object, so + * getting it depends on the specific type. + * @param resource + */ + protected abstract getResourceName(resource: ResponseType): string; + protected abstract getProtocolName(): string; + /** + * Indicates whether responses are "state of the world", i.e. that they + * contain all resources and that omitted previously-seen resources should + * be treated as removed. + */ + protected abstract isStateOfTheWorld(): boolean; } \ No newline at end of file diff --git a/packages/grpc-js/package.json b/packages/grpc-js/package.json index bb8adff8..c0db93ae 100644 --- a/packages/grpc-js/package.json +++ b/packages/grpc-js/package.json @@ -1,6 +1,6 @@ { "name": "@grpc/grpc-js", - "version": "1.6.2", + "version": "1.7.1", "description": "gRPC Library for Node - pure JS implementation", "homepage": "https://grpc.io/", "repository": "https://github.com/grpc/grpc-node/tree/master/packages/grpc-js", @@ -58,7 +58,7 @@ "generate-test-types": "proto-loader-gen-types --keepCase --longs String --enums String --defaults --oneofs --includeComments --include-dirs test/fixtures/ -O test/generated/ --grpcLib ../../src/index test_service.proto" }, "dependencies": { - "@grpc/proto-loader": "^0.6.4", + "@grpc/proto-loader": "^0.7.0", "@types/node": ">=12.12.47" }, "files": [ diff --git a/packages/grpc-js/src/backoff-timeout.ts b/packages/grpc-js/src/backoff-timeout.ts index dc7be277..f523e259 100644 --- a/packages/grpc-js/src/backoff-timeout.ts +++ b/packages/grpc-js/src/backoff-timeout.ts @@ -100,6 +100,7 @@ export class BackoffTimeout { } private runTimer(delay: number) { + clearTimeout(this.timerId); this.timerId = setTimeout(() => { this.callback(); this.running = false; diff --git a/packages/grpc-js/src/call.ts b/packages/grpc-js/src/call.ts index c587a195..bb6d74cc 100644 --- a/packages/grpc-js/src/call.ts +++ b/packages/grpc-js/src/call.ts @@ -76,9 +76,11 @@ export type ClientDuplexStream< * error is not necessarily a problem in gRPC itself. * @param status */ -export function callErrorFromStatus(status: StatusObject): ServiceError { +export function callErrorFromStatus(status: StatusObject, callerStack: string): ServiceError { const message = `${status.code} ${Status[status.code]}: ${status.details}`; - return Object.assign(new Error(message), status); + const error = new Error(message); + const stack = `${error.stack}\nfor call at\n${callerStack}`; + return Object.assign(new Error(message), status, {stack}); } export class ClientUnaryCallImpl diff --git a/packages/grpc-js/src/channelz.ts b/packages/grpc-js/src/channelz.ts index 14c94fd0..5a7a5476 100644 --- a/packages/grpc-js/src/channelz.ts +++ b/packages/grpc-js/src/channelz.ts @@ -347,31 +347,39 @@ const subchannels: (SubchannelEntry | undefined)[] = []; const servers: (ServerEntry | undefined)[] = []; const sockets: (SocketEntry | undefined)[] = []; -export function registerChannelzChannel(name: string, getInfo: () => ChannelInfo): ChannelRef { +export function registerChannelzChannel(name: string, getInfo: () => ChannelInfo, channelzEnabled: boolean): ChannelRef { const id = getNextId(); const ref: ChannelRef = {id, name, kind: 'channel'}; - channels[id] = { ref, getInfo }; + if (channelzEnabled) { + channels[id] = { ref, getInfo }; + } return ref; } -export function registerChannelzSubchannel(name: string, getInfo:() => SubchannelInfo): SubchannelRef { +export function registerChannelzSubchannel(name: string, getInfo:() => SubchannelInfo, channelzEnabled: boolean): SubchannelRef { const id = getNextId(); const ref: SubchannelRef = {id, name, kind: 'subchannel'}; - subchannels[id] = { ref, getInfo }; + if (channelzEnabled) { + subchannels[id] = { ref, getInfo }; + } return ref; } -export function registerChannelzServer(getInfo: () => ServerInfo): ServerRef { +export function registerChannelzServer(getInfo: () => ServerInfo, channelzEnabled: boolean): ServerRef { const id = getNextId(); const ref: ServerRef = {id, kind: 'server'}; - servers[id] = { ref, getInfo }; + if (channelzEnabled) { + servers[id] = { ref, getInfo }; + } return ref; } -export function registerChannelzSocket(name: string, getInfo: () => SocketInfo): SocketRef { +export function registerChannelzSocket(name: string, getInfo: () => SocketInfo, channelzEnabled: boolean): SocketRef { const id = getNextId(); const ref: SocketRef = {id, name, kind: 'socket'}; - sockets[id] = { ref, getInfo}; + if (channelzEnabled) { + sockets[id] = { ref, getInfo}; + } return ref; } diff --git a/packages/grpc-js/src/client.ts b/packages/grpc-js/src/client.ts index 688d8016..d97c9fa3 100644 --- a/packages/grpc-js/src/client.ts +++ b/packages/grpc-js/src/client.ts @@ -109,6 +109,10 @@ export type ClientOptions = Partial & { callInvocationTransformer?: CallInvocationTransformer; }; +function getErrorStackString(error: Error): string { + return error.stack!.split('\n').slice(1).join('\n'); +} + /** * A generic gRPC client. Primarily useful as a base class for all generated * clients. @@ -322,6 +326,7 @@ export class Client { } let responseMessage: ResponseType | null = null; let receivedStatus = false; + const callerStackError = new Error(); call.start(callProperties.metadata, { onReceiveMetadata: (metadata) => { emitter.emit('metadata', metadata); @@ -339,9 +344,19 @@ export class Client { } receivedStatus = true; if (status.code === Status.OK) { - callProperties.callback!(null, responseMessage!); + if (responseMessage === null) { + const callerStack = getErrorStackString(callerStackError); + callProperties.callback!(callErrorFromStatus({ + code: Status.INTERNAL, + details: 'No message received', + metadata: status.metadata + }, callerStack)); + } else { + callProperties.callback!(null, responseMessage); + } } else { - callProperties.callback!(callErrorFromStatus(status)); + const callerStack = getErrorStackString(callerStackError); + callProperties.callback!(callErrorFromStatus(status, callerStack)); } emitter.emit('status', status); }, @@ -439,6 +454,7 @@ export class Client { } let responseMessage: ResponseType | null = null; let receivedStatus = false; + const callerStackError = new Error(); call.start(callProperties.metadata, { onReceiveMetadata: (metadata) => { emitter.emit('metadata', metadata); @@ -456,9 +472,19 @@ export class Client { } receivedStatus = true; if (status.code === Status.OK) { - callProperties.callback!(null, responseMessage!); + if (responseMessage === null) { + const callerStack = getErrorStackString(callerStackError); + callProperties.callback!(callErrorFromStatus({ + code: Status.INTERNAL, + details: 'No message received', + metadata: status.metadata + }, callerStack)); + } else { + callProperties.callback!(null, responseMessage); + } } else { - callProperties.callback!(callErrorFromStatus(status)); + const callerStack = getErrorStackString(callerStackError); + callProperties.callback!(callErrorFromStatus(status, callerStack)); } emitter.emit('status', status); }, @@ -560,6 +586,7 @@ export class Client { call.setCredentials(callProperties.callOptions.credentials); } let receivedStatus = false; + const callerStackError = new Error(); call.start(callProperties.metadata, { onReceiveMetadata(metadata: Metadata) { stream.emit('metadata', metadata); @@ -575,7 +602,8 @@ export class Client { receivedStatus = true; stream.push(null); if (status.code !== Status.OK) { - stream.emit('error', callErrorFromStatus(status)); + const callerStack = getErrorStackString(callerStackError); + stream.emit('error', callErrorFromStatus(status, callerStack)); } stream.emit('status', status); }, @@ -657,6 +685,7 @@ export class Client { call.setCredentials(callProperties.callOptions.credentials); } let receivedStatus = false; + const callerStackError = new Error(); call.start(callProperties.metadata, { onReceiveMetadata(metadata: Metadata) { stream.emit('metadata', metadata); @@ -671,7 +700,8 @@ export class Client { receivedStatus = true; stream.push(null); if (status.code !== Status.OK) { - stream.emit('error', callErrorFromStatus(status)); + const callerStack = getErrorStackString(callerStackError); + stream.emit('error', callErrorFromStatus(status, callerStack)); } stream.emit('status', status); }, diff --git a/packages/grpc-js/src/control-plane-status.ts b/packages/grpc-js/src/control-plane-status.ts new file mode 100644 index 00000000..808d695b --- /dev/null +++ b/packages/grpc-js/src/control-plane-status.ts @@ -0,0 +1,40 @@ +/* + * Copyright 2022 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { Status } from './constants'; + +const INAPPROPRIATE_CONTROL_PLANE_CODES: Status[] = [ + Status.OK, + Status.INVALID_ARGUMENT, + Status.NOT_FOUND, + Status.ALREADY_EXISTS, + Status.FAILED_PRECONDITION, + Status.ABORTED, + Status.OUT_OF_RANGE, + Status.DATA_LOSS +] + +export function restrictControlPlaneStatusCode(code: Status, details: string): {code: Status, details: string} { + if (INAPPROPRIATE_CONTROL_PLANE_CODES.includes(code)) { + return { + code: Status.INTERNAL, + details: `Invalid status from control plane: ${code} ${Status[code]} ${details}` + } + } else { + return {code, details}; + } +} \ No newline at end of file diff --git a/packages/grpc-js/src/experimental.ts b/packages/grpc-js/src/experimental.ts index f286bbcd..92d6d44c 100644 --- a/packages/grpc-js/src/experimental.ts +++ b/packages/grpc-js/src/experimental.ts @@ -1,4 +1,4 @@ -export { trace } from './logging'; +export { trace, log } from './logging'; export { Resolver, ResolverListener, diff --git a/packages/grpc-js/src/internal-channel.ts b/packages/grpc-js/src/internal-channel.ts index 772ed8e1..2a775e7d 100644 --- a/packages/grpc-js/src/internal-channel.ts +++ b/packages/grpc-js/src/internal-channel.ts @@ -49,6 +49,7 @@ import { SubchannelCall } from './subchannel-call'; import { Deadline, getDeadlineTimeoutString } from './deadline'; import { ResolvingCall } from './resolving-call'; import { getNextCallNumber } from './call-number'; +import { restrictControlPlaneStatusCode } from './control-plane-status'; /** * See https://nodejs.org/api/timers.html#timers_setinterval_callback_delay_args @@ -61,6 +62,22 @@ interface ConnectivityStateWatcher { callback: (error?: Error) => void; } +interface NoneConfigResult { + type: 'NONE'; +} + +interface SuccessConfigResult { + type: 'SUCCESS'; + config: CallConfig; +} + +interface ErrorConfigResult { + type: 'ERROR'; + error: StatusObject; +} + +type GetConfigResult = NoneConfigResult | SuccessConfigResult | ErrorConfigResult; + export class InternalChannel { private resolvingLoadBalancer: ResolvingLoadBalancer; @@ -86,6 +103,14 @@ export class InternalChannel { */ private callRefTimer: NodeJS.Timer; private configSelector: ConfigSelector | null = null; + /** + * This is the error from the name resolver if it failed most recently. It + * is only used to end calls that start while there is no config selector + * and the name resolver is in backoff, so it should be nulled if + * configSelector becomes set or the channel state becomes anything other + * than TRANSIENT_FAILURE. + */ + private currentResolutionError: StatusObject | null = null; // Channelz info private readonly channelzEnabled: boolean = true; @@ -135,16 +160,9 @@ export class InternalChannel { } this.channelzTrace = new ChannelzTrace(); + this.channelzRef = registerChannelzChannel(target, () => this.getChannelzInfo(), this.channelzEnabled); if (this.channelzEnabled) { - this.channelzRef = registerChannelzChannel(target, () => this.getChannelzInfo()); this.channelzTrace.addTrace('CT_INFO', 'Channel created'); - } else { - // Dummy channelz ref that will never be used - this.channelzRef = { - kind: 'channel', - id: -1, - name: '' - }; } if (this.options['grpc.default_authority']) { @@ -213,6 +231,7 @@ export class InternalChannel { this.channelzTrace.addTrace('CT_INFO', 'Address resolution succeeded'); } this.configSelector = configSelector; + this.currentResolutionError = null; /* We process the queue asynchronously to ensure that the corresponding * load balancer update has completed. */ process.nextTick(() => { @@ -232,6 +251,9 @@ export class InternalChannel { if (this.configSelectionQueue.length > 0) { this.trace('Name resolution failed with calls queued for config selection'); } + if (this.configSelector === null) { + this.currentResolutionError = {...restrictControlPlaneStatusCode(status.code, status.details), metadata: status.metadata}; + } const localQueue = this.configSelectionQueue; this.configSelectionQueue = []; this.callRefTimerUnref(); @@ -325,6 +347,9 @@ export class InternalChannel { watcherObject.callback(); } } + if (newState !== ConnectivityState.TRANSIENT_FAILURE) { + this.currentResolutionError = null; + } } doPick(metadata: Metadata, extraPickInfo: {[key: string]: string}) { @@ -336,9 +361,25 @@ export class InternalChannel { this.callRefTimerRef(); } - getConfig(method: string, metadata: Metadata) { + getConfig(method: string, metadata: Metadata): GetConfigResult { this.resolvingLoadBalancer.exitIdle(); - return this.configSelector?.(method, metadata) ?? null; + if (this.configSelector) { + return { + type: 'SUCCESS', + config: this.configSelector(method, metadata) + }; + } else { + if (this.currentResolutionError) { + return { + type: 'ERROR', + error: this.currentResolutionError + } + } else { + return { + type: 'NONE' + } + } + } } queueCallForConfig(call: ResolvingCall) { diff --git a/packages/grpc-js/src/load-balancer-child-handler.ts b/packages/grpc-js/src/load-balancer-child-handler.ts index 0591c92f..64b34181 100644 --- a/packages/grpc-js/src/load-balancer-child-handler.ts +++ b/packages/grpc-js/src/load-balancer-child-handler.ts @@ -48,7 +48,7 @@ export class ChildLoadBalancerHandler implements LoadBalancer { } updateState(connectivityState: ConnectivityState, picker: Picker): void { if (this.calledByPendingChild()) { - if (connectivityState !== ConnectivityState.READY) { + if (connectivityState === ConnectivityState.CONNECTING) { return; } this.parent.currentChild?.destroy(); diff --git a/packages/grpc-js/src/load-balancer-outlier-detection.ts b/packages/grpc-js/src/load-balancer-outlier-detection.ts index 5af0e79e..1f1710e7 100644 --- a/packages/grpc-js/src/load-balancer-outlier-detection.ts +++ b/packages/grpc-js/src/load-balancer-outlier-detection.ts @@ -17,7 +17,7 @@ import { ChannelOptions } from "./channel-options"; import { ConnectivityState } from "./connectivity-state"; -import { Status } from "./constants"; +import { LogVerbosity, Status } from "./constants"; import { durationToMs, isDuration, msToDuration } from "./duration"; import { ChannelControlHelper, createChildChannelControlHelper, registerLoadBalancerType } from "./experimental"; import { BaseFilter, Filter, FilterFactory } from "./filter"; @@ -27,11 +27,17 @@ import { PickArgs, Picker, PickResult, PickResultType, QueuePicker, UnavailableP import { Subchannel } from "./subchannel"; import { SubchannelAddress, subchannelAddressToString } from "./subchannel-address"; import { BaseSubchannelWrapper, ConnectivityStateListener, SubchannelInterface } from "./subchannel-interface"; +import * as logging from './logging'; +const TRACER_NAME = 'outlier_detection'; + +function trace(text: string): void { + logging.trace(LogVerbosity.DEBUG, TRACER_NAME, text); +} const TYPE_NAME = 'outlier_detection'; -const OUTLIER_DETECTION_ENABLED = process.env.GRPC_EXPERIMENTAL_ENABLE_OUTLIER_DETECTION === 'true'; +const OUTLIER_DETECTION_ENABLED = (process.env.GRPC_EXPERIMENTAL_ENABLE_OUTLIER_DETECTION ?? 'true') === 'true'; export interface SuccessRateEjectionConfig { readonly stdev_factor: number; @@ -192,12 +198,13 @@ export class OutlierDetectionLoadBalancingConfig implements LoadBalancingConfig } class OutlierDetectionSubchannelWrapper extends BaseSubchannelWrapper implements SubchannelInterface { - private childSubchannelState: ConnectivityState = ConnectivityState.IDLE; + private childSubchannelState: ConnectivityState; private stateListeners: ConnectivityStateListener[] = []; private ejected: boolean = false; private refCount: number = 0; constructor(childSubchannel: SubchannelInterface, private mapEntry?: MapEntry) { super(childSubchannel); + this.childSubchannelState = childSubchannel.getConnectivityState(); childSubchannel.addConnectivityStateListener((subchannel, previousState, newState) => { this.childSubchannelState = newState; if (!this.ejected) { @@ -208,6 +215,14 @@ class OutlierDetectionSubchannelWrapper extends BaseSubchannelWrapper implements }); } + getConnectivityState(): ConnectivityState { + if (this.ejected) { + return ConnectivityState.TRANSIENT_FAILURE; + } else { + return this.childSubchannelState; + } + } + /** * Add a listener function to be called whenever the wrapper's * connectivity state changes. @@ -311,27 +326,34 @@ interface MapEntry { } class OutlierDetectionPicker implements Picker { - constructor(private wrappedPicker: Picker) {} + constructor(private wrappedPicker: Picker, private countCalls: boolean) {} pick(pickArgs: PickArgs): PickResult { const wrappedPick = this.wrappedPicker.pick(pickArgs); if (wrappedPick.pickResultType === PickResultType.COMPLETE) { const subchannelWrapper = wrappedPick.subchannel as OutlierDetectionSubchannelWrapper; const mapEntry = subchannelWrapper.getMapEntry(); if (mapEntry) { - return { - ...wrappedPick, - subchannel: subchannelWrapper.getWrappedSubchannel(), - onCallEnded: statusCode => { + let onCallEnded = wrappedPick.onCallEnded; + if (this.countCalls) { + onCallEnded = statusCode => { if (statusCode === Status.OK) { mapEntry.counter.addSuccess(); } else { mapEntry.counter.addFailure(); } wrappedPick.onCallEnded?.(statusCode); - } + }; + } + return { + ...wrappedPick, + subchannel: subchannelWrapper.getWrappedSubchannel(), + onCallEnded: onCallEnded }; } else { - return wrappedPick; + return { + ...wrappedPick, + subchannel: subchannelWrapper.getWrappedSubchannel() + } } } else { return wrappedPick; @@ -345,6 +367,7 @@ export class OutlierDetectionLoadBalancer implements LoadBalancer { private addressMap: Map = new Map(); private latestConfig: OutlierDetectionLoadBalancingConfig | null = null; private ejectionTimer: NodeJS.Timer; + private timerStartTime: Date | null = null; constructor(channelControlHelper: ChannelControlHelper) { this.childBalancer = new ChildLoadBalancerHandler(createChildChannelControlHelper(channelControlHelper, { @@ -352,12 +375,16 @@ export class OutlierDetectionLoadBalancer implements LoadBalancer { const originalSubchannel = channelControlHelper.createSubchannel(subchannelAddress, subchannelArgs); const mapEntry = this.addressMap.get(subchannelAddressToString(subchannelAddress)); const subchannelWrapper = new OutlierDetectionSubchannelWrapper(originalSubchannel, mapEntry); + if (mapEntry?.currentEjectionTimestamp !== null) { + // If the address is ejected, propagate that to the new subchannel wrapper + subchannelWrapper.eject(); + } mapEntry?.subchannelWrappers.push(subchannelWrapper); return subchannelWrapper; }, updateState: (connectivityState: ConnectivityState, picker: Picker) => { if (connectivityState === ConnectivityState.READY) { - channelControlHelper.updateState(connectivityState, new OutlierDetectionPicker(picker)); + channelControlHelper.updateState(connectivityState, new OutlierDetectionPicker(picker, this.isCountingEnabled())); } else { channelControlHelper.updateState(connectivityState, picker); } @@ -367,6 +394,12 @@ export class OutlierDetectionLoadBalancer implements LoadBalancer { clearInterval(this.ejectionTimer); } + private isCountingEnabled(): boolean { + return this.latestConfig !== null && + (this.latestConfig.getSuccessRateEjectionConfig() !== null || + this.latestConfig.getFailurePercentageEjectionConfig() !== null); + } + private getCurrentEjectionPercent() { let ejectionCount = 0; for (const mapEntry of this.addressMap.values()) { @@ -385,6 +418,7 @@ export class OutlierDetectionLoadBalancer implements LoadBalancer { if (!successRateConfig) { return; } + trace('Running success rate check'); // Step 1 const targetRequestVolume = successRateConfig.request_volume; let addresesWithTargetVolume = 0; @@ -397,24 +431,27 @@ export class OutlierDetectionLoadBalancer implements LoadBalancer { successRates.push(successes/(successes + failures)); } } + trace('Found ' + addresesWithTargetVolume + ' success rate candidates; currentEjectionPercent=' + this.getCurrentEjectionPercent() + ' successRates=[' + successRates + ']'); if (addresesWithTargetVolume < successRateConfig.minimum_hosts) { return; } // Step 2 - const successRateMean = successRates.reduce((a, b) => a + b); - let successRateVariance = 0; + const successRateMean = successRates.reduce((a, b) => a + b) / successRates.length; + let successRateDeviationSum = 0; for (const rate of successRates) { const deviation = rate - successRateMean; - successRateVariance += deviation * deviation; + successRateDeviationSum += deviation * deviation; } + const successRateVariance = successRateDeviationSum / successRates.length; const successRateStdev = Math.sqrt(successRateVariance); const ejectionThreshold = successRateMean - successRateStdev * (successRateConfig.stdev_factor / 1000); + trace('stdev=' + successRateStdev + ' ejectionThreshold=' + ejectionThreshold); // Step 3 - for (const mapEntry of this.addressMap.values()) { + for (const [address, mapEntry] of this.addressMap.entries()) { // Step 3.i - if (this.getCurrentEjectionPercent() > this.latestConfig.getMaxEjectionPercent()) { + if (this.getCurrentEjectionPercent() >= this.latestConfig.getMaxEjectionPercent()) { break; } // Step 3.ii @@ -425,9 +462,12 @@ export class OutlierDetectionLoadBalancer implements LoadBalancer { } // Step 3.iii const successRate = successes / (successes + failures); + trace('Checking candidate ' + address + ' successRate=' + successRate); if (successRate < ejectionThreshold) { const randomNumber = Math.random() * 100; + trace('Candidate ' + address + ' randomNumber=' + randomNumber + ' enforcement_percentage=' + successRateConfig.enforcement_percentage); if (randomNumber < successRateConfig.enforcement_percentage) { + trace('Ejecting candidate ' + address); this.eject(mapEntry, ejectionTimestamp); } } @@ -442,20 +482,30 @@ export class OutlierDetectionLoadBalancer implements LoadBalancer { if (!failurePercentageConfig) { return; } + trace('Running failure percentage check. threshold=' + failurePercentageConfig.threshold + ' request volume threshold=' + failurePercentageConfig.request_volume); // Step 1 - if (this.addressMap.size < failurePercentageConfig.minimum_hosts) { + let addressesWithTargetVolume = 0; + for (const mapEntry of this.addressMap.values()) { + const successes = mapEntry.counter.getLastSuccesses(); + const failures = mapEntry.counter.getLastFailures(); + if (successes + failures >= failurePercentageConfig.request_volume) { + addressesWithTargetVolume += 1; + } + } + if (addressesWithTargetVolume < failurePercentageConfig.minimum_hosts) { return; } // Step 2 - for (const mapEntry of this.addressMap.values()) { + for (const [address, mapEntry] of this.addressMap.entries()) { // Step 2.i - if (this.getCurrentEjectionPercent() > this.latestConfig.getMaxEjectionPercent()) { + if (this.getCurrentEjectionPercent() >= this.latestConfig.getMaxEjectionPercent()) { break; } // Step 2.ii const successes = mapEntry.counter.getLastSuccesses(); const failures = mapEntry.counter.getLastFailures(); + trace('Candidate successes=' + successes + ' failures=' + failures); if (successes + failures < failurePercentageConfig.request_volume) { continue; } @@ -463,7 +513,9 @@ export class OutlierDetectionLoadBalancer implements LoadBalancer { const failurePercentage = (failures * 100) / (failures + successes); if (failurePercentage > failurePercentageConfig.threshold) { const randomNumber = Math.random() * 100; + trace('Candidate ' + address + ' randomNumber=' + randomNumber + ' enforcement_percentage=' + failurePercentageConfig.enforcement_percentage); if (randomNumber < failurePercentageConfig.enforcement_percentage) { + trace('Ejecting candidate ' + address); this.eject(mapEntry, ejectionTimestamp); } } @@ -485,21 +537,32 @@ export class OutlierDetectionLoadBalancer implements LoadBalancer { } } - private runChecks() { - const ejectionTimestamp = new Date(); - + private switchAllBuckets() { for (const mapEntry of this.addressMap.values()) { mapEntry.counter.switchBuckets(); } + } + + private startTimer(delayMs: number) { + this.ejectionTimer = setTimeout(() => this.runChecks(), delayMs); + } + + private runChecks() { + const ejectionTimestamp = new Date(); + trace('Ejection timer running'); + + this.switchAllBuckets(); if (!this.latestConfig) { return; } + this.timerStartTime = ejectionTimestamp; + this.startTimer(this.latestConfig.getIntervalMs()); this.runSuccessRateCheck(ejectionTimestamp); this.runFailurePercentageCheck(ejectionTimestamp); - for (const mapEntry of this.addressMap.values()) { + for (const [address, mapEntry] of this.addressMap.entries()) { if (mapEntry.currentEjectionTimestamp === null) { if (mapEntry.ejectionTimeMultiplier > 0) { mapEntry.ejectionTimeMultiplier -= 1; @@ -510,6 +573,7 @@ export class OutlierDetectionLoadBalancer implements LoadBalancer { const returnTime = new Date(mapEntry.currentEjectionTimestamp.getTime()); returnTime.setMilliseconds(returnTime.getMilliseconds() + Math.min(baseEjectionTimeMs * mapEntry.ejectionTimeMultiplier, Math.max(baseEjectionTimeMs, maxEjectionTimeMs))); if (returnTime < new Date()) { + trace('Unejecting ' + address); this.uneject(mapEntry); } } @@ -526,6 +590,7 @@ export class OutlierDetectionLoadBalancer implements LoadBalancer { } for (const address of subchannelAddresses) { if (!this.addressMap.has(address)) { + trace('Adding map entry for ' + address); this.addressMap.set(address, { counter: new CallCounter(), currentEjectionTimestamp: null, @@ -536,6 +601,7 @@ export class OutlierDetectionLoadBalancer implements LoadBalancer { } for (const key of this.addressMap.keys()) { if (!subchannelAddresses.has(key)) { + trace('Removing map entry for ' + key); this.addressMap.delete(key); } } @@ -545,10 +611,28 @@ export class OutlierDetectionLoadBalancer implements LoadBalancer { ); this.childBalancer.updateAddressList(addressList, childPolicy, attributes); - if (this.latestConfig === null || this.latestConfig.getIntervalMs() !== lbConfig.getIntervalMs()) { - clearInterval(this.ejectionTimer); - this.ejectionTimer = setInterval(() => this.runChecks(), lbConfig.getIntervalMs()); + if (lbConfig.getSuccessRateEjectionConfig() || lbConfig.getFailurePercentageEjectionConfig()) { + if (this.timerStartTime) { + trace('Previous timer existed. Replacing timer'); + clearTimeout(this.ejectionTimer); + const remainingDelay = lbConfig.getIntervalMs() - ((new Date()).getTime() - this.timerStartTime.getTime()); + this.startTimer(remainingDelay); + } else { + trace('Starting new timer'); + this.timerStartTime = new Date(); + this.startTimer(lbConfig.getIntervalMs()); + this.switchAllBuckets(); + } + } else { + trace('Counting disabled. Cancelling timer.'); + this.timerStartTime = null; + clearTimeout(this.ejectionTimer); + for (const mapEntry of this.addressMap.values()) { + this.uneject(mapEntry); + mapEntry.ejectionTimeMultiplier = 0; + } } + this.latestConfig = lbConfig; } exitIdle(): void { @@ -558,6 +642,7 @@ export class OutlierDetectionLoadBalancer implements LoadBalancer { this.childBalancer.resetBackoff(); } destroy(): void { + clearTimeout(this.ejectionTimer); this.childBalancer.destroy(); } getTypeName(): string { diff --git a/packages/grpc-js/src/load-balancer-pick-first.ts b/packages/grpc-js/src/load-balancer-pick-first.ts index bb95aba1..027eae07 100644 --- a/packages/grpc-js/src/load-balancer-pick-first.ts +++ b/packages/grpc-js/src/load-balancer-pick-first.ts @@ -184,8 +184,10 @@ export class PickFirstLoadBalancer implements LoadBalancer { ) { /* If all of the subchannels are IDLE we should go back to a * basic IDLE state where there is no subchannel list to avoid - * holding unused resources */ - this.resetSubchannelList(); + * holding unused resources. We do not reset triedAllSubchannels + * because that is a reminder to request reresolution the next time + * this LB policy needs to connect. */ + this.resetSubchannelList(false); this.updateState(ConnectivityState.IDLE, new QueuePicker(this)); return; } @@ -337,7 +339,7 @@ export class PickFirstLoadBalancer implements LoadBalancer { this.channelControlHelper.updateState(newState, picker); } - private resetSubchannelList() { + private resetSubchannelList(resetTriedAllSubchannels = true) { for (const subchannel of this.subchannels) { subchannel.removeConnectivityStateListener(this.subchannelStateListener); subchannel.unref(); @@ -352,7 +354,9 @@ export class PickFirstLoadBalancer implements LoadBalancer { [ConnectivityState.TRANSIENT_FAILURE]: 0, }; this.subchannels = []; - this.triedAllSubchannels = false; + if (resetTriedAllSubchannels) { + this.triedAllSubchannels = false; + } } /** @@ -425,6 +429,12 @@ export class PickFirstLoadBalancer implements LoadBalancer { } exitIdle() { + if ( + this.currentState === ConnectivityState.IDLE || + this.triedAllSubchannels + ) { + this.channelControlHelper.requestReresolution(); + } for (const subchannel of this.subchannels) { subchannel.startConnecting(); } @@ -433,12 +443,6 @@ export class PickFirstLoadBalancer implements LoadBalancer { this.connectToAddressList(); } } - if ( - this.currentState === ConnectivityState.IDLE || - this.triedAllSubchannels - ) { - this.channelControlHelper.requestReresolution(); - } } resetBackoff() { diff --git a/packages/grpc-js/src/load-balancing-call.ts b/packages/grpc-js/src/load-balancing-call.ts index f791b86b..36af8b68 100644 --- a/packages/grpc-js/src/load-balancing-call.ts +++ b/packages/grpc-js/src/load-balancing-call.ts @@ -28,6 +28,7 @@ import { PickResultType } from "./picker"; import { CallConfig } from "./resolver"; import { splitHostPort } from "./uri-parser"; import * as logging from './logging'; +import { restrictControlPlaneStatusCode } from "./control-plane-status"; const TRACER_NAME = 'load_balancing_call'; @@ -194,10 +195,14 @@ export class LoadBalancingCall implements Call { } }, (error: Error & { code: number }) => { // We assume the error code isn't 0 (Status.OK) + const {code, details} = restrictControlPlaneStatusCode( + typeof error.code === 'number' ? error.code : Status.UNKNOWN, + `Getting metadata from plugin failed with error: ${error.message}` + ) this.outputStatus( { - code: typeof error.code === 'number' ? error.code : Status.UNKNOWN, - details: `Getting metadata from plugin failed with error: ${error.message}`, + code: code, + details: details, metadata: new Metadata() }, 'PROCESSED' @@ -206,13 +211,15 @@ export class LoadBalancingCall implements Call { ); break; case PickResultType.DROP: - this.outputStatus(pickResult.status!, 'DROP'); + const {code, details} = restrictControlPlaneStatusCode(pickResult.status!.code, pickResult.status!.details); + this.outputStatus({code, details, metadata: pickResult.status!.metadata}, 'DROP'); break; case PickResultType.TRANSIENT_FAILURE: if (this.metadata.getOptions().waitForReady) { this.channel.queueCallForPick(this); } else { - this.outputStatus(pickResult.status!, 'PROCESSED'); + const {code, details} = restrictControlPlaneStatusCode(pickResult.status!.code, pickResult.status!.details); + this.outputStatus({code, details, metadata: pickResult.status!.metadata}, 'PROCESSED'); } break; case PickResultType.QUEUE: diff --git a/packages/grpc-js/src/resolver-dns.ts b/packages/grpc-js/src/resolver-dns.ts index 7c4028b0..4b7cb2fe 100644 --- a/packages/grpc-js/src/resolver-dns.ts +++ b/packages/grpc-js/src/resolver-dns.ts @@ -158,7 +158,6 @@ class DnsResolver implements Resolver { if (this.ipResult !== null) { trace('Returning IP address for target ' + uriToString(this.target)); setImmediate(() => { - this.backoff.reset(); this.listener.onSuccessfulResolution( this.ipResult!, null, @@ -167,6 +166,8 @@ class DnsResolver implements Resolver { {} ); }); + this.backoff.stop(); + this.backoff.reset(); return; } if (this.dnsHostname === null) { @@ -178,7 +179,11 @@ class DnsResolver implements Resolver { metadata: new Metadata(), }); }); + this.stopNextResolutionTimer(); } else { + if (this.pendingLookupPromise !== null) { + return; + } trace('Looking up DNS hostname ' + this.dnsHostname); /* We clear out latestLookupResult here to ensure that it contains the * latest result since the last time we started resolving. That way, the @@ -299,6 +304,7 @@ class DnsResolver implements Resolver { } private startNextResolutionTimer() { + clearTimeout(this.nextResolutionTimer); this.nextResolutionTimer = setTimeout(() => { this.stopNextResolutionTimer(); if (this.continueResolving) { @@ -314,9 +320,12 @@ class DnsResolver implements Resolver { } private startResolutionWithBackoff() { + if (this.pendingLookupPromise === null) { + this.continueResolving = false; this.startResolution(); this.backoff.runOnce(); this.startNextResolutionTimer(); + } } updateResolution() { diff --git a/packages/grpc-js/src/resolving-call.ts b/packages/grpc-js/src/resolving-call.ts index 4cf24b4b..76a7bd20 100644 --- a/packages/grpc-js/src/resolving-call.ts +++ b/packages/grpc-js/src/resolving-call.ts @@ -23,6 +23,7 @@ import { FilterStackFactory } from "./filter-stack"; import { InternalChannel } from "./internal-channel"; import { Metadata } from "./metadata"; import * as logging from './logging'; +import { restrictControlPlaneStatusCode } from "./control-plane-status"; const TRACER_NAME = 'resolving_call'; @@ -110,15 +111,25 @@ export class ResolvingCall implements Call { if (!this.metadata || !this.listener) { throw new Error('getConfig called before start'); } - const config = this.channel.getConfig(this.method, this.metadata); - if (!config) { + const configResult = this.channel.getConfig(this.method, this.metadata); + if (configResult.type === 'NONE') { this.channel.queueCallForConfig(this); return; + } else if (configResult.type === 'ERROR') { + if (this.metadata.getOptions().waitForReady) { + this.channel.queueCallForConfig(this); + } else { + this.outputStatus(configResult.error); + } + return; } + // configResult.type === 'SUCCESS' + const config = configResult.config; if (config.status !== Status.OK) { + const {code, details} = restrictControlPlaneStatusCode(config.status, 'Failed to route call to method ' + this.method); this.outputStatus({ - code: config.status, - details: 'Failed to route call to ' + this.method, + code: code, + details: details, metadata: new Metadata() }); return; diff --git a/packages/grpc-js/src/resolving-load-balancer.ts b/packages/grpc-js/src/resolving-load-balancer.ts index 47f7c3bb..da097cc4 100644 --- a/packages/grpc-js/src/resolving-load-balancer.ts +++ b/packages/grpc-js/src/resolving-load-balancer.ts @@ -268,6 +268,7 @@ export class ResolvingLoadBalancer implements LoadBalancer { if (this.currentState === ConnectivityState.IDLE) { this.updateState(ConnectivityState.CONNECTING, new QueuePicker(this)); } + this.backoffTimeout.runOnce(); } private updateState(connectivityState: ConnectivityState, picker: Picker) { @@ -294,19 +295,17 @@ export class ResolvingLoadBalancer implements LoadBalancer { ); this.onFailedResolution(error); } - this.backoffTimeout.runOnce(); } exitIdle() { - this.childLoadBalancer.exitIdle(); - if (this.currentState === ConnectivityState.IDLE) { + if (this.currentState === ConnectivityState.IDLE || this.currentState === ConnectivityState.TRANSIENT_FAILURE) { if (this.backoffTimeout.isRunning()) { this.continueResolving = true; } else { this.updateResolution(); } - this.updateState(ConnectivityState.CONNECTING, new QueuePicker(this)); } + this.childLoadBalancer.exitIdle(); } updateAddressList( diff --git a/packages/grpc-js/src/server-call.ts b/packages/grpc-js/src/server-call.ts index 388a8d33..38b4379e 100644 --- a/packages/grpc-js/src/server-call.ts +++ b/packages/grpc-js/src/server-call.ts @@ -81,6 +81,7 @@ export type ServerSurfaceCall = { getPeer(): string; sendMetadata(responseMetadata: Metadata): void; getDeadline(): Deadline; + getPath(): string; } & EventEmitter; export type ServerUnaryCall = ServerSurfaceCall & { @@ -128,6 +129,10 @@ export class ServerUnaryCallImpl getDeadline(): Deadline { return this.call.getDeadline(); } + + getPath(): string { + return this.call.getPath(); + } } export class ServerReadableStreamImpl @@ -166,6 +171,10 @@ export class ServerReadableStreamImpl getDeadline(): Deadline { return this.call.getDeadline(); } + + getPath(): string { + return this.call.getPath(); + } } export class ServerWritableStreamImpl @@ -203,6 +212,10 @@ export class ServerWritableStreamImpl return this.call.getDeadline(); } + getPath(): string { + return this.call.getPath(); + } + _write( chunk: ResponseType, encoding: string, @@ -280,6 +293,10 @@ export class ServerDuplexStreamImpl return this.call.getDeadline(); } + getPath(): string { + return this.call.getPath(); + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any end(metadata?: any) { if (metadata) { @@ -729,6 +746,8 @@ export class Http2ServerCallStream< call.cancelled = true; call.emit('cancelled', reason); }); + + this.once('callEnd', (status) => call.emit('callEnd', status)); } setupReadable( @@ -902,6 +921,10 @@ export class Http2ServerCallStream< getDeadline(): Deadline { return this.deadline; } + + getPath(): string { + return this.handler.path; + } } /* eslint-disable @typescript-eslint/no-explicit-any */ diff --git a/packages/grpc-js/src/server.ts b/packages/grpc-js/src/server.ts index 829941fa..974c3dfc 100644 --- a/packages/grpc-js/src/server.ts +++ b/packages/grpc-js/src/server.ts @@ -161,17 +161,11 @@ export class Server { if (this.options['grpc.enable_channelz'] === 0) { this.channelzEnabled = false; } + this.channelzRef = registerChannelzServer(() => this.getChannelzInfo(), this.channelzEnabled); if (this.channelzEnabled) { - this.channelzRef = registerChannelzServer(() => this.getChannelzInfo()); this.channelzTrace.addTrace('CT_INFO', 'Server created'); - this.trace('Server constructed'); - } else { - // Dummy channelz ref that will never be used - this.channelzRef = { - kind: 'server', - id: -1 - }; } + this.trace('Server constructed'); } private getChannelzInfo(): ServerInfo { @@ -431,34 +425,28 @@ export class Server { } } let channelzRef: SocketRef; - if (this.channelzEnabled) { - channelzRef = registerChannelzSocket(subchannelAddressToString(boundSubchannelAddress), () => { - return { - localAddress: boundSubchannelAddress, - remoteAddress: null, - security: null, - remoteName: null, - streamsStarted: 0, - streamsSucceeded: 0, - streamsFailed: 0, - messagesSent: 0, - messagesReceived: 0, - keepAlivesSent: 0, - lastLocalStreamCreatedTimestamp: null, - lastRemoteStreamCreatedTimestamp: null, - lastMessageSentTimestamp: null, - lastMessageReceivedTimestamp: null, - localFlowControlWindow: null, - remoteFlowControlWindow: null - }; - }); - this.listenerChildrenTracker.refChild(channelzRef); - } else { - channelzRef = { - kind: 'socket', - id: -1, - name: '' + channelzRef = registerChannelzSocket(subchannelAddressToString(boundSubchannelAddress), () => { + return { + localAddress: boundSubchannelAddress, + remoteAddress: null, + security: null, + remoteName: null, + streamsStarted: 0, + streamsSucceeded: 0, + streamsFailed: 0, + messagesSent: 0, + messagesReceived: 0, + keepAlivesSent: 0, + lastLocalStreamCreatedTimestamp: null, + lastRemoteStreamCreatedTimestamp: null, + lastMessageSentTimestamp: null, + lastMessageReceivedTimestamp: null, + localFlowControlWindow: null, + remoteFlowControlWindow: null }; + }, this.channelzEnabled); + if (this.channelzEnabled) { + this.listenerChildrenTracker.refChild(channelzRef); } this.http2ServerList.push({server: http2Server, channelzRef: channelzRef}); this.trace('Successfully bound ' + subchannelAddressToString(boundSubchannelAddress)); @@ -509,34 +497,28 @@ export class Server { port: boundAddress.port }; let channelzRef: SocketRef; - if (this.channelzEnabled) { - channelzRef = registerChannelzSocket(subchannelAddressToString(boundSubchannelAddress), () => { - return { - localAddress: boundSubchannelAddress, - remoteAddress: null, - security: null, - remoteName: null, - streamsStarted: 0, - streamsSucceeded: 0, - streamsFailed: 0, - messagesSent: 0, - messagesReceived: 0, - keepAlivesSent: 0, - lastLocalStreamCreatedTimestamp: null, - lastRemoteStreamCreatedTimestamp: null, - lastMessageSentTimestamp: null, - lastMessageReceivedTimestamp: null, - localFlowControlWindow: null, - remoteFlowControlWindow: null - }; - }); - this.listenerChildrenTracker.refChild(channelzRef); - } else { - channelzRef = { - kind: 'socket', - id: -1, - name: '' + channelzRef = registerChannelzSocket(subchannelAddressToString(boundSubchannelAddress), () => { + return { + localAddress: boundSubchannelAddress, + remoteAddress: null, + security: null, + remoteName: null, + streamsStarted: 0, + streamsSucceeded: 0, + streamsFailed: 0, + messagesSent: 0, + messagesReceived: 0, + keepAlivesSent: 0, + lastLocalStreamCreatedTimestamp: null, + lastRemoteStreamCreatedTimestamp: null, + lastMessageSentTimestamp: null, + lastMessageReceivedTimestamp: null, + localFlowControlWindow: null, + remoteFlowControlWindow: null }; + }, this.channelzEnabled); + if (this.channelzEnabled) { + this.listenerChildrenTracker.refChild(channelzRef); } this.http2ServerList.push({server: http2Server, channelzRef: channelzRef}); this.trace('Successfully bound ' + subchannelAddressToString(boundSubchannelAddress)); @@ -893,15 +875,7 @@ export class Server { } let channelzRef: SocketRef; - if (this.channelzEnabled) { - channelzRef = registerChannelzSocket(session.socket.remoteAddress ?? 'unknown', this.getChannelzSessionInfoGetter(session)); - } else { - channelzRef = { - kind: 'socket', - id: -1, - name: '' - } - } + channelzRef = registerChannelzSocket(session.socket.remoteAddress ?? 'unknown', this.getChannelzSessionInfoGetter(session), this.channelzEnabled); const channelzSessionInfo: ChannelzSessionInfo = { ref: channelzRef, diff --git a/packages/grpc-js/src/subchannel-call.ts b/packages/grpc-js/src/subchannel-call.ts index ac34823b..e2cd645a 100644 --- a/packages/grpc-js/src/subchannel-call.ts +++ b/packages/grpc-js/src/subchannel-call.ts @@ -167,6 +167,11 @@ export class Http2SubchannelCall implements SubchannelCall { this.handleTrailers(headers); }); http2Stream.on('data', (data: Buffer) => { + /* If the status has already been output, allow the http2 stream to + * drain without processing the data. */ + if (this.statusOutput) { + return; + } this.trace('receive HTTP/2 data frame of length ' + data.length); const messages = this.decoder.write(data); @@ -301,6 +306,11 @@ export class Http2SubchannelCall implements SubchannelCall { process.nextTick(() => { this.listener.onReceiveStatus(this.finalStatus!); }); + /* Leave the http2 stream in flowing state to drain incoming messages, to + * ensure that the stream closure completes. The call stream already does + * not push more messages after the status is output, so the messages go + * nowhere either way. */ + this.http2Stream.resume(); this.subchannel.callUnref(); this.subchannel.removeDisconnectListener(this.disconnectListener); } @@ -404,7 +414,11 @@ export class Http2SubchannelCall implements SubchannelCall { } let details = ''; if (typeof metadataMap['grpc-message'] === 'string') { - details = decodeURI(metadataMap['grpc-message']); + try { + details = decodeURI(metadataMap['grpc-message']); + } catch (e) { + details = metadataMap['grpc-message']; + } metadata.remove('grpc-message'); this.trace( 'received status details string "' + details + '" from server' diff --git a/packages/grpc-js/src/subchannel-pool.ts b/packages/grpc-js/src/subchannel-pool.ts index cd74cad8..b7ef362c 100644 --- a/packages/grpc-js/src/subchannel-pool.ts +++ b/packages/grpc-js/src/subchannel-pool.ts @@ -49,10 +49,8 @@ export class SubchannelPool { /** * A pool of subchannels use for making connections. Subchannels with the * exact same parameters will be reused. - * @param global If true, this is the global subchannel pool. Otherwise, it - * is the pool for a single channel. */ - constructor(private global: boolean) {} + constructor() {} /** * Unrefs all unused subchannels and cancels the cleanup task if all @@ -95,7 +93,7 @@ export class SubchannelPool { * Ensures that the cleanup task is spawned. */ ensureCleanupTask(): void { - if (this.global && this.cleanupTimer === null) { + if (this.cleanupTimer === null) { this.cleanupTimer = setInterval(() => { this.unrefUnusedSubchannels(); }, REF_CHECK_INTERVAL); @@ -156,14 +154,12 @@ export class SubchannelPool { channelCredentials, subchannel, }); - if (this.global) { - subchannel.ref(); - } + subchannel.ref(); return subchannel; } } -const globalSubchannelPool = new SubchannelPool(true); +const globalSubchannelPool = new SubchannelPool(); /** * Get either the global subchannel pool, or a new subchannel pool. @@ -173,6 +169,6 @@ export function getSubchannelPool(global: boolean): SubchannelPool { if (global) { return globalSubchannelPool; } else { - return new SubchannelPool(false); + return new SubchannelPool(); } } diff --git a/packages/grpc-js/src/subchannel.ts b/packages/grpc-js/src/subchannel.ts index 563e6946..104c36c2 100644 --- a/packages/grpc-js/src/subchannel.ts +++ b/packages/grpc-js/src/subchannel.ts @@ -97,7 +97,7 @@ export class Subchannel { * socket disconnects. Used for ending active calls with an UNAVAILABLE * status. */ - private disconnectListeners: Array<() => void> = []; + private disconnectListeners: Set<() => void> = new Set(); private backoffTimeout: BackoffTimeout; @@ -216,16 +216,9 @@ export class Subchannel { this.channelzEnabled = false; } this.channelzTrace = new ChannelzTrace(); + this.channelzRef = registerChannelzSubchannel(this.subchannelAddressString, () => this.getChannelzInfo(), this.channelzEnabled); if (this.channelzEnabled) { - this.channelzRef = registerChannelzSubchannel(this.subchannelAddressString, () => this.getChannelzInfo()); this.channelzTrace.addTrace('CT_INFO', 'Subchannel created'); - } else { - // Dummy channelz ref that will never be used - this.channelzRef = { - kind: 'subchannel', - id: -1, - name: '' - }; } this.trace('Subchannel constructed with options ' + JSON.stringify(options, undefined, 2)); } @@ -317,6 +310,10 @@ export class Subchannel { logging.trace(LogVerbosity.DEBUG, 'subchannel_internals', '(' + this.channelzRef.id + ') ' + this.subchannelAddressString + ' ' + text); } + private keepaliveTrace(text: string): void { + logging.trace(LogVerbosity.DEBUG, 'keepalive', '(' + this.channelzRef.id + ') ' + this.subchannelAddressString + ' ' + text); + } + private handleBackoffTimer() { if (this.continueConnecting) { this.transitionToState( @@ -347,21 +344,27 @@ export class Subchannel { if (this.channelzEnabled) { this.keepalivesSent += 1; } - logging.trace( - LogVerbosity.DEBUG, - 'keepalive', - '(' + this.channelzRef.id + ') ' + this.subchannelAddressString + ' ' + - 'Sending ping' - ); + this.keepaliveTrace('Sending ping with timeout ' + this.keepaliveTimeoutMs + 'ms'); this.keepaliveTimeoutId = setTimeout(() => { - this.transitionToState([ConnectivityState.READY], ConnectivityState.IDLE); + this.keepaliveTrace('Ping timeout passed without response'); + this.handleDisconnect(); }, this.keepaliveTimeoutMs); this.keepaliveTimeoutId.unref?.(); - this.session!.ping( - (err: Error | null, duration: number, payload: Buffer) => { - clearTimeout(this.keepaliveTimeoutId); - } - ); + try { + this.session!.ping( + (err: Error | null, duration: number, payload: Buffer) => { + this.keepaliveTrace('Received ping response'); + clearTimeout(this.keepaliveTimeoutId); + } + ); + } catch (e) { + /* If we fail to send a ping, the connection is no longer functional, so + * we should discard it. */ + this.transitionToState( + [ConnectivityState.READY], + ConnectivityState.TRANSIENT_FAILURE + ); + } } private startKeepalivePings() { @@ -373,6 +376,11 @@ export class Subchannel { * sending pings should also involve some network activity. */ } + /** + * Stop keepalive pings when terminating a connection. This discards the + * outstanding ping timeout, so it should not be called if the same + * connection will still be used. + */ private stopKeepalivePings() { clearInterval(this.keepaliveIntervalId); clearTimeout(this.keepaliveTimeoutId); @@ -396,6 +404,12 @@ export class Subchannel { connectionOptions.maxSessionMemory = this.options[ 'grpc-node.max_session_memory' ]; + } else { + /* By default, set a very large max session memory limit, to effectively + * disable enforcement of the limit. Some testing indicates that Node's + * behavior degrades badly when this limit is reached, so we solve that + * by disabling the check entirely. */ + connectionOptions.maxSessionMemory = Number.MAX_SAFE_INTEGER; } let addressScheme = 'http://'; if ('secureContext' in connectionOptions) { @@ -473,8 +487,8 @@ export class Subchannel { connectionOptions ); this.session = session; + this.channelzSocketRef = registerChannelzSocket(this.subchannelAddressString, () => this.getChannelzSocketInfo()!, this.channelzEnabled); if (this.channelzEnabled) { - this.channelzSocketRef = registerChannelzSocket(this.subchannelAddressString, () => this.getChannelzSocketInfo()!); this.childrenTracker.refChild(this.channelzSocketRef); } session.unref(); @@ -626,6 +640,15 @@ export class Subchannel { ); } + private handleDisconnect() { + this.transitionToState( + [ConnectivityState.READY], + ConnectivityState.TRANSIENT_FAILURE); + for (const listener of this.disconnectListeners.values()) { + listener(); + } + } + /** * Initiate a state transition from any element of oldStates to the new * state. If the current connectivityState is not in oldStates, do nothing. @@ -656,12 +679,7 @@ export class Subchannel { const session = this.session!; session.socket.once('close', () => { if (this.session === session) { - this.transitionToState( - [ConnectivityState.READY], - ConnectivityState.TRANSIENT_FAILURE); - for (const listener of this.disconnectListeners) { - listener(); - } + this.handleDisconnect(); } }); if (this.keepaliveWithoutCalls) { @@ -721,7 +739,7 @@ export class Subchannel { } this.transitionToState( [ConnectivityState.CONNECTING, ConnectivityState.READY], - ConnectivityState.TRANSIENT_FAILURE + ConnectivityState.IDLE ); if (this.channelzEnabled) { unregisterChannelzRef(this.channelzRef); @@ -762,7 +780,7 @@ export class Subchannel { } this.backoffTimeout.unref(); if (!this.keepaliveWithoutCalls) { - this.stopKeepalivePings(); + clearInterval(this.keepaliveIntervalId); } this.checkBothRefcounts(); } @@ -929,14 +947,11 @@ export class Subchannel { } addDisconnectListener(listener: () => void) { - this.disconnectListeners.push(listener); + this.disconnectListeners.add(listener); } removeDisconnectListener(listener: () => void) { - const listenerIndex = this.disconnectListeners.indexOf(listener); - if (listenerIndex > -1) { - this.disconnectListeners.splice(listenerIndex, 1); - } + this.disconnectListeners.delete(listener); } /** diff --git a/packages/grpc-js/test/fixtures/test_service.proto b/packages/grpc-js/test/fixtures/test_service.proto index f99393d1..64ce0d37 100644 --- a/packages/grpc-js/test/fixtures/test_service.proto +++ b/packages/grpc-js/test/fixtures/test_service.proto @@ -25,6 +25,7 @@ message Request { message Response { int32 count = 1; + string message = 2; } service TestService { diff --git a/packages/grpc-js/test/generated/Response.ts b/packages/grpc-js/test/generated/Response.ts index 217fc75e..465ab720 100644 --- a/packages/grpc-js/test/generated/Response.ts +++ b/packages/grpc-js/test/generated/Response.ts @@ -3,8 +3,10 @@ export interface Response { 'count'?: (number); + 'message'?: (string); } export interface Response__Output { 'count': (number); + 'message': (string); } diff --git a/packages/grpc-js/test/generated/TestService.ts b/packages/grpc-js/test/generated/TestService.ts index 75bff33e..e477c99b 100644 --- a/packages/grpc-js/test/generated/TestService.ts +++ b/packages/grpc-js/test/generated/TestService.ts @@ -11,28 +11,28 @@ export interface TestServiceClient extends grpc.Client { bidiStream(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<_Request, _Response__Output>; bidiStream(options?: grpc.CallOptions): grpc.ClientDuplexStream<_Request, _Response__Output>; - ClientStream(metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _Response__Output) => void): grpc.ClientWritableStream<_Request>; - ClientStream(metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _Response__Output) => void): grpc.ClientWritableStream<_Request>; - ClientStream(options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _Response__Output) => void): grpc.ClientWritableStream<_Request>; - ClientStream(callback: (error?: grpc.ServiceError, result?: _Response__Output) => void): grpc.ClientWritableStream<_Request>; - clientStream(metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _Response__Output) => void): grpc.ClientWritableStream<_Request>; - clientStream(metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _Response__Output) => void): grpc.ClientWritableStream<_Request>; - clientStream(options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _Response__Output) => void): grpc.ClientWritableStream<_Request>; - clientStream(callback: (error?: grpc.ServiceError, result?: _Response__Output) => void): grpc.ClientWritableStream<_Request>; + ClientStream(metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_Response__Output>): grpc.ClientWritableStream<_Request>; + ClientStream(metadata: grpc.Metadata, callback: grpc.requestCallback<_Response__Output>): grpc.ClientWritableStream<_Request>; + ClientStream(options: grpc.CallOptions, callback: grpc.requestCallback<_Response__Output>): grpc.ClientWritableStream<_Request>; + ClientStream(callback: grpc.requestCallback<_Response__Output>): grpc.ClientWritableStream<_Request>; + clientStream(metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_Response__Output>): grpc.ClientWritableStream<_Request>; + clientStream(metadata: grpc.Metadata, callback: grpc.requestCallback<_Response__Output>): grpc.ClientWritableStream<_Request>; + clientStream(options: grpc.CallOptions, callback: grpc.requestCallback<_Response__Output>): grpc.ClientWritableStream<_Request>; + clientStream(callback: grpc.requestCallback<_Response__Output>): grpc.ClientWritableStream<_Request>; ServerStream(argument: _Request, metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientReadableStream<_Response__Output>; ServerStream(argument: _Request, options?: grpc.CallOptions): grpc.ClientReadableStream<_Response__Output>; serverStream(argument: _Request, metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientReadableStream<_Response__Output>; serverStream(argument: _Request, options?: grpc.CallOptions): grpc.ClientReadableStream<_Response__Output>; - Unary(argument: _Request, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _Response__Output) => void): grpc.ClientUnaryCall; - Unary(argument: _Request, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _Response__Output) => void): grpc.ClientUnaryCall; - Unary(argument: _Request, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _Response__Output) => void): grpc.ClientUnaryCall; - Unary(argument: _Request, callback: (error?: grpc.ServiceError, result?: _Response__Output) => void): grpc.ClientUnaryCall; - unary(argument: _Request, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _Response__Output) => void): grpc.ClientUnaryCall; - unary(argument: _Request, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _Response__Output) => void): grpc.ClientUnaryCall; - unary(argument: _Request, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _Response__Output) => void): grpc.ClientUnaryCall; - unary(argument: _Request, callback: (error?: grpc.ServiceError, result?: _Response__Output) => void): grpc.ClientUnaryCall; + Unary(argument: _Request, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_Response__Output>): grpc.ClientUnaryCall; + Unary(argument: _Request, metadata: grpc.Metadata, callback: grpc.requestCallback<_Response__Output>): grpc.ClientUnaryCall; + Unary(argument: _Request, options: grpc.CallOptions, callback: grpc.requestCallback<_Response__Output>): grpc.ClientUnaryCall; + Unary(argument: _Request, callback: grpc.requestCallback<_Response__Output>): grpc.ClientUnaryCall; + unary(argument: _Request, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_Response__Output>): grpc.ClientUnaryCall; + unary(argument: _Request, metadata: grpc.Metadata, callback: grpc.requestCallback<_Response__Output>): grpc.ClientUnaryCall; + unary(argument: _Request, options: grpc.CallOptions, callback: grpc.requestCallback<_Response__Output>): grpc.ClientUnaryCall; + unary(argument: _Request, callback: grpc.requestCallback<_Response__Output>): grpc.ClientUnaryCall; } diff --git a/packages/grpc-js/test/test-channel-credentials.ts b/packages/grpc-js/test/test-channel-credentials.ts index d6028f46..2b537ac9 100644 --- a/packages/grpc-js/test/test-channel-credentials.ts +++ b/packages/grpc-js/test/test-channel-credentials.ts @@ -17,12 +17,22 @@ import * as assert from 'assert'; import * as fs from 'fs'; +import * as path from 'path'; import { promisify } from 'util'; +import * as protoLoader from '@grpc/proto-loader'; import { CallCredentials } from '../src/call-credentials'; import { ChannelCredentials } from '../src/channel-credentials'; +import * as grpc from '../src'; +import { ServiceClient, ServiceClientConstructor } from '../src/make-client'; +import { TestServiceClient, TestServiceHandlers } from './generated/TestService'; +import { ProtoGrpcType as TestServiceGrpcType } from './generated/test_service'; -import { assert2, mockFunction } from './common'; +import { assert2, loadProtoFile, mockFunction } from './common'; +import { sendUnaryData, ServerUnaryCall, ServiceError } from '../src'; + +const protoFile = path.join(__dirname, 'fixtures', 'echo_service.proto'); +const echoService = loadProtoFile(protoFile).EchoService as ServiceClientConstructor; class CallCredentialsMock implements CallCredentials { child: CallCredentialsMock | null = null; @@ -138,3 +148,65 @@ describe('ChannelCredentials Implementation', () => { }); }); }); + +describe('ChannelCredentials usage', () => { + let client: ServiceClient; + let server: grpc.Server; + before(async () => { + const {ca, key, cert} = await pFixtures; + const serverCreds = grpc.ServerCredentials.createSsl(null, [{private_key: key, cert_chain: cert}]); + const channelCreds = ChannelCredentials.createSsl(ca); + const callCreds = CallCredentials.createFromMetadataGenerator((options, cb) => { + const metadata = new grpc.Metadata(); + metadata.set('test-key', 'test-value'); + cb(null, metadata); + }); + const combinedCreds = channelCreds.compose(callCreds); + return new Promise((resolve, reject) => { + + server = new grpc.Server(); + server.addService(echoService.service, { + echo(call: ServerUnaryCall, callback: sendUnaryData) { + call.sendMetadata(call.metadata); + callback(null, call.request); + }, + }); + + server.bindAsync( + 'localhost:0', + serverCreds, + (err, port) => { + if (err) { + reject(err); + return; + } + client = new echoService( + `localhost:${port}`, + combinedCreds, + {'grpc.ssl_target_name_override': 'foo.test.google.fr', 'grpc.default_authority': 'foo.test.google.fr'} + ); + server.start(); + resolve(); + } + ); + }); + }); + after(() => { + server.forceShutdown(); + }); + + it('Should send the metadata from call credentials attached to channel credentials', (done) => { + const call = client.echo( + { value: 'test value', value2: 3 }, + assert2.mustCall((error: ServiceError, response: any) => { + assert.ifError(error); + assert.deepStrictEqual(response, { value: 'test value', value2: 3 }); + }) + ); + call.on('metadata', assert2.mustCall((metadata: grpc.Metadata) => { + assert.deepStrictEqual(metadata.get('test-key'), ['test-value']); + + })); + assert2.afterMustCallsSatisfied(done); + }); +}); \ No newline at end of file diff --git a/packages/grpc-js/test/test-client.ts b/packages/grpc-js/test/test-client.ts index 4a02ff3d..21dad99f 100644 --- a/packages/grpc-js/test/test-client.ts +++ b/packages/grpc-js/test/test-client.ts @@ -92,4 +92,28 @@ describe('Client without a server', () => { }); }); }); +}); + +describe('Client with a nonexistent target domain', () => { + let client: Client; + before(() => { + // DNS name that does not exist per RFC 6761 section 6.4 + client = new Client('host.invalid', clientInsecureCreds); + }); + after(() => { + client.close(); + }); + it('should fail multiple calls', function(done) { + this.timeout(5000); + // Regression test for https://github.com/grpc/grpc-node/issues/1411 + client.makeUnaryRequest('/service/method', x => x, x => x, Buffer.from([]), (error, value) => { + assert(error); + assert.strictEqual(error?.code, grpc.status.UNAVAILABLE); + client.makeUnaryRequest('/service/method', x => x, x => x, Buffer.from([]), (error, value) => { + assert(error); + assert.strictEqual(error?.code, grpc.status.UNAVAILABLE); + done(); + }); + }); + }); }); \ No newline at end of file diff --git a/packages/grpc-js/test/test-outlier-detection.ts b/packages/grpc-js/test/test-outlier-detection.ts index 977a3058..74e53676 100644 --- a/packages/grpc-js/test/test-outlier-detection.ts +++ b/packages/grpc-js/test/test-outlier-detection.ts @@ -19,6 +19,7 @@ import * as assert from 'assert'; import * as path from 'path'; import * as grpc from '../src'; import { loadProtoFile } from './common'; +import { OutlierDetectionLoadBalancingConfig } from '../src/load-balancer-outlier-detection' function multiDone(done: Mocha.Done, target: number) { let count = 0; @@ -67,6 +68,251 @@ const protoFile = path.join(__dirname, 'fixtures', 'echo_service.proto'); const EchoService = loadProtoFile(protoFile) .EchoService as grpc.ServiceClientConstructor; +describe('Outlier detection config validation', () => { + describe('interval', () => { + it('Should reject a negative interval', () => { + const loadBalancingConfig = { + interval: { + seconds: -1, + nanos: 0 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /interval parse error: values out of range for non-negative Duaration/); + }); + it('Should reject a large interval', () => { + const loadBalancingConfig = { + interval: { + seconds: 1e12, + nanos: 0 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /interval parse error: values out of range for non-negative Duaration/); + }); + it('Should reject a negative interval.nanos', () => { + const loadBalancingConfig = { + interval: { + seconds: 0, + nanos: -1 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /interval parse error: values out of range for non-negative Duaration/); + }); + it('Should reject a large interval.nanos', () => { + const loadBalancingConfig = { + interval: { + seconds: 0, + nanos: 1e12 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /interval parse error: values out of range for non-negative Duaration/); + }); + }); + describe('base_ejection_time', () => { + it('Should reject a negative base_ejection_time', () => { + const loadBalancingConfig = { + base_ejection_time: { + seconds: -1, + nanos: 0 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /base_ejection_time parse error: values out of range for non-negative Duaration/); + }); + it('Should reject a large base_ejection_time', () => { + const loadBalancingConfig = { + base_ejection_time: { + seconds: 1e12, + nanos: 0 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /base_ejection_time parse error: values out of range for non-negative Duaration/); + }); + it('Should reject a negative base_ejection_time.nanos', () => { + const loadBalancingConfig = { + base_ejection_time: { + seconds: 0, + nanos: -1 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /base_ejection_time parse error: values out of range for non-negative Duaration/); + }); + it('Should reject a large base_ejection_time.nanos', () => { + const loadBalancingConfig = { + base_ejection_time: { + seconds: 0, + nanos: 1e12 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /base_ejection_time parse error: values out of range for non-negative Duaration/); + }); + }); + describe('max_ejection_time', () => { + it('Should reject a negative max_ejection_time', () => { + const loadBalancingConfig = { + max_ejection_time: { + seconds: -1, + nanos: 0 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /max_ejection_time parse error: values out of range for non-negative Duaration/); + }); + it('Should reject a large max_ejection_time', () => { + const loadBalancingConfig = { + max_ejection_time: { + seconds: 1e12, + nanos: 0 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /max_ejection_time parse error: values out of range for non-negative Duaration/); + }); + it('Should reject a negative max_ejection_time.nanos', () => { + const loadBalancingConfig = { + max_ejection_time: { + seconds: 0, + nanos: -1 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /max_ejection_time parse error: values out of range for non-negative Duaration/); + }); + it('Should reject a large max_ejection_time.nanos', () => { + const loadBalancingConfig = { + max_ejection_time: { + seconds: 0, + nanos: 1e12 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /max_ejection_time parse error: values out of range for non-negative Duaration/); + }); + }); + describe('max_ejection_percent', () => { + it('Should reject a value above 100', () => { + const loadBalancingConfig = { + max_ejection_percent: 101, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /max_ejection_percent parse error: value out of range for percentage/); + }); + it('Should reject a negative value', () => { + const loadBalancingConfig = { + max_ejection_percent: -1, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /max_ejection_percent parse error: value out of range for percentage/); + }); + }); + describe('success_rate_ejection.enforcement_percentage', () => { + it('Should reject a value above 100', () => { + const loadBalancingConfig = { + success_rate_ejection: { + enforcement_percentage: 101 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /success_rate_ejection\.enforcement_percentage parse error: value out of range for percentage/); + }); + it('Should reject a negative value', () => { + const loadBalancingConfig = { + success_rate_ejection: { + enforcement_percentage: -1 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /success_rate_ejection\.enforcement_percentage parse error: value out of range for percentage/); + }); + }); + describe('failure_percentage_ejection.threshold', () => { + it('Should reject a value above 100', () => { + const loadBalancingConfig = { + failure_percentage_ejection: { + threshold: 101 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /failure_percentage_ejection\.threshold parse error: value out of range for percentage/); + }); + it('Should reject a negative value', () => { + const loadBalancingConfig = { + failure_percentage_ejection: { + threshold: -1 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /failure_percentage_ejection\.threshold parse error: value out of range for percentage/); + }); + }); + describe('failure_percentage_ejection.enforcement_percentage', () => { + it('Should reject a value above 100', () => { + const loadBalancingConfig = { + failure_percentage_ejection: { + enforcement_percentage: 101 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /failure_percentage_ejection\.enforcement_percentage parse error: value out of range for percentage/); + }); + it('Should reject a negative value', () => { + const loadBalancingConfig = { + failure_percentage_ejection: { + enforcement_percentage: -1 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /failure_percentage_ejection\.enforcement_percentage parse error: value out of range for percentage/); + }); + }); +}); + describe('Outlier detection', () => { const GOOD_PORTS = 4; let goodServer: grpc.Server; diff --git a/packages/grpc-js/test/test-resolver.ts b/packages/grpc-js/test/test-resolver.ts index 1bcaabeb..a3e6793f 100644 --- a/packages/grpc-js/test/test-resolver.ts +++ b/packages/grpc-js/test/test-resolver.ts @@ -356,6 +356,70 @@ describe('Name Resolver', () => { const resolver2 = resolverManager.createResolver(target2, listener, {}); resolver2.updateResolution(); }); + it('should not keep repeating successful resolutions', done => { + const target = resolverManager.mapUriDefaultScheme(parseUri('localhost')!)!; + let resultCount = 0; + const resolver = resolverManager.createResolver(target, { + onSuccessfulResolution: ( + addressList: SubchannelAddress[], + serviceConfig: ServiceConfig | null, + serviceConfigError: StatusObject | null + ) => { + assert( + addressList.some( + addr => + isTcpSubchannelAddress(addr) && + addr.host === '127.0.0.1' && + addr.port === 443 + ) + ); + assert( + addressList.some( + addr => + isTcpSubchannelAddress(addr) && + addr.host === '::1' && + addr.port === 443 + ) + ); + resultCount += 1; + if (resultCount === 1) { + process.nextTick(() => resolver.updateResolution()); + } + }, + onError: (error: StatusObject) => { + assert.ifError(error); + }, + }, {'grpc.dns_min_time_between_resolutions_ms': 2000}); + resolver.updateResolution(); + setTimeout(() => { + assert.strictEqual(resultCount, 2, `resultCount ${resultCount} !== 2`); + done(); + }, 10_000); + }).timeout(15_000); + it('should not keep repeating failed resolutions', done => { + const target = resolverManager.mapUriDefaultScheme(parseUri('host.invalid')!)!; + let resultCount = 0; + const resolver = resolverManager.createResolver(target, { + onSuccessfulResolution: ( + addressList: SubchannelAddress[], + serviceConfig: ServiceConfig | null, + serviceConfigError: StatusObject | null + ) => { + assert.fail('Resolution succeeded unexpectedly'); + }, + onError: (error: StatusObject) => { + resultCount += 1; + if (resultCount === 1) { + process.nextTick(() => resolver.updateResolution()); + } + }, + }, {}); + resolver.updateResolution(); + setTimeout(() => { + assert.strictEqual(resultCount, 2, `resultCount ${resultCount} !== 2`); + done(); + }, 10_000); + }).timeout(15_000); }); describe('UDS Names', () => { it('Should handle a relative Unix Domain Socket name', done => { diff --git a/packages/grpc-js/test/test-server.ts b/packages/grpc-js/test/test-server.ts index 2513b1fe..0c0ba168 100644 --- a/packages/grpc-js/test/test-server.ts +++ b/packages/grpc-js/test/test-server.ts @@ -623,7 +623,7 @@ describe('Generic client and server', () => { describe('Compressed requests', () => { const testServiceHandlers: TestServiceHandlers = { Unary(call, callback) { - callback(null, { count: 500000 }); + callback(null, { count: 500000, message: call.request.message }); }, ClientStream(call, callback) { @@ -847,6 +847,20 @@ describe('Compressed requests', () => { }) }); }); + + it('Should handle large messages', done => { + let longMessage = ''; + for (let i = 0; i < 400000; i++) { + const letter = 'abcdefghijklmnopqrstuvwxyz'[Math.floor(Math.random() * 26)]; + longMessage = longMessage + letter.repeat(10); + } + + client.unary({message: longMessage}, (err, response) => { + assert.ifError(err); + assert.strictEqual(response?.message, longMessage); + done(); + }) + }) /* As of Node 16, Writable and Duplex streams validate the encoding * argument to write, and the flags values we are passing there are not diff --git a/packages/grpc-js/tsconfig.json b/packages/grpc-js/tsconfig.json index ba675db7..310b633c 100644 --- a/packages/grpc-js/tsconfig.json +++ b/packages/grpc-js/tsconfig.json @@ -6,7 +6,8 @@ "target": "es2017", "module": "commonjs", "resolveJsonModule": true, - "incremental": true + "incremental": true, + "types": ["mocha"] }, "include": [ "src/**/*.ts", diff --git a/packages/grpc-tools/build_binaries.sh b/packages/grpc-tools/build_binaries.sh index b26946af..e4488108 100755 --- a/packages/grpc-tools/build_binaries.sh +++ b/packages/grpc-tools/build_binaries.sh @@ -27,38 +27,45 @@ tools_version=$(jq '.version' < package.json | tr -d '"') out_dir=$base/../../artifacts/grpc-tools/v$tools_version mkdir -p "$out_dir" -case $(uname -s) in - Linux) - platform=linux - arch_list=( ia32 x64 ) - ;; - Darwin) - platform=darwin - arch_list=( x64 ) - ;; -esac +build () { + cmake_flag=$* -for arch in "${arch_list[@]}"; do - case $arch in - ia32) - toolchain_flag=-DCMAKE_TOOLCHAIN_FILE=linux_32bit.toolchain.cmake - ;; - *) - toolchain_flag=-DCMAKE_TOOLCHAIN_FILE=linux_64bit.toolchain.cmake - ;; - esac - rm -f $base/build/bin/protoc - rm -f $base/build/bin/grpc_node_plugin + rm -rf $base/build/bin rm -f $base/CMakeCache.txt rm -rf $base/CMakeFiles rm -f $protobuf_base/CMakeCache.txt rm -rf $protobuf_base/CMakeFiles - cmake $toolchain_flag . && cmake --build . --target clean && cmake --build . -- -j 12 - mkdir -p "$base/build/bin" + cmake $cmake_flag . && cmake --build . --target clean && cmake --build . -- -j 12 + mkdir -p $base/build/bin cp -L $protobuf_base/protoc $base/build/bin/protoc cp $base/grpc_node_plugin $base/build/bin/ file $base/build/bin/* - cd $base/build - tar -czf "$out_dir/$platform-$arch.tar.gz" bin/ - cd $base -done \ No newline at end of file +} + +artifacts() { + platform=$1 + arch=$2 + dir=$3 + + tar -czf $out_dir/$platform-$arch.tar.gz -C $(dirname $dir) $(basename $dir) +} + +case $(uname -s) in + Linux) + build -DCMAKE_TOOLCHAIN_FILE=linux_32bit.toolchain.cmake + artifacts linux ia32 $base/build/bin + build -DCMAKE_TOOLCHAIN_FILE=linux_64bit.toolchain.cmake + artifacts linux x64 $base/build/bin + ;; + Darwin) + build -DCMAKE_TOOLCHAIN_FILE=linux_64bit.toolchain.cmake -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" + + for arch in "x64" "arm64"; do + mkdir $base/build/bin/$arch + for bin in protoc grpc_node_plugin; do + lipo -extract x86_64 $base/build/bin/$bin -o $base/build/bin/$arch/$bin + done + artifacts darwin $arch $base/build/bin/$arch/ + done + ;; +esac diff --git a/packages/grpc-tools/package.json b/packages/grpc-tools/package.json index 95faa84c..1c7deb25 100644 --- a/packages/grpc-tools/package.json +++ b/packages/grpc-tools/package.json @@ -1,6 +1,6 @@ { "name": "grpc-tools", - "version": "1.11.2", + "version": "1.11.3", "author": "Google Inc.", "description": "Tools for developing with gRPC on Node.js", "homepage": "https://grpc.io/", diff --git a/packages/proto-loader/README.md b/packages/proto-loader/README.md index 123fad11..818f0efd 100644 --- a/packages/proto-loader/README.md +++ b/packages/proto-loader/README.md @@ -88,6 +88,10 @@ Options: -O, --outDir Directory in which to output files [string] [required] --grpcLib The gRPC implementation library that these types will be used with [string] [required] + --inputTemplate Template for mapping input or "permissive" type names + [string] [default: "%s"] + --outputTemplate Template for mapping output or "restricted" type names + [string] [default: "%s__Output"] ``` ### Example Usage diff --git a/packages/proto-loader/bin/proto-loader-gen-types.ts b/packages/proto-loader/bin/proto-loader-gen-types.ts index a819d12d..bb5b35f8 100644 --- a/packages/proto-loader/bin/proto-loader-gen-types.ts +++ b/packages/proto-loader/bin/proto-loader-gen-types.ts @@ -26,12 +26,25 @@ import * as yargs from 'yargs'; import camelCase = require('lodash.camelcase'); import { loadProtosWithOptions, addCommonProtos } from '../src/util'; +const templateStr = "%s"; +const useNameFmter = ({outputTemplate, inputTemplate}: GeneratorOptions) => { + if (outputTemplate === inputTemplate) { + throw new Error('inputTemplate and outputTemplate must differ') + } + return { + outputName: (n: string) => outputTemplate.replace(templateStr, n), + inputName: (n: string) => inputTemplate.replace(templateStr, n) + }; +} + type GeneratorOptions = Protobuf.IParseOptions & Protobuf.IConversionOptions & { includeDirs?: string[]; grpcLib: string; outDir: string; verbose?: boolean; includeComments?: boolean; + inputTemplate: string; + outputTemplate: string; } class TextFormatter { @@ -114,15 +127,16 @@ function getTypeInterfaceName(type: Protobuf.Type | Protobuf.Enum | Protobuf.Ser return type.fullName.replace(/\./g, '_'); } -function getImportLine(dependency: Protobuf.Type | Protobuf.Enum | Protobuf.Service, from?: Protobuf.Type | Protobuf.Service) { +function getImportLine(dependency: Protobuf.Type | Protobuf.Enum | Protobuf.Service, from: Protobuf.Type | Protobuf.Service | undefined, options: GeneratorOptions) { const filePath = from === undefined ? './' + getImportPath(dependency) : getRelativeImportPath(from, dependency); + const {outputName, inputName} = useNameFmter(options); const typeInterfaceName = getTypeInterfaceName(dependency); let importedTypes: string; /* If the dependency is defined within a message, it will be generated in that * message's file and exported using its typeInterfaceName. */ if (dependency.parent instanceof Protobuf.Type) { if (dependency instanceof Protobuf.Type) { - importedTypes = `${typeInterfaceName}, ${typeInterfaceName}__Output`; + importedTypes = `${inputName(typeInterfaceName)}, ${outputName(typeInterfaceName)}`; } else if (dependency instanceof Protobuf.Enum) { importedTypes = `${typeInterfaceName}`; } else if (dependency instanceof Protobuf.Service) { @@ -132,7 +146,7 @@ function getImportLine(dependency: Protobuf.Type | Protobuf.Enum | Protobuf.Serv } } else { if (dependency instanceof Protobuf.Type) { - importedTypes = `${dependency.name} as ${typeInterfaceName}, ${dependency.name}__Output as ${typeInterfaceName}__Output`; + importedTypes = `${inputName(dependency.name)} as ${inputName(typeInterfaceName)}, ${outputName(dependency.name)} as ${outputName(typeInterfaceName)}`; } else if (dependency instanceof Protobuf.Enum) { importedTypes = `${dependency.name} as ${typeInterfaceName}`; } else if (dependency instanceof Protobuf.Service) { @@ -170,7 +184,8 @@ function formatComment(formatter: TextFormatter, comment?: string | null) { // GENERATOR FUNCTIONS -function getTypeNamePermissive(fieldType: string, resolvedType: Protobuf.Type | Protobuf.Enum | null, repeated: boolean, map: boolean): string { +function getTypeNamePermissive(fieldType: string, resolvedType: Protobuf.Type | Protobuf.Enum | null, repeated: boolean, map: boolean, options: GeneratorOptions): string { + const {inputName} = useNameFmter(options); switch (fieldType) { case 'double': case 'float': @@ -200,9 +215,9 @@ function getTypeNamePermissive(fieldType: string, resolvedType: Protobuf.Type | const typeInterfaceName = getTypeInterfaceName(resolvedType); if (resolvedType instanceof Protobuf.Type) { if (repeated || map) { - return typeInterfaceName; + return inputName(typeInterfaceName); } else { - return `${typeInterfaceName} | null`; + return `${inputName(typeInterfaceName)} | null`; } } else { return `${typeInterfaceName} | keyof typeof ${typeInterfaceName}`; @@ -210,8 +225,8 @@ function getTypeNamePermissive(fieldType: string, resolvedType: Protobuf.Type | } } -function getFieldTypePermissive(field: Protobuf.FieldBase): string { - const valueType = getTypeNamePermissive(field.type, field.resolvedType, field.repeated, field.map); +function getFieldTypePermissive(field: Protobuf.FieldBase, options: GeneratorOptions): string { + const valueType = getTypeNamePermissive(field.type, field.resolvedType, field.repeated, field.map, options); if (field instanceof Protobuf.MapField) { const keyType = field.keyType === 'string' ? 'string' : 'number'; return `{[key: ${keyType}]: ${valueType}}`; @@ -221,23 +236,24 @@ function getFieldTypePermissive(field: Protobuf.FieldBase): string { } function generatePermissiveMessageInterface(formatter: TextFormatter, messageType: Protobuf.Type, options: GeneratorOptions, nameOverride?: string) { + const {inputName} = useNameFmter(options); if (options.includeComments) { formatComment(formatter, messageType.comment); } if (messageType.fullName === '.google.protobuf.Any') { /* This describes the behavior of the Protobuf.js Any wrapper fromObject * replacement function */ - formatter.writeLine('export type Any = AnyExtension | {'); + formatter.writeLine(`export type ${inputName('Any')} = AnyExtension | {`); formatter.writeLine(' type_url: string;'); formatter.writeLine(' value: Buffer | Uint8Array | string;'); formatter.writeLine('}'); return; } - formatter.writeLine(`export interface ${nameOverride ?? messageType.name} {`); + formatter.writeLine(`export interface ${inputName(nameOverride ?? messageType.name)} {`); formatter.indent(); for (const field of messageType.fieldsArray) { const repeatedString = field.repeated ? '[]' : ''; - const type: string = getFieldTypePermissive(field); + const type: string = getFieldTypePermissive(field, options); if (options.includeComments) { formatComment(formatter, field.comment); } @@ -255,6 +271,7 @@ function generatePermissiveMessageInterface(formatter: TextFormatter, messageTyp } function getTypeNameRestricted(fieldType: string, resolvedType: Protobuf.Type | Protobuf.Enum | null, repeated: boolean, map: boolean, options: GeneratorOptions): string { + const {outputName} = useNameFmter(options); switch (fieldType) { case 'double': case 'float': @@ -302,9 +319,9 @@ function getTypeNameRestricted(fieldType: string, resolvedType: Protobuf.Type | /* null is only used to represent absent message values if the defaults * option is set, and only for non-repeated, non-map fields. */ if (options.defaults && !repeated && !map) { - return `${typeInterfaceName}__Output | null`; + return `${outputName(typeInterfaceName)} | null`; } else { - return `${typeInterfaceName}__Output`; + return `${outputName(typeInterfaceName)}`; } } else { if (options.enums == String) { @@ -327,6 +344,7 @@ function getFieldTypeRestricted(field: Protobuf.FieldBase, options: GeneratorOpt } function generateRestrictedMessageInterface(formatter: TextFormatter, messageType: Protobuf.Type, options: GeneratorOptions, nameOverride?: string) { + const {outputName} = useNameFmter(options); if (options.includeComments) { formatComment(formatter, messageType.comment); } @@ -334,13 +352,13 @@ function generateRestrictedMessageInterface(formatter: TextFormatter, messageTyp /* This describes the behavior of the Protobuf.js Any wrapper toObject * replacement function */ let optionalString = options.defaults ? '' : '?'; - formatter.writeLine('export type Any__Output = AnyExtension | {'); + formatter.writeLine(`export type ${outputName('Any')} = AnyExtension | {`); formatter.writeLine(` type_url${optionalString}: string;`); formatter.writeLine(` value${optionalString}: ${getTypeNameRestricted('bytes', null, false, false, options)};`); formatter.writeLine('}'); return; } - formatter.writeLine(`export interface ${nameOverride ?? messageType.name}__Output {`); + formatter.writeLine(`export interface ${outputName(nameOverride ?? messageType.name)} {`); formatter.indent(); for (const field of messageType.fieldsArray) { let fieldGuaranteed: boolean; @@ -389,7 +407,7 @@ function generateMessageInterfaces(formatter: TextFormatter, messageType: Protob continue; } seenDeps.add(dependency.fullName); - formatter.writeLine(getImportLine(dependency, messageType)); + formatter.writeLine(getImportLine(dependency, messageType, options)); } if (field.type.indexOf('64') >= 0) { usesLong = true; @@ -404,7 +422,7 @@ function generateMessageInterfaces(formatter: TextFormatter, messageType: Protob continue; } seenDeps.add(dependency.fullName); - formatter.writeLine(getImportLine(dependency, messageType)); + formatter.writeLine(getImportLine(dependency, messageType, options)); } if (field.type.indexOf('64') >= 0) { usesLong = true; @@ -487,6 +505,7 @@ const CLIENT_RESERVED_METHOD_NAMES = new Set([ ]); function generateServiceClientInterface(formatter: TextFormatter, serviceType: Protobuf.Service, options: GeneratorOptions) { + const {outputName, inputName} = useNameFmter(options); if (options.includeComments) { formatComment(formatter, serviceType.comment); } @@ -501,8 +520,8 @@ function generateServiceClientInterface(formatter: TextFormatter, serviceType: P if (options.includeComments) { formatComment(formatter, method.comment); } - const requestType = getTypeInterfaceName(method.resolvedRequestType!); - const responseType = getTypeInterfaceName(method.resolvedResponseType!) + '__Output'; + const requestType = inputName(getTypeInterfaceName(method.resolvedRequestType!)); + const responseType = outputName(getTypeInterfaceName(method.resolvedResponseType!)); const callbackType = `grpc.requestCallback<${responseType}>`; if (method.requestStream) { if (method.responseStream) { @@ -541,6 +560,7 @@ function generateServiceClientInterface(formatter: TextFormatter, serviceType: P } function generateServiceHandlerInterface(formatter: TextFormatter, serviceType: Protobuf.Service, options: GeneratorOptions) { + const {inputName, outputName} = useNameFmter(options); if (options.includeComments) { formatComment(formatter, serviceType.comment); } @@ -551,8 +571,8 @@ function generateServiceHandlerInterface(formatter: TextFormatter, serviceType: if (options.includeComments) { formatComment(formatter, method.comment); } - const requestType = getTypeInterfaceName(method.resolvedRequestType!) + '__Output'; - const responseType = getTypeInterfaceName(method.resolvedResponseType!); + const requestType = outputName(getTypeInterfaceName(method.resolvedRequestType!)); + const responseType = inputName(getTypeInterfaceName(method.resolvedResponseType!)); if (method.requestStream) { if (method.responseStream) { // Bidi streaming @@ -576,14 +596,15 @@ function generateServiceHandlerInterface(formatter: TextFormatter, serviceType: formatter.writeLine('}'); } -function generateServiceDefinitionInterface(formatter: TextFormatter, serviceType: Protobuf.Service) { +function generateServiceDefinitionInterface(formatter: TextFormatter, serviceType: Protobuf.Service, options: GeneratorOptions) { + const {inputName, outputName} = useNameFmter(options); formatter.writeLine(`export interface ${serviceType.name}Definition extends grpc.ServiceDefinition {`); formatter.indent(); for (const methodName of Object.keys(serviceType.methods).sort()) { const method = serviceType.methods[methodName]; const requestType = getTypeInterfaceName(method.resolvedRequestType!); const responseType = getTypeInterfaceName(method.resolvedResponseType!); - formatter.writeLine(`${methodName}: MethodDefinition<${requestType}, ${responseType}, ${requestType}__Output, ${responseType}__Output>`); + formatter.writeLine(`${methodName}: MethodDefinition<${inputName(requestType)}, ${inputName(responseType)}, ${outputName(requestType)}, ${outputName(responseType)}>`); } formatter.unindent(); formatter.writeLine('}') @@ -601,7 +622,7 @@ function generateServiceInterfaces(formatter: TextFormatter, serviceType: Protob dependencies.add(method.resolvedResponseType!); } for (const dep of Array.from(dependencies.values()).sort(compareName)) { - formatter.writeLine(getImportLine(dep, serviceType)); + formatter.writeLine(getImportLine(dep, serviceType, options)); } formatter.writeLine(''); @@ -611,7 +632,7 @@ function generateServiceInterfaces(formatter: TextFormatter, serviceType: Protob generateServiceHandlerInterface(formatter, serviceType, options); formatter.writeLine(''); - generateServiceDefinitionInterface(formatter, serviceType); + generateServiceDefinitionInterface(formatter, serviceType, options); } function containsDefinition(definitionType: typeof Protobuf.Type | typeof Protobuf.Enum, namespace: Protobuf.NamespaceBase): boolean { @@ -645,7 +666,7 @@ function generateDefinitionImports(formatter: TextFormatter, namespace: Protobuf function generateServiceImports(formatter: TextFormatter, namespace: Protobuf.NamespaceBase, options: GeneratorOptions) { for (const nested of namespace.nestedArray.sort(compareName)) { if (nested instanceof Protobuf.Service) { - formatter.writeLine(getImportLine(nested)); + formatter.writeLine(getImportLine(nested, undefined, options)); } else if (isNamespaceBase(nested) && !(nested instanceof Protobuf.Type) && !(nested instanceof Protobuf.Enum)) { generateServiceImports(formatter, nested, options); } @@ -776,7 +797,7 @@ async function runScript() { .normalize(['includeDirs', 'outDir']) .array('includeDirs') .boolean(['keepCase', 'defaults', 'arrays', 'objects', 'oneofs', 'json', 'verbose', 'includeComments']) - .string(['longs', 'enums', 'bytes']) + .string(['longs', 'enums', 'bytes', 'inputTemplate', 'outputTemplate']) .default('keepCase', false) .default('defaults', false) .default('arrays', false) @@ -787,6 +808,8 @@ async function runScript() { .default('longs', 'Long') .default('enums', 'number') .default('bytes', 'Buffer') + .default('inputTemplate', `${templateStr}`) + .default('outputTemplate', `${templateStr}__Output`) .coerce('longs', value => { switch (value) { case 'String': return String; @@ -805,7 +828,8 @@ async function runScript() { case 'String': return String; default: return undefined; } - }).alias({ + }) + .alias({ includeDirs: 'I', outDir: 'O', verbose: 'v' @@ -822,7 +846,9 @@ async function runScript() { includeComments: 'Generate doc comments from comments in the original files', includeDirs: 'Directories to search for included files', outDir: 'Directory in which to output files', - grpcLib: 'The gRPC implementation library that these types will be used with' + grpcLib: 'The gRPC implementation library that these types will be used with', + inputTemplate: 'Template for mapping input or "permissive" type names', + outputTemplate: 'Template for mapping output or "restricted" type names', }).demandOption(['outDir', 'grpcLib']) .demand(1) .usage('$0 [options] filenames...') diff --git a/packages/proto-loader/golden-generated/google/api/CustomHttpPattern.ts b/packages/proto-loader/golden-generated/google/api/CustomHttpPattern.ts index 2b6490be..2f6e2029 100644 --- a/packages/proto-loader/golden-generated/google/api/CustomHttpPattern.ts +++ b/packages/proto-loader/golden-generated/google/api/CustomHttpPattern.ts @@ -4,7 +4,7 @@ /** * A custom pattern is used for defining custom HTTP verb. */ -export interface CustomHttpPattern { +export interface ICustomHttpPattern { /** * The name of this custom HTTP verb. */ @@ -18,7 +18,7 @@ export interface CustomHttpPattern { /** * A custom pattern is used for defining custom HTTP verb. */ -export interface CustomHttpPattern__Output { +export interface OCustomHttpPattern { /** * The name of this custom HTTP verb. */ diff --git a/packages/proto-loader/golden-generated/google/api/Http.ts b/packages/proto-loader/golden-generated/google/api/Http.ts index e9b3cb30..6b6ae8a6 100644 --- a/packages/proto-loader/golden-generated/google/api/Http.ts +++ b/packages/proto-loader/golden-generated/google/api/Http.ts @@ -1,19 +1,19 @@ // Original file: deps/googleapis/google/api/http.proto -import type { HttpRule as _google_api_HttpRule, HttpRule__Output as _google_api_HttpRule__Output } from '../../google/api/HttpRule'; +import type { IHttpRule as I_google_api_HttpRule, OHttpRule as O_google_api_HttpRule } from '../../google/api/HttpRule'; /** * Defines the HTTP configuration for an API service. It contains a list of * [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method * to one or more HTTP REST API methods. */ -export interface Http { +export interface IHttp { /** * A list of HTTP configuration rules that apply to individual API methods. * * **NOTE:** All service configuration rules follow "last one wins" order. */ - 'rules'?: (_google_api_HttpRule)[]; + 'rules'?: (I_google_api_HttpRule)[]; /** * When set to true, URL path parameters will be fully URI-decoded except in * cases of single segment matches in reserved expansion, where "%2F" will be @@ -30,13 +30,13 @@ export interface Http { * [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method * to one or more HTTP REST API methods. */ -export interface Http__Output { +export interface OHttp { /** * A list of HTTP configuration rules that apply to individual API methods. * * **NOTE:** All service configuration rules follow "last one wins" order. */ - 'rules': (_google_api_HttpRule__Output)[]; + 'rules': (O_google_api_HttpRule)[]; /** * When set to true, URL path parameters will be fully URI-decoded except in * cases of single segment matches in reserved expansion, where "%2F" will be diff --git a/packages/proto-loader/golden-generated/google/api/HttpRule.ts b/packages/proto-loader/golden-generated/google/api/HttpRule.ts index 243a99f8..90efdc00 100644 --- a/packages/proto-loader/golden-generated/google/api/HttpRule.ts +++ b/packages/proto-loader/golden-generated/google/api/HttpRule.ts @@ -1,7 +1,7 @@ // Original file: deps/googleapis/google/api/http.proto -import type { CustomHttpPattern as _google_api_CustomHttpPattern, CustomHttpPattern__Output as _google_api_CustomHttpPattern__Output } from '../../google/api/CustomHttpPattern'; -import type { HttpRule as _google_api_HttpRule, HttpRule__Output as _google_api_HttpRule__Output } from '../../google/api/HttpRule'; +import type { ICustomHttpPattern as I_google_api_CustomHttpPattern, OCustomHttpPattern as O_google_api_CustomHttpPattern } from '../../google/api/CustomHttpPattern'; +import type { IHttpRule as I_google_api_HttpRule, OHttpRule as O_google_api_HttpRule } from '../../google/api/HttpRule'; /** * # gRPC Transcoding @@ -274,7 +274,7 @@ import type { HttpRule as _google_api_HttpRule, HttpRule__Output as _google_api_ * the request or response body to a repeated field. However, some gRPC * Transcoding implementations may not support this feature. */ -export interface HttpRule { +export interface IHttpRule { /** * Selects a method to which this rule applies. * @@ -317,13 +317,13 @@ export interface HttpRule { * HTTP method unspecified for this rule. The wild-card rule is useful * for services that provide content to Web (HTML) clients. */ - 'custom'?: (_google_api_CustomHttpPattern | null); + 'custom'?: (I_google_api_CustomHttpPattern | null); /** * Additional HTTP bindings for the selector. Nested bindings must * not contain an `additional_bindings` field themselves (that is, * the nesting may only be one level deep). */ - 'additional_bindings'?: (_google_api_HttpRule)[]; + 'additional_bindings'?: (I_google_api_HttpRule)[]; /** * Optional. The name of the response field whose value is mapped to the HTTP * response body. When omitted, the entire response message will be used @@ -612,7 +612,7 @@ export interface HttpRule { * the request or response body to a repeated field. However, some gRPC * Transcoding implementations may not support this feature. */ -export interface HttpRule__Output { +export interface OHttpRule { /** * Selects a method to which this rule applies. * @@ -655,13 +655,13 @@ export interface HttpRule__Output { * HTTP method unspecified for this rule. The wild-card rule is useful * for services that provide content to Web (HTML) clients. */ - 'custom'?: (_google_api_CustomHttpPattern__Output | null); + 'custom'?: (O_google_api_CustomHttpPattern | null); /** * Additional HTTP bindings for the selector. Nested bindings must * not contain an `additional_bindings` field themselves (that is, * the nesting may only be one level deep). */ - 'additional_bindings': (_google_api_HttpRule__Output)[]; + 'additional_bindings': (O_google_api_HttpRule)[]; /** * Optional. The name of the response field whose value is mapped to the HTTP * response body. When omitted, the entire response message will be used diff --git a/packages/proto-loader/golden-generated/google/longrunning/CancelOperationRequest.ts b/packages/proto-loader/golden-generated/google/longrunning/CancelOperationRequest.ts index 05fbc842..7e0f15ed 100644 --- a/packages/proto-loader/golden-generated/google/longrunning/CancelOperationRequest.ts +++ b/packages/proto-loader/golden-generated/google/longrunning/CancelOperationRequest.ts @@ -4,7 +4,7 @@ /** * The request message for [Operations.CancelOperation][google.longrunning.Operations.CancelOperation]. */ -export interface CancelOperationRequest { +export interface ICancelOperationRequest { /** * The name of the operation resource to be cancelled. */ @@ -14,7 +14,7 @@ export interface CancelOperationRequest { /** * The request message for [Operations.CancelOperation][google.longrunning.Operations.CancelOperation]. */ -export interface CancelOperationRequest__Output { +export interface OCancelOperationRequest { /** * The name of the operation resource to be cancelled. */ diff --git a/packages/proto-loader/golden-generated/google/longrunning/DeleteOperationRequest.ts b/packages/proto-loader/golden-generated/google/longrunning/DeleteOperationRequest.ts index 0ad87cde..39d669d0 100644 --- a/packages/proto-loader/golden-generated/google/longrunning/DeleteOperationRequest.ts +++ b/packages/proto-loader/golden-generated/google/longrunning/DeleteOperationRequest.ts @@ -4,7 +4,7 @@ /** * The request message for [Operations.DeleteOperation][google.longrunning.Operations.DeleteOperation]. */ -export interface DeleteOperationRequest { +export interface IDeleteOperationRequest { /** * The name of the operation resource to be deleted. */ @@ -14,7 +14,7 @@ export interface DeleteOperationRequest { /** * The request message for [Operations.DeleteOperation][google.longrunning.Operations.DeleteOperation]. */ -export interface DeleteOperationRequest__Output { +export interface ODeleteOperationRequest { /** * The name of the operation resource to be deleted. */ diff --git a/packages/proto-loader/golden-generated/google/longrunning/GetOperationRequest.ts b/packages/proto-loader/golden-generated/google/longrunning/GetOperationRequest.ts index 039f0167..9667e2e8 100644 --- a/packages/proto-loader/golden-generated/google/longrunning/GetOperationRequest.ts +++ b/packages/proto-loader/golden-generated/google/longrunning/GetOperationRequest.ts @@ -4,7 +4,7 @@ /** * The request message for [Operations.GetOperation][google.longrunning.Operations.GetOperation]. */ -export interface GetOperationRequest { +export interface IGetOperationRequest { /** * The name of the operation resource. */ @@ -14,7 +14,7 @@ export interface GetOperationRequest { /** * The request message for [Operations.GetOperation][google.longrunning.Operations.GetOperation]. */ -export interface GetOperationRequest__Output { +export interface OGetOperationRequest { /** * The name of the operation resource. */ diff --git a/packages/proto-loader/golden-generated/google/longrunning/ListOperationsRequest.ts b/packages/proto-loader/golden-generated/google/longrunning/ListOperationsRequest.ts index 294ec677..49dcd39f 100644 --- a/packages/proto-loader/golden-generated/google/longrunning/ListOperationsRequest.ts +++ b/packages/proto-loader/golden-generated/google/longrunning/ListOperationsRequest.ts @@ -4,7 +4,7 @@ /** * The request message for [Operations.ListOperations][google.longrunning.Operations.ListOperations]. */ -export interface ListOperationsRequest { +export interface IListOperationsRequest { /** * The standard list filter. */ @@ -26,7 +26,7 @@ export interface ListOperationsRequest { /** * The request message for [Operations.ListOperations][google.longrunning.Operations.ListOperations]. */ -export interface ListOperationsRequest__Output { +export interface OListOperationsRequest { /** * The standard list filter. */ diff --git a/packages/proto-loader/golden-generated/google/longrunning/ListOperationsResponse.ts b/packages/proto-loader/golden-generated/google/longrunning/ListOperationsResponse.ts index c295aa80..1e8b9ed5 100644 --- a/packages/proto-loader/golden-generated/google/longrunning/ListOperationsResponse.ts +++ b/packages/proto-loader/golden-generated/google/longrunning/ListOperationsResponse.ts @@ -1,15 +1,15 @@ // Original file: deps/googleapis/google/longrunning/operations.proto -import type { Operation as _google_longrunning_Operation, Operation__Output as _google_longrunning_Operation__Output } from '../../google/longrunning/Operation'; +import type { IOperation as I_google_longrunning_Operation, OOperation as O_google_longrunning_Operation } from '../../google/longrunning/Operation'; /** * The response message for [Operations.ListOperations][google.longrunning.Operations.ListOperations]. */ -export interface ListOperationsResponse { +export interface IListOperationsResponse { /** * A list of operations that matches the specified filter in the request. */ - 'operations'?: (_google_longrunning_Operation)[]; + 'operations'?: (I_google_longrunning_Operation)[]; /** * The standard List next-page token. */ @@ -19,11 +19,11 @@ export interface ListOperationsResponse { /** * The response message for [Operations.ListOperations][google.longrunning.Operations.ListOperations]. */ -export interface ListOperationsResponse__Output { +export interface OListOperationsResponse { /** * A list of operations that matches the specified filter in the request. */ - 'operations': (_google_longrunning_Operation__Output)[]; + 'operations': (O_google_longrunning_Operation)[]; /** * The standard List next-page token. */ diff --git a/packages/proto-loader/golden-generated/google/longrunning/Operation.ts b/packages/proto-loader/golden-generated/google/longrunning/Operation.ts index 2a4bbe1e..bbd1d807 100644 --- a/packages/proto-loader/golden-generated/google/longrunning/Operation.ts +++ b/packages/proto-loader/golden-generated/google/longrunning/Operation.ts @@ -1,13 +1,13 @@ // Original file: deps/googleapis/google/longrunning/operations.proto -import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../google/protobuf/Any'; -import type { Status as _google_rpc_Status, Status__Output as _google_rpc_Status__Output } from '../../google/rpc/Status'; +import type { IAny as I_google_protobuf_Any, OAny as O_google_protobuf_Any } from '../../google/protobuf/Any'; +import type { IStatus as I_google_rpc_Status, OStatus as O_google_rpc_Status } from '../../google/rpc/Status'; /** * This resource represents a long-running operation that is the result of a * network API call. */ -export interface Operation { +export interface IOperation { /** * The server-assigned name, which is only unique within the same service that * originally returns it. If you use the default HTTP mapping, the @@ -20,7 +20,7 @@ export interface Operation { * Some services might not provide such metadata. Any method that returns a * long-running operation should document the metadata type, if any. */ - 'metadata'?: (_google_protobuf_Any | null); + 'metadata'?: (I_google_protobuf_Any | null); /** * If the value is `false`, it means the operation is still in progress. * If `true`, the operation is completed, and either `error` or `response` is @@ -30,7 +30,7 @@ export interface Operation { /** * The error result of the operation in case of failure or cancellation. */ - 'error'?: (_google_rpc_Status | null); + 'error'?: (I_google_rpc_Status | null); /** * The normal response of the operation in case of success. If the original * method returns no data on success, such as `Delete`, the response is @@ -41,7 +41,7 @@ export interface Operation { * is `TakeSnapshot()`, the inferred response type is * `TakeSnapshotResponse`. */ - 'response'?: (_google_protobuf_Any | null); + 'response'?: (I_google_protobuf_Any | null); /** * The operation result, which can be either an `error` or a valid `response`. * If `done` == `false`, neither `error` nor `response` is set. @@ -54,7 +54,7 @@ export interface Operation { * This resource represents a long-running operation that is the result of a * network API call. */ -export interface Operation__Output { +export interface OOperation { /** * The server-assigned name, which is only unique within the same service that * originally returns it. If you use the default HTTP mapping, the @@ -67,7 +67,7 @@ export interface Operation__Output { * Some services might not provide such metadata. Any method that returns a * long-running operation should document the metadata type, if any. */ - 'metadata': (_google_protobuf_Any__Output | null); + 'metadata': (O_google_protobuf_Any | null); /** * If the value is `false`, it means the operation is still in progress. * If `true`, the operation is completed, and either `error` or `response` is @@ -77,7 +77,7 @@ export interface Operation__Output { /** * The error result of the operation in case of failure or cancellation. */ - 'error'?: (_google_rpc_Status__Output | null); + 'error'?: (O_google_rpc_Status | null); /** * The normal response of the operation in case of success. If the original * method returns no data on success, such as `Delete`, the response is @@ -88,7 +88,7 @@ export interface Operation__Output { * is `TakeSnapshot()`, the inferred response type is * `TakeSnapshotResponse`. */ - 'response'?: (_google_protobuf_Any__Output | null); + 'response'?: (O_google_protobuf_Any | null); /** * The operation result, which can be either an `error` or a valid `response`. * If `done` == `false`, neither `error` nor `response` is set. diff --git a/packages/proto-loader/golden-generated/google/longrunning/OperationInfo.ts b/packages/proto-loader/golden-generated/google/longrunning/OperationInfo.ts index 343e2f8c..90757441 100644 --- a/packages/proto-loader/golden-generated/google/longrunning/OperationInfo.ts +++ b/packages/proto-loader/golden-generated/google/longrunning/OperationInfo.ts @@ -14,7 +14,7 @@ * }; * } */ -export interface OperationInfo { +export interface IOperationInfo { /** * Required. The message name of the primary return type for this * long-running operation. @@ -51,7 +51,7 @@ export interface OperationInfo { * }; * } */ -export interface OperationInfo__Output { +export interface OOperationInfo { /** * Required. The message name of the primary return type for this * long-running operation. diff --git a/packages/proto-loader/golden-generated/google/longrunning/Operations.ts b/packages/proto-loader/golden-generated/google/longrunning/Operations.ts index 6358cbbf..00d6a95d 100644 --- a/packages/proto-loader/golden-generated/google/longrunning/Operations.ts +++ b/packages/proto-loader/golden-generated/google/longrunning/Operations.ts @@ -2,14 +2,14 @@ import type * as grpc from '@grpc/grpc-js' import type { MethodDefinition } from '@grpc/proto-loader' -import type { CancelOperationRequest as _google_longrunning_CancelOperationRequest, CancelOperationRequest__Output as _google_longrunning_CancelOperationRequest__Output } from '../../google/longrunning/CancelOperationRequest'; -import type { DeleteOperationRequest as _google_longrunning_DeleteOperationRequest, DeleteOperationRequest__Output as _google_longrunning_DeleteOperationRequest__Output } from '../../google/longrunning/DeleteOperationRequest'; -import type { Empty as _google_protobuf_Empty, Empty__Output as _google_protobuf_Empty__Output } from '../../google/protobuf/Empty'; -import type { GetOperationRequest as _google_longrunning_GetOperationRequest, GetOperationRequest__Output as _google_longrunning_GetOperationRequest__Output } from '../../google/longrunning/GetOperationRequest'; -import type { ListOperationsRequest as _google_longrunning_ListOperationsRequest, ListOperationsRequest__Output as _google_longrunning_ListOperationsRequest__Output } from '../../google/longrunning/ListOperationsRequest'; -import type { ListOperationsResponse as _google_longrunning_ListOperationsResponse, ListOperationsResponse__Output as _google_longrunning_ListOperationsResponse__Output } from '../../google/longrunning/ListOperationsResponse'; -import type { Operation as _google_longrunning_Operation, Operation__Output as _google_longrunning_Operation__Output } from '../../google/longrunning/Operation'; -import type { WaitOperationRequest as _google_longrunning_WaitOperationRequest, WaitOperationRequest__Output as _google_longrunning_WaitOperationRequest__Output } from '../../google/longrunning/WaitOperationRequest'; +import type { ICancelOperationRequest as I_google_longrunning_CancelOperationRequest, OCancelOperationRequest as O_google_longrunning_CancelOperationRequest } from '../../google/longrunning/CancelOperationRequest'; +import type { IDeleteOperationRequest as I_google_longrunning_DeleteOperationRequest, ODeleteOperationRequest as O_google_longrunning_DeleteOperationRequest } from '../../google/longrunning/DeleteOperationRequest'; +import type { IEmpty as I_google_protobuf_Empty, OEmpty as O_google_protobuf_Empty } from '../../google/protobuf/Empty'; +import type { IGetOperationRequest as I_google_longrunning_GetOperationRequest, OGetOperationRequest as O_google_longrunning_GetOperationRequest } from '../../google/longrunning/GetOperationRequest'; +import type { IListOperationsRequest as I_google_longrunning_ListOperationsRequest, OListOperationsRequest as O_google_longrunning_ListOperationsRequest } from '../../google/longrunning/ListOperationsRequest'; +import type { IListOperationsResponse as I_google_longrunning_ListOperationsResponse, OListOperationsResponse as O_google_longrunning_ListOperationsResponse } from '../../google/longrunning/ListOperationsResponse'; +import type { IOperation as I_google_longrunning_Operation, OOperation as O_google_longrunning_Operation } from '../../google/longrunning/Operation'; +import type { IWaitOperationRequest as I_google_longrunning_WaitOperationRequest, OWaitOperationRequest as O_google_longrunning_WaitOperationRequest } from '../../google/longrunning/WaitOperationRequest'; /** * Manages long-running operations with an API service. @@ -35,10 +35,10 @@ export interface OperationsClient extends grpc.Client { * an [Operation.error][google.longrunning.Operation.error] value with a [google.rpc.Status.code][google.rpc.Status.code] of 1, * corresponding to `Code.CANCELLED`. */ - CancelOperation(argument: _google_longrunning_CancelOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_google_protobuf_Empty__Output>): grpc.ClientUnaryCall; - CancelOperation(argument: _google_longrunning_CancelOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_google_protobuf_Empty__Output>): grpc.ClientUnaryCall; - CancelOperation(argument: _google_longrunning_CancelOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_google_protobuf_Empty__Output>): grpc.ClientUnaryCall; - CancelOperation(argument: _google_longrunning_CancelOperationRequest, callback: grpc.requestCallback<_google_protobuf_Empty__Output>): grpc.ClientUnaryCall; + CancelOperation(argument: I_google_longrunning_CancelOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + CancelOperation(argument: I_google_longrunning_CancelOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + CancelOperation(argument: I_google_longrunning_CancelOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + CancelOperation(argument: I_google_longrunning_CancelOperationRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * Starts asynchronous cancellation on a long-running operation. The server * makes a best effort to cancel the operation, but success is not @@ -51,10 +51,10 @@ export interface OperationsClient extends grpc.Client { * an [Operation.error][google.longrunning.Operation.error] value with a [google.rpc.Status.code][google.rpc.Status.code] of 1, * corresponding to `Code.CANCELLED`. */ - cancelOperation(argument: _google_longrunning_CancelOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_google_protobuf_Empty__Output>): grpc.ClientUnaryCall; - cancelOperation(argument: _google_longrunning_CancelOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_google_protobuf_Empty__Output>): grpc.ClientUnaryCall; - cancelOperation(argument: _google_longrunning_CancelOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_google_protobuf_Empty__Output>): grpc.ClientUnaryCall; - cancelOperation(argument: _google_longrunning_CancelOperationRequest, callback: grpc.requestCallback<_google_protobuf_Empty__Output>): grpc.ClientUnaryCall; + cancelOperation(argument: I_google_longrunning_CancelOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + cancelOperation(argument: I_google_longrunning_CancelOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + cancelOperation(argument: I_google_longrunning_CancelOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + cancelOperation(argument: I_google_longrunning_CancelOperationRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * Deletes a long-running operation. This method indicates that the client is @@ -62,39 +62,39 @@ export interface OperationsClient extends grpc.Client { * operation. If the server doesn't support this method, it returns * `google.rpc.Code.UNIMPLEMENTED`. */ - DeleteOperation(argument: _google_longrunning_DeleteOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_google_protobuf_Empty__Output>): grpc.ClientUnaryCall; - DeleteOperation(argument: _google_longrunning_DeleteOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_google_protobuf_Empty__Output>): grpc.ClientUnaryCall; - DeleteOperation(argument: _google_longrunning_DeleteOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_google_protobuf_Empty__Output>): grpc.ClientUnaryCall; - DeleteOperation(argument: _google_longrunning_DeleteOperationRequest, callback: grpc.requestCallback<_google_protobuf_Empty__Output>): grpc.ClientUnaryCall; + DeleteOperation(argument: I_google_longrunning_DeleteOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + DeleteOperation(argument: I_google_longrunning_DeleteOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + DeleteOperation(argument: I_google_longrunning_DeleteOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + DeleteOperation(argument: I_google_longrunning_DeleteOperationRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * 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`. */ - deleteOperation(argument: _google_longrunning_DeleteOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_google_protobuf_Empty__Output>): grpc.ClientUnaryCall; - deleteOperation(argument: _google_longrunning_DeleteOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_google_protobuf_Empty__Output>): grpc.ClientUnaryCall; - deleteOperation(argument: _google_longrunning_DeleteOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_google_protobuf_Empty__Output>): grpc.ClientUnaryCall; - deleteOperation(argument: _google_longrunning_DeleteOperationRequest, callback: grpc.requestCallback<_google_protobuf_Empty__Output>): grpc.ClientUnaryCall; + deleteOperation(argument: I_google_longrunning_DeleteOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + deleteOperation(argument: I_google_longrunning_DeleteOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + deleteOperation(argument: I_google_longrunning_DeleteOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + deleteOperation(argument: I_google_longrunning_DeleteOperationRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * 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. */ - GetOperation(argument: _google_longrunning_GetOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_google_longrunning_Operation__Output>): grpc.ClientUnaryCall; - GetOperation(argument: _google_longrunning_GetOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_google_longrunning_Operation__Output>): grpc.ClientUnaryCall; - GetOperation(argument: _google_longrunning_GetOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_google_longrunning_Operation__Output>): grpc.ClientUnaryCall; - GetOperation(argument: _google_longrunning_GetOperationRequest, callback: grpc.requestCallback<_google_longrunning_Operation__Output>): grpc.ClientUnaryCall; + GetOperation(argument: I_google_longrunning_GetOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + GetOperation(argument: I_google_longrunning_GetOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + GetOperation(argument: I_google_longrunning_GetOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + GetOperation(argument: I_google_longrunning_GetOperationRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * 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. */ - getOperation(argument: _google_longrunning_GetOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_google_longrunning_Operation__Output>): grpc.ClientUnaryCall; - getOperation(argument: _google_longrunning_GetOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_google_longrunning_Operation__Output>): grpc.ClientUnaryCall; - getOperation(argument: _google_longrunning_GetOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_google_longrunning_Operation__Output>): grpc.ClientUnaryCall; - getOperation(argument: _google_longrunning_GetOperationRequest, callback: grpc.requestCallback<_google_longrunning_Operation__Output>): grpc.ClientUnaryCall; + getOperation(argument: I_google_longrunning_GetOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + getOperation(argument: I_google_longrunning_GetOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + getOperation(argument: I_google_longrunning_GetOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + getOperation(argument: I_google_longrunning_GetOperationRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * Lists operations that match the specified filter in the request. If the @@ -108,10 +108,10 @@ export interface OperationsClient extends grpc.Client { * collection id, however overriding users must ensure the name binding * is the parent resource, without the operations collection id. */ - ListOperations(argument: _google_longrunning_ListOperationsRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_google_longrunning_ListOperationsResponse__Output>): grpc.ClientUnaryCall; - ListOperations(argument: _google_longrunning_ListOperationsRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_google_longrunning_ListOperationsResponse__Output>): grpc.ClientUnaryCall; - ListOperations(argument: _google_longrunning_ListOperationsRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_google_longrunning_ListOperationsResponse__Output>): grpc.ClientUnaryCall; - ListOperations(argument: _google_longrunning_ListOperationsRequest, callback: grpc.requestCallback<_google_longrunning_ListOperationsResponse__Output>): grpc.ClientUnaryCall; + ListOperations(argument: I_google_longrunning_ListOperationsRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + ListOperations(argument: I_google_longrunning_ListOperationsRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + ListOperations(argument: I_google_longrunning_ListOperationsRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + ListOperations(argument: I_google_longrunning_ListOperationsRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * Lists operations that match the specified filter in the request. If the * server doesn't support this method, it returns `UNIMPLEMENTED`. @@ -124,10 +124,10 @@ export interface OperationsClient extends grpc.Client { * collection id, however overriding users must ensure the name binding * is the parent resource, without the operations collection id. */ - listOperations(argument: _google_longrunning_ListOperationsRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_google_longrunning_ListOperationsResponse__Output>): grpc.ClientUnaryCall; - listOperations(argument: _google_longrunning_ListOperationsRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_google_longrunning_ListOperationsResponse__Output>): grpc.ClientUnaryCall; - listOperations(argument: _google_longrunning_ListOperationsRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_google_longrunning_ListOperationsResponse__Output>): grpc.ClientUnaryCall; - listOperations(argument: _google_longrunning_ListOperationsRequest, callback: grpc.requestCallback<_google_longrunning_ListOperationsResponse__Output>): grpc.ClientUnaryCall; + listOperations(argument: I_google_longrunning_ListOperationsRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + listOperations(argument: I_google_longrunning_ListOperationsRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + listOperations(argument: I_google_longrunning_ListOperationsRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + listOperations(argument: I_google_longrunning_ListOperationsRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * Waits for the specified long-running operation until it is done or reaches @@ -140,10 +140,10 @@ export interface OperationsClient extends grpc.Client { * state before the specified timeout (including immediately), meaning even an * immediate response is no guarantee that the operation is done. */ - WaitOperation(argument: _google_longrunning_WaitOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_google_longrunning_Operation__Output>): grpc.ClientUnaryCall; - WaitOperation(argument: _google_longrunning_WaitOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_google_longrunning_Operation__Output>): grpc.ClientUnaryCall; - WaitOperation(argument: _google_longrunning_WaitOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_google_longrunning_Operation__Output>): grpc.ClientUnaryCall; - WaitOperation(argument: _google_longrunning_WaitOperationRequest, callback: grpc.requestCallback<_google_longrunning_Operation__Output>): grpc.ClientUnaryCall; + WaitOperation(argument: I_google_longrunning_WaitOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + WaitOperation(argument: I_google_longrunning_WaitOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + WaitOperation(argument: I_google_longrunning_WaitOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + WaitOperation(argument: I_google_longrunning_WaitOperationRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * Waits for the specified long-running operation until it is done or reaches * at most a specified timeout, returning the latest state. If the operation @@ -155,10 +155,10 @@ export interface OperationsClient extends grpc.Client { * state before the specified timeout (including immediately), meaning even an * immediate response is no guarantee that the operation is done. */ - waitOperation(argument: _google_longrunning_WaitOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_google_longrunning_Operation__Output>): grpc.ClientUnaryCall; - waitOperation(argument: _google_longrunning_WaitOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_google_longrunning_Operation__Output>): grpc.ClientUnaryCall; - waitOperation(argument: _google_longrunning_WaitOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_google_longrunning_Operation__Output>): grpc.ClientUnaryCall; - waitOperation(argument: _google_longrunning_WaitOperationRequest, callback: grpc.requestCallback<_google_longrunning_Operation__Output>): grpc.ClientUnaryCall; + waitOperation(argument: I_google_longrunning_WaitOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + waitOperation(argument: I_google_longrunning_WaitOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + waitOperation(argument: I_google_longrunning_WaitOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + waitOperation(argument: I_google_longrunning_WaitOperationRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; } @@ -186,7 +186,7 @@ export interface OperationsHandlers extends grpc.UntypedServiceImplementation { * an [Operation.error][google.longrunning.Operation.error] value with a [google.rpc.Status.code][google.rpc.Status.code] of 1, * corresponding to `Code.CANCELLED`. */ - CancelOperation: grpc.handleUnaryCall<_google_longrunning_CancelOperationRequest__Output, _google_protobuf_Empty>; + CancelOperation: grpc.handleUnaryCall; /** * Deletes a long-running operation. This method indicates that the client is @@ -194,14 +194,14 @@ export interface OperationsHandlers extends grpc.UntypedServiceImplementation { * operation. If the server doesn't support this method, it returns * `google.rpc.Code.UNIMPLEMENTED`. */ - DeleteOperation: grpc.handleUnaryCall<_google_longrunning_DeleteOperationRequest__Output, _google_protobuf_Empty>; + DeleteOperation: grpc.handleUnaryCall; /** * 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. */ - GetOperation: grpc.handleUnaryCall<_google_longrunning_GetOperationRequest__Output, _google_longrunning_Operation>; + GetOperation: grpc.handleUnaryCall; /** * Lists operations that match the specified filter in the request. If the @@ -215,7 +215,7 @@ export interface OperationsHandlers extends grpc.UntypedServiceImplementation { * collection id, however overriding users must ensure the name binding * is the parent resource, without the operations collection id. */ - ListOperations: grpc.handleUnaryCall<_google_longrunning_ListOperationsRequest__Output, _google_longrunning_ListOperationsResponse>; + ListOperations: grpc.handleUnaryCall; /** * Waits for the specified long-running operation until it is done or reaches @@ -228,14 +228,14 @@ export interface OperationsHandlers extends grpc.UntypedServiceImplementation { * state before the specified timeout (including immediately), meaning even an * immediate response is no guarantee that the operation is done. */ - WaitOperation: grpc.handleUnaryCall<_google_longrunning_WaitOperationRequest__Output, _google_longrunning_Operation>; + WaitOperation: grpc.handleUnaryCall; } export interface OperationsDefinition extends grpc.ServiceDefinition { - CancelOperation: MethodDefinition<_google_longrunning_CancelOperationRequest, _google_protobuf_Empty, _google_longrunning_CancelOperationRequest__Output, _google_protobuf_Empty__Output> - DeleteOperation: MethodDefinition<_google_longrunning_DeleteOperationRequest, _google_protobuf_Empty, _google_longrunning_DeleteOperationRequest__Output, _google_protobuf_Empty__Output> - GetOperation: MethodDefinition<_google_longrunning_GetOperationRequest, _google_longrunning_Operation, _google_longrunning_GetOperationRequest__Output, _google_longrunning_Operation__Output> - ListOperations: MethodDefinition<_google_longrunning_ListOperationsRequest, _google_longrunning_ListOperationsResponse, _google_longrunning_ListOperationsRequest__Output, _google_longrunning_ListOperationsResponse__Output> - WaitOperation: MethodDefinition<_google_longrunning_WaitOperationRequest, _google_longrunning_Operation, _google_longrunning_WaitOperationRequest__Output, _google_longrunning_Operation__Output> + CancelOperation: MethodDefinition + DeleteOperation: MethodDefinition + GetOperation: MethodDefinition + ListOperations: MethodDefinition + WaitOperation: MethodDefinition } diff --git a/packages/proto-loader/golden-generated/google/longrunning/WaitOperationRequest.ts b/packages/proto-loader/golden-generated/google/longrunning/WaitOperationRequest.ts index f97e39dc..2f11f758 100644 --- a/packages/proto-loader/golden-generated/google/longrunning/WaitOperationRequest.ts +++ b/packages/proto-loader/golden-generated/google/longrunning/WaitOperationRequest.ts @@ -1,11 +1,11 @@ // Original file: deps/googleapis/google/longrunning/operations.proto -import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../google/protobuf/Duration'; +import type { IDuration as I_google_protobuf_Duration, ODuration as O_google_protobuf_Duration } from '../../google/protobuf/Duration'; /** * The request message for [Operations.WaitOperation][google.longrunning.Operations.WaitOperation]. */ -export interface WaitOperationRequest { +export interface IWaitOperationRequest { /** * The name of the operation resource to wait on. */ @@ -15,13 +15,13 @@ export interface WaitOperationRequest { * will be at most the time permitted by the underlying HTTP/RPC protocol. * If RPC context deadline is also specified, the shorter one will be used. */ - 'timeout'?: (_google_protobuf_Duration | null); + 'timeout'?: (I_google_protobuf_Duration | null); } /** * The request message for [Operations.WaitOperation][google.longrunning.Operations.WaitOperation]. */ -export interface WaitOperationRequest__Output { +export interface OWaitOperationRequest { /** * The name of the operation resource to wait on. */ @@ -31,5 +31,5 @@ export interface WaitOperationRequest__Output { * will be at most the time permitted by the underlying HTTP/RPC protocol. * If RPC context deadline is also specified, the shorter one will be used. */ - 'timeout': (_google_protobuf_Duration__Output | null); + 'timeout': (O_google_protobuf_Duration | null); } diff --git a/packages/proto-loader/golden-generated/google/protobuf/Any.ts b/packages/proto-loader/golden-generated/google/protobuf/Any.ts index fe0d05f1..d9ee4e20 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/Any.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/Any.ts @@ -2,12 +2,12 @@ import type { AnyExtension } from '@grpc/proto-loader'; -export type Any = AnyExtension | { +export type IAny = AnyExtension | { type_url: string; value: Buffer | Uint8Array | string; } -export type Any__Output = AnyExtension | { +export type OAny = AnyExtension | { type_url: string; value: Buffer; } diff --git a/packages/proto-loader/golden-generated/google/protobuf/DescriptorProto.ts b/packages/proto-loader/golden-generated/google/protobuf/DescriptorProto.ts index f729437f..5f568ca2 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/DescriptorProto.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/DescriptorProto.ts @@ -1,53 +1,53 @@ // Original file: null -import type { FieldDescriptorProto as _google_protobuf_FieldDescriptorProto, FieldDescriptorProto__Output as _google_protobuf_FieldDescriptorProto__Output } from '../../google/protobuf/FieldDescriptorProto'; -import type { DescriptorProto as _google_protobuf_DescriptorProto, DescriptorProto__Output as _google_protobuf_DescriptorProto__Output } from '../../google/protobuf/DescriptorProto'; -import type { EnumDescriptorProto as _google_protobuf_EnumDescriptorProto, EnumDescriptorProto__Output as _google_protobuf_EnumDescriptorProto__Output } from '../../google/protobuf/EnumDescriptorProto'; -import type { MessageOptions as _google_protobuf_MessageOptions, MessageOptions__Output as _google_protobuf_MessageOptions__Output } from '../../google/protobuf/MessageOptions'; -import type { OneofDescriptorProto as _google_protobuf_OneofDescriptorProto, OneofDescriptorProto__Output as _google_protobuf_OneofDescriptorProto__Output } from '../../google/protobuf/OneofDescriptorProto'; +import type { IFieldDescriptorProto as I_google_protobuf_FieldDescriptorProto, OFieldDescriptorProto as O_google_protobuf_FieldDescriptorProto } from '../../google/protobuf/FieldDescriptorProto'; +import type { IDescriptorProto as I_google_protobuf_DescriptorProto, ODescriptorProto as O_google_protobuf_DescriptorProto } from '../../google/protobuf/DescriptorProto'; +import type { IEnumDescriptorProto as I_google_protobuf_EnumDescriptorProto, OEnumDescriptorProto as O_google_protobuf_EnumDescriptorProto } from '../../google/protobuf/EnumDescriptorProto'; +import type { IMessageOptions as I_google_protobuf_MessageOptions, OMessageOptions as O_google_protobuf_MessageOptions } from '../../google/protobuf/MessageOptions'; +import type { IOneofDescriptorProto as I_google_protobuf_OneofDescriptorProto, OOneofDescriptorProto as O_google_protobuf_OneofDescriptorProto } from '../../google/protobuf/OneofDescriptorProto'; -export interface _google_protobuf_DescriptorProto_ExtensionRange { +export interface I_google_protobuf_DescriptorProto_ExtensionRange { 'start'?: (number); 'end'?: (number); } -export interface _google_protobuf_DescriptorProto_ExtensionRange__Output { +export interface O_google_protobuf_DescriptorProto_ExtensionRange { 'start': (number); 'end': (number); } -export interface _google_protobuf_DescriptorProto_ReservedRange { +export interface I_google_protobuf_DescriptorProto_ReservedRange { 'start'?: (number); 'end'?: (number); } -export interface _google_protobuf_DescriptorProto_ReservedRange__Output { +export interface O_google_protobuf_DescriptorProto_ReservedRange { 'start': (number); 'end': (number); } -export interface DescriptorProto { +export interface IDescriptorProto { 'name'?: (string); - 'field'?: (_google_protobuf_FieldDescriptorProto)[]; - 'nestedType'?: (_google_protobuf_DescriptorProto)[]; - 'enumType'?: (_google_protobuf_EnumDescriptorProto)[]; - 'extensionRange'?: (_google_protobuf_DescriptorProto_ExtensionRange)[]; - 'extension'?: (_google_protobuf_FieldDescriptorProto)[]; - 'options'?: (_google_protobuf_MessageOptions | null); - 'oneofDecl'?: (_google_protobuf_OneofDescriptorProto)[]; - 'reservedRange'?: (_google_protobuf_DescriptorProto_ReservedRange)[]; + 'field'?: (I_google_protobuf_FieldDescriptorProto)[]; + 'nestedType'?: (I_google_protobuf_DescriptorProto)[]; + 'enumType'?: (I_google_protobuf_EnumDescriptorProto)[]; + 'extensionRange'?: (I_google_protobuf_DescriptorProto_ExtensionRange)[]; + 'extension'?: (I_google_protobuf_FieldDescriptorProto)[]; + 'options'?: (I_google_protobuf_MessageOptions | null); + 'oneofDecl'?: (I_google_protobuf_OneofDescriptorProto)[]; + 'reservedRange'?: (I_google_protobuf_DescriptorProto_ReservedRange)[]; 'reservedName'?: (string)[]; } -export interface DescriptorProto__Output { +export interface ODescriptorProto { 'name': (string); - 'field': (_google_protobuf_FieldDescriptorProto__Output)[]; - 'nestedType': (_google_protobuf_DescriptorProto__Output)[]; - 'enumType': (_google_protobuf_EnumDescriptorProto__Output)[]; - 'extensionRange': (_google_protobuf_DescriptorProto_ExtensionRange__Output)[]; - 'extension': (_google_protobuf_FieldDescriptorProto__Output)[]; - 'options': (_google_protobuf_MessageOptions__Output | null); - 'oneofDecl': (_google_protobuf_OneofDescriptorProto__Output)[]; - 'reservedRange': (_google_protobuf_DescriptorProto_ReservedRange__Output)[]; + 'field': (O_google_protobuf_FieldDescriptorProto)[]; + 'nestedType': (O_google_protobuf_DescriptorProto)[]; + 'enumType': (O_google_protobuf_EnumDescriptorProto)[]; + 'extensionRange': (O_google_protobuf_DescriptorProto_ExtensionRange)[]; + 'extension': (O_google_protobuf_FieldDescriptorProto)[]; + 'options': (O_google_protobuf_MessageOptions | null); + 'oneofDecl': (O_google_protobuf_OneofDescriptorProto)[]; + 'reservedRange': (O_google_protobuf_DescriptorProto_ReservedRange)[]; 'reservedName': (string)[]; } diff --git a/packages/proto-loader/golden-generated/google/protobuf/Duration.ts b/packages/proto-loader/golden-generated/google/protobuf/Duration.ts index 8595377a..d5e3be89 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/Duration.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/Duration.ts @@ -2,12 +2,12 @@ import type { Long } from '@grpc/proto-loader'; -export interface Duration { +export interface IDuration { 'seconds'?: (number | string | Long); 'nanos'?: (number); } -export interface Duration__Output { +export interface ODuration { 'seconds': (string); 'nanos': (number); } diff --git a/packages/proto-loader/golden-generated/google/protobuf/Empty.ts b/packages/proto-loader/golden-generated/google/protobuf/Empty.ts index f32c2a28..6594cc86 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/Empty.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/Empty.ts @@ -1,8 +1,8 @@ // Original file: null -export interface Empty { +export interface IEmpty { } -export interface Empty__Output { +export interface OEmpty { } diff --git a/packages/proto-loader/golden-generated/google/protobuf/EnumDescriptorProto.ts b/packages/proto-loader/golden-generated/google/protobuf/EnumDescriptorProto.ts index dc4c9673..30f52c61 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/EnumDescriptorProto.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/EnumDescriptorProto.ts @@ -1,16 +1,16 @@ // Original file: null -import type { EnumValueDescriptorProto as _google_protobuf_EnumValueDescriptorProto, EnumValueDescriptorProto__Output as _google_protobuf_EnumValueDescriptorProto__Output } from '../../google/protobuf/EnumValueDescriptorProto'; -import type { EnumOptions as _google_protobuf_EnumOptions, EnumOptions__Output as _google_protobuf_EnumOptions__Output } from '../../google/protobuf/EnumOptions'; +import type { IEnumValueDescriptorProto as I_google_protobuf_EnumValueDescriptorProto, OEnumValueDescriptorProto as O_google_protobuf_EnumValueDescriptorProto } from '../../google/protobuf/EnumValueDescriptorProto'; +import type { IEnumOptions as I_google_protobuf_EnumOptions, OEnumOptions as O_google_protobuf_EnumOptions } from '../../google/protobuf/EnumOptions'; -export interface EnumDescriptorProto { +export interface IEnumDescriptorProto { 'name'?: (string); - 'value'?: (_google_protobuf_EnumValueDescriptorProto)[]; - 'options'?: (_google_protobuf_EnumOptions | null); + 'value'?: (I_google_protobuf_EnumValueDescriptorProto)[]; + 'options'?: (I_google_protobuf_EnumOptions | null); } -export interface EnumDescriptorProto__Output { +export interface OEnumDescriptorProto { 'name': (string); - 'value': (_google_protobuf_EnumValueDescriptorProto__Output)[]; - 'options': (_google_protobuf_EnumOptions__Output | null); + 'value': (O_google_protobuf_EnumValueDescriptorProto)[]; + 'options': (O_google_protobuf_EnumOptions | null); } diff --git a/packages/proto-loader/golden-generated/google/protobuf/EnumOptions.ts b/packages/proto-loader/golden-generated/google/protobuf/EnumOptions.ts index b92ade4f..6d2a0c2c 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/EnumOptions.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/EnumOptions.ts @@ -1,15 +1,15 @@ // Original file: null -import type { UninterpretedOption as _google_protobuf_UninterpretedOption, UninterpretedOption__Output as _google_protobuf_UninterpretedOption__Output } from '../../google/protobuf/UninterpretedOption'; +import type { IUninterpretedOption as I_google_protobuf_UninterpretedOption, OUninterpretedOption as O_google_protobuf_UninterpretedOption } from '../../google/protobuf/UninterpretedOption'; -export interface EnumOptions { +export interface IEnumOptions { 'allowAlias'?: (boolean); 'deprecated'?: (boolean); - 'uninterpretedOption'?: (_google_protobuf_UninterpretedOption)[]; + 'uninterpretedOption'?: (I_google_protobuf_UninterpretedOption)[]; } -export interface EnumOptions__Output { +export interface OEnumOptions { 'allowAlias': (boolean); 'deprecated': (boolean); - 'uninterpretedOption': (_google_protobuf_UninterpretedOption__Output)[]; + 'uninterpretedOption': (O_google_protobuf_UninterpretedOption)[]; } diff --git a/packages/proto-loader/golden-generated/google/protobuf/EnumValueDescriptorProto.ts b/packages/proto-loader/golden-generated/google/protobuf/EnumValueDescriptorProto.ts index 7f8e57ea..44cfcde4 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/EnumValueDescriptorProto.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/EnumValueDescriptorProto.ts @@ -1,15 +1,15 @@ // Original file: null -import type { EnumValueOptions as _google_protobuf_EnumValueOptions, EnumValueOptions__Output as _google_protobuf_EnumValueOptions__Output } from '../../google/protobuf/EnumValueOptions'; +import type { IEnumValueOptions as I_google_protobuf_EnumValueOptions, OEnumValueOptions as O_google_protobuf_EnumValueOptions } from '../../google/protobuf/EnumValueOptions'; -export interface EnumValueDescriptorProto { +export interface IEnumValueDescriptorProto { 'name'?: (string); 'number'?: (number); - 'options'?: (_google_protobuf_EnumValueOptions | null); + 'options'?: (I_google_protobuf_EnumValueOptions | null); } -export interface EnumValueDescriptorProto__Output { +export interface OEnumValueDescriptorProto { 'name': (string); 'number': (number); - 'options': (_google_protobuf_EnumValueOptions__Output | null); + 'options': (O_google_protobuf_EnumValueOptions | null); } diff --git a/packages/proto-loader/golden-generated/google/protobuf/EnumValueOptions.ts b/packages/proto-loader/golden-generated/google/protobuf/EnumValueOptions.ts index e60ee6f4..14338111 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/EnumValueOptions.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/EnumValueOptions.ts @@ -1,13 +1,13 @@ // Original file: null -import type { UninterpretedOption as _google_protobuf_UninterpretedOption, UninterpretedOption__Output as _google_protobuf_UninterpretedOption__Output } from '../../google/protobuf/UninterpretedOption'; +import type { IUninterpretedOption as I_google_protobuf_UninterpretedOption, OUninterpretedOption as O_google_protobuf_UninterpretedOption } from '../../google/protobuf/UninterpretedOption'; -export interface EnumValueOptions { +export interface IEnumValueOptions { 'deprecated'?: (boolean); - 'uninterpretedOption'?: (_google_protobuf_UninterpretedOption)[]; + 'uninterpretedOption'?: (I_google_protobuf_UninterpretedOption)[]; } -export interface EnumValueOptions__Output { +export interface OEnumValueOptions { 'deprecated': (boolean); - 'uninterpretedOption': (_google_protobuf_UninterpretedOption__Output)[]; + 'uninterpretedOption': (O_google_protobuf_UninterpretedOption)[]; } diff --git a/packages/proto-loader/golden-generated/google/protobuf/FieldDescriptorProto.ts b/packages/proto-loader/golden-generated/google/protobuf/FieldDescriptorProto.ts index c511e2ef..0a713e9d 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/FieldDescriptorProto.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/FieldDescriptorProto.ts @@ -1,6 +1,6 @@ // Original file: null -import type { FieldOptions as _google_protobuf_FieldOptions, FieldOptions__Output as _google_protobuf_FieldOptions__Output } from '../../google/protobuf/FieldOptions'; +import type { IFieldOptions as I_google_protobuf_FieldOptions, OFieldOptions as O_google_protobuf_FieldOptions } from '../../google/protobuf/FieldOptions'; // Original file: null @@ -33,7 +33,7 @@ export enum _google_protobuf_FieldDescriptorProto_Type { TYPE_SINT64 = 18, } -export interface FieldDescriptorProto { +export interface IFieldDescriptorProto { 'name'?: (string); 'extendee'?: (string); 'number'?: (number); @@ -41,12 +41,12 @@ export interface FieldDescriptorProto { 'type'?: (_google_protobuf_FieldDescriptorProto_Type | keyof typeof _google_protobuf_FieldDescriptorProto_Type); 'typeName'?: (string); 'defaultValue'?: (string); - 'options'?: (_google_protobuf_FieldOptions | null); + 'options'?: (I_google_protobuf_FieldOptions | null); 'oneofIndex'?: (number); 'jsonName'?: (string); } -export interface FieldDescriptorProto__Output { +export interface OFieldDescriptorProto { 'name': (string); 'extendee': (string); 'number': (number); @@ -54,7 +54,7 @@ export interface FieldDescriptorProto__Output { 'type': (keyof typeof _google_protobuf_FieldDescriptorProto_Type); 'typeName': (string); 'defaultValue': (string); - 'options': (_google_protobuf_FieldOptions__Output | null); + 'options': (O_google_protobuf_FieldOptions | null); 'oneofIndex': (number); 'jsonName': (string); } diff --git a/packages/proto-loader/golden-generated/google/protobuf/FieldOptions.ts b/packages/proto-loader/golden-generated/google/protobuf/FieldOptions.ts index 8304053f..076b3598 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/FieldOptions.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/FieldOptions.ts @@ -1,6 +1,6 @@ // Original file: null -import type { UninterpretedOption as _google_protobuf_UninterpretedOption, UninterpretedOption__Output as _google_protobuf_UninterpretedOption__Output } from '../../google/protobuf/UninterpretedOption'; +import type { IUninterpretedOption as I_google_protobuf_UninterpretedOption, OUninterpretedOption as O_google_protobuf_UninterpretedOption } from '../../google/protobuf/UninterpretedOption'; import type { FieldBehavior as _google_api_FieldBehavior } from '../../google/api/FieldBehavior'; // Original file: null @@ -19,24 +19,24 @@ export enum _google_protobuf_FieldOptions_JSType { JS_NUMBER = 2, } -export interface FieldOptions { +export interface IFieldOptions { 'ctype'?: (_google_protobuf_FieldOptions_CType | keyof typeof _google_protobuf_FieldOptions_CType); 'packed'?: (boolean); 'deprecated'?: (boolean); 'lazy'?: (boolean); 'jstype'?: (_google_protobuf_FieldOptions_JSType | keyof typeof _google_protobuf_FieldOptions_JSType); 'weak'?: (boolean); - 'uninterpretedOption'?: (_google_protobuf_UninterpretedOption)[]; + 'uninterpretedOption'?: (I_google_protobuf_UninterpretedOption)[]; '.google.api.field_behavior'?: (_google_api_FieldBehavior | keyof typeof _google_api_FieldBehavior)[]; } -export interface FieldOptions__Output { +export interface OFieldOptions { 'ctype': (keyof typeof _google_protobuf_FieldOptions_CType); 'packed': (boolean); 'deprecated': (boolean); 'lazy': (boolean); 'jstype': (keyof typeof _google_protobuf_FieldOptions_JSType); 'weak': (boolean); - 'uninterpretedOption': (_google_protobuf_UninterpretedOption__Output)[]; + 'uninterpretedOption': (O_google_protobuf_UninterpretedOption)[]; '.google.api.field_behavior': (keyof typeof _google_api_FieldBehavior)[]; } diff --git a/packages/proto-loader/golden-generated/google/protobuf/FileDescriptorProto.ts b/packages/proto-loader/golden-generated/google/protobuf/FileDescriptorProto.ts index b723da7c..c98732f9 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/FileDescriptorProto.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/FileDescriptorProto.ts @@ -1,37 +1,37 @@ // Original file: null -import type { DescriptorProto as _google_protobuf_DescriptorProto, DescriptorProto__Output as _google_protobuf_DescriptorProto__Output } from '../../google/protobuf/DescriptorProto'; -import type { EnumDescriptorProto as _google_protobuf_EnumDescriptorProto, EnumDescriptorProto__Output as _google_protobuf_EnumDescriptorProto__Output } from '../../google/protobuf/EnumDescriptorProto'; -import type { ServiceDescriptorProto as _google_protobuf_ServiceDescriptorProto, ServiceDescriptorProto__Output as _google_protobuf_ServiceDescriptorProto__Output } from '../../google/protobuf/ServiceDescriptorProto'; -import type { FieldDescriptorProto as _google_protobuf_FieldDescriptorProto, FieldDescriptorProto__Output as _google_protobuf_FieldDescriptorProto__Output } from '../../google/protobuf/FieldDescriptorProto'; -import type { FileOptions as _google_protobuf_FileOptions, FileOptions__Output as _google_protobuf_FileOptions__Output } from '../../google/protobuf/FileOptions'; -import type { SourceCodeInfo as _google_protobuf_SourceCodeInfo, SourceCodeInfo__Output as _google_protobuf_SourceCodeInfo__Output } from '../../google/protobuf/SourceCodeInfo'; +import type { IDescriptorProto as I_google_protobuf_DescriptorProto, ODescriptorProto as O_google_protobuf_DescriptorProto } from '../../google/protobuf/DescriptorProto'; +import type { IEnumDescriptorProto as I_google_protobuf_EnumDescriptorProto, OEnumDescriptorProto as O_google_protobuf_EnumDescriptorProto } from '../../google/protobuf/EnumDescriptorProto'; +import type { IServiceDescriptorProto as I_google_protobuf_ServiceDescriptorProto, OServiceDescriptorProto as O_google_protobuf_ServiceDescriptorProto } from '../../google/protobuf/ServiceDescriptorProto'; +import type { IFieldDescriptorProto as I_google_protobuf_FieldDescriptorProto, OFieldDescriptorProto as O_google_protobuf_FieldDescriptorProto } from '../../google/protobuf/FieldDescriptorProto'; +import type { IFileOptions as I_google_protobuf_FileOptions, OFileOptions as O_google_protobuf_FileOptions } from '../../google/protobuf/FileOptions'; +import type { ISourceCodeInfo as I_google_protobuf_SourceCodeInfo, OSourceCodeInfo as O_google_protobuf_SourceCodeInfo } from '../../google/protobuf/SourceCodeInfo'; -export interface FileDescriptorProto { +export interface IFileDescriptorProto { 'name'?: (string); 'package'?: (string); 'dependency'?: (string)[]; - 'messageType'?: (_google_protobuf_DescriptorProto)[]; - 'enumType'?: (_google_protobuf_EnumDescriptorProto)[]; - 'service'?: (_google_protobuf_ServiceDescriptorProto)[]; - 'extension'?: (_google_protobuf_FieldDescriptorProto)[]; - 'options'?: (_google_protobuf_FileOptions | null); - 'sourceCodeInfo'?: (_google_protobuf_SourceCodeInfo | null); + 'messageType'?: (I_google_protobuf_DescriptorProto)[]; + 'enumType'?: (I_google_protobuf_EnumDescriptorProto)[]; + 'service'?: (I_google_protobuf_ServiceDescriptorProto)[]; + 'extension'?: (I_google_protobuf_FieldDescriptorProto)[]; + 'options'?: (I_google_protobuf_FileOptions | null); + 'sourceCodeInfo'?: (I_google_protobuf_SourceCodeInfo | null); 'publicDependency'?: (number)[]; 'weakDependency'?: (number)[]; 'syntax'?: (string); } -export interface FileDescriptorProto__Output { +export interface OFileDescriptorProto { 'name': (string); 'package': (string); 'dependency': (string)[]; - 'messageType': (_google_protobuf_DescriptorProto__Output)[]; - 'enumType': (_google_protobuf_EnumDescriptorProto__Output)[]; - 'service': (_google_protobuf_ServiceDescriptorProto__Output)[]; - 'extension': (_google_protobuf_FieldDescriptorProto__Output)[]; - 'options': (_google_protobuf_FileOptions__Output | null); - 'sourceCodeInfo': (_google_protobuf_SourceCodeInfo__Output | null); + 'messageType': (O_google_protobuf_DescriptorProto)[]; + 'enumType': (O_google_protobuf_EnumDescriptorProto)[]; + 'service': (O_google_protobuf_ServiceDescriptorProto)[]; + 'extension': (O_google_protobuf_FieldDescriptorProto)[]; + 'options': (O_google_protobuf_FileOptions | null); + 'sourceCodeInfo': (O_google_protobuf_SourceCodeInfo | null); 'publicDependency': (number)[]; 'weakDependency': (number)[]; 'syntax': (string); diff --git a/packages/proto-loader/golden-generated/google/protobuf/FileDescriptorSet.ts b/packages/proto-loader/golden-generated/google/protobuf/FileDescriptorSet.ts index 74ded247..9c940ed5 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/FileDescriptorSet.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/FileDescriptorSet.ts @@ -1,11 +1,11 @@ // Original file: null -import type { FileDescriptorProto as _google_protobuf_FileDescriptorProto, FileDescriptorProto__Output as _google_protobuf_FileDescriptorProto__Output } from '../../google/protobuf/FileDescriptorProto'; +import type { IFileDescriptorProto as I_google_protobuf_FileDescriptorProto, OFileDescriptorProto as O_google_protobuf_FileDescriptorProto } from '../../google/protobuf/FileDescriptorProto'; -export interface FileDescriptorSet { - 'file'?: (_google_protobuf_FileDescriptorProto)[]; +export interface IFileDescriptorSet { + 'file'?: (I_google_protobuf_FileDescriptorProto)[]; } -export interface FileDescriptorSet__Output { - 'file': (_google_protobuf_FileDescriptorProto__Output)[]; +export interface OFileDescriptorSet { + 'file': (O_google_protobuf_FileDescriptorProto)[]; } diff --git a/packages/proto-loader/golden-generated/google/protobuf/FileOptions.ts b/packages/proto-loader/golden-generated/google/protobuf/FileOptions.ts index 573e847c..2b832e0f 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/FileOptions.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/FileOptions.ts @@ -1,6 +1,6 @@ // Original file: null -import type { UninterpretedOption as _google_protobuf_UninterpretedOption, UninterpretedOption__Output as _google_protobuf_UninterpretedOption__Output } from '../../google/protobuf/UninterpretedOption'; +import type { IUninterpretedOption as I_google_protobuf_UninterpretedOption, OUninterpretedOption as O_google_protobuf_UninterpretedOption } from '../../google/protobuf/UninterpretedOption'; // Original file: null @@ -10,7 +10,7 @@ export enum _google_protobuf_FileOptions_OptimizeMode { LITE_RUNTIME = 3, } -export interface FileOptions { +export interface IFileOptions { 'javaPackage'?: (string); 'javaOuterClassname'?: (string); 'optimizeFor'?: (_google_protobuf_FileOptions_OptimizeMode | keyof typeof _google_protobuf_FileOptions_OptimizeMode); @@ -25,10 +25,10 @@ export interface FileOptions { 'ccEnableArenas'?: (boolean); 'objcClassPrefix'?: (string); 'csharpNamespace'?: (string); - 'uninterpretedOption'?: (_google_protobuf_UninterpretedOption)[]; + 'uninterpretedOption'?: (I_google_protobuf_UninterpretedOption)[]; } -export interface FileOptions__Output { +export interface OFileOptions { 'javaPackage': (string); 'javaOuterClassname': (string); 'optimizeFor': (keyof typeof _google_protobuf_FileOptions_OptimizeMode); @@ -43,5 +43,5 @@ export interface FileOptions__Output { 'ccEnableArenas': (boolean); 'objcClassPrefix': (string); 'csharpNamespace': (string); - 'uninterpretedOption': (_google_protobuf_UninterpretedOption__Output)[]; + 'uninterpretedOption': (O_google_protobuf_UninterpretedOption)[]; } diff --git a/packages/proto-loader/golden-generated/google/protobuf/GeneratedCodeInfo.ts b/packages/proto-loader/golden-generated/google/protobuf/GeneratedCodeInfo.ts index 019fb0e1..62f9dc71 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/GeneratedCodeInfo.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/GeneratedCodeInfo.ts @@ -1,24 +1,24 @@ // Original file: null -export interface _google_protobuf_GeneratedCodeInfo_Annotation { +export interface I_google_protobuf_GeneratedCodeInfo_Annotation { 'path'?: (number)[]; 'sourceFile'?: (string); 'begin'?: (number); 'end'?: (number); } -export interface _google_protobuf_GeneratedCodeInfo_Annotation__Output { +export interface O_google_protobuf_GeneratedCodeInfo_Annotation { 'path': (number)[]; 'sourceFile': (string); 'begin': (number); 'end': (number); } -export interface GeneratedCodeInfo { - 'annotation'?: (_google_protobuf_GeneratedCodeInfo_Annotation)[]; +export interface IGeneratedCodeInfo { + 'annotation'?: (I_google_protobuf_GeneratedCodeInfo_Annotation)[]; } -export interface GeneratedCodeInfo__Output { - 'annotation': (_google_protobuf_GeneratedCodeInfo_Annotation__Output)[]; +export interface OGeneratedCodeInfo { + 'annotation': (O_google_protobuf_GeneratedCodeInfo_Annotation)[]; } diff --git a/packages/proto-loader/golden-generated/google/protobuf/MessageOptions.ts b/packages/proto-loader/golden-generated/google/protobuf/MessageOptions.ts index 31f669eb..8c8885e6 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/MessageOptions.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/MessageOptions.ts @@ -1,19 +1,19 @@ // Original file: null -import type { UninterpretedOption as _google_protobuf_UninterpretedOption, UninterpretedOption__Output as _google_protobuf_UninterpretedOption__Output } from '../../google/protobuf/UninterpretedOption'; +import type { IUninterpretedOption as I_google_protobuf_UninterpretedOption, OUninterpretedOption as O_google_protobuf_UninterpretedOption } from '../../google/protobuf/UninterpretedOption'; -export interface MessageOptions { +export interface IMessageOptions { 'messageSetWireFormat'?: (boolean); 'noStandardDescriptorAccessor'?: (boolean); 'deprecated'?: (boolean); 'mapEntry'?: (boolean); - 'uninterpretedOption'?: (_google_protobuf_UninterpretedOption)[]; + 'uninterpretedOption'?: (I_google_protobuf_UninterpretedOption)[]; } -export interface MessageOptions__Output { +export interface OMessageOptions { 'messageSetWireFormat': (boolean); 'noStandardDescriptorAccessor': (boolean); 'deprecated': (boolean); 'mapEntry': (boolean); - 'uninterpretedOption': (_google_protobuf_UninterpretedOption__Output)[]; + 'uninterpretedOption': (O_google_protobuf_UninterpretedOption)[]; } diff --git a/packages/proto-loader/golden-generated/google/protobuf/MethodDescriptorProto.ts b/packages/proto-loader/golden-generated/google/protobuf/MethodDescriptorProto.ts index c76c0ea2..0826370d 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/MethodDescriptorProto.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/MethodDescriptorProto.ts @@ -1,21 +1,21 @@ // Original file: null -import type { MethodOptions as _google_protobuf_MethodOptions, MethodOptions__Output as _google_protobuf_MethodOptions__Output } from '../../google/protobuf/MethodOptions'; +import type { IMethodOptions as I_google_protobuf_MethodOptions, OMethodOptions as O_google_protobuf_MethodOptions } from '../../google/protobuf/MethodOptions'; -export interface MethodDescriptorProto { +export interface IMethodDescriptorProto { 'name'?: (string); 'inputType'?: (string); 'outputType'?: (string); - 'options'?: (_google_protobuf_MethodOptions | null); + 'options'?: (I_google_protobuf_MethodOptions | null); 'clientStreaming'?: (boolean); 'serverStreaming'?: (boolean); } -export interface MethodDescriptorProto__Output { +export interface OMethodDescriptorProto { 'name': (string); 'inputType': (string); 'outputType': (string); - 'options': (_google_protobuf_MethodOptions__Output | null); + 'options': (O_google_protobuf_MethodOptions | null); 'clientStreaming': (boolean); 'serverStreaming': (boolean); } diff --git a/packages/proto-loader/golden-generated/google/protobuf/MethodOptions.ts b/packages/proto-loader/golden-generated/google/protobuf/MethodOptions.ts index 7581b964..5f0b6900 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/MethodOptions.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/MethodOptions.ts @@ -1,21 +1,21 @@ // Original file: null -import type { UninterpretedOption as _google_protobuf_UninterpretedOption, UninterpretedOption__Output as _google_protobuf_UninterpretedOption__Output } from '../../google/protobuf/UninterpretedOption'; -import type { OperationInfo as _google_longrunning_OperationInfo, OperationInfo__Output as _google_longrunning_OperationInfo__Output } from '../../google/longrunning/OperationInfo'; -import type { HttpRule as _google_api_HttpRule, HttpRule__Output as _google_api_HttpRule__Output } from '../../google/api/HttpRule'; +import type { IUninterpretedOption as I_google_protobuf_UninterpretedOption, OUninterpretedOption as O_google_protobuf_UninterpretedOption } from '../../google/protobuf/UninterpretedOption'; +import type { IOperationInfo as I_google_longrunning_OperationInfo, OOperationInfo as O_google_longrunning_OperationInfo } from '../../google/longrunning/OperationInfo'; +import type { IHttpRule as I_google_api_HttpRule, OHttpRule as O_google_api_HttpRule } from '../../google/api/HttpRule'; -export interface MethodOptions { +export interface IMethodOptions { 'deprecated'?: (boolean); - 'uninterpretedOption'?: (_google_protobuf_UninterpretedOption)[]; - '.google.longrunning.operation_info'?: (_google_longrunning_OperationInfo | null); + 'uninterpretedOption'?: (I_google_protobuf_UninterpretedOption)[]; + '.google.longrunning.operation_info'?: (I_google_longrunning_OperationInfo | null); '.google.api.method_signature'?: (string)[]; - '.google.api.http'?: (_google_api_HttpRule | null); + '.google.api.http'?: (I_google_api_HttpRule | null); } -export interface MethodOptions__Output { +export interface OMethodOptions { 'deprecated': (boolean); - 'uninterpretedOption': (_google_protobuf_UninterpretedOption__Output)[]; - '.google.longrunning.operation_info': (_google_longrunning_OperationInfo__Output | null); + 'uninterpretedOption': (O_google_protobuf_UninterpretedOption)[]; + '.google.longrunning.operation_info': (O_google_longrunning_OperationInfo | null); '.google.api.method_signature': (string)[]; - '.google.api.http': (_google_api_HttpRule__Output | null); + '.google.api.http': (O_google_api_HttpRule | null); } diff --git a/packages/proto-loader/golden-generated/google/protobuf/OneofDescriptorProto.ts b/packages/proto-loader/golden-generated/google/protobuf/OneofDescriptorProto.ts index 636f13ed..6394270e 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/OneofDescriptorProto.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/OneofDescriptorProto.ts @@ -1,13 +1,13 @@ // Original file: null -import type { OneofOptions as _google_protobuf_OneofOptions, OneofOptions__Output as _google_protobuf_OneofOptions__Output } from '../../google/protobuf/OneofOptions'; +import type { IOneofOptions as I_google_protobuf_OneofOptions, OOneofOptions as O_google_protobuf_OneofOptions } from '../../google/protobuf/OneofOptions'; -export interface OneofDescriptorProto { +export interface IOneofDescriptorProto { 'name'?: (string); - 'options'?: (_google_protobuf_OneofOptions | null); + 'options'?: (I_google_protobuf_OneofOptions | null); } -export interface OneofDescriptorProto__Output { +export interface OOneofDescriptorProto { 'name': (string); - 'options': (_google_protobuf_OneofOptions__Output | null); + 'options': (O_google_protobuf_OneofOptions | null); } diff --git a/packages/proto-loader/golden-generated/google/protobuf/OneofOptions.ts b/packages/proto-loader/golden-generated/google/protobuf/OneofOptions.ts index d81d3479..73280ad7 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/OneofOptions.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/OneofOptions.ts @@ -1,11 +1,11 @@ // Original file: null -import type { UninterpretedOption as _google_protobuf_UninterpretedOption, UninterpretedOption__Output as _google_protobuf_UninterpretedOption__Output } from '../../google/protobuf/UninterpretedOption'; +import type { IUninterpretedOption as I_google_protobuf_UninterpretedOption, OUninterpretedOption as O_google_protobuf_UninterpretedOption } from '../../google/protobuf/UninterpretedOption'; -export interface OneofOptions { - 'uninterpretedOption'?: (_google_protobuf_UninterpretedOption)[]; +export interface IOneofOptions { + 'uninterpretedOption'?: (I_google_protobuf_UninterpretedOption)[]; } -export interface OneofOptions__Output { - 'uninterpretedOption': (_google_protobuf_UninterpretedOption__Output)[]; +export interface OOneofOptions { + 'uninterpretedOption': (O_google_protobuf_UninterpretedOption)[]; } diff --git a/packages/proto-loader/golden-generated/google/protobuf/ServiceDescriptorProto.ts b/packages/proto-loader/golden-generated/google/protobuf/ServiceDescriptorProto.ts index 40c9263e..a0427fda 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/ServiceDescriptorProto.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/ServiceDescriptorProto.ts @@ -1,16 +1,16 @@ // Original file: null -import type { MethodDescriptorProto as _google_protobuf_MethodDescriptorProto, MethodDescriptorProto__Output as _google_protobuf_MethodDescriptorProto__Output } from '../../google/protobuf/MethodDescriptorProto'; -import type { ServiceOptions as _google_protobuf_ServiceOptions, ServiceOptions__Output as _google_protobuf_ServiceOptions__Output } from '../../google/protobuf/ServiceOptions'; +import type { IMethodDescriptorProto as I_google_protobuf_MethodDescriptorProto, OMethodDescriptorProto as O_google_protobuf_MethodDescriptorProto } from '../../google/protobuf/MethodDescriptorProto'; +import type { IServiceOptions as I_google_protobuf_ServiceOptions, OServiceOptions as O_google_protobuf_ServiceOptions } from '../../google/protobuf/ServiceOptions'; -export interface ServiceDescriptorProto { +export interface IServiceDescriptorProto { 'name'?: (string); - 'method'?: (_google_protobuf_MethodDescriptorProto)[]; - 'options'?: (_google_protobuf_ServiceOptions | null); + 'method'?: (I_google_protobuf_MethodDescriptorProto)[]; + 'options'?: (I_google_protobuf_ServiceOptions | null); } -export interface ServiceDescriptorProto__Output { +export interface OServiceDescriptorProto { 'name': (string); - 'method': (_google_protobuf_MethodDescriptorProto__Output)[]; - 'options': (_google_protobuf_ServiceOptions__Output | null); + 'method': (O_google_protobuf_MethodDescriptorProto)[]; + 'options': (O_google_protobuf_ServiceOptions | null); } diff --git a/packages/proto-loader/golden-generated/google/protobuf/ServiceOptions.ts b/packages/proto-loader/golden-generated/google/protobuf/ServiceOptions.ts index c0522eca..0ddc8e18 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/ServiceOptions.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/ServiceOptions.ts @@ -1,17 +1,17 @@ // Original file: null -import type { UninterpretedOption as _google_protobuf_UninterpretedOption, UninterpretedOption__Output as _google_protobuf_UninterpretedOption__Output } from '../../google/protobuf/UninterpretedOption'; +import type { IUninterpretedOption as I_google_protobuf_UninterpretedOption, OUninterpretedOption as O_google_protobuf_UninterpretedOption } from '../../google/protobuf/UninterpretedOption'; -export interface ServiceOptions { +export interface IServiceOptions { 'deprecated'?: (boolean); - 'uninterpretedOption'?: (_google_protobuf_UninterpretedOption)[]; + 'uninterpretedOption'?: (I_google_protobuf_UninterpretedOption)[]; '.google.api.default_host'?: (string); '.google.api.oauth_scopes'?: (string); } -export interface ServiceOptions__Output { +export interface OServiceOptions { 'deprecated': (boolean); - 'uninterpretedOption': (_google_protobuf_UninterpretedOption__Output)[]; + 'uninterpretedOption': (O_google_protobuf_UninterpretedOption)[]; '.google.api.default_host': (string); '.google.api.oauth_scopes': (string); } diff --git a/packages/proto-loader/golden-generated/google/protobuf/SourceCodeInfo.ts b/packages/proto-loader/golden-generated/google/protobuf/SourceCodeInfo.ts index d30e59b4..4d085660 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/SourceCodeInfo.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/SourceCodeInfo.ts @@ -1,7 +1,7 @@ // Original file: null -export interface _google_protobuf_SourceCodeInfo_Location { +export interface I_google_protobuf_SourceCodeInfo_Location { 'path'?: (number)[]; 'span'?: (number)[]; 'leadingComments'?: (string); @@ -9,7 +9,7 @@ export interface _google_protobuf_SourceCodeInfo_Location { 'leadingDetachedComments'?: (string)[]; } -export interface _google_protobuf_SourceCodeInfo_Location__Output { +export interface O_google_protobuf_SourceCodeInfo_Location { 'path': (number)[]; 'span': (number)[]; 'leadingComments': (string); @@ -17,10 +17,10 @@ export interface _google_protobuf_SourceCodeInfo_Location__Output { 'leadingDetachedComments': (string)[]; } -export interface SourceCodeInfo { - 'location'?: (_google_protobuf_SourceCodeInfo_Location)[]; +export interface ISourceCodeInfo { + 'location'?: (I_google_protobuf_SourceCodeInfo_Location)[]; } -export interface SourceCodeInfo__Output { - 'location': (_google_protobuf_SourceCodeInfo_Location__Output)[]; +export interface OSourceCodeInfo { + 'location': (O_google_protobuf_SourceCodeInfo_Location)[]; } diff --git a/packages/proto-loader/golden-generated/google/protobuf/Timestamp.ts b/packages/proto-loader/golden-generated/google/protobuf/Timestamp.ts index ceaa32b5..06d75613 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/Timestamp.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/Timestamp.ts @@ -2,12 +2,12 @@ import type { Long } from '@grpc/proto-loader'; -export interface Timestamp { +export interface ITimestamp { 'seconds'?: (number | string | Long); 'nanos'?: (number); } -export interface Timestamp__Output { +export interface OTimestamp { 'seconds': (string); 'nanos': (number); } diff --git a/packages/proto-loader/golden-generated/google/protobuf/UninterpretedOption.ts b/packages/proto-loader/golden-generated/google/protobuf/UninterpretedOption.ts index 433820f5..fa0feaf5 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/UninterpretedOption.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/UninterpretedOption.ts @@ -2,18 +2,18 @@ import type { Long } from '@grpc/proto-loader'; -export interface _google_protobuf_UninterpretedOption_NamePart { +export interface I_google_protobuf_UninterpretedOption_NamePart { 'namePart'?: (string); 'isExtension'?: (boolean); } -export interface _google_protobuf_UninterpretedOption_NamePart__Output { +export interface O_google_protobuf_UninterpretedOption_NamePart { 'namePart': (string); 'isExtension': (boolean); } -export interface UninterpretedOption { - 'name'?: (_google_protobuf_UninterpretedOption_NamePart)[]; +export interface IUninterpretedOption { + 'name'?: (I_google_protobuf_UninterpretedOption_NamePart)[]; 'identifierValue'?: (string); 'positiveIntValue'?: (number | string | Long); 'negativeIntValue'?: (number | string | Long); @@ -22,8 +22,8 @@ export interface UninterpretedOption { 'aggregateValue'?: (string); } -export interface UninterpretedOption__Output { - 'name': (_google_protobuf_UninterpretedOption_NamePart__Output)[]; +export interface OUninterpretedOption { + 'name': (O_google_protobuf_UninterpretedOption_NamePart)[]; 'identifierValue': (string); 'positiveIntValue': (string); 'negativeIntValue': (string); diff --git a/packages/proto-loader/golden-generated/google/rpc/Status.ts b/packages/proto-loader/golden-generated/google/rpc/Status.ts index 4ce45b6a..05cf71c5 100644 --- a/packages/proto-loader/golden-generated/google/rpc/Status.ts +++ b/packages/proto-loader/golden-generated/google/rpc/Status.ts @@ -1,6 +1,6 @@ // Original file: deps/googleapis/google/rpc/status.proto -import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../google/protobuf/Any'; +import type { IAny as I_google_protobuf_Any, OAny as O_google_protobuf_Any } from '../../google/protobuf/Any'; /** * The `Status` type defines a logical error model that is suitable for @@ -11,7 +11,7 @@ import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__ * You can find out more about this error model and how to work with it in the * [API Design Guide](https://cloud.google.com/apis/design/errors). */ -export interface Status { +export interface IStatus { /** * The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code]. */ @@ -26,7 +26,7 @@ export interface Status { * A list of messages that carry the error details. There is a common set of * message types for APIs to use. */ - 'details'?: (_google_protobuf_Any)[]; + 'details'?: (I_google_protobuf_Any)[]; } /** @@ -38,7 +38,7 @@ export interface Status { * You can find out more about this error model and how to work with it in the * [API Design Guide](https://cloud.google.com/apis/design/errors). */ -export interface Status__Output { +export interface OStatus { /** * The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code]. */ @@ -53,5 +53,5 @@ export interface Status__Output { * A list of messages that carry the error details. There is a common set of * message types for APIs to use. */ - 'details': (_google_protobuf_Any__Output)[]; + 'details': (O_google_protobuf_Any)[]; } diff --git a/packages/proto-loader/golden-generated/google/showcase/v1beta1/BlockRequest.ts b/packages/proto-loader/golden-generated/google/showcase/v1beta1/BlockRequest.ts index 383c409c..29d10f6d 100644 --- a/packages/proto-loader/golden-generated/google/showcase/v1beta1/BlockRequest.ts +++ b/packages/proto-loader/golden-generated/google/showcase/v1beta1/BlockRequest.ts @@ -1,45 +1,45 @@ // Original file: deps/gapic-showcase/schema/google/showcase/v1beta1/echo.proto -import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../google/protobuf/Duration'; -import type { Status as _google_rpc_Status, Status__Output as _google_rpc_Status__Output } from '../../../google/rpc/Status'; -import type { BlockResponse as _google_showcase_v1beta1_BlockResponse, BlockResponse__Output as _google_showcase_v1beta1_BlockResponse__Output } from '../../../google/showcase/v1beta1/BlockResponse'; +import type { IDuration as I_google_protobuf_Duration, ODuration as O_google_protobuf_Duration } from '../../../google/protobuf/Duration'; +import type { IStatus as I_google_rpc_Status, OStatus as O_google_rpc_Status } from '../../../google/rpc/Status'; +import type { IBlockResponse as I_google_showcase_v1beta1_BlockResponse, OBlockResponse as O_google_showcase_v1beta1_BlockResponse } from '../../../google/showcase/v1beta1/BlockResponse'; /** * The request for Block method. */ -export interface BlockRequest { +export interface IBlockRequest { /** * The amount of time to block before returning a response. */ - 'response_delay'?: (_google_protobuf_Duration | null); + 'response_delay'?: (I_google_protobuf_Duration | null); /** * The error that will be returned by the server. If this code is specified * to be the OK rpc code, an empty response will be returned. */ - 'error'?: (_google_rpc_Status | null); + 'error'?: (I_google_rpc_Status | null); /** * The response to be returned that will signify successful method call. */ - 'success'?: (_google_showcase_v1beta1_BlockResponse | null); + 'success'?: (I_google_showcase_v1beta1_BlockResponse | null); 'response'?: "error"|"success"; } /** * The request for Block method. */ -export interface BlockRequest__Output { +export interface OBlockRequest { /** * The amount of time to block before returning a response. */ - 'response_delay': (_google_protobuf_Duration__Output | null); + 'response_delay': (O_google_protobuf_Duration | null); /** * The error that will be returned by the server. If this code is specified * to be the OK rpc code, an empty response will be returned. */ - 'error'?: (_google_rpc_Status__Output | null); + 'error'?: (O_google_rpc_Status | null); /** * The response to be returned that will signify successful method call. */ - 'success'?: (_google_showcase_v1beta1_BlockResponse__Output | null); + 'success'?: (O_google_showcase_v1beta1_BlockResponse | null); 'response': "error"|"success"; } diff --git a/packages/proto-loader/golden-generated/google/showcase/v1beta1/BlockResponse.ts b/packages/proto-loader/golden-generated/google/showcase/v1beta1/BlockResponse.ts index 5634b19d..3bb9bddf 100644 --- a/packages/proto-loader/golden-generated/google/showcase/v1beta1/BlockResponse.ts +++ b/packages/proto-loader/golden-generated/google/showcase/v1beta1/BlockResponse.ts @@ -4,7 +4,7 @@ /** * The response for Block method. */ -export interface BlockResponse { +export interface IBlockResponse { /** * This content can contain anything, the server will not depend on a value * here. @@ -15,7 +15,7 @@ export interface BlockResponse { /** * The response for Block method. */ -export interface BlockResponse__Output { +export interface OBlockResponse { /** * This content can contain anything, the server will not depend on a value * here. diff --git a/packages/proto-loader/golden-generated/google/showcase/v1beta1/Echo.ts b/packages/proto-loader/golden-generated/google/showcase/v1beta1/Echo.ts index 30ecc8e2..a0330fe6 100644 --- a/packages/proto-loader/golden-generated/google/showcase/v1beta1/Echo.ts +++ b/packages/proto-loader/golden-generated/google/showcase/v1beta1/Echo.ts @@ -2,15 +2,15 @@ import type * as grpc from '@grpc/grpc-js' import type { MethodDefinition } from '@grpc/proto-loader' -import type { BlockRequest as _google_showcase_v1beta1_BlockRequest, BlockRequest__Output as _google_showcase_v1beta1_BlockRequest__Output } from '../../../google/showcase/v1beta1/BlockRequest'; -import type { BlockResponse as _google_showcase_v1beta1_BlockResponse, BlockResponse__Output as _google_showcase_v1beta1_BlockResponse__Output } from '../../../google/showcase/v1beta1/BlockResponse'; -import type { EchoRequest as _google_showcase_v1beta1_EchoRequest, EchoRequest__Output as _google_showcase_v1beta1_EchoRequest__Output } from '../../../google/showcase/v1beta1/EchoRequest'; -import type { EchoResponse as _google_showcase_v1beta1_EchoResponse, EchoResponse__Output as _google_showcase_v1beta1_EchoResponse__Output } from '../../../google/showcase/v1beta1/EchoResponse'; -import type { ExpandRequest as _google_showcase_v1beta1_ExpandRequest, ExpandRequest__Output as _google_showcase_v1beta1_ExpandRequest__Output } from '../../../google/showcase/v1beta1/ExpandRequest'; -import type { Operation as _google_longrunning_Operation, Operation__Output as _google_longrunning_Operation__Output } from '../../../google/longrunning/Operation'; -import type { PagedExpandRequest as _google_showcase_v1beta1_PagedExpandRequest, PagedExpandRequest__Output as _google_showcase_v1beta1_PagedExpandRequest__Output } from '../../../google/showcase/v1beta1/PagedExpandRequest'; -import type { PagedExpandResponse as _google_showcase_v1beta1_PagedExpandResponse, PagedExpandResponse__Output as _google_showcase_v1beta1_PagedExpandResponse__Output } from '../../../google/showcase/v1beta1/PagedExpandResponse'; -import type { WaitRequest as _google_showcase_v1beta1_WaitRequest, WaitRequest__Output as _google_showcase_v1beta1_WaitRequest__Output } from '../../../google/showcase/v1beta1/WaitRequest'; +import type { IBlockRequest as I_google_showcase_v1beta1_BlockRequest, OBlockRequest as O_google_showcase_v1beta1_BlockRequest } from '../../../google/showcase/v1beta1/BlockRequest'; +import type { IBlockResponse as I_google_showcase_v1beta1_BlockResponse, OBlockResponse as O_google_showcase_v1beta1_BlockResponse } from '../../../google/showcase/v1beta1/BlockResponse'; +import type { IEchoRequest as I_google_showcase_v1beta1_EchoRequest, OEchoRequest as O_google_showcase_v1beta1_EchoRequest } from '../../../google/showcase/v1beta1/EchoRequest'; +import type { IEchoResponse as I_google_showcase_v1beta1_EchoResponse, OEchoResponse as O_google_showcase_v1beta1_EchoResponse } from '../../../google/showcase/v1beta1/EchoResponse'; +import type { IExpandRequest as I_google_showcase_v1beta1_ExpandRequest, OExpandRequest as O_google_showcase_v1beta1_ExpandRequest } from '../../../google/showcase/v1beta1/ExpandRequest'; +import type { IOperation as I_google_longrunning_Operation, OOperation as O_google_longrunning_Operation } from '../../../google/longrunning/Operation'; +import type { IPagedExpandRequest as I_google_showcase_v1beta1_PagedExpandRequest, OPagedExpandRequest as O_google_showcase_v1beta1_PagedExpandRequest } from '../../../google/showcase/v1beta1/PagedExpandRequest'; +import type { IPagedExpandResponse as I_google_showcase_v1beta1_PagedExpandResponse, OPagedExpandResponse as O_google_showcase_v1beta1_PagedExpandResponse } from '../../../google/showcase/v1beta1/PagedExpandResponse'; +import type { IWaitRequest as I_google_showcase_v1beta1_WaitRequest, OWaitRequest as O_google_showcase_v1beta1_WaitRequest } from '../../../google/showcase/v1beta1/WaitRequest'; /** * This service is used showcase the four main types of rpcs - unary, server @@ -25,115 +25,115 @@ export interface EchoClient extends grpc.Client { * and then return the response or error. * This method showcases how a client handles delays or retries. */ - Block(argument: _google_showcase_v1beta1_BlockRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_google_showcase_v1beta1_BlockResponse__Output>): grpc.ClientUnaryCall; - Block(argument: _google_showcase_v1beta1_BlockRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_google_showcase_v1beta1_BlockResponse__Output>): grpc.ClientUnaryCall; - Block(argument: _google_showcase_v1beta1_BlockRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_google_showcase_v1beta1_BlockResponse__Output>): grpc.ClientUnaryCall; - Block(argument: _google_showcase_v1beta1_BlockRequest, callback: grpc.requestCallback<_google_showcase_v1beta1_BlockResponse__Output>): grpc.ClientUnaryCall; + Block(argument: I_google_showcase_v1beta1_BlockRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + Block(argument: I_google_showcase_v1beta1_BlockRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + Block(argument: I_google_showcase_v1beta1_BlockRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + Block(argument: I_google_showcase_v1beta1_BlockRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * This method will block (wait) for the requested amount of time * and then return the response or error. * This method showcases how a client handles delays or retries. */ - block(argument: _google_showcase_v1beta1_BlockRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_google_showcase_v1beta1_BlockResponse__Output>): grpc.ClientUnaryCall; - block(argument: _google_showcase_v1beta1_BlockRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_google_showcase_v1beta1_BlockResponse__Output>): grpc.ClientUnaryCall; - block(argument: _google_showcase_v1beta1_BlockRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_google_showcase_v1beta1_BlockResponse__Output>): grpc.ClientUnaryCall; - block(argument: _google_showcase_v1beta1_BlockRequest, callback: grpc.requestCallback<_google_showcase_v1beta1_BlockResponse__Output>): grpc.ClientUnaryCall; + block(argument: I_google_showcase_v1beta1_BlockRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + block(argument: I_google_showcase_v1beta1_BlockRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + block(argument: I_google_showcase_v1beta1_BlockRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + block(argument: I_google_showcase_v1beta1_BlockRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * This method, upon receiving a request on the stream, the same content will * be passed back on the stream. This method showcases bidirectional * streaming rpcs. */ - Chat(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<_google_showcase_v1beta1_EchoRequest, _google_showcase_v1beta1_EchoResponse__Output>; - Chat(options?: grpc.CallOptions): grpc.ClientDuplexStream<_google_showcase_v1beta1_EchoRequest, _google_showcase_v1beta1_EchoResponse__Output>; + Chat(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream; + Chat(options?: grpc.CallOptions): grpc.ClientDuplexStream; /** * This method, upon receiving a request on the stream, the same content will * be passed back on the stream. This method showcases bidirectional * streaming rpcs. */ - chat(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<_google_showcase_v1beta1_EchoRequest, _google_showcase_v1beta1_EchoResponse__Output>; - chat(options?: grpc.CallOptions): grpc.ClientDuplexStream<_google_showcase_v1beta1_EchoRequest, _google_showcase_v1beta1_EchoResponse__Output>; + chat(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream; + chat(options?: grpc.CallOptions): grpc.ClientDuplexStream; /** * This method will collect the words given to it. When the stream is closed * by the client, this method will return the a concatenation of the strings * passed to it. This method showcases client-side streaming rpcs. */ - Collect(metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_google_showcase_v1beta1_EchoResponse__Output>): grpc.ClientWritableStream<_google_showcase_v1beta1_EchoRequest>; - Collect(metadata: grpc.Metadata, callback: grpc.requestCallback<_google_showcase_v1beta1_EchoResponse__Output>): grpc.ClientWritableStream<_google_showcase_v1beta1_EchoRequest>; - Collect(options: grpc.CallOptions, callback: grpc.requestCallback<_google_showcase_v1beta1_EchoResponse__Output>): grpc.ClientWritableStream<_google_showcase_v1beta1_EchoRequest>; - Collect(callback: grpc.requestCallback<_google_showcase_v1beta1_EchoResponse__Output>): grpc.ClientWritableStream<_google_showcase_v1beta1_EchoRequest>; + Collect(metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientWritableStream; + Collect(metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientWritableStream; + Collect(options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientWritableStream; + Collect(callback: grpc.requestCallback): grpc.ClientWritableStream; /** * This method will collect the words given to it. When the stream is closed * by the client, this method will return the a concatenation of the strings * passed to it. This method showcases client-side streaming rpcs. */ - collect(metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_google_showcase_v1beta1_EchoResponse__Output>): grpc.ClientWritableStream<_google_showcase_v1beta1_EchoRequest>; - collect(metadata: grpc.Metadata, callback: grpc.requestCallback<_google_showcase_v1beta1_EchoResponse__Output>): grpc.ClientWritableStream<_google_showcase_v1beta1_EchoRequest>; - collect(options: grpc.CallOptions, callback: grpc.requestCallback<_google_showcase_v1beta1_EchoResponse__Output>): grpc.ClientWritableStream<_google_showcase_v1beta1_EchoRequest>; - collect(callback: grpc.requestCallback<_google_showcase_v1beta1_EchoResponse__Output>): grpc.ClientWritableStream<_google_showcase_v1beta1_EchoRequest>; + collect(metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientWritableStream; + collect(metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientWritableStream; + collect(options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientWritableStream; + collect(callback: grpc.requestCallback): grpc.ClientWritableStream; /** * This method simply echos the request. This method is showcases unary rpcs. */ - Echo(argument: _google_showcase_v1beta1_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_google_showcase_v1beta1_EchoResponse__Output>): grpc.ClientUnaryCall; - Echo(argument: _google_showcase_v1beta1_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_google_showcase_v1beta1_EchoResponse__Output>): grpc.ClientUnaryCall; - Echo(argument: _google_showcase_v1beta1_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_google_showcase_v1beta1_EchoResponse__Output>): grpc.ClientUnaryCall; - Echo(argument: _google_showcase_v1beta1_EchoRequest, callback: grpc.requestCallback<_google_showcase_v1beta1_EchoResponse__Output>): grpc.ClientUnaryCall; + Echo(argument: I_google_showcase_v1beta1_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + Echo(argument: I_google_showcase_v1beta1_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + Echo(argument: I_google_showcase_v1beta1_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + Echo(argument: I_google_showcase_v1beta1_EchoRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * This method simply echos the request. This method is showcases unary rpcs. */ - echo(argument: _google_showcase_v1beta1_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_google_showcase_v1beta1_EchoResponse__Output>): grpc.ClientUnaryCall; - echo(argument: _google_showcase_v1beta1_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_google_showcase_v1beta1_EchoResponse__Output>): grpc.ClientUnaryCall; - echo(argument: _google_showcase_v1beta1_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_google_showcase_v1beta1_EchoResponse__Output>): grpc.ClientUnaryCall; - echo(argument: _google_showcase_v1beta1_EchoRequest, callback: grpc.requestCallback<_google_showcase_v1beta1_EchoResponse__Output>): grpc.ClientUnaryCall; + echo(argument: I_google_showcase_v1beta1_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + echo(argument: I_google_showcase_v1beta1_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + echo(argument: I_google_showcase_v1beta1_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + echo(argument: I_google_showcase_v1beta1_EchoRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * This method split the given content into words and will pass each word back * through the stream. This method showcases server-side streaming rpcs. */ - Expand(argument: _google_showcase_v1beta1_ExpandRequest, metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientReadableStream<_google_showcase_v1beta1_EchoResponse__Output>; - Expand(argument: _google_showcase_v1beta1_ExpandRequest, options?: grpc.CallOptions): grpc.ClientReadableStream<_google_showcase_v1beta1_EchoResponse__Output>; + Expand(argument: I_google_showcase_v1beta1_ExpandRequest, metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientReadableStream; + Expand(argument: I_google_showcase_v1beta1_ExpandRequest, options?: grpc.CallOptions): grpc.ClientReadableStream; /** * This method split the given content into words and will pass each word back * through the stream. This method showcases server-side streaming rpcs. */ - expand(argument: _google_showcase_v1beta1_ExpandRequest, metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientReadableStream<_google_showcase_v1beta1_EchoResponse__Output>; - expand(argument: _google_showcase_v1beta1_ExpandRequest, options?: grpc.CallOptions): grpc.ClientReadableStream<_google_showcase_v1beta1_EchoResponse__Output>; + expand(argument: I_google_showcase_v1beta1_ExpandRequest, metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientReadableStream; + expand(argument: I_google_showcase_v1beta1_ExpandRequest, options?: grpc.CallOptions): grpc.ClientReadableStream; /** * This is similar to the Expand method but instead of returning a stream of * expanded words, this method returns a paged list of expanded words. */ - PagedExpand(argument: _google_showcase_v1beta1_PagedExpandRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_google_showcase_v1beta1_PagedExpandResponse__Output>): grpc.ClientUnaryCall; - PagedExpand(argument: _google_showcase_v1beta1_PagedExpandRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_google_showcase_v1beta1_PagedExpandResponse__Output>): grpc.ClientUnaryCall; - PagedExpand(argument: _google_showcase_v1beta1_PagedExpandRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_google_showcase_v1beta1_PagedExpandResponse__Output>): grpc.ClientUnaryCall; - PagedExpand(argument: _google_showcase_v1beta1_PagedExpandRequest, callback: grpc.requestCallback<_google_showcase_v1beta1_PagedExpandResponse__Output>): grpc.ClientUnaryCall; + PagedExpand(argument: I_google_showcase_v1beta1_PagedExpandRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + PagedExpand(argument: I_google_showcase_v1beta1_PagedExpandRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + PagedExpand(argument: I_google_showcase_v1beta1_PagedExpandRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + PagedExpand(argument: I_google_showcase_v1beta1_PagedExpandRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * This is similar to the Expand method but instead of returning a stream of * expanded words, this method returns a paged list of expanded words. */ - pagedExpand(argument: _google_showcase_v1beta1_PagedExpandRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_google_showcase_v1beta1_PagedExpandResponse__Output>): grpc.ClientUnaryCall; - pagedExpand(argument: _google_showcase_v1beta1_PagedExpandRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_google_showcase_v1beta1_PagedExpandResponse__Output>): grpc.ClientUnaryCall; - pagedExpand(argument: _google_showcase_v1beta1_PagedExpandRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_google_showcase_v1beta1_PagedExpandResponse__Output>): grpc.ClientUnaryCall; - pagedExpand(argument: _google_showcase_v1beta1_PagedExpandRequest, callback: grpc.requestCallback<_google_showcase_v1beta1_PagedExpandResponse__Output>): grpc.ClientUnaryCall; + pagedExpand(argument: I_google_showcase_v1beta1_PagedExpandRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + pagedExpand(argument: I_google_showcase_v1beta1_PagedExpandRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + pagedExpand(argument: I_google_showcase_v1beta1_PagedExpandRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + pagedExpand(argument: I_google_showcase_v1beta1_PagedExpandRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * This method will wait the requested amount of and then return. * This method showcases how a client handles a request timing out. */ - Wait(argument: _google_showcase_v1beta1_WaitRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_google_longrunning_Operation__Output>): grpc.ClientUnaryCall; - Wait(argument: _google_showcase_v1beta1_WaitRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_google_longrunning_Operation__Output>): grpc.ClientUnaryCall; - Wait(argument: _google_showcase_v1beta1_WaitRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_google_longrunning_Operation__Output>): grpc.ClientUnaryCall; - Wait(argument: _google_showcase_v1beta1_WaitRequest, callback: grpc.requestCallback<_google_longrunning_Operation__Output>): grpc.ClientUnaryCall; + Wait(argument: I_google_showcase_v1beta1_WaitRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + Wait(argument: I_google_showcase_v1beta1_WaitRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + Wait(argument: I_google_showcase_v1beta1_WaitRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + Wait(argument: I_google_showcase_v1beta1_WaitRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * This method will wait the requested amount of and then return. * This method showcases how a client handles a request timing out. */ - wait(argument: _google_showcase_v1beta1_WaitRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_google_longrunning_Operation__Output>): grpc.ClientUnaryCall; - wait(argument: _google_showcase_v1beta1_WaitRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_google_longrunning_Operation__Output>): grpc.ClientUnaryCall; - wait(argument: _google_showcase_v1beta1_WaitRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_google_longrunning_Operation__Output>): grpc.ClientUnaryCall; - wait(argument: _google_showcase_v1beta1_WaitRequest, callback: grpc.requestCallback<_google_longrunning_Operation__Output>): grpc.ClientUnaryCall; + wait(argument: I_google_showcase_v1beta1_WaitRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + wait(argument: I_google_showcase_v1beta1_WaitRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + wait(argument: I_google_showcase_v1beta1_WaitRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + wait(argument: I_google_showcase_v1beta1_WaitRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; } @@ -150,53 +150,53 @@ export interface EchoHandlers extends grpc.UntypedServiceImplementation { * and then return the response or error. * This method showcases how a client handles delays or retries. */ - Block: grpc.handleUnaryCall<_google_showcase_v1beta1_BlockRequest__Output, _google_showcase_v1beta1_BlockResponse>; + Block: grpc.handleUnaryCall; /** * This method, upon receiving a request on the stream, the same content will * be passed back on the stream. This method showcases bidirectional * streaming rpcs. */ - Chat: grpc.handleBidiStreamingCall<_google_showcase_v1beta1_EchoRequest__Output, _google_showcase_v1beta1_EchoResponse>; + Chat: grpc.handleBidiStreamingCall; /** * This method will collect the words given to it. When the stream is closed * by the client, this method will return the a concatenation of the strings * passed to it. This method showcases client-side streaming rpcs. */ - Collect: grpc.handleClientStreamingCall<_google_showcase_v1beta1_EchoRequest__Output, _google_showcase_v1beta1_EchoResponse>; + Collect: grpc.handleClientStreamingCall; /** * This method simply echos the request. This method is showcases unary rpcs. */ - Echo: grpc.handleUnaryCall<_google_showcase_v1beta1_EchoRequest__Output, _google_showcase_v1beta1_EchoResponse>; + Echo: grpc.handleUnaryCall; /** * This method split the given content into words and will pass each word back * through the stream. This method showcases server-side streaming rpcs. */ - Expand: grpc.handleServerStreamingCall<_google_showcase_v1beta1_ExpandRequest__Output, _google_showcase_v1beta1_EchoResponse>; + Expand: grpc.handleServerStreamingCall; /** * This is similar to the Expand method but instead of returning a stream of * expanded words, this method returns a paged list of expanded words. */ - PagedExpand: grpc.handleUnaryCall<_google_showcase_v1beta1_PagedExpandRequest__Output, _google_showcase_v1beta1_PagedExpandResponse>; + PagedExpand: grpc.handleUnaryCall; /** * This method will wait the requested amount of and then return. * This method showcases how a client handles a request timing out. */ - Wait: grpc.handleUnaryCall<_google_showcase_v1beta1_WaitRequest__Output, _google_longrunning_Operation>; + Wait: grpc.handleUnaryCall; } export interface EchoDefinition extends grpc.ServiceDefinition { - Block: MethodDefinition<_google_showcase_v1beta1_BlockRequest, _google_showcase_v1beta1_BlockResponse, _google_showcase_v1beta1_BlockRequest__Output, _google_showcase_v1beta1_BlockResponse__Output> - Chat: MethodDefinition<_google_showcase_v1beta1_EchoRequest, _google_showcase_v1beta1_EchoResponse, _google_showcase_v1beta1_EchoRequest__Output, _google_showcase_v1beta1_EchoResponse__Output> - Collect: MethodDefinition<_google_showcase_v1beta1_EchoRequest, _google_showcase_v1beta1_EchoResponse, _google_showcase_v1beta1_EchoRequest__Output, _google_showcase_v1beta1_EchoResponse__Output> - Echo: MethodDefinition<_google_showcase_v1beta1_EchoRequest, _google_showcase_v1beta1_EchoResponse, _google_showcase_v1beta1_EchoRequest__Output, _google_showcase_v1beta1_EchoResponse__Output> - Expand: MethodDefinition<_google_showcase_v1beta1_ExpandRequest, _google_showcase_v1beta1_EchoResponse, _google_showcase_v1beta1_ExpandRequest__Output, _google_showcase_v1beta1_EchoResponse__Output> - PagedExpand: MethodDefinition<_google_showcase_v1beta1_PagedExpandRequest, _google_showcase_v1beta1_PagedExpandResponse, _google_showcase_v1beta1_PagedExpandRequest__Output, _google_showcase_v1beta1_PagedExpandResponse__Output> - Wait: MethodDefinition<_google_showcase_v1beta1_WaitRequest, _google_longrunning_Operation, _google_showcase_v1beta1_WaitRequest__Output, _google_longrunning_Operation__Output> + Block: MethodDefinition + Chat: MethodDefinition + Collect: MethodDefinition + Echo: MethodDefinition + Expand: MethodDefinition + PagedExpand: MethodDefinition + Wait: MethodDefinition } diff --git a/packages/proto-loader/golden-generated/google/showcase/v1beta1/EchoRequest.ts b/packages/proto-loader/golden-generated/google/showcase/v1beta1/EchoRequest.ts index fb2bb67d..649a5d50 100644 --- a/packages/proto-loader/golden-generated/google/showcase/v1beta1/EchoRequest.ts +++ b/packages/proto-loader/golden-generated/google/showcase/v1beta1/EchoRequest.ts @@ -1,6 +1,6 @@ // Original file: deps/gapic-showcase/schema/google/showcase/v1beta1/echo.proto -import type { Status as _google_rpc_Status, Status__Output as _google_rpc_Status__Output } from '../../../google/rpc/Status'; +import type { IStatus as I_google_rpc_Status, OStatus as O_google_rpc_Status } from '../../../google/rpc/Status'; import type { Severity as _google_showcase_v1beta1_Severity } from '../../../google/showcase/v1beta1/Severity'; /** @@ -9,7 +9,7 @@ import type { Severity as _google_showcase_v1beta1_Severity } from '../../../goo * If status is set in this message * then the status will be returned as an error. */ -export interface EchoRequest { +export interface IEchoRequest { /** * The content to be echoed by the server. */ @@ -17,7 +17,7 @@ export interface EchoRequest { /** * The error to be thrown by the server. */ - 'error'?: (_google_rpc_Status | null); + 'error'?: (I_google_rpc_Status | null); /** * The severity to be echoed by the server. */ @@ -31,7 +31,7 @@ export interface EchoRequest { * If status is set in this message * then the status will be returned as an error. */ -export interface EchoRequest__Output { +export interface OEchoRequest { /** * The content to be echoed by the server. */ @@ -39,7 +39,7 @@ export interface EchoRequest__Output { /** * The error to be thrown by the server. */ - 'error'?: (_google_rpc_Status__Output | null); + 'error'?: (O_google_rpc_Status | null); /** * The severity to be echoed by the server. */ diff --git a/packages/proto-loader/golden-generated/google/showcase/v1beta1/EchoResponse.ts b/packages/proto-loader/golden-generated/google/showcase/v1beta1/EchoResponse.ts index 3fda238a..96b7ba25 100644 --- a/packages/proto-loader/golden-generated/google/showcase/v1beta1/EchoResponse.ts +++ b/packages/proto-loader/golden-generated/google/showcase/v1beta1/EchoResponse.ts @@ -5,7 +5,7 @@ import type { Severity as _google_showcase_v1beta1_Severity } from '../../../goo /** * The response message for the Echo methods. */ -export interface EchoResponse { +export interface IEchoResponse { /** * The content specified in the request. */ @@ -19,7 +19,7 @@ export interface EchoResponse { /** * The response message for the Echo methods. */ -export interface EchoResponse__Output { +export interface OEchoResponse { /** * The content specified in the request. */ diff --git a/packages/proto-loader/golden-generated/google/showcase/v1beta1/ExpandRequest.ts b/packages/proto-loader/golden-generated/google/showcase/v1beta1/ExpandRequest.ts index 33ce73c1..4347a617 100644 --- a/packages/proto-loader/golden-generated/google/showcase/v1beta1/ExpandRequest.ts +++ b/packages/proto-loader/golden-generated/google/showcase/v1beta1/ExpandRequest.ts @@ -1,11 +1,11 @@ // Original file: deps/gapic-showcase/schema/google/showcase/v1beta1/echo.proto -import type { Status as _google_rpc_Status, Status__Output as _google_rpc_Status__Output } from '../../../google/rpc/Status'; +import type { IStatus as I_google_rpc_Status, OStatus as O_google_rpc_Status } from '../../../google/rpc/Status'; /** * The request message for the Expand method. */ -export interface ExpandRequest { +export interface IExpandRequest { /** * The content that will be split into words and returned on the stream. */ @@ -13,13 +13,13 @@ export interface ExpandRequest { /** * The error that is thrown after all words are sent on the stream. */ - 'error'?: (_google_rpc_Status | null); + 'error'?: (I_google_rpc_Status | null); } /** * The request message for the Expand method. */ -export interface ExpandRequest__Output { +export interface OExpandRequest { /** * The content that will be split into words and returned on the stream. */ @@ -27,5 +27,5 @@ export interface ExpandRequest__Output { /** * The error that is thrown after all words are sent on the stream. */ - 'error': (_google_rpc_Status__Output | null); + 'error': (O_google_rpc_Status | null); } diff --git a/packages/proto-loader/golden-generated/google/showcase/v1beta1/PagedExpandRequest.ts b/packages/proto-loader/golden-generated/google/showcase/v1beta1/PagedExpandRequest.ts index 13c94513..8c68ba99 100644 --- a/packages/proto-loader/golden-generated/google/showcase/v1beta1/PagedExpandRequest.ts +++ b/packages/proto-loader/golden-generated/google/showcase/v1beta1/PagedExpandRequest.ts @@ -4,7 +4,7 @@ /** * The request for the PagedExpand method. */ -export interface PagedExpandRequest { +export interface IPagedExpandRequest { /** * The string to expand. */ @@ -22,7 +22,7 @@ export interface PagedExpandRequest { /** * The request for the PagedExpand method. */ -export interface PagedExpandRequest__Output { +export interface OPagedExpandRequest { /** * The string to expand. */ diff --git a/packages/proto-loader/golden-generated/google/showcase/v1beta1/PagedExpandResponse.ts b/packages/proto-loader/golden-generated/google/showcase/v1beta1/PagedExpandResponse.ts index 823de43e..3b3ef90c 100644 --- a/packages/proto-loader/golden-generated/google/showcase/v1beta1/PagedExpandResponse.ts +++ b/packages/proto-loader/golden-generated/google/showcase/v1beta1/PagedExpandResponse.ts @@ -1,15 +1,15 @@ // Original file: deps/gapic-showcase/schema/google/showcase/v1beta1/echo.proto -import type { EchoResponse as _google_showcase_v1beta1_EchoResponse, EchoResponse__Output as _google_showcase_v1beta1_EchoResponse__Output } from '../../../google/showcase/v1beta1/EchoResponse'; +import type { IEchoResponse as I_google_showcase_v1beta1_EchoResponse, OEchoResponse as O_google_showcase_v1beta1_EchoResponse } from '../../../google/showcase/v1beta1/EchoResponse'; /** * The response for the PagedExpand method. */ -export interface PagedExpandResponse { +export interface IPagedExpandResponse { /** * The words that were expanded. */ - 'responses'?: (_google_showcase_v1beta1_EchoResponse)[]; + 'responses'?: (I_google_showcase_v1beta1_EchoResponse)[]; /** * The next page token. */ @@ -19,11 +19,11 @@ export interface PagedExpandResponse { /** * The response for the PagedExpand method. */ -export interface PagedExpandResponse__Output { +export interface OPagedExpandResponse { /** * The words that were expanded. */ - 'responses': (_google_showcase_v1beta1_EchoResponse__Output)[]; + 'responses': (O_google_showcase_v1beta1_EchoResponse)[]; /** * The next page token. */ diff --git a/packages/proto-loader/golden-generated/google/showcase/v1beta1/WaitMetadata.ts b/packages/proto-loader/golden-generated/google/showcase/v1beta1/WaitMetadata.ts index 5f17b445..ddbe77c2 100644 --- a/packages/proto-loader/golden-generated/google/showcase/v1beta1/WaitMetadata.ts +++ b/packages/proto-loader/golden-generated/google/showcase/v1beta1/WaitMetadata.ts @@ -1,23 +1,23 @@ // Original file: deps/gapic-showcase/schema/google/showcase/v1beta1/echo.proto -import type { Timestamp as _google_protobuf_Timestamp, Timestamp__Output as _google_protobuf_Timestamp__Output } from '../../../google/protobuf/Timestamp'; +import type { ITimestamp as I_google_protobuf_Timestamp, OTimestamp as O_google_protobuf_Timestamp } from '../../../google/protobuf/Timestamp'; /** * The metadata for Wait operation. */ -export interface WaitMetadata { +export interface IWaitMetadata { /** * The time that this operation will complete. */ - 'end_time'?: (_google_protobuf_Timestamp | null); + 'end_time'?: (I_google_protobuf_Timestamp | null); } /** * The metadata for Wait operation. */ -export interface WaitMetadata__Output { +export interface OWaitMetadata { /** * The time that this operation will complete. */ - 'end_time': (_google_protobuf_Timestamp__Output | null); + 'end_time': (O_google_protobuf_Timestamp | null); } diff --git a/packages/proto-loader/golden-generated/google/showcase/v1beta1/WaitRequest.ts b/packages/proto-loader/golden-generated/google/showcase/v1beta1/WaitRequest.ts index 46c095b6..331a6694 100644 --- a/packages/proto-loader/golden-generated/google/showcase/v1beta1/WaitRequest.ts +++ b/packages/proto-loader/golden-generated/google/showcase/v1beta1/WaitRequest.ts @@ -1,31 +1,31 @@ // Original file: deps/gapic-showcase/schema/google/showcase/v1beta1/echo.proto -import type { Timestamp as _google_protobuf_Timestamp, Timestamp__Output as _google_protobuf_Timestamp__Output } from '../../../google/protobuf/Timestamp'; -import type { Status as _google_rpc_Status, Status__Output as _google_rpc_Status__Output } from '../../../google/rpc/Status'; -import type { WaitResponse as _google_showcase_v1beta1_WaitResponse, WaitResponse__Output as _google_showcase_v1beta1_WaitResponse__Output } from '../../../google/showcase/v1beta1/WaitResponse'; -import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../google/protobuf/Duration'; +import type { ITimestamp as I_google_protobuf_Timestamp, OTimestamp as O_google_protobuf_Timestamp } from '../../../google/protobuf/Timestamp'; +import type { IStatus as I_google_rpc_Status, OStatus as O_google_rpc_Status } from '../../../google/rpc/Status'; +import type { IWaitResponse as I_google_showcase_v1beta1_WaitResponse, OWaitResponse as O_google_showcase_v1beta1_WaitResponse } from '../../../google/showcase/v1beta1/WaitResponse'; +import type { IDuration as I_google_protobuf_Duration, ODuration as O_google_protobuf_Duration } from '../../../google/protobuf/Duration'; /** * The request for Wait method. */ -export interface WaitRequest { +export interface IWaitRequest { /** * The time that this operation will complete. */ - 'end_time'?: (_google_protobuf_Timestamp | null); + 'end_time'?: (I_google_protobuf_Timestamp | null); /** * The error that will be returned by the server. If this code is specified * to be the OK rpc code, an empty response will be returned. */ - 'error'?: (_google_rpc_Status | null); + 'error'?: (I_google_rpc_Status | null); /** * The response to be returned on operation completion. */ - 'success'?: (_google_showcase_v1beta1_WaitResponse | null); + 'success'?: (I_google_showcase_v1beta1_WaitResponse | null); /** * The duration of this operation. */ - 'ttl'?: (_google_protobuf_Duration | null); + 'ttl'?: (I_google_protobuf_Duration | null); 'end'?: "end_time"|"ttl"; 'response'?: "error"|"success"; } @@ -33,24 +33,24 @@ export interface WaitRequest { /** * The request for Wait method. */ -export interface WaitRequest__Output { +export interface OWaitRequest { /** * The time that this operation will complete. */ - 'end_time'?: (_google_protobuf_Timestamp__Output | null); + 'end_time'?: (O_google_protobuf_Timestamp | null); /** * The error that will be returned by the server. If this code is specified * to be the OK rpc code, an empty response will be returned. */ - 'error'?: (_google_rpc_Status__Output | null); + 'error'?: (O_google_rpc_Status | null); /** * The response to be returned on operation completion. */ - 'success'?: (_google_showcase_v1beta1_WaitResponse__Output | null); + 'success'?: (O_google_showcase_v1beta1_WaitResponse | null); /** * The duration of this operation. */ - 'ttl'?: (_google_protobuf_Duration__Output | null); + 'ttl'?: (O_google_protobuf_Duration | null); 'end': "end_time"|"ttl"; 'response': "error"|"success"; } diff --git a/packages/proto-loader/golden-generated/google/showcase/v1beta1/WaitResponse.ts b/packages/proto-loader/golden-generated/google/showcase/v1beta1/WaitResponse.ts index 84b804f6..667b450e 100644 --- a/packages/proto-loader/golden-generated/google/showcase/v1beta1/WaitResponse.ts +++ b/packages/proto-loader/golden-generated/google/showcase/v1beta1/WaitResponse.ts @@ -4,7 +4,7 @@ /** * The result of the Wait operation. */ -export interface WaitResponse { +export interface IWaitResponse { /** * This content of the result. */ @@ -14,7 +14,7 @@ export interface WaitResponse { /** * The result of the Wait operation. */ -export interface WaitResponse__Output { +export interface OWaitResponse { /** * This content of the result. */ diff --git a/packages/proto-loader/package.json b/packages/proto-loader/package.json index 9b9431dc..cae7635f 100644 --- a/packages/proto-loader/package.json +++ b/packages/proto-loader/package.json @@ -1,6 +1,6 @@ { "name": "@grpc/proto-loader", - "version": "0.6.9", + "version": "0.7.3", "author": "Google Inc.", "contributors": [ { @@ -24,7 +24,7 @@ "fix": "gts fix", "pretest": "npm run compile", "posttest": "npm run check", - "generate-golden": "node ./build/bin/proto-loader-gen-types.js --keepCase --longs=String --enums=String --defaults --oneofs --json --includeComments -I deps/gapic-showcase/schema/ deps/googleapis/ -O ./golden-generated --grpcLib @grpc/grpc-js google/showcase/v1beta1/echo.proto", + "generate-golden": "node ./build/bin/proto-loader-gen-types.js --keepCase --longs=String --enums=String --defaults --oneofs --json --includeComments --inputTemplate=I%s --outputTemplate=O%s -I deps/gapic-showcase/schema/ deps/googleapis/ -O ./golden-generated --grpcLib @grpc/grpc-js google/showcase/v1beta1/echo.proto", "validate-golden": "rm -rf ./golden-generated-old && mv ./golden-generated/ ./golden-generated-old && npm run generate-golden && diff -rb ./golden-generated ./golden-generated-old" }, "repository": { @@ -38,8 +38,8 @@ "files": [ "LICENSE", "build/src/*.d.ts", - "build/src/*.js", - "build/bin/*.js" + "build/src/*.{js,js.map}", + "build/bin/*.{js,js.map}" ], "bin": { "proto-loader-gen-types": "./build/bin/proto-loader-gen-types.js" @@ -48,7 +48,7 @@ "@types/long": "^4.0.1", "lodash.camelcase": "^4.3.0", "long": "^4.0.0", - "protobufjs": "^6.10.0", + "protobufjs": "^7.0.0", "yargs": "^16.2.0" }, "devDependencies": { @@ -58,9 +58,9 @@ "@types/node": "^10.17.26", "@types/yargs": "^16.0.4", "clang-format": "^1.2.2", - "gts": "^1.1.0", + "gts": "^3.1.0", "rimraf": "^3.0.2", - "typescript": "~3.8.3" + "typescript": "~4.7.4" }, "engines": { "node": ">=6" diff --git a/packages/proto-loader/src/index.ts b/packages/proto-loader/src/index.ts index 24a24940..d607668a 100644 --- a/packages/proto-loader/src/index.ts +++ b/packages/proto-loader/src/index.ts @@ -22,9 +22,9 @@ import * as descriptor from 'protobufjs/ext/descriptor'; import { loadProtosWithOptionsSync, loadProtosWithOptions, Options, addCommonProtos } from './util'; -export { Long } from 'long'; +import Long = require('long'); -export { Options }; +export { Options, Long }; /** * This type exists for use with code generated by the proto-loader-gen-types diff --git a/test/kokoro/xds_k8s_lb.cfg b/test/kokoro/xds_k8s_lb.cfg new file mode 100644 index 00000000..09aa3d17 --- /dev/null +++ b/test/kokoro/xds_k8s_lb.cfg @@ -0,0 +1,26 @@ +# Copyright 2022 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Config file for Kokoro (in protobuf text format) + +# Location of the continuous shell script in repository. +build_file: "grpc-node/packages/grpc-js-xds/scripts/xds_k8s_lb.sh" +timeout_mins: 180 +action { + define_artifacts { + regex: "artifacts/**/*sponge_log.xml" + regex: "artifacts/**/*.log" + strip_prefix: "artifacts" + } +} diff --git a/test/kokoro/xds_k8s_url_map.cfg b/test/kokoro/xds_k8s_url_map.cfg new file mode 100644 index 00000000..50d523b6 --- /dev/null +++ b/test/kokoro/xds_k8s_url_map.cfg @@ -0,0 +1,26 @@ +# Copyright 2022 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Config file for Kokoro (in protobuf text format) + +# Location of the continuous shell script in repository. +build_file: "grpc-node/packages/grpc-js-xds/scripts/xds_k8s_url_map.sh" +timeout_mins: 180 +action { + define_artifacts { + regex: "artifacts/**/*sponge_log.xml" + regex: "artifacts/**/*.log" + strip_prefix: "artifacts" + } +}