UNPKG

4.68 kBPlain TextView Raw
1/*
2 * Copyright 2019 gRPC authors.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18import { Subchannel } from './subchannel';
19import { StatusObject } from './call-stream';
20import { Metadata } from './metadata';
21import { Status } from './constants';
22import { LoadBalancer } from './load-balancer';
23import { FilterFactory, Filter } from './filter';
24import { SubchannelInterface } from './subchannel-interface';
25
26export enum PickResultType {
27 COMPLETE,
28 QUEUE,
29 TRANSIENT_FAILURE,
30 DROP,
31}
32
33export interface PickResult {
34 pickResultType: PickResultType;
35 /**
36 * The subchannel to use as the transport for the call. Only meaningful if
37 * `pickResultType` is COMPLETE. If null, indicates that the call should be
38 * dropped.
39 */
40 subchannel: SubchannelInterface | null;
41 /**
42 * The status object to end the call with. Populated if and only if
43 * `pickResultType` is TRANSIENT_FAILURE.
44 */
45 status: StatusObject | null;
46 /**
47 * Extra FilterFactory (can be multiple encapsulated in a FilterStackFactory)
48 * provided by the load balancer to be used with the call. For technical
49 * reasons filters from this factory will not see sendMetadata events.
50 */
51 extraFilterFactories: FilterFactory<Filter>[];
52 onCallStarted: (() => void) | null;
53}
54
55export interface CompletePickResult extends PickResult {
56 pickResultType: PickResultType.COMPLETE;
57 subchannel: SubchannelInterface | null;
58 status: null;
59 extraFilterFactories: FilterFactory<Filter>[];
60 onCallStarted: (() => void) | null;
61}
62
63export interface QueuePickResult extends PickResult {
64 pickResultType: PickResultType.QUEUE;
65 subchannel: null;
66 status: null;
67 extraFilterFactories: [];
68 onCallStarted: null;
69}
70
71export interface TransientFailurePickResult extends PickResult {
72 pickResultType: PickResultType.TRANSIENT_FAILURE;
73 subchannel: null;
74 status: StatusObject;
75 extraFilterFactories: [];
76 onCallStarted: null;
77}
78
79export interface DropCallPickResult extends PickResult {
80 pickResultType: PickResultType.DROP;
81 subchannel: null;
82 status: StatusObject;
83 extraFilterFactories: [];
84 onCallStarted: null;
85}
86
87export interface PickArgs {
88 metadata: Metadata;
89 extraPickInfo: { [key: string]: string };
90}
91
92/**
93 * A proxy object representing the momentary state of a load balancer. Picks
94 * subchannels or returns other information based on that state. Should be
95 * replaced every time the load balancer changes state.
96 */
97export interface Picker {
98 pick(pickArgs: PickArgs): PickResult;
99}
100
101/**
102 * A standard picker representing a load balancer in the TRANSIENT_FAILURE
103 * state. Always responds to every pick request with an UNAVAILABLE status.
104 */
105export class UnavailablePicker implements Picker {
106 private status: StatusObject;
107 constructor(status?: StatusObject) {
108 if (status !== undefined) {
109 this.status = status;
110 } else {
111 this.status = {
112 code: Status.UNAVAILABLE,
113 details: 'No connection established',
114 metadata: new Metadata(),
115 };
116 }
117 }
118 pick(pickArgs: PickArgs): TransientFailurePickResult {
119 return {
120 pickResultType: PickResultType.TRANSIENT_FAILURE,
121 subchannel: null,
122 status: this.status,
123 extraFilterFactories: [],
124 onCallStarted: null,
125 };
126 }
127}
128
129/**
130 * A standard picker representing a load balancer in the IDLE or CONNECTING
131 * state. Always responds to every pick request with a QUEUE pick result
132 * indicating that the pick should be tried again with the next `Picker`. Also
133 * reports back to the load balancer that a connection should be established
134 * once any pick is attempted.
135 */
136export class QueuePicker {
137 private calledExitIdle = false;
138 // Constructed with a load balancer. Calls exitIdle on it the first time pick is called
139 constructor(private loadBalancer: LoadBalancer) {}
140
141 pick(pickArgs: PickArgs): QueuePickResult {
142 if (!this.calledExitIdle) {
143 process.nextTick(() => {
144 this.loadBalancer.exitIdle();
145 });
146 this.calledExitIdle = true;
147 }
148 return {
149 pickResultType: PickResultType.QUEUE,
150 subchannel: null,
151 status: null,
152 extraFilterFactories: [],
153 onCallStarted: null,
154 };
155 }
156}
157
\No newline at end of file