Skip to content

Commit 5336a9b

Browse files
Merge branch 'main' into parth/upstream-sync
2 parents 1a182ae + 891a46c commit 5336a9b

4 files changed

Lines changed: 29 additions & 5 deletions

File tree

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
],
4848
"main": "./build/extension/extension",
4949
"rovoDev": {
50-
"version": "0.13.27"
50+
"version": "0.13.28"
5151
},
5252
"scripts": {
5353
"vscode:uninstall": "node ./build/extension/uninstall.js",
@@ -1889,4 +1889,4 @@
18891889
},
18901890
"jws": "^4.0.1"
18911891
}
1892-
}
1892+
}

src/atlclients/authStore.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ export class CredentialManager implements Disposable {
5656
private negotiator: Negotiator;
5757
private _refreshInFlight = new Map<string, Promise<void>>();
5858
private mutex = new Mutex();
59+
private _failedRefreshCache = new Map<string, { attemptsCount: number; lastAttemptAt: Date }>();
5960

6061
constructor(
6162
context: ExtensionContext,
@@ -393,7 +394,10 @@ export class CredentialManager implements Disposable {
393394

394395
if (credentials.expirationDate) {
395396
const diff = credentials.expirationDate - Date.now();
396-
Logger.debug(`${Math.floor(diff / 1000)} seconds remaining for auth token.`);
397+
Logger.debug(
398+
`${Math.floor(diff / 1000)} seconds remaining for ${site.name} refresh token. ${diff > GRACE_PERIOD ? 'No refresh needed yet.' : 'refreshing...'}`,
399+
);
400+
397401
if (diff > GRACE_PERIOD) {
398402
return credentials; // no need to refresh, we have enough time left
399403
}
@@ -552,6 +556,17 @@ export class CredentialManager implements Disposable {
552556
if (!isOAuthInfo(credentials)) {
553557
return undefined;
554558
}
559+
560+
const failedRefresh = this._failedRefreshCache.get(site.credentialId);
561+
if (failedRefresh) {
562+
const RETRY_DELAY = 5 * Time.MINUTES;
563+
// if we already had multiple failed attempts recently, don't try again yet until enough time has passed
564+
if (failedRefresh.attemptsCount > 5 && Date.now() - failedRefresh.lastAttemptAt.getTime() < RETRY_DELAY) {
565+
Logger.debug(`Skipping token refresh for credentialID: ${site.credentialId} due to previous failures.`);
566+
return undefined;
567+
}
568+
}
569+
555570
Logger.debug(`refreshingAccessToken for ${site.baseApiUrl} credentialID: ${site.credentialId}`);
556571

557572
const provider: OAuthProvider | undefined = oauthProviderForSite(site);
@@ -569,9 +584,16 @@ export class CredentialManager implements Disposable {
569584
}
570585

571586
await this.saveAuthInfo(site, credentials);
587+
if (this._failedRefreshCache.has(site.credentialId)) {
588+
this._failedRefreshCache.delete(site.credentialId);
589+
}
572590
Logger.debug(`Successfully saved refreshed tokens for credentialId: ${site.credentialId}`);
573591
} else if (tokenResponse.shouldInvalidate) {
574592
credentials.state = AuthInfoState.Invalid;
593+
this._failedRefreshCache.set(site.credentialId, {
594+
attemptsCount: (this._failedRefreshCache.get(site.credentialId)?.attemptsCount ?? 0) + 1,
595+
lastAttemptAt: new Date(),
596+
});
575597
await this.saveAuthInfo(site, credentials);
576598
}
577599
}

src/atlclients/basicInterceptor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { AuthInterceptor } from './authInterceptor';
88
import { CredentialManager } from './authStore';
99

1010
/**
11-
* BasicInterceptor detects any 401 or 403 responses from the REST service and blocks any further requests unitl the
11+
* BasicInterceptor detects any 401 or 403 responses from the REST service and blocks any further requests until the
1212
* user has updated their password.
1313
*/
1414
export class BasicInterceptor implements AuthInterceptor {

src/atlclients/oauthRefresher.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,9 @@ export class OAuthRefesher implements Disposable {
7474
}
7575
} catch (err) {
7676
const responseStatusDescription = err.response?.status ? ` ${err.response.status}` : '';
77-
Logger.error(err, 'Error while refreshing tokens' + responseStatusDescription);
77+
const axiosErrorData = ` (Axios message: ${err?.response?.data?.error}. Axios description: ${err?.response?.data?.error_description})`;
78+
79+
Logger.error(err, 'Error while refreshing tokens' + responseStatusDescription + axiosErrorData);
7880
if (err.response?.status === 401 || err.response?.status === 403) {
7981
Logger.debug(`Invalidating credentials due to ${err.response.status} while refreshing tokens`);
8082
response.shouldInvalidate = true;

0 commit comments

Comments
 (0)