UNPKG

5.98 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-interface';
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 * Discard all resources owned by the resolver. A later call to
86 * `updateResolution` should reinitialize those resources. No
87 * `ResolverListener` callbacks should be called after `destroy` is called
88 * until `updateResolution` is called again.
89 */
90 destroy(): void;
91}
92
93export interface ResolverConstructor {
94 new (
95 target: GrpcUri,
96 listener: ResolverListener,
97 channelOptions: ChannelOptions
98 ): Resolver;
99 /**
100 * Get the default authority for a target. This loosely corresponds to that
101 * target's hostname. Throws an error if this resolver class cannot parse the
102 * `target`.
103 * @param target
104 */
105 getDefaultAuthority(target: GrpcUri): string;
106}
107
108const registeredResolvers: { [scheme: string]: ResolverConstructor } = {};
109let defaultScheme: string | null = null;
110
111/**
112 * Register a resolver class to handle target names prefixed with the `prefix`
113 * string. This prefix should correspond to a URI scheme name listed in the
114 * [gRPC Name Resolution document](https://github.com/grpc/grpc/blob/master/doc/naming.md)
115 * @param prefix
116 * @param resolverClass
117 */
118export function registerResolver(
119 scheme: string,
120 resolverClass: ResolverConstructor
121) {
122 registeredResolvers[scheme] = resolverClass;
123}
124
125/**
126 * Register a default resolver to handle target names that do not start with
127 * any registered prefix.
128 * @param resolverClass
129 */
130export function registerDefaultScheme(scheme: string) {
131 defaultScheme = scheme;
132}
133
134/**
135 * Create a name resolver for the specified target, if possible. Throws an
136 * error if no such name resolver can be created.
137 * @param target
138 * @param listener
139 */
140export function createResolver(
141 target: GrpcUri,
142 listener: ResolverListener,
143 options: ChannelOptions
144): Resolver {
145 if (target.scheme !== undefined && target.scheme in registeredResolvers) {
146 return new registeredResolvers[target.scheme](target, listener, options);
147 } else {
148 throw new Error(
149 `No resolver could be created for target ${uriToString(target)}`
150 );
151 }
152}
153
154/**
155 * Get the default authority for the specified target, if possible. Throws an
156 * error if no registered name resolver can parse that target string.
157 * @param target
158 */
159export function getDefaultAuthority(target: GrpcUri): string {
160 if (target.scheme !== undefined && target.scheme in registeredResolvers) {
161 return registeredResolvers[target.scheme].getDefaultAuthority(target);
162 } else {
163 throw new Error(`Invalid target ${uriToString(target)}`);
164 }
165}
166
167export function mapUriDefaultScheme(target: GrpcUri): GrpcUri | null {
168 if (target.scheme === undefined || !(target.scheme in registeredResolvers)) {
169 if (defaultScheme !== null) {
170 return {
171 scheme: defaultScheme,
172 authority: undefined,
173 path: uriToString(target),
174 };
175 } else {
176 return null;
177 }
178 }
179 return target;
180}