UNPKG

5.8 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 { MethodConfig, ServiceConfig } from './service-config';
19import { StatusObject } from './call-stream';
20import { SubchannelAddress } from './subchannel-address';
21import { GrpcUri, uriToString } from './uri-parser';
22import { ChannelOptions } from './channel-options';
23import { Metadata } from './metadata';
24import { Status } from './constants';
25import { Filter, FilterFactory } from './filter';
26
27export interface CallConfig {
28 methodConfig: MethodConfig;
29 onCommitted?: () => void;
30 pickInformation: { [key: string]: string };
31 status: Status;
32 dynamicFilterFactories: FilterFactory<Filter>[];
33}
34
35/**
36 * Selects a configuration for a method given the name and metadata. Defined in
37 * https://github.com/grpc/proposal/blob/master/A31-xds-timeout-support-and-config-selector.md#new-functionality-in-grpc
38 */
39export interface ConfigSelector {
40 (methodName: string, metadata: Metadata): CallConfig;
41}
42
43/**
44 * A listener object passed to the resolver's constructor that provides name
45 * resolution updates back to the resolver's owner.
46 */
47export interface ResolverListener {
48 /**
49 * Called whenever the resolver has new name resolution results to report
50 * @param addressList The new list of backend addresses
51 * @param serviceConfig The new service configuration corresponding to the
52 * `addressList`. Will be `null` if no service configuration was
53 * retrieved or if the service configuration was invalid
54 * @param serviceConfigError If non-`null`, indicates that the retrieved
55 * service configuration was invalid
56 */
57 onSuccessfulResolution(
58 addressList: SubchannelAddress[],
59 serviceConfig: ServiceConfig | null,
60 serviceConfigError: StatusObject | null,
61 configSelector: ConfigSelector | null,
62 attributes: { [key: string]: unknown }
63 ): void;
64 /**
65 * Called whenever a name resolution attempt fails.
66 * @param error Describes how resolution failed
67 */
68 onError(error: StatusObject): void;
69}
70
71/**
72 * A resolver class that handles one or more of the name syntax schemes defined
73 * in the [gRPC Name Resolution document](https://github.com/grpc/grpc/blob/master/doc/naming.md)
74 */
75export interface Resolver {
76 /**
77 * Indicates that the caller wants new name resolution data. Calling this
78 * function may eventually result in calling one of the `ResolverListener`
79 * functions, but that is not guaranteed. Those functions will never be
80 * called synchronously with the constructor or updateResolution.
81 */
82 updateResolution(): void;
83
84 /**
85 * Destroy the resolver. Should be called when the owning channel shuts down.
86 */
87 destroy(): void;
88}
89
90export interface ResolverConstructor {
91 new (
92 target: GrpcUri,
93 listener: ResolverListener,
94 channelOptions: ChannelOptions
95 ): Resolver;
96 /**
97 * Get the default authority for a target. This loosely corresponds to that
98 * target's hostname. Throws an error if this resolver class cannot parse the
99 * `target`.
100 * @param target
101 */
102 getDefaultAuthority(target: GrpcUri): string;
103}
104
105const registeredResolvers: { [scheme: string]: ResolverConstructor } = {};
106let defaultScheme: string | null = null;
107
108/**
109 * Register a resolver class to handle target names prefixed with the `prefix`
110 * string. This prefix should correspond to a URI scheme name listed in the
111 * [gRPC Name Resolution document](https://github.com/grpc/grpc/blob/master/doc/naming.md)
112 * @param prefix
113 * @param resolverClass
114 */
115export function registerResolver(
116 scheme: string,
117 resolverClass: ResolverConstructor
118) {
119 registeredResolvers[scheme] = resolverClass;
120}
121
122/**
123 * Register a default resolver to handle target names that do not start with
124 * any registered prefix.
125 * @param resolverClass
126 */
127export function registerDefaultScheme(scheme: string) {
128 defaultScheme = scheme;
129}
130
131/**
132 * Create a name resolver for the specified target, if possible. Throws an
133 * error if no such name resolver can be created.
134 * @param target
135 * @param listener
136 */
137export function createResolver(
138 target: GrpcUri,
139 listener: ResolverListener,
140 options: ChannelOptions
141): Resolver {
142 if (target.scheme !== undefined && target.scheme in registeredResolvers) {
143 return new registeredResolvers[target.scheme](target, listener, options);
144 } else {
145 throw new Error(
146 `No resolver could be created for target ${uriToString(target)}`
147 );
148 }
149}
150
151/**
152 * Get the default authority for the specified target, if possible. Throws an
153 * error if no registered name resolver can parse that target string.
154 * @param target
155 */
156export function getDefaultAuthority(target: GrpcUri): string {
157 if (target.scheme !== undefined && target.scheme in registeredResolvers) {
158 return registeredResolvers[target.scheme].getDefaultAuthority(target);
159 } else {
160 throw new Error(`Invalid target ${uriToString(target)}`);
161 }
162}
163
164export function mapUriDefaultScheme(target: GrpcUri): GrpcUri | null {
165 if (target.scheme === undefined || !(target.scheme in registeredResolvers)) {
166 if (defaultScheme !== null) {
167 return {
168 scheme: defaultScheme,
169 authority: undefined,
170 path: uriToString(target),
171 };
172 } else {
173 return null;
174 }
175 }
176 return target;
177}