Skip to content

Commit 1f2a22e

Browse files
feat: deferred client initialization (#75)
This PR includes changes from googleapis/gapic-generator-typescript#317 that will move the asynchronous initialization and authentication from the client constructor to an `initialize()` method. This method will be automatically called when the first RPC call is performed. The client library usage has not changed, there is no need to update any code. If you want to make sure the client is authenticated _before_ the first RPC call, you can do ```js await client.initialize(); ``` manually before calling any client method.
1 parent 6ca9763 commit 1f2a22e

File tree

3 files changed

+159
-31
lines changed

3 files changed

+159
-31
lines changed

packages/google-devtools-cloudbuild/src/v1/cloud_build_client.ts

+75-28
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,14 @@ export class CloudBuildClient {
5151
private _descriptors: Descriptors = {page: {}, stream: {}, longrunning: {}};
5252
private _innerApiCalls: {[name: string]: Function};
5353
private _terminated = false;
54+
private _opts: ClientOptions;
55+
private _gaxModule: typeof gax | typeof gax.fallback;
56+
private _gaxGrpc: gax.GrpcClient | gax.fallback.GrpcClient;
57+
private _protos: {};
58+
private _defaults: {[method: string]: gax.CallSettings};
5459
auth: gax.GoogleAuth;
5560
operationsClient: gax.OperationsClient;
56-
cloudBuildStub: Promise<{[name: string]: Function}>;
61+
cloudBuildStub?: Promise<{[name: string]: Function}>;
5762

5863
/**
5964
* Construct an instance of CloudBuildClient.
@@ -77,8 +82,6 @@ export class CloudBuildClient {
7782
* app is running in an environment which supports
7883
* {@link https://developers.google.com/identity/protocols/application-default-credentials Application Default Credentials},
7984
* your project ID will be detected automatically.
80-
* @param {function} [options.promise] - Custom promise module to use instead
81-
* of native Promises.
8285
* @param {string} [options.apiEndpoint] - The domain name of the
8386
* API remote host.
8487
*/
@@ -108,25 +111,28 @@ export class CloudBuildClient {
108111
// If we are in browser, we are already using fallback because of the
109112
// "browser" field in package.json.
110113
// But if we were explicitly requested to use fallback, let's do it now.
111-
const gaxModule = !isBrowser && opts.fallback ? gax.fallback : gax;
114+
this._gaxModule = !isBrowser && opts.fallback ? gax.fallback : gax;
112115

113116
// Create a `gaxGrpc` object, with any grpc-specific options
114117
// sent to the client.
115118
opts.scopes = (this.constructor as typeof CloudBuildClient).scopes;
116-
const gaxGrpc = new gaxModule.GrpcClient(opts);
119+
this._gaxGrpc = new this._gaxModule.GrpcClient(opts);
120+
121+
// Save options to use in initialize() method.
122+
this._opts = opts;
117123

118124
// Save the auth object to the client, for use by other methods.
119-
this.auth = gaxGrpc.auth as gax.GoogleAuth;
125+
this.auth = this._gaxGrpc.auth as gax.GoogleAuth;
120126

121127
// Determine the client header string.
122-
const clientHeader = [`gax/${gaxModule.version}`, `gapic/${version}`];
128+
const clientHeader = [`gax/${this._gaxModule.version}`, `gapic/${version}`];
123129
if (typeof process !== 'undefined' && 'versions' in process) {
124130
clientHeader.push(`gl-node/${process.versions.node}`);
125131
} else {
126-
clientHeader.push(`gl-web/${gaxModule.version}`);
132+
clientHeader.push(`gl-web/${this._gaxModule.version}`);
127133
}
128134
if (!opts.fallback) {
129-
clientHeader.push(`grpc/${gaxGrpc.grpcVersion}`);
135+
clientHeader.push(`grpc/${this._gaxGrpc.grpcVersion}`);
130136
}
131137
if (opts.libName && opts.libVersion) {
132138
clientHeader.push(`${opts.libName}/${opts.libVersion}`);
@@ -142,20 +148,20 @@ export class CloudBuildClient {
142148
'protos',
143149
'protos.json'
144150
);
145-
const protos = gaxGrpc.loadProto(
151+
this._protos = this._gaxGrpc.loadProto(
146152
opts.fallback ? require('../../protos/protos.json') : nodejsProtoPath
147153
);
148154

149155
// Some of the methods on this service return "paged" results,
150156
// (e.g. 50 results at a time, with tokens to get subsequent
151157
// pages). Denote the keys used for pagination and results.
152158
this._descriptors.page = {
153-
listBuilds: new gaxModule.PageDescriptor(
159+
listBuilds: new this._gaxModule.PageDescriptor(
154160
'pageToken',
155161
'nextPageToken',
156162
'builds'
157163
),
158-
listBuildTriggers: new gaxModule.PageDescriptor(
164+
listBuildTriggers: new this._gaxModule.PageDescriptor(
159165
'pageToken',
160166
'nextPageToken',
161167
'triggers'
@@ -166,13 +172,15 @@ export class CloudBuildClient {
166172
// an Operation object that allows for tracking of the operation,
167173
// rather than holding a request open.
168174
const protoFilesRoot = opts.fallback
169-
? gaxModule.protobuf.Root.fromJSON(require('../../protos/protos.json'))
170-
: gaxModule.protobuf.loadSync(nodejsProtoPath);
175+
? this._gaxModule.protobuf.Root.fromJSON(
176+
require('../../protos/protos.json')
177+
)
178+
: this._gaxModule.protobuf.loadSync(nodejsProtoPath);
171179

172-
this.operationsClient = gaxModule
180+
this.operationsClient = this._gaxModule
173181
.lro({
174182
auth: this.auth,
175-
grpc: 'grpc' in gaxGrpc ? gaxGrpc.grpc : undefined,
183+
grpc: 'grpc' in this._gaxGrpc ? this._gaxGrpc.grpc : undefined,
176184
})
177185
.operationsClient(opts);
178186
const createBuildResponse = protoFilesRoot.lookup(
@@ -195,25 +203,25 @@ export class CloudBuildClient {
195203
) as gax.protobuf.Type;
196204

197205
this._descriptors.longrunning = {
198-
createBuild: new gaxModule.LongrunningDescriptor(
206+
createBuild: new this._gaxModule.LongrunningDescriptor(
199207
this.operationsClient,
200208
createBuildResponse.decode.bind(createBuildResponse),
201209
createBuildMetadata.decode.bind(createBuildMetadata)
202210
),
203-
retryBuild: new gaxModule.LongrunningDescriptor(
211+
retryBuild: new this._gaxModule.LongrunningDescriptor(
204212
this.operationsClient,
205213
retryBuildResponse.decode.bind(retryBuildResponse),
206214
retryBuildMetadata.decode.bind(retryBuildMetadata)
207215
),
208-
runBuildTrigger: new gaxModule.LongrunningDescriptor(
216+
runBuildTrigger: new this._gaxModule.LongrunningDescriptor(
209217
this.operationsClient,
210218
runBuildTriggerResponse.decode.bind(runBuildTriggerResponse),
211219
runBuildTriggerMetadata.decode.bind(runBuildTriggerMetadata)
212220
),
213221
};
214222

215223
// Put together the default options sent with requests.
216-
const defaults = gaxGrpc.constructSettings(
224+
this._defaults = this._gaxGrpc.constructSettings(
217225
'google.devtools.cloudbuild.v1.CloudBuild',
218226
gapicConfig as gax.ClientConfig,
219227
opts.clientConfig || {},
@@ -224,17 +232,35 @@ export class CloudBuildClient {
224232
// of calling the API is handled in `google-gax`, with this code
225233
// merely providing the destination and request information.
226234
this._innerApiCalls = {};
235+
}
236+
237+
/**
238+
* Initialize the client.
239+
* Performs asynchronous operations (such as authentication) and prepares the client.
240+
* This function will be called automatically when any class method is called for the
241+
* first time, but if you need to initialize it before calling an actual method,
242+
* feel free to call initialize() directly.
243+
*
244+
* You can await on this method if you want to make sure the client is initialized.
245+
*
246+
* @returns {Promise} A promise that resolves to an authenticated service stub.
247+
*/
248+
initialize() {
249+
// If the client stub promise is already initialized, return immediately.
250+
if (this.cloudBuildStub) {
251+
return this.cloudBuildStub;
252+
}
227253

228254
// Put together the "service stub" for
229255
// google.devtools.cloudbuild.v1.CloudBuild.
230-
this.cloudBuildStub = gaxGrpc.createStub(
231-
opts.fallback
232-
? (protos as protobuf.Root).lookupService(
256+
this.cloudBuildStub = this._gaxGrpc.createStub(
257+
this._opts.fallback
258+
? (this._protos as protobuf.Root).lookupService(
233259
'google.devtools.cloudbuild.v1.CloudBuild'
234260
)
235261
: // tslint:disable-next-line no-any
236-
(protos as any).google.devtools.cloudbuild.v1.CloudBuild,
237-
opts
262+
(this._protos as any).google.devtools.cloudbuild.v1.CloudBuild,
263+
this._opts
238264
) as Promise<{[method: string]: Function}>;
239265

240266
// Iterate over each of the methods that the service provides
@@ -271,9 +297,9 @@ export class CloudBuildClient {
271297
}
272298
);
273299

274-
const apiCall = gaxModule.createApiCall(
300+
const apiCall = this._gaxModule.createApiCall(
275301
innerCallPromise,
276-
defaults[methodName],
302+
this._defaults[methodName],
277303
this._descriptors.page[methodName] ||
278304
this._descriptors.stream[methodName] ||
279305
this._descriptors.longrunning[methodName]
@@ -287,6 +313,8 @@ export class CloudBuildClient {
287313
return apiCall(argument, callOptions, callback);
288314
};
289315
}
316+
317+
return this.cloudBuildStub;
290318
}
291319

292320
/**
@@ -407,6 +435,7 @@ export class CloudBuildClient {
407435
options = optionsOrCallback as gax.CallOptions;
408436
}
409437
options = options || {};
438+
this.initialize();
410439
return this._innerApiCalls.getBuild(request, options, callback);
411440
}
412441
cancelBuild(
@@ -474,6 +503,7 @@ export class CloudBuildClient {
474503
options = optionsOrCallback as gax.CallOptions;
475504
}
476505
options = options || {};
506+
this.initialize();
477507
return this._innerApiCalls.cancelBuild(request, options, callback);
478508
}
479509
createBuildTrigger(
@@ -551,6 +581,7 @@ export class CloudBuildClient {
551581
options = optionsOrCallback as gax.CallOptions;
552582
}
553583
options = options || {};
584+
this.initialize();
554585
return this._innerApiCalls.createBuildTrigger(request, options, callback);
555586
}
556587
getBuildTrigger(
@@ -628,6 +659,7 @@ export class CloudBuildClient {
628659
options = optionsOrCallback as gax.CallOptions;
629660
}
630661
options = options || {};
662+
this.initialize();
631663
return this._innerApiCalls.getBuildTrigger(request, options, callback);
632664
}
633665
deleteBuildTrigger(
@@ -705,6 +737,7 @@ export class CloudBuildClient {
705737
options = optionsOrCallback as gax.CallOptions;
706738
}
707739
options = options || {};
740+
this.initialize();
708741
return this._innerApiCalls.deleteBuildTrigger(request, options, callback);
709742
}
710743
updateBuildTrigger(
@@ -784,6 +817,7 @@ export class CloudBuildClient {
784817
options = optionsOrCallback as gax.CallOptions;
785818
}
786819
options = options || {};
820+
this.initialize();
787821
return this._innerApiCalls.updateBuildTrigger(request, options, callback);
788822
}
789823
createWorkerPool(
@@ -861,6 +895,7 @@ export class CloudBuildClient {
861895
options = optionsOrCallback as gax.CallOptions;
862896
}
863897
options = options || {};
898+
this.initialize();
864899
return this._innerApiCalls.createWorkerPool(request, options, callback);
865900
}
866901
getWorkerPool(
@@ -937,6 +972,7 @@ export class CloudBuildClient {
937972
options = optionsOrCallback as gax.CallOptions;
938973
}
939974
options = options || {};
975+
this.initialize();
940976
return this._innerApiCalls.getWorkerPool(request, options, callback);
941977
}
942978
deleteWorkerPool(
@@ -1013,6 +1049,7 @@ export class CloudBuildClient {
10131049
options = optionsOrCallback as gax.CallOptions;
10141050
}
10151051
options = options || {};
1052+
this.initialize();
10161053
return this._innerApiCalls.deleteWorkerPool(request, options, callback);
10171054
}
10181055
updateWorkerPool(
@@ -1091,6 +1128,7 @@ export class CloudBuildClient {
10911128
options = optionsOrCallback as gax.CallOptions;
10921129
}
10931130
options = options || {};
1131+
this.initialize();
10941132
return this._innerApiCalls.updateWorkerPool(request, options, callback);
10951133
}
10961134
listWorkerPools(
@@ -1166,6 +1204,7 @@ export class CloudBuildClient {
11661204
options = optionsOrCallback as gax.CallOptions;
11671205
}
11681206
options = options || {};
1207+
this.initialize();
11691208
return this._innerApiCalls.listWorkerPools(request, options, callback);
11701209
}
11711210

@@ -1252,6 +1291,7 @@ export class CloudBuildClient {
12521291
options = optionsOrCallback as gax.CallOptions;
12531292
}
12541293
options = options || {};
1294+
this.initialize();
12551295
return this._innerApiCalls.createBuild(request, options, callback);
12561296
}
12571297
retryBuild(
@@ -1359,6 +1399,7 @@ export class CloudBuildClient {
13591399
options = optionsOrCallback as gax.CallOptions;
13601400
}
13611401
options = options || {};
1402+
this.initialize();
13621403
return this._innerApiCalls.retryBuild(request, options, callback);
13631404
}
13641405
runBuildTrigger(
@@ -1442,6 +1483,7 @@ export class CloudBuildClient {
14421483
options = optionsOrCallback as gax.CallOptions;
14431484
}
14441485
options = options || {};
1486+
this.initialize();
14451487
return this._innerApiCalls.runBuildTrigger(request, options, callback);
14461488
}
14471489
listBuilds(
@@ -1527,6 +1569,7 @@ export class CloudBuildClient {
15271569
options = optionsOrCallback as gax.CallOptions;
15281570
}
15291571
options = options || {};
1572+
this.initialize();
15301573
return this._innerApiCalls.listBuilds(request, options, callback);
15311574
}
15321575

@@ -1565,6 +1608,7 @@ export class CloudBuildClient {
15651608
request = request || {};
15661609
options = options || {};
15671610
const callSettings = new gax.CallSettings(options);
1611+
this.initialize();
15681612
return this._descriptors.page.listBuilds.createStream(
15691613
this._innerApiCalls.listBuilds as gax.GaxCall,
15701614
request,
@@ -1651,6 +1695,7 @@ export class CloudBuildClient {
16511695
options = optionsOrCallback as gax.CallOptions;
16521696
}
16531697
options = options || {};
1698+
this.initialize();
16541699
return this._innerApiCalls.listBuildTriggers(request, options, callback);
16551700
}
16561701

@@ -1687,6 +1732,7 @@ export class CloudBuildClient {
16871732
request = request || {};
16881733
options = options || {};
16891734
const callSettings = new gax.CallSettings(options);
1735+
this.initialize();
16901736
return this._descriptors.page.listBuildTriggers.createStream(
16911737
this._innerApiCalls.listBuildTriggers as gax.GaxCall,
16921738
request,
@@ -1700,8 +1746,9 @@ export class CloudBuildClient {
17001746
* The client will no longer be usable and all future behavior is undefined.
17011747
*/
17021748
close(): Promise<void> {
1749+
this.initialize();
17031750
if (!this._terminated) {
1704-
return this.cloudBuildStub.then(stub => {
1751+
return this.cloudBuildStub!.then(stub => {
17051752
this._terminated = true;
17061753
stub.close();
17071754
});

packages/google-devtools-cloudbuild/synth.metadata

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
{
2-
"updateTime": "2020-02-29T19:14:13.934361Z",
2+
"updateTime": "2020-03-05T23:03:38.966192Z",
33
"sources": [
44
{
55
"git": {
66
"name": "googleapis",
77
"remote": "https://github.com/googleapis/googleapis.git",
8-
"sha": "83c6f84035ee0f80eaa44d8b688a010461cc4080",
9-
"internalRef": "297918498"
8+
"sha": "f0b581b5bdf803e45201ecdb3688b60e381628a8",
9+
"internalRef": "299181282",
10+
"log": "f0b581b5bdf803e45201ecdb3688b60e381628a8\nfix: recommendationengine/v1beta1 update some comments\n\nPiperOrigin-RevId: 299181282\n\n10e9a0a833dc85ff8f05b2c67ebe5ac785fe04ff\nbuild: add generated BUILD file for Routes Preferred API\n\nPiperOrigin-RevId: 299164808\n\n86738c956a8238d7c77f729be78b0ed887a6c913\npublish v1p1beta1: update with absolute address in comments\n\nPiperOrigin-RevId: 299152383\n\n73d9f2ad4591de45c2e1f352bc99d70cbd2a6d95\npublish v1: update with absolute address in comments\n\nPiperOrigin-RevId: 299147194\n\nd2158f24cb77b0b0ccfe68af784c6a628705e3c6\npublish v1beta2: update with absolute address in comments\n\nPiperOrigin-RevId: 299147086\n\n7fca61292c11b4cd5b352cee1a50bf88819dd63b\npublish v1p2beta1: update with absolute address in comments\n\nPiperOrigin-RevId: 299146903\n\n583b7321624736e2c490e328f4b1957335779295\npublish v1p3beta1: update with absolute address in comments\n\nPiperOrigin-RevId: 299146674\n\n638253bf86d1ce1c314108a089b7351440c2f0bf\nfix: add java_multiple_files option for automl text_sentiment.proto\n\nPiperOrigin-RevId: 298971070\n\n373d655703bf914fb8b0b1cc4071d772bac0e0d1\nUpdate Recs AI Beta public bazel file\n\nPiperOrigin-RevId: 298961623\n\ndcc5d00fc8a8d8b56f16194d7c682027b2c66a3b\nfix: add java_multiple_files option for automl classification.proto\n\nPiperOrigin-RevId: 298953301\n\na3f791827266f3496a6a5201d58adc4bb265c2a3\nchore: automl/v1 publish annotations and retry config\n\nPiperOrigin-RevId: 298942178\n\n01c681586d8d6dbd60155289b587aee678530bd9\nMark return_immediately in PullRequest deprecated.\n\nPiperOrigin-RevId: 298893281\n\nc9f5e9c4bfed54bbd09227e990e7bded5f90f31c\nRemove out of date documentation for predicate support on the Storage API\n\nPiperOrigin-RevId: 298883309\n\nfd5b3b8238d783b04692a113ffe07c0363f5de0f\ngenerate webrisk v1 proto\n\nPiperOrigin-RevId: 298847934\n\n541b1ded4abadcc38e8178680b0677f65594ea6f\nUpdate cloud asset api v1p4beta1.\n\nPiperOrigin-RevId: 298686266\n\nc0d171acecb4f5b0bfd2c4ca34fc54716574e300\n Updated to include the Notification v1 API.\n\nPiperOrigin-RevId: 298652775\n\n2346a9186c0bff2c9cc439f2459d558068637e05\nAdd Service Directory v1beta1 protos and configs\n\nPiperOrigin-RevId: 298625638\n\na78ed801b82a5c6d9c5368e24b1412212e541bb7\nPublishing v3 protos and configs.\n\nPiperOrigin-RevId: 298607357\n\n4a180bfff8a21645b3a935c2756e8d6ab18a74e0\nautoml/v1beta1 publish proto updates\n\nPiperOrigin-RevId: 298484782\n\n6de6e938b7df1cd62396563a067334abeedb9676\nchore: use the latest gapic-generator and protoc-java-resource-name-plugin in Bazel workspace.\n\nPiperOrigin-RevId: 298474513\n\n244ab2b83a82076a1fa7be63b7e0671af73f5c02\nAdds service config definition for bigqueryreservation v1\n\nPiperOrigin-RevId: 298455048\n\n"
1011
}
1112
},
1213
{

0 commit comments

Comments
 (0)