Skip to content

Commit 9381d3e

Browse files
feat: deferred client initialization (#304)
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 c13d673 commit 9381d3e

5 files changed

Lines changed: 194 additions & 54 deletions

File tree

packages/google-cloud-oslogin/src/v1/os_login_service_client.ts

Lines changed: 55 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,13 @@ export class OsLoginServiceClient {
4444
private _innerApiCalls: {[name: string]: Function};
4545
private _pathTemplates: {[name: string]: gax.PathTemplate};
4646
private _terminated = false;
47+
private _opts: ClientOptions;
48+
private _gaxModule: typeof gax | typeof gax.fallback;
49+
private _gaxGrpc: gax.GrpcClient | gax.fallback.GrpcClient;
50+
private _protos: {};
51+
private _defaults: {[method: string]: gax.CallSettings};
4752
auth: gax.GoogleAuth;
48-
osLoginServiceStub: Promise<{[name: string]: Function}>;
53+
osLoginServiceStub?: Promise<{[name: string]: Function}>;
4954

5055
/**
5156
* Construct an instance of OsLoginServiceClient.
@@ -69,8 +74,6 @@ export class OsLoginServiceClient {
6974
* app is running in an environment which supports
7075
* {@link https://developers.google.com/identity/protocols/application-default-credentials Application Default Credentials},
7176
* your project ID will be detected automatically.
72-
* @param {function} [options.promise] - Custom promise module to use instead
73-
* of native Promises.
7477
* @param {string} [options.apiEndpoint] - The domain name of the
7578
* API remote host.
7679
*/
@@ -100,25 +103,28 @@ export class OsLoginServiceClient {
100103
// If we are in browser, we are already using fallback because of the
101104
// "browser" field in package.json.
102105
// But if we were explicitly requested to use fallback, let's do it now.
103-
const gaxModule = !isBrowser && opts.fallback ? gax.fallback : gax;
106+
this._gaxModule = !isBrowser && opts.fallback ? gax.fallback : gax;
104107

105108
// Create a `gaxGrpc` object, with any grpc-specific options
106109
// sent to the client.
107110
opts.scopes = (this.constructor as typeof OsLoginServiceClient).scopes;
108-
const gaxGrpc = new gaxModule.GrpcClient(opts);
111+
this._gaxGrpc = new this._gaxModule.GrpcClient(opts);
112+
113+
// Save options to use in initialize() method.
114+
this._opts = opts;
109115

110116
// Save the auth object to the client, for use by other methods.
111-
this.auth = gaxGrpc.auth as gax.GoogleAuth;
117+
this.auth = this._gaxGrpc.auth as gax.GoogleAuth;
112118

113119
// Determine the client header string.
114-
const clientHeader = [`gax/${gaxModule.version}`, `gapic/${version}`];
120+
const clientHeader = [`gax/${this._gaxModule.version}`, `gapic/${version}`];
115121
if (typeof process !== 'undefined' && 'versions' in process) {
116122
clientHeader.push(`gl-node/${process.versions.node}`);
117123
} else {
118-
clientHeader.push(`gl-web/${gaxModule.version}`);
124+
clientHeader.push(`gl-web/${this._gaxModule.version}`);
119125
}
120126
if (!opts.fallback) {
121-
clientHeader.push(`grpc/${gaxGrpc.grpcVersion}`);
127+
clientHeader.push(`grpc/${this._gaxGrpc.grpcVersion}`);
122128
}
123129
if (opts.libName && opts.libVersion) {
124130
clientHeader.push(`${opts.libName}/${opts.libVersion}`);
@@ -134,25 +140,25 @@ export class OsLoginServiceClient {
134140
'protos',
135141
'protos.json'
136142
);
137-
const protos = gaxGrpc.loadProto(
143+
this._protos = this._gaxGrpc.loadProto(
138144
opts.fallback ? require('../../protos/protos.json') : nodejsProtoPath
139145
);
140146

141147
// This API contains "path templates"; forward-slash-separated
142148
// identifiers to uniquely identify resources within the API.
143149
// Create useful helper objects for these.
144150
this._pathTemplates = {
145-
posixAccountPathTemplate: new gaxModule.PathTemplate(
151+
posixAccountPathTemplate: new this._gaxModule.PathTemplate(
146152
'users/{user}/projects/{project}'
147153
),
148-
sshPublicKeyPathTemplate: new gaxModule.PathTemplate(
154+
sshPublicKeyPathTemplate: new this._gaxModule.PathTemplate(
149155
'users/{user}/sshPublicKeys/{fingerprint}'
150156
),
151-
userPathTemplate: new gaxModule.PathTemplate('users/{user}'),
157+
userPathTemplate: new this._gaxModule.PathTemplate('users/{user}'),
152158
};
153159

154160
// Put together the default options sent with requests.
155-
const defaults = gaxGrpc.constructSettings(
161+
this._defaults = this._gaxGrpc.constructSettings(
156162
'google.cloud.oslogin.v1.OsLoginService',
157163
gapicConfig as gax.ClientConfig,
158164
opts.clientConfig || {},
@@ -163,17 +169,35 @@ export class OsLoginServiceClient {
163169
// of calling the API is handled in `google-gax`, with this code
164170
// merely providing the destination and request information.
165171
this._innerApiCalls = {};
172+
}
173+
174+
/**
175+
* Initialize the client.
176+
* Performs asynchronous operations (such as authentication) and prepares the client.
177+
* This function will be called automatically when any class method is called for the
178+
* first time, but if you need to initialize it before calling an actual method,
179+
* feel free to call initialize() directly.
180+
*
181+
* You can await on this method if you want to make sure the client is initialized.
182+
*
183+
* @returns {Promise} A promise that resolves to an authenticated service stub.
184+
*/
185+
initialize() {
186+
// If the client stub promise is already initialized, return immediately.
187+
if (this.osLoginServiceStub) {
188+
return this.osLoginServiceStub;
189+
}
166190

167191
// Put together the "service stub" for
168192
// google.cloud.oslogin.v1.OsLoginService.
169-
this.osLoginServiceStub = gaxGrpc.createStub(
170-
opts.fallback
171-
? (protos as protobuf.Root).lookupService(
193+
this.osLoginServiceStub = this._gaxGrpc.createStub(
194+
this._opts.fallback
195+
? (this._protos as protobuf.Root).lookupService(
172196
'google.cloud.oslogin.v1.OsLoginService'
173197
)
174198
: // tslint:disable-next-line no-any
175-
(protos as any).google.cloud.oslogin.v1.OsLoginService,
176-
opts
199+
(this._protos as any).google.cloud.oslogin.v1.OsLoginService,
200+
this._opts
177201
) as Promise<{[method: string]: Function}>;
178202

179203
// Iterate over each of the methods that the service provides
@@ -200,9 +224,9 @@ export class OsLoginServiceClient {
200224
}
201225
);
202226

203-
const apiCall = gaxModule.createApiCall(
227+
const apiCall = this._gaxModule.createApiCall(
204228
innerCallPromise,
205-
defaults[methodName],
229+
this._defaults[methodName],
206230
this._descriptors.page[methodName] ||
207231
this._descriptors.stream[methodName] ||
208232
this._descriptors.longrunning[methodName]
@@ -216,6 +240,8 @@ export class OsLoginServiceClient {
216240
return apiCall(argument, callOptions, callback);
217241
};
218242
}
243+
244+
return this.osLoginServiceStub;
219245
}
220246

221247
/**
@@ -351,6 +377,7 @@ export class OsLoginServiceClient {
351377
] = gax.routingHeader.fromParams({
352378
name: request.name || '',
353379
});
380+
this.initialize();
354381
return this._innerApiCalls.deletePosixAccount(request, options, callback);
355382
}
356383
deleteSshPublicKey(
@@ -433,6 +460,7 @@ export class OsLoginServiceClient {
433460
] = gax.routingHeader.fromParams({
434461
name: request.name || '',
435462
});
463+
this.initialize();
436464
return this._innerApiCalls.deleteSshPublicKey(request, options, callback);
437465
}
438466
getLoginProfile(
@@ -510,6 +538,7 @@ export class OsLoginServiceClient {
510538
] = gax.routingHeader.fromParams({
511539
name: request.name || '',
512540
});
541+
this.initialize();
513542
return this._innerApiCalls.getLoginProfile(request, options, callback);
514543
}
515544
getSshPublicKey(
@@ -584,6 +613,7 @@ export class OsLoginServiceClient {
584613
] = gax.routingHeader.fromParams({
585614
name: request.name || '',
586615
});
616+
this.initialize();
587617
return this._innerApiCalls.getSshPublicKey(request, options, callback);
588618
}
589619
importSshPublicKey(
@@ -670,6 +700,7 @@ export class OsLoginServiceClient {
670700
] = gax.routingHeader.fromParams({
671701
parent: request.parent || '',
672702
});
703+
this.initialize();
673704
return this._innerApiCalls.importSshPublicKey(request, options, callback);
674705
}
675706
updateSshPublicKey(
@@ -757,6 +788,7 @@ export class OsLoginServiceClient {
757788
] = gax.routingHeader.fromParams({
758789
name: request.name || '',
759790
});
791+
this.initialize();
760792
return this._innerApiCalls.updateSshPublicKey(request, options, callback);
761793
}
762794

@@ -869,8 +901,9 @@ export class OsLoginServiceClient {
869901
* The client will no longer be usable and all future behavior is undefined.
870902
*/
871903
close(): Promise<void> {
904+
this.initialize();
872905
if (!this._terminated) {
873-
return this.osLoginServiceStub.then(stub => {
906+
return this.osLoginServiceStub!.then(stub => {
874907
this._terminated = true;
875908
stub.close();
876909
});

0 commit comments

Comments
 (0)