-
Notifications
You must be signed in to change notification settings - Fork 243
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto retry when a feed is rated limited based on host
- Loading branch information
Showing
5 changed files
with
165 additions
and
55 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
58 changes: 58 additions & 0 deletions
58
services/feed-requests/src/shared/utils/retry-until-true.ts
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,58 @@ | ||
export class RetryException extends Error {} | ||
|
||
const delay = (timeout: number) => | ||
new Promise<void>((resolve) => setTimeout(resolve, timeout)); | ||
|
||
/** | ||
* Repeatedly calls the provided function until it returns true or the maximum timeout is reached. | ||
* | ||
* @param {() => Promise<boolean>} fn - The function to be called repeatedly. | ||
* @param {number} startTimeout - The initial timeout in milliseconds. | ||
* @param {number} maxTimeout - The maximum timeout in milliseconds. | ||
* Uses exponential backoff for retries. | ||
* @returns {Promise<void>} A promise that resolves when the function returns true or rejects if | ||
* the maximum timeout is reached. | ||
*/ | ||
const retryUntilTrue = ( | ||
fn: () => Promise<boolean>, | ||
startTimeout: number, | ||
maxTimeout: number, | ||
) => { | ||
return new Promise<void>(async (resolve, reject) => { | ||
try { | ||
let currentTimeout = startTimeout; | ||
|
||
while (true) { | ||
if (await fn()) { | ||
resolve(); | ||
|
||
return; | ||
} | ||
|
||
await delay(currentTimeout); | ||
currentTimeout = Math.min(currentTimeout * 1.5, maxTimeout); | ||
|
||
if (currentTimeout >= maxTimeout) { | ||
break; | ||
} | ||
} | ||
|
||
reject( | ||
new RetryException( | ||
`Timeout reached (next timeout of ${currentTimeout} is greater than max timeout of` + | ||
` ${maxTimeout})`, | ||
), | ||
); | ||
} catch (err) { | ||
const toThrow = new RetryException((err as Error).message); | ||
|
||
if (err instanceof Error) { | ||
toThrow.stack = err.stack; | ||
} | ||
|
||
reject(toThrow); | ||
} | ||
}); | ||
}; | ||
|
||
export default retryUntilTrue; |
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,5 @@ | ||
import { URL } from 'node:url'; | ||
|
||
export const getUrlHost = (url: string) => { | ||
return new URL(url).host; | ||
}; |