2 Object.defineProperty(exports, "__esModule", { value: true });
5 * Copyright 2018 gRPC authors.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
20 const grpc = require("grpc");
21 const util = require("util");
22 const gcp_channel_factory_1 = require("./gcp_channel_factory");
23 exports.GcpChannelFactory = gcp_channel_factory_1.GcpChannelFactory;
24 const protoRoot = require("./generated/grpc_gcp");
25 var ApiConfig = protoRoot.grpc.gcp.ApiConfig;
26 var AffinityConfig = protoRoot.grpc.gcp.AffinityConfig;
28 * Create ApiConfig proto message from config object.
29 * @param apiDefinition Api object that specifies channel pool configuation.
30 * @return A protobuf message type.
32 function createGcpApiConfig(apiDefinition) {
33 return ApiConfig.fromObject(apiDefinition);
35 exports.createGcpApiConfig = createGcpApiConfig;
37 * Function for creating a gcp channel factory.
39 * @param address The address of the server to connect to.
40 * @param credentials Channel credentials to use when connecting
41 * @param options A map of channel options that will be passed to the core.
42 * @return {GcpChannelFactory} A GcpChannelFactory instance.
44 function gcpChannelFactoryOverride(address, credentials, options) {
45 return new gcp_channel_factory_1.GcpChannelFactory(address, credentials, options);
47 exports.gcpChannelFactoryOverride = gcpChannelFactoryOverride;
49 * Pass in call properties and return a new object with modified values.
50 * This function will be used together with gcpChannelFactoryOverride
51 * when constructing a grpc Client.
53 * @param callProperties Call properties with channel factory object.
54 * @return Modified call properties with selected grpc channel object.
56 function gcpCallInvocationTransformer(callProperties) {
57 const channelFactory = callProperties.channel;
58 if (!channelFactory || !(channelFactory instanceof gcp_channel_factory_1.GcpChannelFactory)) {
59 // The gcpCallInvocationTransformer needs to use gcp channel factory.
60 return callProperties;
62 const argument = callProperties.argument;
63 const metadata = callProperties.metadata;
64 const call = callProperties.call;
65 const methodDefinition = callProperties.methodDefinition;
66 const path = methodDefinition.path;
67 const callOptions = callProperties.callOptions;
68 const callback = callProperties.callback;
69 const preProcessResult = preProcess(channelFactory, path, argument);
70 const channelRef = preProcessResult.channelRef;
71 const boundKey = preProcessResult.boundKey;
72 const postProcessInterceptor = (
73 // tslint:disable-next-line:no-any options can be any object
74 options, nextCall) => {
75 // tslint:disable-next-line:no-any protobuf message
78 start: (metadata, listener, next) => {
80 onReceiveMetadata: (metadata, next) => {
83 // tslint:disable-next-line:no-any protobuf message
84 onReceiveMessage: (message, next) => {
86 firstMessage = message;
89 onReceiveStatus: (status, next) => {
90 if (status.code === grpc.status.OK) {
91 postProcess(channelFactory, channelRef, path, boundKey, firstMessage);
96 next(metadata, newListener);
98 // tslint:disable-next-line:no-any protobuf message
99 sendMessage: (message, next) => {
102 halfClose: (next) => {
109 return new grpc.InterceptingCall(nextCall(options), requester);
111 // Append interceptor to existing interceptors list.
112 const newCallOptions = Object.assign({}, callOptions);
113 const interceptors = callOptions.interceptors ? callOptions.interceptors : [];
114 newCallOptions.interceptors = interceptors.concat([postProcessInterceptor]);
119 channel: channelRef.getChannel(),
121 callOptions: newCallOptions,
125 exports.gcpCallInvocationTransformer = gcpCallInvocationTransformer;
127 * Handle channel affinity and pick a channel before call starts.
128 * @param channelFactory The channel management factory.
129 * @param path Method path.
130 * @param argument The request arguments object.
131 * @return Result containing bound affinity key and the chosen channel ref
134 function preProcess(channelFactory, path,
135 // tslint:disable-next-line:no-any protobuf message
137 const affinityConfig = channelFactory.getAffinityConfig(path);
139 if (argument && affinityConfig) {
140 const command = affinityConfig.command;
141 if (command === AffinityConfig.Command.BOUND ||
142 command === AffinityConfig.Command.UNBIND) {
143 boundKey = getAffinityKeyFromMessage(affinityConfig.affinityKey, argument);
146 const channelRef = channelFactory.getChannelRef(boundKey);
147 channelRef.activeStreamsCountIncr();
154 * Handle channel affinity and streams count after call is done.
155 * @param channelFactory The channel management factory.
156 * @param channelRef ChannelRef instance that contains a real grpc channel.
157 * @param path Method path.
158 * @param boundKey Affinity key bound to a channel.
159 * @param responseMsg Response proto message.
161 function postProcess(channelFactory, channelRef, path, boundKey,
162 // tslint:disable-next-line:no-any protobuf message
164 if (!channelFactory || !responseMsg)
166 const affinityConfig = channelFactory.getAffinityConfig(path);
167 if (affinityConfig && affinityConfig.command) {
168 const command = affinityConfig.command;
169 if (command === AffinityConfig.Command.BIND) {
170 const affinityKey = getAffinityKeyFromMessage(affinityConfig.affinityKey, responseMsg);
171 channelFactory.bind(channelRef, affinityKey);
173 else if (command === AffinityConfig.Command.UNBIND) {
174 channelFactory.unbind(boundKey);
177 channelRef.activeStreamsCountDecr();
180 * Retrieve affinity key specified in the proto message.
181 * @param affinityKeyName affinity key locator.
182 * @param message proto message that contains affinity info.
183 * @return Affinity key string.
185 function getAffinityKeyFromMessage(affinityKeyName,
186 // tslint:disable-next-line:no-any protobuf message
188 if (affinityKeyName) {
189 let currMessage = message;
190 const names = affinityKeyName.split('.');
192 for (; i < names.length; i++) {
193 if (currMessage[names[i]]) {
194 // check if the proto message is generated by protobufjs.
195 currMessage = currMessage[names[i]];
198 // otherwise use jspb format.
199 const getter = 'get' + names[i].charAt(0).toUpperCase() + names[i].substr(1);
200 if (!currMessage || typeof currMessage[getter] !== 'function')
202 currMessage = currMessage[getter]();
205 if (i !== 0 && i === names.length)
208 console.error(util.format('Cannot find affinity value from proto message using affinity_key: %s.', affinityKeyName));
211 //# sourceMappingURL=index.js.map