|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import { StatusObject } from './call-interface'; |
|
import { Metadata } from './metadata'; |
|
import { Status } from './constants'; |
|
import { LoadBalancer } from './load-balancer'; |
|
import { SubchannelInterface } from './subchannel-interface'; |
|
|
|
export enum PickResultType { |
|
COMPLETE, |
|
QUEUE, |
|
TRANSIENT_FAILURE, |
|
DROP, |
|
} |
|
|
|
export interface PickResult { |
|
pickResultType: PickResultType; |
|
|
|
|
|
|
|
|
|
|
|
subchannel: SubchannelInterface | null; |
|
|
|
|
|
|
|
|
|
status: StatusObject | null; |
|
onCallStarted: (() => void) | null; |
|
onCallEnded: ((statusCode: Status) => void) | null; |
|
} |
|
|
|
export interface CompletePickResult extends PickResult { |
|
pickResultType: PickResultType.COMPLETE; |
|
subchannel: SubchannelInterface | null; |
|
status: null; |
|
onCallStarted: (() => void) | null; |
|
onCallEnded: ((statusCode: Status) => void) | null; |
|
} |
|
|
|
export interface QueuePickResult extends PickResult { |
|
pickResultType: PickResultType.QUEUE; |
|
subchannel: null; |
|
status: null; |
|
onCallStarted: null; |
|
onCallEnded: null; |
|
} |
|
|
|
export interface TransientFailurePickResult extends PickResult { |
|
pickResultType: PickResultType.TRANSIENT_FAILURE; |
|
subchannel: null; |
|
status: StatusObject; |
|
onCallStarted: null; |
|
onCallEnded: null; |
|
} |
|
|
|
export interface DropCallPickResult extends PickResult { |
|
pickResultType: PickResultType.DROP; |
|
subchannel: null; |
|
status: StatusObject; |
|
onCallStarted: null; |
|
onCallEnded: null; |
|
} |
|
|
|
export interface PickArgs { |
|
metadata: Metadata; |
|
extraPickInfo: { [key: string]: string }; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
export interface Picker { |
|
pick(pickArgs: PickArgs): PickResult; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
export class UnavailablePicker implements Picker { |
|
private status: StatusObject; |
|
constructor(status?: Partial<StatusObject>) { |
|
this.status = { |
|
code: Status.UNAVAILABLE, |
|
details: 'No connection established', |
|
metadata: new Metadata(), |
|
...status, |
|
}; |
|
} |
|
pick(pickArgs: PickArgs): TransientFailurePickResult { |
|
return { |
|
pickResultType: PickResultType.TRANSIENT_FAILURE, |
|
subchannel: null, |
|
status: this.status, |
|
onCallStarted: null, |
|
onCallEnded: null, |
|
}; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export class QueuePicker { |
|
private calledExitIdle = false; |
|
|
|
constructor(private loadBalancer: LoadBalancer) {} |
|
|
|
pick(pickArgs: PickArgs): QueuePickResult { |
|
if (!this.calledExitIdle) { |
|
process.nextTick(() => { |
|
this.loadBalancer.exitIdle(); |
|
}); |
|
this.calledExitIdle = true; |
|
} |
|
return { |
|
pickResultType: PickResultType.QUEUE, |
|
subchannel: null, |
|
status: null, |
|
onCallStarted: null, |
|
onCallEnded: null, |
|
}; |
|
} |
|
} |
|
|