-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[core-http] Throttling retry policy fix in core-http (#15832)
Fixes #15796 ## Problem The throttlingRetryPolicy in core-http has the potential to retry for an extended period if the service continues returning "retry after" headers on subsequent calls. Here's the snippet of code that handles the "retry after" retries: ```typescript public async sendRequest(httpRequest: WebResource): Promise<HttpOperationResponse> { return this._nextPolicy.sendRequest(httpRequest.clone()).catch((err) => { // other code elided.... return delay(delayInMs).then((_: any) => this.sendRequest(httpRequest.clone())); ``` ## Solution Update delay such that it respects abort signal. Similar to what I had to do for app-config at #15721
- Loading branch information
1 parent
35739ab
commit bb9896d
Showing
13 changed files
with
156 additions
and
93 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT license. | ||
|
||
import { isDefined } from "./typeguards"; | ||
import { AbortError, AbortSignalLike } from "@azure/abort-controller"; | ||
const StandardAbortMessage = "The operation was aborted."; | ||
|
||
/** | ||
* A wrapper for setTimeout that resolves a promise after delayInMs milliseconds. | ||
* @param delayInMs - The number of milliseconds to be delayed. | ||
* @param value - The value to be resolved with after a timeout of t milliseconds. | ||
* @param options - The options for delay - currently abort options | ||
* @param abortSignal - The abortSignal associated with containing operation. | ||
* @param abortErrorMsg - The abort error message associated with containing operation. | ||
* @returns - Resolved promise | ||
*/ | ||
export function delay<T>( | ||
delayInMs: number, | ||
value?: T, | ||
options?: { | ||
abortSignal?: AbortSignalLike; | ||
abortErrorMsg?: string; | ||
} | ||
): Promise<T | void> { | ||
return new Promise((resolve, reject) => { | ||
let timer: ReturnType<typeof setTimeout> | undefined = undefined; | ||
let onAborted: (() => void) | undefined = undefined; | ||
|
||
const rejectOnAbort = (): void => { | ||
return reject( | ||
new AbortError(options?.abortErrorMsg ? options?.abortErrorMsg : StandardAbortMessage) | ||
); | ||
}; | ||
|
||
const removeListeners = (): void => { | ||
if (options?.abortSignal && onAborted) { | ||
options.abortSignal.removeEventListener("abort", onAborted); | ||
} | ||
}; | ||
|
||
onAborted = (): void => { | ||
if (isDefined(timer)) { | ||
clearTimeout(timer); | ||
} | ||
removeListeners(); | ||
return rejectOnAbort(); | ||
}; | ||
|
||
if (options?.abortSignal && options.abortSignal.aborted) { | ||
return rejectOnAbort(); | ||
} | ||
|
||
timer = setTimeout(() => { | ||
removeListeners(); | ||
resolve(value); | ||
}, delayInMs); | ||
|
||
if (options?.abortSignal) { | ||
options.abortSignal.addEventListener("abort", onAborted); | ||
} | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT license. | ||
|
||
/** | ||
* Helper TypeGuard that checks if the value is not null or undefined. | ||
* @param thing - Anything | ||
* @internal | ||
*/ | ||
export function isDefined<T>(thing: T | undefined | null): thing is T { | ||
return typeof thing !== "undefined" && thing !== null; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.