mirror of
https://github.com/grpc/grpc-node.git
synced 2025-12-08 18:23:54 +00:00
Merge branch 'master' into grpc-js_retry
This commit is contained in:
commit
67bec19b4e
@ -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
|
||||
|
||||
@ -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`)
|
||||
- [Outlier Detection](https://github.com/grpc/proposal/blob/master/A50-xds-outlier-detection.md)
|
||||
38
packages/grpc-js-xds/interop/Dockerfile
Normal file
38
packages/grpc-js-xds/interop/Dockerfile
Normal file
@ -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 <TAG> -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" ]
|
||||
@ -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"
|
||||
|
||||
178
packages/grpc-js-xds/scripts/xds_k8s_lb.sh
Executable file
178
packages/grpc-js-xds/scripts/xds_k8s_lb.sh
Executable file
@ -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/<branch name>/<job name>
|
||||
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 "$@"
|
||||
162
packages/grpc-js-xds/scripts/xds_k8s_url_map.sh
Normal file
162
packages/grpc-js-xds/scripts/xds_k8s_url_map.sh
Normal file
@ -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 "$@"
|
||||
@ -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';
|
||||
export const EXPERIMENTAL_OUTLIER_DETECTION = (process.env.GRPC_EXPERIMENTAL_ENABLE_OUTLIER_DETECTION ?? 'true') === 'true';
|
||||
@ -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<SuccessRateEjectionConfig> | null = null;
|
||||
/* Success rate ejection is enabled by default, so we only disable it if
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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<string, XdsClusterManagerChild> = new Map<string, XdsClusterManagerChild>();
|
||||
// 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<string, Picker> = new Map<string, Picker>();
|
||||
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 {
|
||||
|
||||
@ -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<string, HttpFilterConfig>();
|
||||
|
||||
@ -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 ||
|
||||
|
||||
@ -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<Cluster__Output> {
|
||||
versionInfo = '';
|
||||
nonce = '';
|
||||
|
||||
private watchers: Map<string, Watcher<Cluster__Output>[]> = new Map<
|
||||
string,
|
||||
Watcher<Cluster__Output>[]
|
||||
>();
|
||||
|
||||
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<Cluster__Output>): 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<Cluster__Output> implements XdsStreamState<Cluster__Output> {
|
||||
protected isStateOfTheWorld(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
removeWatcher(clusterName: string, watcher: Watcher<Cluster__Output>): 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<Cluster__Output> {
|
||||
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<Cluster__Output> {
|
||||
}
|
||||
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>): 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<Cluster__Output>[], 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<string> = new Set<string>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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<ClusterLoadAssignment__Output> {
|
||||
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<ClusterLoadAssignment__Output>[]
|
||||
> = new Map<string, Watcher<ClusterLoadAssignment__Output>[]>();
|
||||
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<ClusterLoadAssignment__Output>
|
||||
): 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<ClusterLoadAssignment__Output> implements XdsStreamState<ClusterLoadAssignment__Output> {
|
||||
protected getResourceName(resource: ClusterLoadAssignment__Output): string {
|
||||
return resource.cluster_name;
|
||||
}
|
||||
|
||||
removeWatcher(
|
||||
edsServiceName: string,
|
||||
watcher: Watcher<ClusterLoadAssignment__Output>
|
||||
): 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<ClusterLoadAssignment__Output> {
|
||||
* 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<number, number> = 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<ClusterLoadAssignment__Output> {
|
||||
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<ClusterLoadAssignment__Output>[], 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<string> = new Set<string>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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<Listener__Output> {
|
||||
versionInfo = '';
|
||||
nonce = '';
|
||||
|
||||
private watchers: Map<string, Watcher<Listener__Output>[]> = new Map<string, Watcher<Listener__Output>[]>();
|
||||
private latestResponses: Listener__Output[] = [];
|
||||
private latestIsV2 = false;
|
||||
|
||||
constructor(private rdsState: RdsState, private updateResourceNames: () => void) {}
|
||||
|
||||
addWatcher(targetName: string, watcher: Watcher<Listener__Output>) {
|
||||
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<Listener__Output> implements XdsStreamState<Listener__Output> {
|
||||
protected getResourceName(resource: Listener__Output): string {
|
||||
return resource.name;
|
||||
}
|
||||
protected getProtocolName(): string {
|
||||
return 'LDS';
|
||||
}
|
||||
protected isStateOfTheWorld(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
removeWatcher(targetName: string, watcher: Watcher<Listener__Output>): 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<Listener__Output> {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private handleMissingNames(allTargetNames: Set<string>): 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<Listener__Output>[], 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<string>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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<RouteConfiguration__Output> {
|
||||
versionInfo = '';
|
||||
nonce = '';
|
||||
|
||||
private watchers: Map<string, Watcher<RouteConfiguration__Output>[]> = new Map<string, Watcher<RouteConfiguration__Output>[]>();
|
||||
private latestResponses: RouteConfiguration__Output[] = [];
|
||||
private latestIsV2 = false;
|
||||
|
||||
constructor(private updateResourceNames: () => void) {}
|
||||
|
||||
addWatcher(routeConfigName: string, watcher: Watcher<RouteConfiguration__Output>) {
|
||||
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<RouteConfiguration__Output> implements XdsStreamState<RouteConfiguration__Output> {
|
||||
protected isStateOfTheWorld(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
removeWatcher(routeConfigName: string, watcher: Watcher<RouteConfiguration__Output>): 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<RouteConfiguration__Output> {
|
||||
}
|
||||
}
|
||||
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<RouteConfiguration__Output> {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
handleResponses(responses: ResourcePair<RouteConfiguration__Output>[], 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<string>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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<UpdateType> {
|
||||
/* 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<ResponseType> {
|
||||
handleResponses(responses: ResourcePair<ResponseType>[], isV2: boolean): HandleResponseResult;
|
||||
|
||||
reportStreamError(status: StatusObject): void;
|
||||
reportAdsStreamStart(): void;
|
||||
|
||||
addWatcher(name: string, watcher: Watcher<ResponseType>): void;
|
||||
removeWatcher(resourceName: string, watcher: Watcher<ResponseType>): void;
|
||||
}
|
||||
|
||||
interface SubscriptionEntry<ResponseType> {
|
||||
watchers: Watcher<ResponseType>[];
|
||||
cachedResponse: ResponseType | null;
|
||||
resourceTimer: NodeJS.Timer;
|
||||
deletionIgnored: boolean;
|
||||
}
|
||||
|
||||
const RESOURCE_TIMEOUT_MS = 15_000;
|
||||
|
||||
export abstract class BaseXdsStreamState<ResponseType> implements XdsStreamState<ResponseType> {
|
||||
versionInfo = '';
|
||||
nonce = '';
|
||||
|
||||
private subscriptions: Map<string, SubscriptionEntry<ResponseType>> = new Map<string, SubscriptionEntry<ResponseType>>();
|
||||
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<ResponseType>) {
|
||||
clearTimeout(subscriptionEntry.resourceTimer);
|
||||
subscriptionEntry.resourceTimer = setTimeout(() => {
|
||||
for (const watcher of subscriptionEntry.watchers) {
|
||||
watcher.onResourceDoesNotExist();
|
||||
}
|
||||
}, RESOURCE_TIMEOUT_MS);
|
||||
}
|
||||
|
||||
addWatcher(name: string, watcher: Watcher<ResponseType>): 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<ResponseType>): 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<ResponseType>[], 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<string>();
|
||||
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>): 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;
|
||||
}
|
||||
@ -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": [
|
||||
|
||||
@ -100,6 +100,7 @@ export class BackoffTimeout {
|
||||
}
|
||||
|
||||
private runTimer(delay: number) {
|
||||
clearTimeout(this.timerId);
|
||||
this.timerId = setTimeout(() => {
|
||||
this.callback();
|
||||
this.running = false;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -109,6 +109,10 @@ export type ClientOptions = Partial<ChannelOptions> & {
|
||||
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);
|
||||
},
|
||||
|
||||
40
packages/grpc-js/src/control-plane-status.ts
Normal file
40
packages/grpc-js/src/control-plane-status.ts
Normal file
@ -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};
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
export { trace } from './logging';
|
||||
export { trace, log } from './logging';
|
||||
export {
|
||||
Resolver,
|
||||
ResolverListener,
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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<string, MapEntry> = new Map<string, MapEntry>();
|
||||
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 {
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -81,6 +81,7 @@ export type ServerSurfaceCall = {
|
||||
getPeer(): string;
|
||||
sendMetadata(responseMetadata: Metadata): void;
|
||||
getDeadline(): Deadline;
|
||||
getPath(): string;
|
||||
} & EventEmitter;
|
||||
|
||||
export type ServerUnaryCall<RequestType, ResponseType> = ServerSurfaceCall & {
|
||||
@ -128,6 +129,10 @@ export class ServerUnaryCallImpl<RequestType, ResponseType>
|
||||
getDeadline(): Deadline {
|
||||
return this.call.getDeadline();
|
||||
}
|
||||
|
||||
getPath(): string {
|
||||
return this.call.getPath();
|
||||
}
|
||||
}
|
||||
|
||||
export class ServerReadableStreamImpl<RequestType, ResponseType>
|
||||
@ -166,6 +171,10 @@ export class ServerReadableStreamImpl<RequestType, ResponseType>
|
||||
getDeadline(): Deadline {
|
||||
return this.call.getDeadline();
|
||||
}
|
||||
|
||||
getPath(): string {
|
||||
return this.call.getPath();
|
||||
}
|
||||
}
|
||||
|
||||
export class ServerWritableStreamImpl<RequestType, ResponseType>
|
||||
@ -203,6 +212,10 @@ export class ServerWritableStreamImpl<RequestType, ResponseType>
|
||||
return this.call.getDeadline();
|
||||
}
|
||||
|
||||
getPath(): string {
|
||||
return this.call.getPath();
|
||||
}
|
||||
|
||||
_write(
|
||||
chunk: ResponseType,
|
||||
encoding: string,
|
||||
@ -280,6 +293,10 @@ export class ServerDuplexStreamImpl<RequestType, ResponseType>
|
||||
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 */
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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'
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -25,6 +25,7 @@ message Request {
|
||||
|
||||
message Response {
|
||||
int32 count = 1;
|
||||
string message = 2;
|
||||
}
|
||||
|
||||
service TestService {
|
||||
|
||||
@ -3,8 +3,10 @@
|
||||
|
||||
export interface Response {
|
||||
'count'?: (number);
|
||||
'message'?: (string);
|
||||
}
|
||||
|
||||
export interface Response__Output {
|
||||
'count': (number);
|
||||
'message': (string);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -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<void>((resolve, reject) => {
|
||||
|
||||
server = new grpc.Server();
|
||||
server.addService(echoService.service, {
|
||||
echo(call: ServerUnaryCall<any, any>, callback: sendUnaryData<any>) {
|
||||
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);
|
||||
});
|
||||
});
|
||||
@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -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;
|
||||
|
||||
@ -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 => {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -6,7 +6,8 @@
|
||||
"target": "es2017",
|
||||
"module": "commonjs",
|
||||
"resolveJsonModule": true,
|
||||
"incremental": true
|
||||
"incremental": true,
|
||||
"types": ["mocha"]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@ -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/",
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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...')
|
||||
|
||||
@ -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.
|
||||
*/
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
*/
|
||||
|
||||
@ -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.
|
||||
*/
|
||||
|
||||
@ -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.
|
||||
*/
|
||||
|
||||
@ -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.
|
||||
*/
|
||||
|
||||
@ -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.
|
||||
*/
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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<O_google_protobuf_Empty>): grpc.ClientUnaryCall;
|
||||
CancelOperation(argument: I_google_longrunning_CancelOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<O_google_protobuf_Empty>): grpc.ClientUnaryCall;
|
||||
CancelOperation(argument: I_google_longrunning_CancelOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback<O_google_protobuf_Empty>): grpc.ClientUnaryCall;
|
||||
CancelOperation(argument: I_google_longrunning_CancelOperationRequest, callback: grpc.requestCallback<O_google_protobuf_Empty>): 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<O_google_protobuf_Empty>): grpc.ClientUnaryCall;
|
||||
cancelOperation(argument: I_google_longrunning_CancelOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<O_google_protobuf_Empty>): grpc.ClientUnaryCall;
|
||||
cancelOperation(argument: I_google_longrunning_CancelOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback<O_google_protobuf_Empty>): grpc.ClientUnaryCall;
|
||||
cancelOperation(argument: I_google_longrunning_CancelOperationRequest, callback: grpc.requestCallback<O_google_protobuf_Empty>): 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<O_google_protobuf_Empty>): grpc.ClientUnaryCall;
|
||||
DeleteOperation(argument: I_google_longrunning_DeleteOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<O_google_protobuf_Empty>): grpc.ClientUnaryCall;
|
||||
DeleteOperation(argument: I_google_longrunning_DeleteOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback<O_google_protobuf_Empty>): grpc.ClientUnaryCall;
|
||||
DeleteOperation(argument: I_google_longrunning_DeleteOperationRequest, callback: grpc.requestCallback<O_google_protobuf_Empty>): 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<O_google_protobuf_Empty>): grpc.ClientUnaryCall;
|
||||
deleteOperation(argument: I_google_longrunning_DeleteOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<O_google_protobuf_Empty>): grpc.ClientUnaryCall;
|
||||
deleteOperation(argument: I_google_longrunning_DeleteOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback<O_google_protobuf_Empty>): grpc.ClientUnaryCall;
|
||||
deleteOperation(argument: I_google_longrunning_DeleteOperationRequest, callback: grpc.requestCallback<O_google_protobuf_Empty>): 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<O_google_longrunning_Operation>): grpc.ClientUnaryCall;
|
||||
GetOperation(argument: I_google_longrunning_GetOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<O_google_longrunning_Operation>): grpc.ClientUnaryCall;
|
||||
GetOperation(argument: I_google_longrunning_GetOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback<O_google_longrunning_Operation>): grpc.ClientUnaryCall;
|
||||
GetOperation(argument: I_google_longrunning_GetOperationRequest, callback: grpc.requestCallback<O_google_longrunning_Operation>): 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<O_google_longrunning_Operation>): grpc.ClientUnaryCall;
|
||||
getOperation(argument: I_google_longrunning_GetOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<O_google_longrunning_Operation>): grpc.ClientUnaryCall;
|
||||
getOperation(argument: I_google_longrunning_GetOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback<O_google_longrunning_Operation>): grpc.ClientUnaryCall;
|
||||
getOperation(argument: I_google_longrunning_GetOperationRequest, callback: grpc.requestCallback<O_google_longrunning_Operation>): 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<O_google_longrunning_ListOperationsResponse>): grpc.ClientUnaryCall;
|
||||
ListOperations(argument: I_google_longrunning_ListOperationsRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<O_google_longrunning_ListOperationsResponse>): grpc.ClientUnaryCall;
|
||||
ListOperations(argument: I_google_longrunning_ListOperationsRequest, options: grpc.CallOptions, callback: grpc.requestCallback<O_google_longrunning_ListOperationsResponse>): grpc.ClientUnaryCall;
|
||||
ListOperations(argument: I_google_longrunning_ListOperationsRequest, callback: grpc.requestCallback<O_google_longrunning_ListOperationsResponse>): 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<O_google_longrunning_ListOperationsResponse>): grpc.ClientUnaryCall;
|
||||
listOperations(argument: I_google_longrunning_ListOperationsRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<O_google_longrunning_ListOperationsResponse>): grpc.ClientUnaryCall;
|
||||
listOperations(argument: I_google_longrunning_ListOperationsRequest, options: grpc.CallOptions, callback: grpc.requestCallback<O_google_longrunning_ListOperationsResponse>): grpc.ClientUnaryCall;
|
||||
listOperations(argument: I_google_longrunning_ListOperationsRequest, callback: grpc.requestCallback<O_google_longrunning_ListOperationsResponse>): 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<O_google_longrunning_Operation>): grpc.ClientUnaryCall;
|
||||
WaitOperation(argument: I_google_longrunning_WaitOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<O_google_longrunning_Operation>): grpc.ClientUnaryCall;
|
||||
WaitOperation(argument: I_google_longrunning_WaitOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback<O_google_longrunning_Operation>): grpc.ClientUnaryCall;
|
||||
WaitOperation(argument: I_google_longrunning_WaitOperationRequest, callback: grpc.requestCallback<O_google_longrunning_Operation>): 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<O_google_longrunning_Operation>): grpc.ClientUnaryCall;
|
||||
waitOperation(argument: I_google_longrunning_WaitOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<O_google_longrunning_Operation>): grpc.ClientUnaryCall;
|
||||
waitOperation(argument: I_google_longrunning_WaitOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback<O_google_longrunning_Operation>): grpc.ClientUnaryCall;
|
||||
waitOperation(argument: I_google_longrunning_WaitOperationRequest, callback: grpc.requestCallback<O_google_longrunning_Operation>): 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<O_google_longrunning_CancelOperationRequest, I_google_protobuf_Empty>;
|
||||
|
||||
/**
|
||||
* 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<O_google_longrunning_DeleteOperationRequest, I_google_protobuf_Empty>;
|
||||
|
||||
/**
|
||||
* 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<O_google_longrunning_GetOperationRequest, I_google_longrunning_Operation>;
|
||||
|
||||
/**
|
||||
* 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<O_google_longrunning_ListOperationsRequest, I_google_longrunning_ListOperationsResponse>;
|
||||
|
||||
/**
|
||||
* 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<O_google_longrunning_WaitOperationRequest, I_google_longrunning_Operation>;
|
||||
|
||||
}
|
||||
|
||||
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<I_google_longrunning_CancelOperationRequest, I_google_protobuf_Empty, O_google_longrunning_CancelOperationRequest, O_google_protobuf_Empty>
|
||||
DeleteOperation: MethodDefinition<I_google_longrunning_DeleteOperationRequest, I_google_protobuf_Empty, O_google_longrunning_DeleteOperationRequest, O_google_protobuf_Empty>
|
||||
GetOperation: MethodDefinition<I_google_longrunning_GetOperationRequest, I_google_longrunning_Operation, O_google_longrunning_GetOperationRequest, O_google_longrunning_Operation>
|
||||
ListOperations: MethodDefinition<I_google_longrunning_ListOperationsRequest, I_google_longrunning_ListOperationsResponse, O_google_longrunning_ListOperationsRequest, O_google_longrunning_ListOperationsResponse>
|
||||
WaitOperation: MethodDefinition<I_google_longrunning_WaitOperationRequest, I_google_longrunning_Operation, O_google_longrunning_WaitOperationRequest, O_google_longrunning_Operation>
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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)[];
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
// Original file: null
|
||||
|
||||
|
||||
export interface Empty {
|
||||
export interface IEmpty {
|
||||
}
|
||||
|
||||
export interface Empty__Output {
|
||||
export interface OEmpty {
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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)[];
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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)[];
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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)[];
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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)[];
|
||||
}
|
||||
|
||||
@ -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)[];
|
||||
}
|
||||
|
||||
@ -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)[];
|
||||
}
|
||||
|
||||
@ -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)[];
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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)[];
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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)[];
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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)[];
|
||||
}
|
||||
|
||||
@ -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";
|
||||
}
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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<O_google_showcase_v1beta1_BlockResponse>): grpc.ClientUnaryCall;
|
||||
Block(argument: I_google_showcase_v1beta1_BlockRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<O_google_showcase_v1beta1_BlockResponse>): grpc.ClientUnaryCall;
|
||||
Block(argument: I_google_showcase_v1beta1_BlockRequest, options: grpc.CallOptions, callback: grpc.requestCallback<O_google_showcase_v1beta1_BlockResponse>): grpc.ClientUnaryCall;
|
||||
Block(argument: I_google_showcase_v1beta1_BlockRequest, callback: grpc.requestCallback<O_google_showcase_v1beta1_BlockResponse>): 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<O_google_showcase_v1beta1_BlockResponse>): grpc.ClientUnaryCall;
|
||||
block(argument: I_google_showcase_v1beta1_BlockRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<O_google_showcase_v1beta1_BlockResponse>): grpc.ClientUnaryCall;
|
||||
block(argument: I_google_showcase_v1beta1_BlockRequest, options: grpc.CallOptions, callback: grpc.requestCallback<O_google_showcase_v1beta1_BlockResponse>): grpc.ClientUnaryCall;
|
||||
block(argument: I_google_showcase_v1beta1_BlockRequest, callback: grpc.requestCallback<O_google_showcase_v1beta1_BlockResponse>): 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<I_google_showcase_v1beta1_EchoRequest, O_google_showcase_v1beta1_EchoResponse>;
|
||||
Chat(options?: grpc.CallOptions): grpc.ClientDuplexStream<I_google_showcase_v1beta1_EchoRequest, O_google_showcase_v1beta1_EchoResponse>;
|
||||
/**
|
||||
* 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<I_google_showcase_v1beta1_EchoRequest, O_google_showcase_v1beta1_EchoResponse>;
|
||||
chat(options?: grpc.CallOptions): grpc.ClientDuplexStream<I_google_showcase_v1beta1_EchoRequest, O_google_showcase_v1beta1_EchoResponse>;
|
||||
|
||||
/**
|
||||
* 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<O_google_showcase_v1beta1_EchoResponse>): grpc.ClientWritableStream<I_google_showcase_v1beta1_EchoRequest>;
|
||||
Collect(metadata: grpc.Metadata, callback: grpc.requestCallback<O_google_showcase_v1beta1_EchoResponse>): grpc.ClientWritableStream<I_google_showcase_v1beta1_EchoRequest>;
|
||||
Collect(options: grpc.CallOptions, callback: grpc.requestCallback<O_google_showcase_v1beta1_EchoResponse>): grpc.ClientWritableStream<I_google_showcase_v1beta1_EchoRequest>;
|
||||
Collect(callback: grpc.requestCallback<O_google_showcase_v1beta1_EchoResponse>): grpc.ClientWritableStream<I_google_showcase_v1beta1_EchoRequest>;
|
||||
/**
|
||||
* 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<O_google_showcase_v1beta1_EchoResponse>): grpc.ClientWritableStream<I_google_showcase_v1beta1_EchoRequest>;
|
||||
collect(metadata: grpc.Metadata, callback: grpc.requestCallback<O_google_showcase_v1beta1_EchoResponse>): grpc.ClientWritableStream<I_google_showcase_v1beta1_EchoRequest>;
|
||||
collect(options: grpc.CallOptions, callback: grpc.requestCallback<O_google_showcase_v1beta1_EchoResponse>): grpc.ClientWritableStream<I_google_showcase_v1beta1_EchoRequest>;
|
||||
collect(callback: grpc.requestCallback<O_google_showcase_v1beta1_EchoResponse>): grpc.ClientWritableStream<I_google_showcase_v1beta1_EchoRequest>;
|
||||
|
||||
/**
|
||||
* 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<O_google_showcase_v1beta1_EchoResponse>): grpc.ClientUnaryCall;
|
||||
Echo(argument: I_google_showcase_v1beta1_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<O_google_showcase_v1beta1_EchoResponse>): grpc.ClientUnaryCall;
|
||||
Echo(argument: I_google_showcase_v1beta1_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<O_google_showcase_v1beta1_EchoResponse>): grpc.ClientUnaryCall;
|
||||
Echo(argument: I_google_showcase_v1beta1_EchoRequest, callback: grpc.requestCallback<O_google_showcase_v1beta1_EchoResponse>): 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<O_google_showcase_v1beta1_EchoResponse>): grpc.ClientUnaryCall;
|
||||
echo(argument: I_google_showcase_v1beta1_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<O_google_showcase_v1beta1_EchoResponse>): grpc.ClientUnaryCall;
|
||||
echo(argument: I_google_showcase_v1beta1_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<O_google_showcase_v1beta1_EchoResponse>): grpc.ClientUnaryCall;
|
||||
echo(argument: I_google_showcase_v1beta1_EchoRequest, callback: grpc.requestCallback<O_google_showcase_v1beta1_EchoResponse>): 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<O_google_showcase_v1beta1_EchoResponse>;
|
||||
Expand(argument: I_google_showcase_v1beta1_ExpandRequest, options?: grpc.CallOptions): grpc.ClientReadableStream<O_google_showcase_v1beta1_EchoResponse>;
|
||||
/**
|
||||
* 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<O_google_showcase_v1beta1_EchoResponse>;
|
||||
expand(argument: I_google_showcase_v1beta1_ExpandRequest, options?: grpc.CallOptions): grpc.ClientReadableStream<O_google_showcase_v1beta1_EchoResponse>;
|
||||
|
||||
/**
|
||||
* 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<O_google_showcase_v1beta1_PagedExpandResponse>): grpc.ClientUnaryCall;
|
||||
PagedExpand(argument: I_google_showcase_v1beta1_PagedExpandRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<O_google_showcase_v1beta1_PagedExpandResponse>): grpc.ClientUnaryCall;
|
||||
PagedExpand(argument: I_google_showcase_v1beta1_PagedExpandRequest, options: grpc.CallOptions, callback: grpc.requestCallback<O_google_showcase_v1beta1_PagedExpandResponse>): grpc.ClientUnaryCall;
|
||||
PagedExpand(argument: I_google_showcase_v1beta1_PagedExpandRequest, callback: grpc.requestCallback<O_google_showcase_v1beta1_PagedExpandResponse>): 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<O_google_showcase_v1beta1_PagedExpandResponse>): grpc.ClientUnaryCall;
|
||||
pagedExpand(argument: I_google_showcase_v1beta1_PagedExpandRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<O_google_showcase_v1beta1_PagedExpandResponse>): grpc.ClientUnaryCall;
|
||||
pagedExpand(argument: I_google_showcase_v1beta1_PagedExpandRequest, options: grpc.CallOptions, callback: grpc.requestCallback<O_google_showcase_v1beta1_PagedExpandResponse>): grpc.ClientUnaryCall;
|
||||
pagedExpand(argument: I_google_showcase_v1beta1_PagedExpandRequest, callback: grpc.requestCallback<O_google_showcase_v1beta1_PagedExpandResponse>): 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<O_google_longrunning_Operation>): grpc.ClientUnaryCall;
|
||||
Wait(argument: I_google_showcase_v1beta1_WaitRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<O_google_longrunning_Operation>): grpc.ClientUnaryCall;
|
||||
Wait(argument: I_google_showcase_v1beta1_WaitRequest, options: grpc.CallOptions, callback: grpc.requestCallback<O_google_longrunning_Operation>): grpc.ClientUnaryCall;
|
||||
Wait(argument: I_google_showcase_v1beta1_WaitRequest, callback: grpc.requestCallback<O_google_longrunning_Operation>): 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<O_google_longrunning_Operation>): grpc.ClientUnaryCall;
|
||||
wait(argument: I_google_showcase_v1beta1_WaitRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<O_google_longrunning_Operation>): grpc.ClientUnaryCall;
|
||||
wait(argument: I_google_showcase_v1beta1_WaitRequest, options: grpc.CallOptions, callback: grpc.requestCallback<O_google_longrunning_Operation>): grpc.ClientUnaryCall;
|
||||
wait(argument: I_google_showcase_v1beta1_WaitRequest, callback: grpc.requestCallback<O_google_longrunning_Operation>): 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<O_google_showcase_v1beta1_BlockRequest, I_google_showcase_v1beta1_BlockResponse>;
|
||||
|
||||
/**
|
||||
* 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<O_google_showcase_v1beta1_EchoRequest, I_google_showcase_v1beta1_EchoResponse>;
|
||||
|
||||
/**
|
||||
* 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<O_google_showcase_v1beta1_EchoRequest, I_google_showcase_v1beta1_EchoResponse>;
|
||||
|
||||
/**
|
||||
* 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<O_google_showcase_v1beta1_EchoRequest, I_google_showcase_v1beta1_EchoResponse>;
|
||||
|
||||
/**
|
||||
* 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<O_google_showcase_v1beta1_ExpandRequest, I_google_showcase_v1beta1_EchoResponse>;
|
||||
|
||||
/**
|
||||
* 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<O_google_showcase_v1beta1_PagedExpandRequest, I_google_showcase_v1beta1_PagedExpandResponse>;
|
||||
|
||||
/**
|
||||
* 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<O_google_showcase_v1beta1_WaitRequest, I_google_longrunning_Operation>;
|
||||
|
||||
}
|
||||
|
||||
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<I_google_showcase_v1beta1_BlockRequest, I_google_showcase_v1beta1_BlockResponse, O_google_showcase_v1beta1_BlockRequest, O_google_showcase_v1beta1_BlockResponse>
|
||||
Chat: MethodDefinition<I_google_showcase_v1beta1_EchoRequest, I_google_showcase_v1beta1_EchoResponse, O_google_showcase_v1beta1_EchoRequest, O_google_showcase_v1beta1_EchoResponse>
|
||||
Collect: MethodDefinition<I_google_showcase_v1beta1_EchoRequest, I_google_showcase_v1beta1_EchoResponse, O_google_showcase_v1beta1_EchoRequest, O_google_showcase_v1beta1_EchoResponse>
|
||||
Echo: MethodDefinition<I_google_showcase_v1beta1_EchoRequest, I_google_showcase_v1beta1_EchoResponse, O_google_showcase_v1beta1_EchoRequest, O_google_showcase_v1beta1_EchoResponse>
|
||||
Expand: MethodDefinition<I_google_showcase_v1beta1_ExpandRequest, I_google_showcase_v1beta1_EchoResponse, O_google_showcase_v1beta1_ExpandRequest, O_google_showcase_v1beta1_EchoResponse>
|
||||
PagedExpand: MethodDefinition<I_google_showcase_v1beta1_PagedExpandRequest, I_google_showcase_v1beta1_PagedExpandResponse, O_google_showcase_v1beta1_PagedExpandRequest, O_google_showcase_v1beta1_PagedExpandResponse>
|
||||
Wait: MethodDefinition<I_google_showcase_v1beta1_WaitRequest, I_google_longrunning_Operation, O_google_showcase_v1beta1_WaitRequest, O_google_longrunning_Operation>
|
||||
}
|
||||
|
||||
@ -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.
|
||||
*/
|
||||
|
||||
@ -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.
|
||||
*/
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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.
|
||||
*/
|
||||
|
||||
@ -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.
|
||||
*/
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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";
|
||||
}
|
||||
|
||||
@ -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.
|
||||
*/
|
||||
|
||||
@ -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"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user