Skip to content

Commit d28b9e8

Browse files
committed
grpc-js: Return LB policy configs from resolvers in JSON form
1 parent 14b11f6 commit d28b9e8

10 files changed

+119
-94
lines changed

packages/grpc-js/src/experimental.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,15 @@ export {
88
} from './resolver';
99
export { GrpcUri, uriToString } from './uri-parser';
1010
export { Duration, durationToMs } from './duration';
11-
export { ServiceConfig, MethodConfig, RetryPolicy } from './service-config';
1211
export { BackoffTimeout } from './backoff-timeout';
1312
export {
1413
LoadBalancer,
15-
LoadBalancingConfig,
14+
TypedLoadBalancingConfig,
1615
ChannelControlHelper,
1716
createChildChannelControlHelper,
1817
registerLoadBalancerType,
19-
getFirstUsableConfig,
20-
validateLoadBalancingConfig,
18+
selectLbConfigFromList,
19+
parseLoadBalancingConfig
2120
} from './load-balancer';
2221
export {
2322
SubchannelAddress,
@@ -42,7 +41,7 @@ export {
4241
ConnectivityStateListener,
4342
} from './subchannel-interface';
4443
export {
45-
OutlierDetectionLoadBalancingConfig,
44+
OutlierDetectionRawConfig,
4645
SuccessRateEjectionConfig,
4746
FailurePercentageEjectionConfig,
4847
} from './load-balancer-outlier-detection';

packages/grpc-js/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,8 @@ export { getChannelzServiceDefinition, getChannelzHandlers } from './channelz';
261261

262262
export { addAdminServicesToServer } from './admin';
263263

264+
export { ServiceConfig, LoadBalancingConfig, MethodConfig, RetryPolicy } from './service-config';
265+
264266
import * as experimental from './experimental';
265267
export { experimental };
266268

packages/grpc-js/src/load-balancer-child-handler.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import {
1919
LoadBalancer,
2020
ChannelControlHelper,
21-
LoadBalancingConfig,
21+
TypedLoadBalancingConfig,
2222
createLoadBalancer,
2323
} from './load-balancer';
2424
import { SubchannelAddress } from './subchannel-address';
@@ -33,7 +33,7 @@ const TYPE_NAME = 'child_load_balancer_helper';
3333
export class ChildLoadBalancerHandler implements LoadBalancer {
3434
private currentChild: LoadBalancer | null = null;
3535
private pendingChild: LoadBalancer | null = null;
36-
private latestConfig: LoadBalancingConfig | null = null;
36+
private latestConfig: TypedLoadBalancingConfig | null = null;
3737

3838
private ChildPolicyHelper = class {
3939
private child: LoadBalancer | null = null;
@@ -87,8 +87,8 @@ export class ChildLoadBalancerHandler implements LoadBalancer {
8787
constructor(private readonly channelControlHelper: ChannelControlHelper) {}
8888

8989
protected configUpdateRequiresNewPolicyInstance(
90-
oldConfig: LoadBalancingConfig,
91-
newConfig: LoadBalancingConfig
90+
oldConfig: TypedLoadBalancingConfig,
91+
newConfig: TypedLoadBalancingConfig
9292
): boolean {
9393
return oldConfig.getLoadBalancerName() !== newConfig.getLoadBalancerName();
9494
}
@@ -101,7 +101,7 @@ export class ChildLoadBalancerHandler implements LoadBalancer {
101101
*/
102102
updateAddressList(
103103
addressList: SubchannelAddress[],
104-
lbConfig: LoadBalancingConfig,
104+
lbConfig: TypedLoadBalancingConfig,
105105
attributes: { [key: string]: unknown }
106106
): void {
107107
let childToUpdate: LoadBalancer;

packages/grpc-js/src/load-balancer-outlier-detection.ts

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,16 @@
1818
import { ChannelOptions } from './channel-options';
1919
import { ConnectivityState } from './connectivity-state';
2020
import { LogVerbosity, Status } from './constants';
21-
import { durationToMs, isDuration, msToDuration } from './duration';
21+
import { Duration, durationToMs, isDuration, msToDuration } from './duration';
2222
import {
2323
ChannelControlHelper,
2424
createChildChannelControlHelper,
2525
registerLoadBalancerType,
2626
} from './experimental';
2727
import {
28-
getFirstUsableConfig,
28+
selectLbConfigFromList,
2929
LoadBalancer,
30-
LoadBalancingConfig,
31-
validateLoadBalancingConfig,
30+
TypedLoadBalancingConfig,
3231
} from './load-balancer';
3332
import { ChildLoadBalancerHandler } from './load-balancer-child-handler';
3433
import { PickArgs, Picker, PickResult, PickResultType } from './picker';
@@ -42,6 +41,7 @@ import {
4241
SubchannelInterface,
4342
} from './subchannel-interface';
4443
import * as logging from './logging';
44+
import { LoadBalancingConfig } from './service-config';
4545

4646
const TRACER_NAME = 'outlier_detection';
4747

@@ -68,6 +68,16 @@ export interface FailurePercentageEjectionConfig {
6868
readonly request_volume: number;
6969
}
7070

71+
export interface OutlierDetectionRawConfig {
72+
interval?: Duration;
73+
base_ejection_time?: Duration;
74+
max_ejection_time?: Duration;
75+
max_ejection_percent?: number;
76+
success_rate_ejection?: Partial<SuccessRateEjectionConfig>;
77+
failure_percentage_ejection?: Partial<FailurePercentageEjectionConfig>;
78+
child_policy: LoadBalancingConfig[];
79+
}
80+
7181
const defaultSuccessRateEjectionConfig: SuccessRateEjectionConfig = {
7282
stdev_factor: 1900,
7383
enforcement_percentage: 100,
@@ -147,7 +157,7 @@ function validatePercentage(obj: any, fieldName: string, objectName?: string) {
147157
}
148158

149159
export class OutlierDetectionLoadBalancingConfig
150-
implements LoadBalancingConfig
160+
implements TypedLoadBalancingConfig
151161
{
152162
private readonly intervalMs: number;
153163
private readonly baseEjectionTimeMs: number;
@@ -163,11 +173,10 @@ export class OutlierDetectionLoadBalancingConfig
163173
maxEjectionPercent: number | null,
164174
successRateEjection: Partial<SuccessRateEjectionConfig> | null,
165175
failurePercentageEjection: Partial<FailurePercentageEjectionConfig> | null,
166-
private readonly childPolicy: LoadBalancingConfig[]
176+
private readonly childPolicy: TypedLoadBalancingConfig
167177
) {
168178
if (
169-
childPolicy.length > 0 &&
170-
childPolicy[0].getLoadBalancerName() === 'pick_first'
179+
childPolicy.getLoadBalancerName() === 'pick_first'
171180
) {
172181
throw new Error(
173182
'outlier_detection LB policy cannot have a pick_first child policy'
@@ -198,7 +207,7 @@ export class OutlierDetectionLoadBalancingConfig
198207
max_ejection_percent: this.maxEjectionPercent,
199208
success_rate_ejection: this.successRateEjection,
200209
failure_percentage_ejection: this.failurePercentageEjection,
201-
child_policy: this.childPolicy.map(policy => policy.toJsonObject()),
210+
child_policy: [this.childPolicy.toJsonObject()]
202211
};
203212
}
204213

@@ -220,24 +229,10 @@ export class OutlierDetectionLoadBalancingConfig
220229
getFailurePercentageEjectionConfig(): FailurePercentageEjectionConfig | null {
221230
return this.failurePercentageEjection;
222231
}
223-
getChildPolicy(): LoadBalancingConfig[] {
232+
getChildPolicy(): TypedLoadBalancingConfig {
224233
return this.childPolicy;
225234
}
226235

227-
copyWithChildPolicy(
228-
childPolicy: LoadBalancingConfig[]
229-
): OutlierDetectionLoadBalancingConfig {
230-
return new OutlierDetectionLoadBalancingConfig(
231-
this.intervalMs,
232-
this.baseEjectionTimeMs,
233-
this.maxEjectionTimeMs,
234-
this.maxEjectionPercent,
235-
this.successRateEjection,
236-
this.failurePercentageEjection,
237-
childPolicy
238-
);
239-
}
240-
241236
static createFromJson(obj: any): OutlierDetectionLoadBalancingConfig {
242237
validatePositiveDuration(obj, 'interval');
243238
validatePositiveDuration(obj, 'base_ejection_time');
@@ -303,14 +298,22 @@ export class OutlierDetectionLoadBalancingConfig
303298
);
304299
}
305300

301+
if (!('child_policy' in obj) || !Array.isArray(obj.child_policy)) {
302+
throw new Error('outlier detection config child_policy must be an array');
303+
}
304+
const childPolicy = selectLbConfigFromList(obj.child_policy);
305+
if (!childPolicy) {
306+
throw new Error('outlier detection config child_policy: no valid recognized policy found');
307+
}
308+
306309
return new OutlierDetectionLoadBalancingConfig(
307310
obj.interval ? durationToMs(obj.interval) : null,
308311
obj.base_ejection_time ? durationToMs(obj.base_ejection_time) : null,
309312
obj.max_ejection_time ? durationToMs(obj.max_ejection_time) : null,
310313
obj.max_ejection_percent ?? null,
311314
obj.success_rate_ejection,
312315
obj.failure_percentage_ejection,
313-
obj.child_policy.map(validateLoadBalancingConfig)
316+
childPolicy
314317
);
315318
}
316319
}
@@ -794,7 +797,7 @@ export class OutlierDetectionLoadBalancer implements LoadBalancer {
794797

795798
updateAddressList(
796799
addressList: SubchannelAddress[],
797-
lbConfig: LoadBalancingConfig,
800+
lbConfig: TypedLoadBalancingConfig,
798801
attributes: { [key: string]: unknown }
799802
): void {
800803
if (!(lbConfig instanceof OutlierDetectionLoadBalancingConfig)) {
@@ -821,10 +824,7 @@ export class OutlierDetectionLoadBalancer implements LoadBalancer {
821824
this.addressMap.delete(key);
822825
}
823826
}
824-
const childPolicy: LoadBalancingConfig = getFirstUsableConfig(
825-
lbConfig.getChildPolicy(),
826-
true
827-
);
827+
const childPolicy = lbConfig.getChildPolicy();
828828
this.childBalancer.updateAddressList(addressList, childPolicy, attributes);
829829

830830
if (

packages/grpc-js/src/load-balancer-pick-first.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import {
1919
LoadBalancer,
2020
ChannelControlHelper,
21-
LoadBalancingConfig,
21+
TypedLoadBalancingConfig,
2222
registerDefaultLoadBalancerType,
2323
registerLoadBalancerType,
2424
} from './load-balancer';
@@ -53,7 +53,7 @@ const TYPE_NAME = 'pick_first';
5353
*/
5454
const CONNECTION_DELAY_INTERVAL_MS = 250;
5555

56-
export class PickFirstLoadBalancingConfig implements LoadBalancingConfig {
56+
export class PickFirstLoadBalancingConfig implements TypedLoadBalancingConfig {
5757
constructor(private readonly shuffleAddressList: boolean) {}
5858

5959
getLoadBalancerName(): string {
@@ -374,7 +374,7 @@ export class PickFirstLoadBalancer implements LoadBalancer {
374374

375375
updateAddressList(
376376
addressList: SubchannelAddress[],
377-
lbConfig: LoadBalancingConfig
377+
lbConfig: TypedLoadBalancingConfig
378378
): void {
379379
if (!(lbConfig instanceof PickFirstLoadBalancingConfig)) {
380380
return;

packages/grpc-js/src/load-balancer-round-robin.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import {
1919
LoadBalancer,
2020
ChannelControlHelper,
21-
LoadBalancingConfig,
21+
TypedLoadBalancingConfig,
2222
registerLoadBalancerType,
2323
} from './load-balancer';
2424
import { ConnectivityState } from './connectivity-state';
@@ -49,7 +49,7 @@ function trace(text: string): void {
4949

5050
const TYPE_NAME = 'round_robin';
5151

52-
class RoundRobinLoadBalancingConfig implements LoadBalancingConfig {
52+
class RoundRobinLoadBalancingConfig implements TypedLoadBalancingConfig {
5353
getLoadBalancerName(): string {
5454
return TYPE_NAME;
5555
}
@@ -192,7 +192,7 @@ export class RoundRobinLoadBalancer implements LoadBalancer {
192192

193193
updateAddressList(
194194
addressList: SubchannelAddress[],
195-
lbConfig: LoadBalancingConfig
195+
lbConfig: TypedLoadBalancingConfig
196196
): void {
197197
this.resetSubchannelList();
198198
trace(

0 commit comments

Comments
 (0)