Merge branch 'master' into grpc-js_retry

This commit is contained in:
Michael Lumish 2022-10-11 16:42:19 -07:00
commit 67bec19b4e
103 changed files with 2220 additions and 1295 deletions

View File

@ -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

View File

@ -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)

View 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" ]

View File

@ -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"

View 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 "$@"

View 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 "$@"

View File

@ -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';

View File

@ -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

View File

@ -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;

View File

@ -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();
}

View File

@ -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 {

View File

@ -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>();

View File

@ -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 ||

View File

@ -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);
}
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -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;
}

View File

@ -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": [

View File

@ -100,6 +100,7 @@ export class BackoffTimeout {
}
private runTimer(delay: number) {
clearTimeout(this.timerId);
this.timerId = setTimeout(() => {
this.callback();
this.running = false;

View File

@ -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

View File

@ -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;
}

View File

@ -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);
},

View 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};
}
}

View File

@ -1,4 +1,4 @@
export { trace } from './logging';
export { trace, log } from './logging';
export {
Resolver,
ResolverListener,

View File

@ -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) {

View File

@ -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();

View File

@ -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 {

View File

@ -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() {

View File

@ -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:

View File

@ -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() {

View File

@ -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;

View File

@ -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(

View File

@ -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 */

View File

@ -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,

View File

@ -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'

View File

@ -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();
}
}

View File

@ -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);
}
/**

View File

@ -25,6 +25,7 @@ message Request {
message Response {
int32 count = 1;
string message = 2;
}
service TestService {

View File

@ -3,8 +3,10 @@
export interface Response {
'count'?: (number);
'message'?: (string);
}
export interface Response__Output {
'count': (number);
'message': (string);
}

View File

@ -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;
}

View File

@ -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);
});
});

View File

@ -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();
});
});
});
});

View File

@ -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;

View File

@ -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 => {

View File

@ -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

View File

@ -6,7 +6,8 @@
"target": "es2017",
"module": "commonjs",
"resolveJsonModule": true,
"incremental": true
"incremental": true,
"types": ["mocha"]
},
"include": [
"src/**/*.ts",

View File

@ -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

View File

@ -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/",

View File

@ -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

View File

@ -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...')

View File

@ -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.
*/

View File

@ -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

View File

@ -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

View File

@ -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.
*/

View File

@ -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.
*/

View File

@ -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.
*/

View File

@ -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.
*/

View File

@ -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.
*/

View File

@ -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.

View File

@ -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.

View File

@ -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>
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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)[];
}

View File

@ -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);
}

View File

@ -1,8 +1,8 @@
// Original file: null
export interface Empty {
export interface IEmpty {
}
export interface Empty__Output {
export interface OEmpty {
}

View File

@ -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);
}

View File

@ -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)[];
}

View File

@ -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);
}

View File

@ -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)[];
}

View File

@ -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);
}

View File

@ -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)[];
}

View File

@ -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);

View File

@ -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)[];
}

View File

@ -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)[];
}

View File

@ -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)[];
}

View File

@ -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)[];
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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)[];
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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)[];
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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)[];
}

View File

@ -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";
}

View File

@ -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.

View File

@ -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>
}

View File

@ -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.
*/

View File

@ -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.
*/

View File

@ -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);
}

View File

@ -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.
*/

View File

@ -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.
*/

View File

@ -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);
}

View File

@ -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";
}

View File

@ -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.
*/

View File

@ -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