Skip to content

Commit

Permalink
feat: Group Concurrent getClient Requests (#1848)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielbankhead committed Aug 19, 2024
1 parent 5fc3bcc commit 243ce28
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 1 deletion.
21 changes: 20 additions & 1 deletion src/auth/googleauth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,10 @@ export class GoogleAuth<T extends AuthClient = JSONClient> {
apiKey: string | null;

cachedCredential: AnyAuthClient | T | null = null;
/**
* A pending {@link AuthClient}. Used for concurrent {@link GoogleAuth.getClient} calls.
*/
#pendingAuthClient: Promise<AnyAuthClient | T> | null = null;

/**
* Scopes populated by the client library by default. We differentiate between
Expand Down Expand Up @@ -1007,7 +1011,22 @@ export class GoogleAuth<T extends AuthClient = JSONClient> {
async getClient(): Promise<AnyAuthClient | T> {
if (this.cachedCredential) {
return this.cachedCredential;
} else if (this.jsonContent) {
}

// Use an existing auth client request, or cache a new one
this.#pendingAuthClient =
this.#pendingAuthClient || this.#determineClient();

try {
return await this.#pendingAuthClient;
} finally {
// reset the pending auth client in case it is changed later
this.#pendingAuthClient = null;
}
}

async #determineClient() {
if (this.jsonContent) {
return this._cacheClientFromJSON(this.jsonContent, this.clientOptions);
} else if (this.keyFilename) {
const filePath = path.resolve(this.keyFilename);
Expand Down
22 changes: 22 additions & 0 deletions test/test.googleauth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2617,6 +2617,28 @@ describe('googleauth', () => {

assert(actualClient instanceof ExternalAccountAuthorizedUserClient);
});

it('should return the same instance for concurrent requests', async () => {
// Set up a mock to return path to a valid credentials file.
mockEnvVar(
'GOOGLE_APPLICATION_CREDENTIALS',
'./test/fixtures/external-account-authorized-user-cred.json'
);
const auth = new GoogleAuth();

let client: AuthClient | null = null;
const getClientCalls = await Promise.all([
auth.getClient(),
auth.getClient(),
auth.getClient(),
]);

for (const resClient of getClientCalls) {
if (!client) client = resClient;

assert(client === resClient);
}
});
});

describe('sign()', () => {
Expand Down

0 comments on commit 243ce28

Please sign in to comment.