load-balancing-config.ts
4.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/*
* Copyright 2019 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.
*
*/
/* This file is an implementation of gRFC A24:
* https://github.com/grpc/proposal/blob/master/A24-lb-policy-config.md. Each
* function here takes an object with unknown structure and returns its
* specific object type if the input has the right structure, and throws an
* error otherwise. */
/* The any type is purposely used here. All functions validate their input at
* runtime */
/* eslint-disable @typescript-eslint/no-explicit-any */
export type PickFirstConfig = {};
export type RoundRobinConfig = {};
export interface XdsConfig {
balancerName: string;
childPolicy: LoadBalancingConfig[];
fallbackPolicy: LoadBalancingConfig[];
}
export interface GrpcLbConfig {
childPolicy: LoadBalancingConfig[];
}
export interface PriorityChild {
config: LoadBalancingConfig[];
}
export interface PriorityLbConfig {
children: Map<string, PriorityChild>;
priorities: string[];
}
export interface PickFirstLoadBalancingConfig {
name: 'pick_first';
pick_first: PickFirstConfig;
}
export interface RoundRobinLoadBalancingConfig {
name: 'round_robin';
round_robin: RoundRobinConfig;
}
export interface XdsLoadBalancingConfig {
name: 'xds';
xds: XdsConfig;
}
export interface GrpcLbLoadBalancingConfig {
name: 'grpclb';
grpclb: GrpcLbConfig;
}
export interface PriorityLoadBalancingConfig {
name: 'priority';
priority: PriorityLbConfig;
}
export type LoadBalancingConfig =
| PickFirstLoadBalancingConfig
| RoundRobinLoadBalancingConfig
| XdsLoadBalancingConfig
| GrpcLbLoadBalancingConfig
| PriorityLoadBalancingConfig;
export function isRoundRobinLoadBalancingConfig(
lbconfig: LoadBalancingConfig
): lbconfig is RoundRobinLoadBalancingConfig {
return lbconfig.name === 'round_robin';
}
export function isXdsLoadBalancingConfig(
lbconfig: LoadBalancingConfig
): lbconfig is XdsLoadBalancingConfig {
return lbconfig.name === 'xds';
}
export function isGrpcLbLoadBalancingConfig(
lbconfig: LoadBalancingConfig
): lbconfig is GrpcLbLoadBalancingConfig {
return lbconfig.name === 'grpclb';
}
export function isPriorityLoadBalancingConfig(
lbconfig: LoadBalancingConfig
): lbconfig is PriorityLoadBalancingConfig {
return lbconfig.name === 'priority';
}
/* In these functions we assume the input came from a JSON object. Therefore we
* expect that the prototype is uninteresting and that `in` can be used
* effectively */
function validateXdsConfig(xds: any): XdsConfig {
if (!('balancerName' in xds) || typeof xds.balancerName !== 'string') {
throw new Error('Invalid xds config: invalid balancerName');
}
const xdsConfig: XdsConfig = {
balancerName: xds.balancerName,
childPolicy: [],
fallbackPolicy: [],
};
if ('childPolicy' in xds) {
if (!Array.isArray(xds.childPolicy)) {
throw new Error('Invalid xds config: invalid childPolicy');
}
for (const policy of xds.childPolicy) {
xdsConfig.childPolicy.push(validateConfig(policy));
}
}
if ('fallbackPolicy' in xds) {
if (!Array.isArray(xds.fallbackPolicy)) {
throw new Error('Invalid xds config: invalid fallbackPolicy');
}
for (const policy of xds.fallbackPolicy) {
xdsConfig.fallbackPolicy.push(validateConfig(policy));
}
}
return xdsConfig;
}
function validateGrpcLbConfig(grpclb: any): GrpcLbConfig {
const grpcLbConfig: GrpcLbConfig = {
childPolicy: [],
};
if ('childPolicy' in grpclb) {
if (!Array.isArray(grpclb.childPolicy)) {
throw new Error('Invalid xds config: invalid childPolicy');
}
for (const policy of grpclb.childPolicy) {
grpcLbConfig.childPolicy.push(validateConfig(policy));
}
}
return grpcLbConfig;
}
export function validateConfig(obj: any): LoadBalancingConfig {
if ('round_robin' in obj) {
if ('xds' in obj || 'grpclb' in obj) {
throw new Error('Multiple load balancing policies configured');
}
if (obj['round_robin'] instanceof Object) {
return {
name: 'round_robin',
round_robin: {},
};
}
}
if ('xds' in obj) {
if ('grpclb' in obj) {
throw new Error('Multiple load balancing policies configured');
}
return {
name: 'xds',
xds: validateXdsConfig(obj.xds),
};
}
if ('grpclb' in obj) {
return {
name: 'grpclb',
grpclb: validateGrpcLbConfig(obj.grpclb),
};
}
throw new Error('No recognized load balancing policy configured');
}