Merge pull request #3001 from murgatroid99/grpc-js-xds_wrr

grpc-js-xds: Register weighted_round_robin as a custom LB policy
This commit is contained in:
Michael Lumish 2025-08-27 10:54:52 -07:00 committed by GitHub
commit 9d601da651
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 482 additions and 159 deletions

View File

@ -72,6 +72,7 @@ const runTests = checkTask(() => {
process.env.GRPC_EXPERIMENTAL_XDS_FEDERATION = 'true';
process.env.GRPC_EXPERIMENTAL_PICKFIRST_LB_CONFIG = 'true';
process.env.GRPC_XDS_EXPERIMENTAL_RBAC = 'true';
process.env.GRPC_EXPERIMENTAL_XDS_WRR_LB = 'true';
if (Number(process.versions.node.split('.')[0]) <= 14) {
process.env.GRPC_XDS_EXPERIMENTAL_ENABLE_RING_HASH = 'false';
}

View File

@ -12,7 +12,7 @@
"prepare": "npm run generate-types && npm run generate-interop-types && npm run generate-test-types && npm run compile",
"pretest": "npm run compile",
"posttest": "npm run check",
"generate-types": "proto-loader-gen-types --keepCase --longs String --enums String --defaults --oneofs --includeComments --includeDirs deps/envoy-api/ deps/xds/ deps/googleapis/ deps/protoc-gen-validate/ -O src/generated/ --grpcLib @grpc/grpc-js envoy/service/discovery/v3/ads.proto envoy/service/load_stats/v3/lrs.proto envoy/config/listener/v3/listener.proto envoy/config/route/v3/route.proto envoy/config/cluster/v3/cluster.proto envoy/config/endpoint/v3/endpoint.proto envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto udpa/type/v1/typed_struct.proto xds/type/v3/typed_struct.proto envoy/extensions/filters/http/fault/v3/fault.proto envoy/service/status/v3/csds.proto envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.proto envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.proto envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.proto envoy/extensions/clusters/aggregate/v3/cluster.proto envoy/extensions/transport_sockets/tls/v3/tls.proto envoy/config/rbac/v3/rbac.proto envoy/extensions/filters/http/rbac/v3/rbac.proto",
"generate-types": "proto-loader-gen-types --keepCase --longs String --enums String --defaults --oneofs --includeComments --includeDirs deps/envoy-api/ deps/xds/ deps/googleapis/ deps/protoc-gen-validate/ -O src/generated/ --grpcLib @grpc/grpc-js envoy/service/discovery/v3/ads.proto envoy/service/load_stats/v3/lrs.proto envoy/config/listener/v3/listener.proto envoy/config/route/v3/route.proto envoy/config/cluster/v3/cluster.proto envoy/config/endpoint/v3/endpoint.proto envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto udpa/type/v1/typed_struct.proto xds/type/v3/typed_struct.proto envoy/extensions/filters/http/fault/v3/fault.proto envoy/service/status/v3/csds.proto envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.proto envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.proto envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.proto envoy/extensions/clusters/aggregate/v3/cluster.proto envoy/extensions/transport_sockets/tls/v3/tls.proto envoy/config/rbac/v3/rbac.proto envoy/extensions/filters/http/rbac/v3/rbac.proto envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.proto",
"generate-interop-types": "proto-loader-gen-types --keep-case --longs String --enums String --defaults --oneofs --json --includeComments --includeDirs proto/ -O interop/generated --grpcLib @grpc/grpc-js grpc/testing/test.proto",
"generate-test-types": "proto-loader-gen-types --keep-case --longs String --enums String --defaults --oneofs --json --includeComments --includeDirs proto/ -O test/generated --grpcLib @grpc/grpc-js grpc/testing/echo.proto"
},

View File

@ -28,3 +28,4 @@ export const EXPERIMENTAL_PICK_FIRST = (process.env.GRPC_EXPERIMENTAL_PICKFIRST_
export const EXPERIMENTAL_DUALSTACK_ENDPOINTS = (process.env.GRPC_EXPERIMENTAL_XDS_DUALSTACK_ENDPOINTS ?? 'true') === 'true';
export const AGGREGATE_CLUSTER_BACKWARDS_COMPAT = (process.env.GRPC_XDS_AGGREGATE_CLUSTER_BACKWARD_COMPAT ?? 'false') === 'true';
export const EXPERIMENTAL_RBAC = (process.env.GRPC_XDS_EXPERIMENTAL_RBAC ?? 'false') === 'true';
export const EXPERIMENTAL_WRR_LB = (process.env.GRPC_EXPERIMENTAL_XDS_WRR_LB ?? 'false') === 'true';

View File

@ -0,0 +1,153 @@
import type * as grpc from '@grpc/grpc-js';
import type { EnumTypeDefinition, MessageTypeDefinition } from '@grpc/proto-loader';
import type { ClientSideWeightedRoundRobin as _envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_v3_ClientSideWeightedRoundRobin, ClientSideWeightedRoundRobin__Output as _envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_v3_ClientSideWeightedRoundRobin__Output } from './envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/ClientSideWeightedRoundRobin';
import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from './google/protobuf/BoolValue';
import type { BytesValue as _google_protobuf_BytesValue, BytesValue__Output as _google_protobuf_BytesValue__Output } from './google/protobuf/BytesValue';
import type { DescriptorProto as _google_protobuf_DescriptorProto, DescriptorProto__Output as _google_protobuf_DescriptorProto__Output } from './google/protobuf/DescriptorProto';
import type { DoubleValue as _google_protobuf_DoubleValue, DoubleValue__Output as _google_protobuf_DoubleValue__Output } from './google/protobuf/DoubleValue';
import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from './google/protobuf/Duration';
import type { EnumDescriptorProto as _google_protobuf_EnumDescriptorProto, EnumDescriptorProto__Output as _google_protobuf_EnumDescriptorProto__Output } from './google/protobuf/EnumDescriptorProto';
import type { EnumOptions as _google_protobuf_EnumOptions, EnumOptions__Output as _google_protobuf_EnumOptions__Output } from './google/protobuf/EnumOptions';
import type { EnumValueDescriptorProto as _google_protobuf_EnumValueDescriptorProto, EnumValueDescriptorProto__Output as _google_protobuf_EnumValueDescriptorProto__Output } from './google/protobuf/EnumValueDescriptorProto';
import type { EnumValueOptions as _google_protobuf_EnumValueOptions, EnumValueOptions__Output as _google_protobuf_EnumValueOptions__Output } from './google/protobuf/EnumValueOptions';
import type { ExtensionRangeOptions as _google_protobuf_ExtensionRangeOptions, ExtensionRangeOptions__Output as _google_protobuf_ExtensionRangeOptions__Output } from './google/protobuf/ExtensionRangeOptions';
import type { FeatureSet as _google_protobuf_FeatureSet, FeatureSet__Output as _google_protobuf_FeatureSet__Output } from './google/protobuf/FeatureSet';
import type { FeatureSetDefaults as _google_protobuf_FeatureSetDefaults, FeatureSetDefaults__Output as _google_protobuf_FeatureSetDefaults__Output } from './google/protobuf/FeatureSetDefaults';
import type { FieldDescriptorProto as _google_protobuf_FieldDescriptorProto, FieldDescriptorProto__Output as _google_protobuf_FieldDescriptorProto__Output } from './google/protobuf/FieldDescriptorProto';
import type { FieldOptions as _google_protobuf_FieldOptions, FieldOptions__Output as _google_protobuf_FieldOptions__Output } from './google/protobuf/FieldOptions';
import type { FileDescriptorProto as _google_protobuf_FileDescriptorProto, FileDescriptorProto__Output as _google_protobuf_FileDescriptorProto__Output } from './google/protobuf/FileDescriptorProto';
import type { FileDescriptorSet as _google_protobuf_FileDescriptorSet, FileDescriptorSet__Output as _google_protobuf_FileDescriptorSet__Output } from './google/protobuf/FileDescriptorSet';
import type { FileOptions as _google_protobuf_FileOptions, FileOptions__Output as _google_protobuf_FileOptions__Output } from './google/protobuf/FileOptions';
import type { FloatValue as _google_protobuf_FloatValue, FloatValue__Output as _google_protobuf_FloatValue__Output } from './google/protobuf/FloatValue';
import type { GeneratedCodeInfo as _google_protobuf_GeneratedCodeInfo, GeneratedCodeInfo__Output as _google_protobuf_GeneratedCodeInfo__Output } from './google/protobuf/GeneratedCodeInfo';
import type { Int32Value as _google_protobuf_Int32Value, Int32Value__Output as _google_protobuf_Int32Value__Output } from './google/protobuf/Int32Value';
import type { Int64Value as _google_protobuf_Int64Value, Int64Value__Output as _google_protobuf_Int64Value__Output } from './google/protobuf/Int64Value';
import type { MessageOptions as _google_protobuf_MessageOptions, MessageOptions__Output as _google_protobuf_MessageOptions__Output } from './google/protobuf/MessageOptions';
import type { MethodDescriptorProto as _google_protobuf_MethodDescriptorProto, MethodDescriptorProto__Output as _google_protobuf_MethodDescriptorProto__Output } from './google/protobuf/MethodDescriptorProto';
import type { MethodOptions as _google_protobuf_MethodOptions, MethodOptions__Output as _google_protobuf_MethodOptions__Output } from './google/protobuf/MethodOptions';
import type { OneofDescriptorProto as _google_protobuf_OneofDescriptorProto, OneofDescriptorProto__Output as _google_protobuf_OneofDescriptorProto__Output } from './google/protobuf/OneofDescriptorProto';
import type { OneofOptions as _google_protobuf_OneofOptions, OneofOptions__Output as _google_protobuf_OneofOptions__Output } from './google/protobuf/OneofOptions';
import type { ServiceDescriptorProto as _google_protobuf_ServiceDescriptorProto, ServiceDescriptorProto__Output as _google_protobuf_ServiceDescriptorProto__Output } from './google/protobuf/ServiceDescriptorProto';
import type { ServiceOptions as _google_protobuf_ServiceOptions, ServiceOptions__Output as _google_protobuf_ServiceOptions__Output } from './google/protobuf/ServiceOptions';
import type { SourceCodeInfo as _google_protobuf_SourceCodeInfo, SourceCodeInfo__Output as _google_protobuf_SourceCodeInfo__Output } from './google/protobuf/SourceCodeInfo';
import type { StringValue as _google_protobuf_StringValue, StringValue__Output as _google_protobuf_StringValue__Output } from './google/protobuf/StringValue';
import type { Timestamp as _google_protobuf_Timestamp, Timestamp__Output as _google_protobuf_Timestamp__Output } from './google/protobuf/Timestamp';
import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from './google/protobuf/UInt32Value';
import type { UInt64Value as _google_protobuf_UInt64Value, UInt64Value__Output as _google_protobuf_UInt64Value__Output } from './google/protobuf/UInt64Value';
import type { UninterpretedOption as _google_protobuf_UninterpretedOption, UninterpretedOption__Output as _google_protobuf_UninterpretedOption__Output } from './google/protobuf/UninterpretedOption';
import type { StatusAnnotation as _udpa_annotations_StatusAnnotation, StatusAnnotation__Output as _udpa_annotations_StatusAnnotation__Output } from './udpa/annotations/StatusAnnotation';
import type { AnyRules as _validate_AnyRules, AnyRules__Output as _validate_AnyRules__Output } from './validate/AnyRules';
import type { BoolRules as _validate_BoolRules, BoolRules__Output as _validate_BoolRules__Output } from './validate/BoolRules';
import type { BytesRules as _validate_BytesRules, BytesRules__Output as _validate_BytesRules__Output } from './validate/BytesRules';
import type { DoubleRules as _validate_DoubleRules, DoubleRules__Output as _validate_DoubleRules__Output } from './validate/DoubleRules';
import type { DurationRules as _validate_DurationRules, DurationRules__Output as _validate_DurationRules__Output } from './validate/DurationRules';
import type { EnumRules as _validate_EnumRules, EnumRules__Output as _validate_EnumRules__Output } from './validate/EnumRules';
import type { FieldRules as _validate_FieldRules, FieldRules__Output as _validate_FieldRules__Output } from './validate/FieldRules';
import type { Fixed32Rules as _validate_Fixed32Rules, Fixed32Rules__Output as _validate_Fixed32Rules__Output } from './validate/Fixed32Rules';
import type { Fixed64Rules as _validate_Fixed64Rules, Fixed64Rules__Output as _validate_Fixed64Rules__Output } from './validate/Fixed64Rules';
import type { FloatRules as _validate_FloatRules, FloatRules__Output as _validate_FloatRules__Output } from './validate/FloatRules';
import type { Int32Rules as _validate_Int32Rules, Int32Rules__Output as _validate_Int32Rules__Output } from './validate/Int32Rules';
import type { Int64Rules as _validate_Int64Rules, Int64Rules__Output as _validate_Int64Rules__Output } from './validate/Int64Rules';
import type { MapRules as _validate_MapRules, MapRules__Output as _validate_MapRules__Output } from './validate/MapRules';
import type { MessageRules as _validate_MessageRules, MessageRules__Output as _validate_MessageRules__Output } from './validate/MessageRules';
import type { RepeatedRules as _validate_RepeatedRules, RepeatedRules__Output as _validate_RepeatedRules__Output } from './validate/RepeatedRules';
import type { SFixed32Rules as _validate_SFixed32Rules, SFixed32Rules__Output as _validate_SFixed32Rules__Output } from './validate/SFixed32Rules';
import type { SFixed64Rules as _validate_SFixed64Rules, SFixed64Rules__Output as _validate_SFixed64Rules__Output } from './validate/SFixed64Rules';
import type { SInt32Rules as _validate_SInt32Rules, SInt32Rules__Output as _validate_SInt32Rules__Output } from './validate/SInt32Rules';
import type { SInt64Rules as _validate_SInt64Rules, SInt64Rules__Output as _validate_SInt64Rules__Output } from './validate/SInt64Rules';
import type { StringRules as _validate_StringRules, StringRules__Output as _validate_StringRules__Output } from './validate/StringRules';
import type { TimestampRules as _validate_TimestampRules, TimestampRules__Output as _validate_TimestampRules__Output } from './validate/TimestampRules';
import type { UInt32Rules as _validate_UInt32Rules, UInt32Rules__Output as _validate_UInt32Rules__Output } from './validate/UInt32Rules';
import type { UInt64Rules as _validate_UInt64Rules, UInt64Rules__Output as _validate_UInt64Rules__Output } from './validate/UInt64Rules';
type SubtypeConstructor<Constructor extends new (...args: any) => any, Subtype> = {
new(...args: ConstructorParameters<Constructor>): Subtype;
};
export interface ProtoGrpcType {
envoy: {
extensions: {
load_balancing_policies: {
client_side_weighted_round_robin: {
v3: {
ClientSideWeightedRoundRobin: MessageTypeDefinition<_envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_v3_ClientSideWeightedRoundRobin, _envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_v3_ClientSideWeightedRoundRobin__Output>
}
}
}
}
}
google: {
protobuf: {
BoolValue: MessageTypeDefinition<_google_protobuf_BoolValue, _google_protobuf_BoolValue__Output>
BytesValue: MessageTypeDefinition<_google_protobuf_BytesValue, _google_protobuf_BytesValue__Output>
DescriptorProto: MessageTypeDefinition<_google_protobuf_DescriptorProto, _google_protobuf_DescriptorProto__Output>
DoubleValue: MessageTypeDefinition<_google_protobuf_DoubleValue, _google_protobuf_DoubleValue__Output>
Duration: MessageTypeDefinition<_google_protobuf_Duration, _google_protobuf_Duration__Output>
Edition: EnumTypeDefinition
EnumDescriptorProto: MessageTypeDefinition<_google_protobuf_EnumDescriptorProto, _google_protobuf_EnumDescriptorProto__Output>
EnumOptions: MessageTypeDefinition<_google_protobuf_EnumOptions, _google_protobuf_EnumOptions__Output>
EnumValueDescriptorProto: MessageTypeDefinition<_google_protobuf_EnumValueDescriptorProto, _google_protobuf_EnumValueDescriptorProto__Output>
EnumValueOptions: MessageTypeDefinition<_google_protobuf_EnumValueOptions, _google_protobuf_EnumValueOptions__Output>
ExtensionRangeOptions: MessageTypeDefinition<_google_protobuf_ExtensionRangeOptions, _google_protobuf_ExtensionRangeOptions__Output>
FeatureSet: MessageTypeDefinition<_google_protobuf_FeatureSet, _google_protobuf_FeatureSet__Output>
FeatureSetDefaults: MessageTypeDefinition<_google_protobuf_FeatureSetDefaults, _google_protobuf_FeatureSetDefaults__Output>
FieldDescriptorProto: MessageTypeDefinition<_google_protobuf_FieldDescriptorProto, _google_protobuf_FieldDescriptorProto__Output>
FieldOptions: MessageTypeDefinition<_google_protobuf_FieldOptions, _google_protobuf_FieldOptions__Output>
FileDescriptorProto: MessageTypeDefinition<_google_protobuf_FileDescriptorProto, _google_protobuf_FileDescriptorProto__Output>
FileDescriptorSet: MessageTypeDefinition<_google_protobuf_FileDescriptorSet, _google_protobuf_FileDescriptorSet__Output>
FileOptions: MessageTypeDefinition<_google_protobuf_FileOptions, _google_protobuf_FileOptions__Output>
FloatValue: MessageTypeDefinition<_google_protobuf_FloatValue, _google_protobuf_FloatValue__Output>
GeneratedCodeInfo: MessageTypeDefinition<_google_protobuf_GeneratedCodeInfo, _google_protobuf_GeneratedCodeInfo__Output>
Int32Value: MessageTypeDefinition<_google_protobuf_Int32Value, _google_protobuf_Int32Value__Output>
Int64Value: MessageTypeDefinition<_google_protobuf_Int64Value, _google_protobuf_Int64Value__Output>
MessageOptions: MessageTypeDefinition<_google_protobuf_MessageOptions, _google_protobuf_MessageOptions__Output>
MethodDescriptorProto: MessageTypeDefinition<_google_protobuf_MethodDescriptorProto, _google_protobuf_MethodDescriptorProto__Output>
MethodOptions: MessageTypeDefinition<_google_protobuf_MethodOptions, _google_protobuf_MethodOptions__Output>
OneofDescriptorProto: MessageTypeDefinition<_google_protobuf_OneofDescriptorProto, _google_protobuf_OneofDescriptorProto__Output>
OneofOptions: MessageTypeDefinition<_google_protobuf_OneofOptions, _google_protobuf_OneofOptions__Output>
ServiceDescriptorProto: MessageTypeDefinition<_google_protobuf_ServiceDescriptorProto, _google_protobuf_ServiceDescriptorProto__Output>
ServiceOptions: MessageTypeDefinition<_google_protobuf_ServiceOptions, _google_protobuf_ServiceOptions__Output>
SourceCodeInfo: MessageTypeDefinition<_google_protobuf_SourceCodeInfo, _google_protobuf_SourceCodeInfo__Output>
StringValue: MessageTypeDefinition<_google_protobuf_StringValue, _google_protobuf_StringValue__Output>
SymbolVisibility: EnumTypeDefinition
Timestamp: MessageTypeDefinition<_google_protobuf_Timestamp, _google_protobuf_Timestamp__Output>
UInt32Value: MessageTypeDefinition<_google_protobuf_UInt32Value, _google_protobuf_UInt32Value__Output>
UInt64Value: MessageTypeDefinition<_google_protobuf_UInt64Value, _google_protobuf_UInt64Value__Output>
UninterpretedOption: MessageTypeDefinition<_google_protobuf_UninterpretedOption, _google_protobuf_UninterpretedOption__Output>
}
}
udpa: {
annotations: {
PackageVersionStatus: EnumTypeDefinition
StatusAnnotation: MessageTypeDefinition<_udpa_annotations_StatusAnnotation, _udpa_annotations_StatusAnnotation__Output>
}
}
validate: {
AnyRules: MessageTypeDefinition<_validate_AnyRules, _validate_AnyRules__Output>
BoolRules: MessageTypeDefinition<_validate_BoolRules, _validate_BoolRules__Output>
BytesRules: MessageTypeDefinition<_validate_BytesRules, _validate_BytesRules__Output>
DoubleRules: MessageTypeDefinition<_validate_DoubleRules, _validate_DoubleRules__Output>
DurationRules: MessageTypeDefinition<_validate_DurationRules, _validate_DurationRules__Output>
EnumRules: MessageTypeDefinition<_validate_EnumRules, _validate_EnumRules__Output>
FieldRules: MessageTypeDefinition<_validate_FieldRules, _validate_FieldRules__Output>
Fixed32Rules: MessageTypeDefinition<_validate_Fixed32Rules, _validate_Fixed32Rules__Output>
Fixed64Rules: MessageTypeDefinition<_validate_Fixed64Rules, _validate_Fixed64Rules__Output>
FloatRules: MessageTypeDefinition<_validate_FloatRules, _validate_FloatRules__Output>
Int32Rules: MessageTypeDefinition<_validate_Int32Rules, _validate_Int32Rules__Output>
Int64Rules: MessageTypeDefinition<_validate_Int64Rules, _validate_Int64Rules__Output>
KnownRegex: EnumTypeDefinition
MapRules: MessageTypeDefinition<_validate_MapRules, _validate_MapRules__Output>
MessageRules: MessageTypeDefinition<_validate_MessageRules, _validate_MessageRules__Output>
RepeatedRules: MessageTypeDefinition<_validate_RepeatedRules, _validate_RepeatedRules__Output>
SFixed32Rules: MessageTypeDefinition<_validate_SFixed32Rules, _validate_SFixed32Rules__Output>
SFixed64Rules: MessageTypeDefinition<_validate_SFixed64Rules, _validate_SFixed64Rules__Output>
SInt32Rules: MessageTypeDefinition<_validate_SInt32Rules, _validate_SInt32Rules__Output>
SInt64Rules: MessageTypeDefinition<_validate_SInt64Rules, _validate_SInt64Rules__Output>
StringRules: MessageTypeDefinition<_validate_StringRules, _validate_StringRules__Output>
TimestampRules: MessageTypeDefinition<_validate_TimestampRules, _validate_TimestampRules__Output>
UInt32Rules: MessageTypeDefinition<_validate_UInt32Rules, _validate_UInt32Rules__Output>
UInt64Rules: MessageTypeDefinition<_validate_UInt64Rules, _validate_UInt64Rules__Output>
}
}

View File

@ -0,0 +1,129 @@
// Original file: deps/envoy-api/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.proto
import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../../google/protobuf/BoolValue';
import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../../../google/protobuf/Duration';
import type { FloatValue as _google_protobuf_FloatValue, FloatValue__Output as _google_protobuf_FloatValue__Output } from '../../../../../google/protobuf/FloatValue';
/**
* Configuration for the client_side_weighted_round_robin LB policy.
*
* This policy differs from the built-in ROUND_ROBIN policy in terms of
* how the endpoint weights are determined. In the ROUND_ROBIN policy,
* the endpoint weights are sent by the control plane via EDS. However,
* in this policy, the endpoint weights are instead determined via qps (queries
* per second), eps (errors per second), and utilization metrics sent by the
* endpoint using the Open Request Cost Aggregation (ORCA) protocol. Utilization
* is determined by using the ORCA application_utilization field, if set, or
* else falling back to the cpu_utilization field. All queries count toward qps,
* regardless of result. Only failed queries count toward eps. A config
* parameter error_utilization_penalty controls the penalty to adjust endpoint
* weights using eps and qps. The weight of a given endpoint is computed as:
* qps / (utilization + eps/qps * error_utilization_penalty)
*
* See the :ref:`load balancing architecture overview<arch_overview_load_balancing_types>` for more information.
*
* [#next-free-field: 7]
*/
export interface ClientSideWeightedRoundRobin {
/**
* Whether to enable out-of-band utilization reporting collection from
* the endpoints. By default, per-request utilization reporting is used.
*/
'enable_oob_load_report'?: (_google_protobuf_BoolValue | null);
/**
* Load reporting interval to request from the server. Note that the
* server may not provide reports as frequently as the client requests.
* Used only when enable_oob_load_report is true. Default is 10 seconds.
*/
'oob_reporting_period'?: (_google_protobuf_Duration | null);
/**
* A given endpoint must report load metrics continuously for at least
* this long before the endpoint weight will be used. This avoids
* churn when the set of endpoint addresses changes. Takes effect
* both immediately after we establish a connection to an endpoint and
* after weight_expiration_period has caused us to stop using the most
* recent load metrics. Default is 10 seconds.
*/
'blackout_period'?: (_google_protobuf_Duration | null);
/**
* If a given endpoint has not reported load metrics in this long,
* then we stop using the reported weight. This ensures that we do
* not continue to use very stale weights. Once we stop using a stale
* value, if we later start seeing fresh reports again, the
* blackout_period applies. Defaults to 3 minutes.
*/
'weight_expiration_period'?: (_google_protobuf_Duration | null);
/**
* How often endpoint weights are recalculated. Values less than 100ms are
* capped at 100ms. Default is 1 second.
*/
'weight_update_period'?: (_google_protobuf_Duration | null);
/**
* The multiplier used to adjust endpoint weights with the error rate
* calculated as eps/qps. Configuration is rejected if this value is negative.
* Default is 1.0.
*/
'error_utilization_penalty'?: (_google_protobuf_FloatValue | null);
}
/**
* Configuration for the client_side_weighted_round_robin LB policy.
*
* This policy differs from the built-in ROUND_ROBIN policy in terms of
* how the endpoint weights are determined. In the ROUND_ROBIN policy,
* the endpoint weights are sent by the control plane via EDS. However,
* in this policy, the endpoint weights are instead determined via qps (queries
* per second), eps (errors per second), and utilization metrics sent by the
* endpoint using the Open Request Cost Aggregation (ORCA) protocol. Utilization
* is determined by using the ORCA application_utilization field, if set, or
* else falling back to the cpu_utilization field. All queries count toward qps,
* regardless of result. Only failed queries count toward eps. A config
* parameter error_utilization_penalty controls the penalty to adjust endpoint
* weights using eps and qps. The weight of a given endpoint is computed as:
* qps / (utilization + eps/qps * error_utilization_penalty)
*
* See the :ref:`load balancing architecture overview<arch_overview_load_balancing_types>` for more information.
*
* [#next-free-field: 7]
*/
export interface ClientSideWeightedRoundRobin__Output {
/**
* Whether to enable out-of-band utilization reporting collection from
* the endpoints. By default, per-request utilization reporting is used.
*/
'enable_oob_load_report': (_google_protobuf_BoolValue__Output | null);
/**
* Load reporting interval to request from the server. Note that the
* server may not provide reports as frequently as the client requests.
* Used only when enable_oob_load_report is true. Default is 10 seconds.
*/
'oob_reporting_period': (_google_protobuf_Duration__Output | null);
/**
* A given endpoint must report load metrics continuously for at least
* this long before the endpoint weight will be used. This avoids
* churn when the set of endpoint addresses changes. Takes effect
* both immediately after we establish a connection to an endpoint and
* after weight_expiration_period has caused us to stop using the most
* recent load metrics. Default is 10 seconds.
*/
'blackout_period': (_google_protobuf_Duration__Output | null);
/**
* If a given endpoint has not reported load metrics in this long,
* then we stop using the reported weight. This ensures that we do
* not continue to use very stale weights. Once we stop using a stale
* value, if we later start seeing fresh reports again, the
* blackout_period applies. Defaults to 3 minutes.
*/
'weight_expiration_period': (_google_protobuf_Duration__Output | null);
/**
* How often endpoint weights are recalculated. Values less than 100ms are
* capped at 100ms. Default is 1 second.
*/
'weight_update_period': (_google_protobuf_Duration__Output | null);
/**
* The multiplier used to adjust endpoint weights with the error rate
* calculated as eps/qps. Configuration is rejected if this value is negative.
* Default is 1.0.
*/
'error_utilization_penalty': (_google_protobuf_FloatValue__Output | null);
}

View File

@ -2,7 +2,6 @@
import type { FeatureSet as _google_protobuf_FeatureSet, FeatureSet__Output as _google_protobuf_FeatureSet__Output } from '../../google/protobuf/FeatureSet';
import type { UninterpretedOption as _google_protobuf_UninterpretedOption, UninterpretedOption__Output as _google_protobuf_UninterpretedOption__Output } from '../../google/protobuf/UninterpretedOption';
import type { MigrateAnnotation as _udpa_annotations_MigrateAnnotation, MigrateAnnotation__Output as _udpa_annotations_MigrateAnnotation__Output } from '../../udpa/annotations/MigrateAnnotation';
export interface EnumOptions {
'allowAlias'?: (boolean);
@ -13,7 +12,6 @@ export interface EnumOptions {
'deprecatedLegacyJsonFieldConflicts'?: (boolean);
'features'?: (_google_protobuf_FeatureSet | null);
'uninterpretedOption'?: (_google_protobuf_UninterpretedOption)[];
'.udpa.annotations.enum_migrate'?: (_udpa_annotations_MigrateAnnotation | null);
}
export interface EnumOptions__Output {
@ -25,5 +23,4 @@ export interface EnumOptions__Output {
'deprecatedLegacyJsonFieldConflicts': (boolean);
'features': (_google_protobuf_FeatureSet__Output | null);
'uninterpretedOption': (_google_protobuf_UninterpretedOption__Output)[];
'.udpa.annotations.enum_migrate': (_udpa_annotations_MigrateAnnotation__Output | null);
}

View File

@ -3,7 +3,6 @@
import type { FeatureSet as _google_protobuf_FeatureSet, FeatureSet__Output as _google_protobuf_FeatureSet__Output } from '../../google/protobuf/FeatureSet';
import type { _google_protobuf_FieldOptions_FeatureSupport, _google_protobuf_FieldOptions_FeatureSupport__Output } from '../../google/protobuf/FieldOptions';
import type { UninterpretedOption as _google_protobuf_UninterpretedOption, UninterpretedOption__Output as _google_protobuf_UninterpretedOption__Output } from '../../google/protobuf/UninterpretedOption';
import type { MigrateAnnotation as _udpa_annotations_MigrateAnnotation, MigrateAnnotation__Output as _udpa_annotations_MigrateAnnotation__Output } from '../../udpa/annotations/MigrateAnnotation';
export interface EnumValueOptions {
'deprecated'?: (boolean);
@ -11,9 +10,6 @@ export interface EnumValueOptions {
'debugRedact'?: (boolean);
'featureSupport'?: (_google_protobuf_FieldOptions_FeatureSupport | null);
'uninterpretedOption'?: (_google_protobuf_UninterpretedOption)[];
'.envoy.annotations.disallowed_by_default_enum'?: (boolean);
'.udpa.annotations.enum_value_migrate'?: (_udpa_annotations_MigrateAnnotation | null);
'.envoy.annotations.deprecated_at_minor_version_enum'?: (string);
}
export interface EnumValueOptions__Output {
@ -22,7 +18,4 @@ export interface EnumValueOptions__Output {
'debugRedact': (boolean);
'featureSupport': (_google_protobuf_FieldOptions_FeatureSupport__Output | null);
'uninterpretedOption': (_google_protobuf_UninterpretedOption__Output)[];
'.envoy.annotations.disallowed_by_default_enum': (boolean);
'.udpa.annotations.enum_value_migrate': (_udpa_annotations_MigrateAnnotation__Output | null);
'.envoy.annotations.deprecated_at_minor_version_enum': (string);
}

View File

@ -3,8 +3,6 @@
import type { FeatureSet as _google_protobuf_FeatureSet, FeatureSet__Output as _google_protobuf_FeatureSet__Output } from '../../google/protobuf/FeatureSet';
import type { UninterpretedOption as _google_protobuf_UninterpretedOption, UninterpretedOption__Output as _google_protobuf_UninterpretedOption__Output } from '../../google/protobuf/UninterpretedOption';
import type { FieldRules as _validate_FieldRules, FieldRules__Output as _validate_FieldRules__Output } from '../../validate/FieldRules';
import type { FieldMigrateAnnotation as _udpa_annotations_FieldMigrateAnnotation, FieldMigrateAnnotation__Output as _udpa_annotations_FieldMigrateAnnotation__Output } from '../../udpa/annotations/FieldMigrateAnnotation';
import type { FieldStatusAnnotation as _xds_annotations_v3_FieldStatusAnnotation, FieldStatusAnnotation__Output as _xds_annotations_v3_FieldStatusAnnotation__Output } from '../../xds/annotations/v3/FieldStatusAnnotation';
import type { Edition as _google_protobuf_Edition, Edition__Output as _google_protobuf_Edition__Output } from '../../google/protobuf/Edition';
// Original file: null
@ -143,10 +141,6 @@ export interface FieldOptions {
'featureSupport'?: (_google_protobuf_FieldOptions_FeatureSupport | null);
'uninterpretedOption'?: (_google_protobuf_UninterpretedOption)[];
'.validate.rules'?: (_validate_FieldRules | null);
'.envoy.annotations.deprecated_at_minor_version'?: (string);
'.udpa.annotations.field_migrate'?: (_udpa_annotations_FieldMigrateAnnotation | null);
'.envoy.annotations.disallowed_by_default'?: (boolean);
'.xds.annotations.v3.field_status'?: (_xds_annotations_v3_FieldStatusAnnotation | null);
}
export interface FieldOptions__Output {
@ -168,8 +162,4 @@ export interface FieldOptions__Output {
'featureSupport': (_google_protobuf_FieldOptions_FeatureSupport__Output | null);
'uninterpretedOption': (_google_protobuf_UninterpretedOption__Output)[];
'.validate.rules': (_validate_FieldRules__Output | null);
'.envoy.annotations.deprecated_at_minor_version': (string);
'.udpa.annotations.field_migrate': (_udpa_annotations_FieldMigrateAnnotation__Output | null);
'.envoy.annotations.disallowed_by_default': (boolean);
'.xds.annotations.v3.field_status': (_xds_annotations_v3_FieldStatusAnnotation__Output | null);
}

View File

@ -2,9 +2,7 @@
import type { FeatureSet as _google_protobuf_FeatureSet, FeatureSet__Output as _google_protobuf_FeatureSet__Output } from '../../google/protobuf/FeatureSet';
import type { UninterpretedOption as _google_protobuf_UninterpretedOption, UninterpretedOption__Output as _google_protobuf_UninterpretedOption__Output } from '../../google/protobuf/UninterpretedOption';
import type { FileMigrateAnnotation as _udpa_annotations_FileMigrateAnnotation, FileMigrateAnnotation__Output as _udpa_annotations_FileMigrateAnnotation__Output } from '../../udpa/annotations/FileMigrateAnnotation';
import type { StatusAnnotation as _udpa_annotations_StatusAnnotation, StatusAnnotation__Output as _udpa_annotations_StatusAnnotation__Output } from '../../udpa/annotations/StatusAnnotation';
import type { FileStatusAnnotation as _xds_annotations_v3_FileStatusAnnotation, FileStatusAnnotation__Output as _xds_annotations_v3_FileStatusAnnotation__Output } from '../../xds/annotations/v3/FileStatusAnnotation';
// Original file: null
@ -49,9 +47,7 @@ export interface FileOptions {
'rubyPackage'?: (string);
'features'?: (_google_protobuf_FeatureSet | null);
'uninterpretedOption'?: (_google_protobuf_UninterpretedOption)[];
'.udpa.annotations.file_migrate'?: (_udpa_annotations_FileMigrateAnnotation | null);
'.udpa.annotations.file_status'?: (_udpa_annotations_StatusAnnotation | null);
'.xds.annotations.v3.file_status'?: (_xds_annotations_v3_FileStatusAnnotation | null);
}
export interface FileOptions__Output {
@ -79,7 +75,5 @@ export interface FileOptions__Output {
'rubyPackage': (string);
'features': (_google_protobuf_FeatureSet__Output | null);
'uninterpretedOption': (_google_protobuf_UninterpretedOption__Output)[];
'.udpa.annotations.file_migrate': (_udpa_annotations_FileMigrateAnnotation__Output | null);
'.udpa.annotations.file_status': (_udpa_annotations_StatusAnnotation__Output | null);
'.xds.annotations.v3.file_status': (_xds_annotations_v3_FileStatusAnnotation__Output | null);
}

View File

@ -2,9 +2,6 @@
import type { FeatureSet as _google_protobuf_FeatureSet, FeatureSet__Output as _google_protobuf_FeatureSet__Output } from '../../google/protobuf/FeatureSet';
import type { UninterpretedOption as _google_protobuf_UninterpretedOption, UninterpretedOption__Output as _google_protobuf_UninterpretedOption__Output } from '../../google/protobuf/UninterpretedOption';
import type { VersioningAnnotation as _udpa_annotations_VersioningAnnotation, VersioningAnnotation__Output as _udpa_annotations_VersioningAnnotation__Output } from '../../udpa/annotations/VersioningAnnotation';
import type { MigrateAnnotation as _udpa_annotations_MigrateAnnotation, MigrateAnnotation__Output as _udpa_annotations_MigrateAnnotation__Output } from '../../udpa/annotations/MigrateAnnotation';
import type { MessageStatusAnnotation as _xds_annotations_v3_MessageStatusAnnotation, MessageStatusAnnotation__Output as _xds_annotations_v3_MessageStatusAnnotation__Output } from '../../xds/annotations/v3/MessageStatusAnnotation';
export interface MessageOptions {
'messageSetWireFormat'?: (boolean);
@ -18,9 +15,6 @@ export interface MessageOptions {
'features'?: (_google_protobuf_FeatureSet | null);
'uninterpretedOption'?: (_google_protobuf_UninterpretedOption)[];
'.validate.disabled'?: (boolean);
'.udpa.annotations.versioning'?: (_udpa_annotations_VersioningAnnotation | null);
'.udpa.annotations.message_migrate'?: (_udpa_annotations_MigrateAnnotation | null);
'.xds.annotations.v3.message_status'?: (_xds_annotations_v3_MessageStatusAnnotation | null);
}
export interface MessageOptions__Output {
@ -35,7 +29,4 @@ export interface MessageOptions__Output {
'features': (_google_protobuf_FeatureSet__Output | null);
'uninterpretedOption': (_google_protobuf_UninterpretedOption__Output)[];
'.validate.disabled': (boolean);
'.udpa.annotations.versioning': (_udpa_annotations_VersioningAnnotation__Output | null);
'.udpa.annotations.message_migrate': (_udpa_annotations_MigrateAnnotation__Output | null);
'.xds.annotations.v3.message_status': (_xds_annotations_v3_MessageStatusAnnotation__Output | null);
}

View File

@ -1,58 +1,10 @@
import type * as grpc from '@grpc/grpc-js';
import type { EnumTypeDefinition, MessageTypeDefinition } from '@grpc/proto-loader';
import type { DescriptorProto as _google_protobuf_DescriptorProto, DescriptorProto__Output as _google_protobuf_DescriptorProto__Output } from './google/protobuf/DescriptorProto';
import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from './google/protobuf/Duration';
import type { EnumDescriptorProto as _google_protobuf_EnumDescriptorProto, EnumDescriptorProto__Output as _google_protobuf_EnumDescriptorProto__Output } from './google/protobuf/EnumDescriptorProto';
import type { EnumOptions as _google_protobuf_EnumOptions, EnumOptions__Output as _google_protobuf_EnumOptions__Output } from './google/protobuf/EnumOptions';
import type { EnumValueDescriptorProto as _google_protobuf_EnumValueDescriptorProto, EnumValueDescriptorProto__Output as _google_protobuf_EnumValueDescriptorProto__Output } from './google/protobuf/EnumValueDescriptorProto';
import type { EnumValueOptions as _google_protobuf_EnumValueOptions, EnumValueOptions__Output as _google_protobuf_EnumValueOptions__Output } from './google/protobuf/EnumValueOptions';
import type { ExtensionRangeOptions as _google_protobuf_ExtensionRangeOptions, ExtensionRangeOptions__Output as _google_protobuf_ExtensionRangeOptions__Output } from './google/protobuf/ExtensionRangeOptions';
import type { FeatureSet as _google_protobuf_FeatureSet, FeatureSet__Output as _google_protobuf_FeatureSet__Output } from './google/protobuf/FeatureSet';
import type { FeatureSetDefaults as _google_protobuf_FeatureSetDefaults, FeatureSetDefaults__Output as _google_protobuf_FeatureSetDefaults__Output } from './google/protobuf/FeatureSetDefaults';
import type { FieldDescriptorProto as _google_protobuf_FieldDescriptorProto, FieldDescriptorProto__Output as _google_protobuf_FieldDescriptorProto__Output } from './google/protobuf/FieldDescriptorProto';
import type { FieldOptions as _google_protobuf_FieldOptions, FieldOptions__Output as _google_protobuf_FieldOptions__Output } from './google/protobuf/FieldOptions';
import type { FileDescriptorProto as _google_protobuf_FileDescriptorProto, FileDescriptorProto__Output as _google_protobuf_FileDescriptorProto__Output } from './google/protobuf/FileDescriptorProto';
import type { FileDescriptorSet as _google_protobuf_FileDescriptorSet, FileDescriptorSet__Output as _google_protobuf_FileDescriptorSet__Output } from './google/protobuf/FileDescriptorSet';
import type { FileOptions as _google_protobuf_FileOptions, FileOptions__Output as _google_protobuf_FileOptions__Output } from './google/protobuf/FileOptions';
import type { GeneratedCodeInfo as _google_protobuf_GeneratedCodeInfo, GeneratedCodeInfo__Output as _google_protobuf_GeneratedCodeInfo__Output } from './google/protobuf/GeneratedCodeInfo';
import type { ListValue as _google_protobuf_ListValue, ListValue__Output as _google_protobuf_ListValue__Output } from './google/protobuf/ListValue';
import type { MessageOptions as _google_protobuf_MessageOptions, MessageOptions__Output as _google_protobuf_MessageOptions__Output } from './google/protobuf/MessageOptions';
import type { MethodDescriptorProto as _google_protobuf_MethodDescriptorProto, MethodDescriptorProto__Output as _google_protobuf_MethodDescriptorProto__Output } from './google/protobuf/MethodDescriptorProto';
import type { MethodOptions as _google_protobuf_MethodOptions, MethodOptions__Output as _google_protobuf_MethodOptions__Output } from './google/protobuf/MethodOptions';
import type { OneofDescriptorProto as _google_protobuf_OneofDescriptorProto, OneofDescriptorProto__Output as _google_protobuf_OneofDescriptorProto__Output } from './google/protobuf/OneofDescriptorProto';
import type { OneofOptions as _google_protobuf_OneofOptions, OneofOptions__Output as _google_protobuf_OneofOptions__Output } from './google/protobuf/OneofOptions';
import type { ServiceDescriptorProto as _google_protobuf_ServiceDescriptorProto, ServiceDescriptorProto__Output as _google_protobuf_ServiceDescriptorProto__Output } from './google/protobuf/ServiceDescriptorProto';
import type { ServiceOptions as _google_protobuf_ServiceOptions, ServiceOptions__Output as _google_protobuf_ServiceOptions__Output } from './google/protobuf/ServiceOptions';
import type { SourceCodeInfo as _google_protobuf_SourceCodeInfo, SourceCodeInfo__Output as _google_protobuf_SourceCodeInfo__Output } from './google/protobuf/SourceCodeInfo';
import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from './google/protobuf/Struct';
import type { Timestamp as _google_protobuf_Timestamp, Timestamp__Output as _google_protobuf_Timestamp__Output } from './google/protobuf/Timestamp';
import type { UninterpretedOption as _google_protobuf_UninterpretedOption, UninterpretedOption__Output as _google_protobuf_UninterpretedOption__Output } from './google/protobuf/UninterpretedOption';
import type { Value as _google_protobuf_Value, Value__Output as _google_protobuf_Value__Output } from './google/protobuf/Value';
import type { TypedStruct as _udpa_type_v1_TypedStruct, TypedStruct__Output as _udpa_type_v1_TypedStruct__Output } from './udpa/type/v1/TypedStruct';
import type { AnyRules as _validate_AnyRules, AnyRules__Output as _validate_AnyRules__Output } from './validate/AnyRules';
import type { BoolRules as _validate_BoolRules, BoolRules__Output as _validate_BoolRules__Output } from './validate/BoolRules';
import type { BytesRules as _validate_BytesRules, BytesRules__Output as _validate_BytesRules__Output } from './validate/BytesRules';
import type { DoubleRules as _validate_DoubleRules, DoubleRules__Output as _validate_DoubleRules__Output } from './validate/DoubleRules';
import type { DurationRules as _validate_DurationRules, DurationRules__Output as _validate_DurationRules__Output } from './validate/DurationRules';
import type { EnumRules as _validate_EnumRules, EnumRules__Output as _validate_EnumRules__Output } from './validate/EnumRules';
import type { FieldRules as _validate_FieldRules, FieldRules__Output as _validate_FieldRules__Output } from './validate/FieldRules';
import type { Fixed32Rules as _validate_Fixed32Rules, Fixed32Rules__Output as _validate_Fixed32Rules__Output } from './validate/Fixed32Rules';
import type { Fixed64Rules as _validate_Fixed64Rules, Fixed64Rules__Output as _validate_Fixed64Rules__Output } from './validate/Fixed64Rules';
import type { FloatRules as _validate_FloatRules, FloatRules__Output as _validate_FloatRules__Output } from './validate/FloatRules';
import type { Int32Rules as _validate_Int32Rules, Int32Rules__Output as _validate_Int32Rules__Output } from './validate/Int32Rules';
import type { Int64Rules as _validate_Int64Rules, Int64Rules__Output as _validate_Int64Rules__Output } from './validate/Int64Rules';
import type { MapRules as _validate_MapRules, MapRules__Output as _validate_MapRules__Output } from './validate/MapRules';
import type { MessageRules as _validate_MessageRules, MessageRules__Output as _validate_MessageRules__Output } from './validate/MessageRules';
import type { RepeatedRules as _validate_RepeatedRules, RepeatedRules__Output as _validate_RepeatedRules__Output } from './validate/RepeatedRules';
import type { SFixed32Rules as _validate_SFixed32Rules, SFixed32Rules__Output as _validate_SFixed32Rules__Output } from './validate/SFixed32Rules';
import type { SFixed64Rules as _validate_SFixed64Rules, SFixed64Rules__Output as _validate_SFixed64Rules__Output } from './validate/SFixed64Rules';
import type { SInt32Rules as _validate_SInt32Rules, SInt32Rules__Output as _validate_SInt32Rules__Output } from './validate/SInt32Rules';
import type { SInt64Rules as _validate_SInt64Rules, SInt64Rules__Output as _validate_SInt64Rules__Output } from './validate/SInt64Rules';
import type { StringRules as _validate_StringRules, StringRules__Output as _validate_StringRules__Output } from './validate/StringRules';
import type { TimestampRules as _validate_TimestampRules, TimestampRules__Output as _validate_TimestampRules__Output } from './validate/TimestampRules';
import type { UInt32Rules as _validate_UInt32Rules, UInt32Rules__Output as _validate_UInt32Rules__Output } from './validate/UInt32Rules';
import type { UInt64Rules as _validate_UInt64Rules, UInt64Rules__Output as _validate_UInt64Rules__Output } from './validate/UInt64Rules';
import type { TypedStruct as _xds_type_v3_TypedStruct, TypedStruct__Output as _xds_type_v3_TypedStruct__Output } from './xds/type/v3/TypedStruct';
type SubtypeConstructor<Constructor extends new (...args: any) => any, Subtype> = {
@ -62,36 +14,9 @@ type SubtypeConstructor<Constructor extends new (...args: any) => any, Subtype>
export interface ProtoGrpcType {
google: {
protobuf: {
DescriptorProto: MessageTypeDefinition<_google_protobuf_DescriptorProto, _google_protobuf_DescriptorProto__Output>
Duration: MessageTypeDefinition<_google_protobuf_Duration, _google_protobuf_Duration__Output>
Edition: EnumTypeDefinition
EnumDescriptorProto: MessageTypeDefinition<_google_protobuf_EnumDescriptorProto, _google_protobuf_EnumDescriptorProto__Output>
EnumOptions: MessageTypeDefinition<_google_protobuf_EnumOptions, _google_protobuf_EnumOptions__Output>
EnumValueDescriptorProto: MessageTypeDefinition<_google_protobuf_EnumValueDescriptorProto, _google_protobuf_EnumValueDescriptorProto__Output>
EnumValueOptions: MessageTypeDefinition<_google_protobuf_EnumValueOptions, _google_protobuf_EnumValueOptions__Output>
ExtensionRangeOptions: MessageTypeDefinition<_google_protobuf_ExtensionRangeOptions, _google_protobuf_ExtensionRangeOptions__Output>
FeatureSet: MessageTypeDefinition<_google_protobuf_FeatureSet, _google_protobuf_FeatureSet__Output>
FeatureSetDefaults: MessageTypeDefinition<_google_protobuf_FeatureSetDefaults, _google_protobuf_FeatureSetDefaults__Output>
FieldDescriptorProto: MessageTypeDefinition<_google_protobuf_FieldDescriptorProto, _google_protobuf_FieldDescriptorProto__Output>
FieldOptions: MessageTypeDefinition<_google_protobuf_FieldOptions, _google_protobuf_FieldOptions__Output>
FileDescriptorProto: MessageTypeDefinition<_google_protobuf_FileDescriptorProto, _google_protobuf_FileDescriptorProto__Output>
FileDescriptorSet: MessageTypeDefinition<_google_protobuf_FileDescriptorSet, _google_protobuf_FileDescriptorSet__Output>
FileOptions: MessageTypeDefinition<_google_protobuf_FileOptions, _google_protobuf_FileOptions__Output>
GeneratedCodeInfo: MessageTypeDefinition<_google_protobuf_GeneratedCodeInfo, _google_protobuf_GeneratedCodeInfo__Output>
ListValue: MessageTypeDefinition<_google_protobuf_ListValue, _google_protobuf_ListValue__Output>
MessageOptions: MessageTypeDefinition<_google_protobuf_MessageOptions, _google_protobuf_MessageOptions__Output>
MethodDescriptorProto: MessageTypeDefinition<_google_protobuf_MethodDescriptorProto, _google_protobuf_MethodDescriptorProto__Output>
MethodOptions: MessageTypeDefinition<_google_protobuf_MethodOptions, _google_protobuf_MethodOptions__Output>
NullValue: EnumTypeDefinition
OneofDescriptorProto: MessageTypeDefinition<_google_protobuf_OneofDescriptorProto, _google_protobuf_OneofDescriptorProto__Output>
OneofOptions: MessageTypeDefinition<_google_protobuf_OneofOptions, _google_protobuf_OneofOptions__Output>
ServiceDescriptorProto: MessageTypeDefinition<_google_protobuf_ServiceDescriptorProto, _google_protobuf_ServiceDescriptorProto__Output>
ServiceOptions: MessageTypeDefinition<_google_protobuf_ServiceOptions, _google_protobuf_ServiceOptions__Output>
SourceCodeInfo: MessageTypeDefinition<_google_protobuf_SourceCodeInfo, _google_protobuf_SourceCodeInfo__Output>
Struct: MessageTypeDefinition<_google_protobuf_Struct, _google_protobuf_Struct__Output>
SymbolVisibility: EnumTypeDefinition
Timestamp: MessageTypeDefinition<_google_protobuf_Timestamp, _google_protobuf_Timestamp__Output>
UninterpretedOption: MessageTypeDefinition<_google_protobuf_UninterpretedOption, _google_protobuf_UninterpretedOption__Output>
Value: MessageTypeDefinition<_google_protobuf_Value, _google_protobuf_Value__Output>
}
}
@ -102,32 +27,6 @@ export interface ProtoGrpcType {
}
}
}
validate: {
AnyRules: MessageTypeDefinition<_validate_AnyRules, _validate_AnyRules__Output>
BoolRules: MessageTypeDefinition<_validate_BoolRules, _validate_BoolRules__Output>
BytesRules: MessageTypeDefinition<_validate_BytesRules, _validate_BytesRules__Output>
DoubleRules: MessageTypeDefinition<_validate_DoubleRules, _validate_DoubleRules__Output>
DurationRules: MessageTypeDefinition<_validate_DurationRules, _validate_DurationRules__Output>
EnumRules: MessageTypeDefinition<_validate_EnumRules, _validate_EnumRules__Output>
FieldRules: MessageTypeDefinition<_validate_FieldRules, _validate_FieldRules__Output>
Fixed32Rules: MessageTypeDefinition<_validate_Fixed32Rules, _validate_Fixed32Rules__Output>
Fixed64Rules: MessageTypeDefinition<_validate_Fixed64Rules, _validate_Fixed64Rules__Output>
FloatRules: MessageTypeDefinition<_validate_FloatRules, _validate_FloatRules__Output>
Int32Rules: MessageTypeDefinition<_validate_Int32Rules, _validate_Int32Rules__Output>
Int64Rules: MessageTypeDefinition<_validate_Int64Rules, _validate_Int64Rules__Output>
KnownRegex: EnumTypeDefinition
MapRules: MessageTypeDefinition<_validate_MapRules, _validate_MapRules__Output>
MessageRules: MessageTypeDefinition<_validate_MessageRules, _validate_MessageRules__Output>
RepeatedRules: MessageTypeDefinition<_validate_RepeatedRules, _validate_RepeatedRules__Output>
SFixed32Rules: MessageTypeDefinition<_validate_SFixed32Rules, _validate_SFixed32Rules__Output>
SFixed64Rules: MessageTypeDefinition<_validate_SFixed64Rules, _validate_SFixed64Rules__Output>
SInt32Rules: MessageTypeDefinition<_validate_SInt32Rules, _validate_SInt32Rules__Output>
SInt64Rules: MessageTypeDefinition<_validate_SInt64Rules, _validate_SInt64Rules__Output>
StringRules: MessageTypeDefinition<_validate_StringRules, _validate_StringRules__Output>
TimestampRules: MessageTypeDefinition<_validate_TimestampRules, _validate_TimestampRules__Output>
UInt32Rules: MessageTypeDefinition<_validate_UInt32Rules, _validate_UInt32Rules__Output>
UInt64Rules: MessageTypeDefinition<_validate_UInt64Rules, _validate_UInt64Rules__Output>
}
xds: {
type: {
v3: {

View File

@ -8,8 +8,8 @@ import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__
*/
export interface _xds_core_v3_CollectionEntry_InlineEntry {
/**
* Optional name to describe the inlined resource. Resource names must
* [a-zA-Z0-9_-\./]+ (TODO(htuch): turn this into a PGV constraint once
* Optional name to describe the inlined resource. Resource names must match
* ``[a-zA-Z0-9_-\./]+`` (TODO(htuch): turn this into a PGV constraint once
* finalized, probably should be a RFC3986 pchar). This name allows
* reference via the #entry directive in ResourceLocator.
*/
@ -30,8 +30,8 @@ export interface _xds_core_v3_CollectionEntry_InlineEntry {
*/
export interface _xds_core_v3_CollectionEntry_InlineEntry__Output {
/**
* Optional name to describe the inlined resource. Resource names must
* [a-zA-Z0-9_-\./]+ (TODO(htuch): turn this into a PGV constraint once
* Optional name to describe the inlined resource. Resource names must match
* ``[a-zA-Z0-9_-\./]+`` (TODO(htuch): turn this into a PGV constraint once
* finalized, probably should be a RFC3986 pchar). This name allows
* reference via the #entry directive in ResourceLocator.
*/
@ -52,6 +52,8 @@ export interface _xds_core_v3_CollectionEntry_InlineEntry__Output {
* appearing inside a list collection resource. List collection resources are
* regular Resource messages of type:
*
* .. code-block:: proto
*
* message <T>Collection {
* repeated CollectionEntry resources = 1;
* }
@ -73,6 +75,8 @@ export interface CollectionEntry {
* appearing inside a list collection resource. List collection resources are
* regular Resource messages of type:
*
* .. code-block:: proto
*
* message <T>Collection {
* repeated CollectionEntry resources = 1;
* }

View File

@ -6,6 +6,7 @@
* global context parameters, per-resource type client feature capabilities and per-resource
* type functional attributes. All per-resource type attributes will be `xds.resource.`
* prefixed and some of these are documented below:
*
* `xds.resource.listening_address`: The value is "IP:port" (e.g. "10.1.1.3:8080") which is
* the listening address of a Listener. Used in a Listener resource query.
*/
@ -18,6 +19,7 @@ export interface ContextParams {
* global context parameters, per-resource type client feature capabilities and per-resource
* type functional attributes. All per-resource type attributes will be `xds.resource.`
* prefixed and some of these are documented below:
*
* `xds.resource.listening_address`: The value is "IP:port" (e.g. "10.1.1.3:8080") which is
* the listening address of a Listener. Used in a Listener resource query.
*/

View File

@ -271,10 +271,9 @@ export interface Matcher {
*/
'matcher_tree'?: (_xds_type_matcher_v3_Matcher_MatcherTree | null);
/**
* Optional OnMatch to use if the matcher failed.
* If specified, the OnMatch is used, and the matcher is considered
* to have matched.
* If not specified, the matcher is considered not to have matched.
* Optional OnMatch to use if no matcher above matched (e.g., if there are no matchers specified
* above, or if none of the matches specified above succeeded).
* If no matcher above matched and this field is not populated, the match will be considered unsuccessful.
*/
'on_no_match'?: (_xds_type_matcher_v3_Matcher_OnMatch | null);
'matcher_type'?: "matcher_list"|"matcher_tree";
@ -297,10 +296,9 @@ export interface Matcher__Output {
*/
'matcher_tree'?: (_xds_type_matcher_v3_Matcher_MatcherTree__Output | null);
/**
* Optional OnMatch to use if the matcher failed.
* If specified, the OnMatch is used, and the matcher is considered
* to have matched.
* If not specified, the matcher is considered not to have matched.
* Optional OnMatch to use if no matcher above matched (e.g., if there are no matchers specified
* above, or if none of the matches specified above succeeded).
* If no matcher above matched and this field is not populated, the match will be considered unsuccessful.
*/
'on_no_match': (_xds_type_matcher_v3_Matcher_OnMatch__Output | null);
'matcher_type'?: "matcher_list"|"matcher_tree";

View File

@ -13,6 +13,7 @@ import type { Struct as _google_protobuf_Struct, Struct__Output as _google_proto
* When packing an opaque extension config, packing the expected type into Any is preferred
* wherever possible for its efficiency. TypedStruct should be used only if a proto descriptor
* is not available, for example if:
*
* - A control plane sends opaque message that is originally from external source in human readable
* format such as JSON or YAML.
* - The control plane doesn't have the knowledge of the protocol buffer schema hence it cannot
@ -23,6 +24,7 @@ import type { Struct as _google_protobuf_Struct, Struct__Output as _google_proto
* When a DPLB receives a TypedStruct in Any, it should:
* - Check if the type_url of the TypedStruct matches the type the extension expects.
* - Convert value to the type described in type_url and perform validation.
*
* TODO(lizan): Figure out how TypeStruct should be used with DPLB extensions that doesn't link
* protobuf descriptor with DPLB itself, (e.g. gRPC LB Plugin, Envoy WASM extensions).
*/
@ -50,6 +52,7 @@ export interface TypedStruct {
* When packing an opaque extension config, packing the expected type into Any is preferred
* wherever possible for its efficiency. TypedStruct should be used only if a proto descriptor
* is not available, for example if:
*
* - A control plane sends opaque message that is originally from external source in human readable
* format such as JSON or YAML.
* - The control plane doesn't have the knowledge of the protocol buffer schema hence it cannot
@ -60,6 +63,7 @@ export interface TypedStruct {
* When a DPLB receives a TypedStruct in Any, it should:
* - Check if the type_url of the TypedStruct matches the type the extension expects.
* - Convert value to the type described in type_url and perform validation.
*
* TODO(lizan): Figure out how TypeStruct should be used with DPLB extensions that doesn't link
* protobuf descriptor with DPLB itself, (e.g. gRPC LB Plugin, Envoy WASM extensions).
*/

View File

@ -30,6 +30,7 @@ import * as csds from './csds';
import * as round_robin_lb from './lb-policy-registry/round-robin';
import * as typed_struct_lb from './lb-policy-registry/typed-struct';
import * as pick_first_lb from './lb-policy-registry/pick-first';
import * as weighted_round_robin_lb from './lb-policy-registry/weighted-round-robin';
export { XdsServer } from './server';
export { XdsChannelCredentials, XdsServerCredentials } from './xds-credentials';
@ -59,4 +60,5 @@ export function register() {
round_robin_lb.setup();
typed_struct_lb.setup();
pick_first_lb.setup();
weighted_round_robin_lb.setup();
}

View File

@ -0,0 +1,80 @@
/*
* Copyright 2025 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 { LoadBalancingConfig } from "@grpc/grpc-js";
import { LoadBalancingPolicy__Output } from "../generated/envoy/config/cluster/v3/LoadBalancingPolicy";
import { TypedExtensionConfig__Output } from "../generated/envoy/config/core/v3/TypedExtensionConfig";
import { loadProtosWithOptionsSync } from "@grpc/proto-loader/build/src/util";
import { Any__Output } from "../generated/google/protobuf/Any";
import { ClientSideWeightedRoundRobin__Output } from "../generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/ClientSideWeightedRoundRobin";
import { EXPERIMENTAL_WRR_LB } from "../environment";
import { registerLbPolicy } from "../lb-policy-registry";
const WEIGHTED_ROUND_ROBIN_TYPE_URL = 'type.googleapis.com/envoy.extensions.load_balancing_policies.client_side_weighted_round_robin.v3.ClientSideWeightedRoundRobin';
const resourceRoot = loadProtosWithOptionsSync([
'envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.proto'], {
keepCase: true,
includeDirs: [
// Paths are relative to src/build/lb-policy-registry
__dirname + '/../../../deps/envoy-api/',
__dirname + '/../../../deps/xds/',
__dirname + '/../../../deps/protoc-gen-validate'
],
}
);
const toObjectOptions = {
longs: String,
enums: String,
defaults: true,
oneofs: true
};
function decodeWeightedRoundRobinConfig(message: Any__Output): ClientSideWeightedRoundRobin__Output {
const name = message.type_url.substring(message.type_url.lastIndexOf('/') + 1);
const type = resourceRoot.lookup(name);
if (type) {
const decodedMessage = (type as any).decode(message.value);
return decodedMessage.$type.toObject(decodedMessage, toObjectOptions) as ClientSideWeightedRoundRobin__Output;
} else {
throw new Error(`TypedStruct parsing error: unexpected type URL ${message.type_url}`);
}
}
function convertToLoadBalancingPolicy(protoPolicy: TypedExtensionConfig__Output, selectChildPolicy: (childPolicy: LoadBalancingPolicy__Output) => LoadBalancingConfig): LoadBalancingConfig | null {
if (protoPolicy.typed_config?.type_url !== WEIGHTED_ROUND_ROBIN_TYPE_URL) {
throw new Error(`Pick first LB policy parsing error: unexpected type URL ${protoPolicy.typed_config?.type_url}`);
}
const wrrMessage = decodeWeightedRoundRobinConfig(protoPolicy.typed_config);
return {
weighted_round_robin: {
enable_oob_load_report: wrrMessage.enable_oob_load_report?.value,
oob_load_reporting_period: wrrMessage.oob_reporting_period,
blackout_period: wrrMessage.blackout_period,
weight_expiration_period: wrrMessage.weight_expiration_period,
weight_update_period: wrrMessage.weight_update_period,
error_utilization_penalty: wrrMessage.error_utilization_penalty?.value
}
}
}
export function setup() {
if (EXPERIMENTAL_WRR_LB) {
registerLbPolicy(WEIGHTED_ROUND_ROBIN_TYPE_URL, convertToLoadBalancingPolicy);
}
}

View File

@ -173,7 +173,7 @@ class XdsClusterImplPicker implements Picker {
return {
pickResultType: originalPick.pickResultType,
status: originalPick.status,
subchannel: pickSubchannel?.getWrappedSubchannel() ?? null,
subchannel: pickSubchannel?.getWrappedSubchannel?.() ?? null,
onCallStarted: () => {
originalPick.onCallStarted?.();
pickSubchannel?.getStatsObject()?.addCallStarted();

View File

@ -40,6 +40,7 @@ import parseLoadBalancingConfig = experimental.parseLoadBalancingConfig;
import registerLoadBalancerType = experimental.registerLoadBalancerType;
import StatusOr = experimental.StatusOr;
import { PickFirst } from "../src/generated/envoy/extensions/load_balancing_policies/pick_first/v3/PickFirst";
import { ClientSideWeightedRoundRobin } from "../src/generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/ClientSideWeightedRoundRobin";
const LB_POLICY_NAME = 'test.RpcBehaviorLoadBalancer';
@ -344,5 +345,70 @@ describe('Custom LB policies', () => {
const error = await client.sendOneCallAsync();
assert.strictEqual(error, null);
});
it('Should handle weighted_round_robin', async () => {
const lbPolicy: ClientSideWeightedRoundRobin & AnyExtension = {
'@type': 'type.googleapis.com/envoy.extensions.load_balancing_policies.client_side_weighted_round_robin.v3.ClientSideWeightedRoundRobin',
enable_oob_load_report: { value: true },
oob_reporting_period: { seconds: 1 },
blackout_period: { seconds: 1 },
weight_expiration_period: { seconds: 1 },
weight_update_period: { seconds: 1 },
error_utilization_penalty: { value: 0.5 }
};
xdsServer.addResponseListener((typeUrl, responseState) => {
if (responseState.state === 'NACKED') {
client?.stopCalls();
assert.fail(`Client NACKED ${typeUrl} resource with message ${responseState.errorMessage}`);
}
});
const [backend] = await createBackends(1);
const serverRoute = new FakeServerRoute(backend.getPort(), 'serverRoute');
xdsServer.setRdsResource(serverRoute.getRouteConfiguration());
xdsServer.setLdsResource(serverRoute.getListener());
const cluster = new FakeEdsCluster('cluster1', 'endpoint1', [{backends: [backend], locality:{region: 'region1'}}], lbPolicy);
const routeGroup = new FakeRouteGroup('listener1', 'route1', [{cluster: cluster}]);
xdsServer.setEdsResource(cluster.getEndpointConfig());
xdsServer.setCdsResource(cluster.getClusterConfig());
xdsServer.setRdsResource(routeGroup.getRouteConfiguration());
xdsServer.setLdsResource(routeGroup.getListener());
await routeGroup.startAllBackends(xdsServer);
client = XdsTestClient.createFromServer('listener1', xdsServer);
const error = await client.sendOneCallAsync();
assert.strictEqual(error, null);
});
it('Should distribute traffic among backends with weighted_round_robin', async () => {
const lbPolicy: ClientSideWeightedRoundRobin & AnyExtension = {
'@type': 'type.googleapis.com/envoy.extensions.load_balancing_policies.client_side_weighted_round_robin.v3.ClientSideWeightedRoundRobin',
enable_oob_load_report: { value: true },
oob_reporting_period: { seconds: 1 },
blackout_period: { seconds: 1 },
weight_expiration_period: { seconds: 1 },
weight_update_period: { seconds: 1 },
error_utilization_penalty: { value: 0.5 }
};
xdsServer.addResponseListener((typeUrl, responseState) => {
if (responseState.state === 'NACKED') {
client?.stopCalls();
assert.fail(`Client NACKED ${typeUrl} resource with message ${responseState.errorMessage}`);
}
});
const [backend1, backend2] = await createBackends(2);
const serverRoute1 = new FakeServerRoute(backend1.getPort(), 'serverRoute');
const serverRoute2 = new FakeServerRoute(backend2.getPort(), 'serverRoute2');
xdsServer.setRdsResource(serverRoute1.getRouteConfiguration());
xdsServer.setLdsResource(serverRoute1.getListener());
xdsServer.setRdsResource(serverRoute2.getRouteConfiguration());
xdsServer.setLdsResource(serverRoute2.getListener());
const cluster = new FakeEdsCluster('cluster1', 'endpoint1', [{backends: [backend1, backend2], locality:{region: 'region1'}}], lbPolicy);
const routeGroup = new FakeRouteGroup('listener1', 'route1', [{cluster: cluster}]);
xdsServer.setEdsResource(cluster.getEndpointConfig());
xdsServer.setCdsResource(cluster.getClusterConfig());
xdsServer.setRdsResource(routeGroup.getRouteConfiguration());
xdsServer.setLdsResource(routeGroup.getListener());
await routeGroup.startAllBackends(xdsServer);
client = XdsTestClient.createFromServer('listener1', xdsServer);
client.startCalls(100);
await routeGroup.waitForAllBackendsToReceiveTraffic();
client.stopCalls();
});
});

View File

@ -53,6 +53,7 @@ const loadedProtos = loadPackageDefinition(loadSync(
'envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.proto',
'envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.proto',
'envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.proto',
'envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.proto',
'envoy/extensions/transport_sockets/tls/v3/tls.proto',
'xds/type/v3/typed_struct.proto',
'envoy/extensions/filters/http/router/v3/router.proto',

View File

@ -47,6 +47,10 @@ export function isDuration(value: any): value is Duration {
return typeof value.seconds === 'number' && typeof value.nanos === 'number';
}
export function isDurationMessage(value: any): value is DurationMessage {
return typeof value.seconds === 'string' && typeof value.nanos === 'number';
}
const durationRegex = /^(\d+)(?:\.(\d+))?s$/;
export function parseDuration(value: string): Duration | null {
const match = value.match(durationRegex);

View File

@ -19,13 +19,13 @@ import { StatusOr } from './call-interface';
import { ChannelOptions } from './channel-options';
import { ConnectivityState } from './connectivity-state';
import { LogVerbosity } from './constants';
import { Duration, durationToMs, durationToString, isDuration, msToDuration, parseDuration } from './duration';
import { Duration, durationMessageToDuration, durationToMs, durationToString, isDuration, isDurationMessage, msToDuration, parseDuration } from './duration';
import { OrcaLoadReport__Output } from './generated/xds/data/orca/v3/OrcaLoadReport';
import { ChannelControlHelper, createChildChannelControlHelper, LoadBalancer, registerLoadBalancerType, TypedLoadBalancingConfig } from './load-balancer';
import { LeafLoadBalancer } from './load-balancer-pick-first';
import * as logging from './logging';
import { createMetricsReader, MetricsListener, OrcaOobMetricsSubchannelWrapper } from './orca';
import { PickArgs, Picker, PickResult, QueuePicker, UnavailablePicker } from './picker';
import { PickArgs, Picker, PickResult, PickResultType, QueuePicker, UnavailablePicker } from './picker';
import { PriorityQueue } from './priority-queue';
import { Endpoint, endpointToString } from './subchannel-address';
@ -70,10 +70,12 @@ function validateFieldType(
}
function parseDurationField(obj: any, fieldName: string): number | null {
if (fieldName in obj && obj[fieldName] !== undefined) {
if (fieldName in obj && obj[fieldName] !== undefined && obj[fieldName] !== null) {
let durationObject: Duration;
if (isDuration(obj[fieldName])) {
durationObject = obj[fieldName];
} else if (isDurationMessage(obj[fieldName])) {
durationObject = durationMessageToDuration(obj[fieldName]);
} else if (typeof obj[fieldName] === 'string') {
const parsedDuration = parseDuration(obj[fieldName]);
if (!parsedDuration) {
@ -207,11 +209,19 @@ class WeightedRoundRobinPicker implements Picker {
deadline: entry.deadline + entry.period
})
const childPick = entry.picker.pick(pickArgs);
if (this.metricsHandler) {
return {
...childPick,
onCallEnded: createMetricsReader(loadReport => this.metricsHandler!(loadReport, entry.endpointName), childPick.onCallEnded)
};
if (childPick.pickResultType === PickResultType.COMPLETE) {
if (this.metricsHandler) {
return {
...childPick,
onCallEnded: createMetricsReader(loadReport => this.metricsHandler!(loadReport, entry.endpointName), childPick.onCallEnded)
};
} else {
const subchannelWrapper = childPick.subchannel as OrcaOobMetricsSubchannelWrapper;
return {
...childPick,
subchannel: subchannelWrapper.getWrappedSubchannel()
}
}
} else {
return childPick;
}

View File

@ -338,6 +338,10 @@ export class OrcaOobMetricsSubchannelWrapper extends BaseSubchannelWrapper {
super(child);
this.addDataWatcher(new OobMetricsDataWatcher(metricsListener, intervalMs));
}
getWrappedSubchannel(): SubchannelInterface {
return this.child;
}
}
function createOobMetricsDataProducer(subchannel: Subchannel) {