feat: configure queue retry delays with min/max bounds and update exponential backoff defaults
This commit is contained in:
13
src/index.ts
13
src/index.ts
@@ -123,9 +123,13 @@ export default {
|
|||||||
},
|
},
|
||||||
} satisfies ExportedHandler<Env>;
|
} satisfies ExportedHandler<Env>;
|
||||||
|
|
||||||
const retryDelayConfig: Record<QueueName, DurationLike> = {
|
const retryDelayConfig: Partial<
|
||||||
ANILIST_UPDATES: Duration.fromObject({ minutes: 1 }),
|
Record<QueueName, { min: DurationLike; max: DurationLike }>
|
||||||
NEW_EPISODE: Duration.fromObject({ hours: 1 }),
|
> = {
|
||||||
|
NEW_EPISODE: {
|
||||||
|
min: Duration.fromObject({ hours: 1 }),
|
||||||
|
max: Duration.fromObject({ hours: 12 }),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
function onMessageQueue<QN extends QueueName>(
|
function onMessageQueue<QN extends QueueName>(
|
||||||
@@ -144,7 +148,8 @@ function onMessageQueue<QN extends QueueName>(
|
|||||||
message.retry({
|
message.retry({
|
||||||
delaySeconds: calculateExponentialBackoff({
|
delaySeconds: calculateExponentialBackoff({
|
||||||
attempt: message.attempts,
|
attempt: message.attempts,
|
||||||
baseMin: retryDelayConfig[messageBatch.queue as QN],
|
baseMin: retryDelayConfig[messageBatch.queue as QN]?.min,
|
||||||
|
absCap: retryDelayConfig[messageBatch.queue as QN]?.max,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,11 +18,14 @@ interface CalculateExponentialBackoffOptions {
|
|||||||
*
|
*
|
||||||
* @returns A random duration between the nominal minimum and maximum, in seconds.
|
* @returns A random duration between the nominal minimum and maximum, in seconds.
|
||||||
*/
|
*/
|
||||||
export function calculateExponentialBackoff(
|
export function calculateExponentialBackoff({
|
||||||
{ attempt, baseMin: baseMinDuration = Duration.fromObject({ seconds: 1 }), absCap: absCapDuration = Duration.fromObject({ seconds: 60 }), fuzzFactor = 0.2 }: CalculateExponentialBackoffOptions
|
attempt,
|
||||||
): number {
|
baseMin: baseMinDuration = Duration.fromObject({ minutes: 1 }),
|
||||||
const baseMin = Duration.fromDurationLike(baseMinDuration).as('seconds');
|
absCap: absCapDuration = Duration.fromObject({ hours: 1 }),
|
||||||
const absCap = Duration.fromDurationLike(absCapDuration).as('seconds');
|
fuzzFactor = 0.2,
|
||||||
|
}: CalculateExponentialBackoffOptions): number {
|
||||||
|
const baseMin = Duration.fromDurationLike(baseMinDuration).as("seconds");
|
||||||
|
const absCap = Duration.fromDurationLike(absCapDuration).as("seconds");
|
||||||
|
|
||||||
// 1. Calculate nominal boundaries
|
// 1. Calculate nominal boundaries
|
||||||
// Example: If baseMin is 1s, the nominal boundaries are 1s, 2s, 4s, 8s... (The 'ceiling' grows exponentially)
|
// Example: If baseMin is 1s, the nominal boundaries are 1s, 2s, 4s, 8s... (The 'ceiling' grows exponentially)
|
||||||
@@ -37,7 +40,8 @@ export function calculateExponentialBackoff(
|
|||||||
// 3. Fuzz the Max (The Ceiling)
|
// 3. Fuzz the Max (The Ceiling)
|
||||||
// Example: If ceiling is 4s (and fuzz is 0.2), it becomes random between 3.2s and 4.8s
|
// Example: If ceiling is 4s (and fuzz is 0.2), it becomes random between 3.2s and 4.8s
|
||||||
const maxFuzz = nominalCeiling * fuzzFactor;
|
const maxFuzz = nominalCeiling * fuzzFactor;
|
||||||
const fuzzedCeiling = nominalCeiling + (Math.random() * 2 * maxFuzz - maxFuzz);
|
const fuzzedCeiling =
|
||||||
|
nominalCeiling + (Math.random() * 2 * maxFuzz - maxFuzz);
|
||||||
|
|
||||||
// Safety: Ensure we don't return a negative number or cross boundaries weirdly
|
// Safety: Ensure we don't return a negative number or cross boundaries weirdly
|
||||||
// (e.g. if fuzz makes min > max, we swap or clamp)
|
// (e.g. if fuzz makes min > max, we swap or clamp)
|
||||||
|
|||||||
Reference in New Issue
Block a user