@vouchington/queue-errors
v0.2.1
Published
glide-mq retry classification and worker rate-limit helpers.
Readme
@vouchington/queue-errors
General-purpose error classification helpers for glide-mq workers. This package owns queue mechanics only: applications supply provider-specific status extraction, rate-limit detection, and cooldown policy.
Install
pnpm add @vouchington/queue-errors glide-mqGlideMQ is a peer dependency so workers and these helpers share the same control-flow error classes.
HTTP retry classification
wrapHttpForRetry makes ordinary HTTP 4xx errors terminal by throwing GlideMQ's
UnrecoverableError. It rethrows timeouts (408), rate limits (429), 5xx, and failures with no
recognized status so GlideMQ can apply its configured retry policy.
import { wrapHttpForRetry } from '@vouchington/queue-errors'
await callProvider().catch(wrapHttpForRetry)Use getStatus for provider-specific error shapes and isRetryableStatus to choose which client
responses are transient. Supplying isRetryableStatus replaces the default 408/429/5xx policy for
every recognized 400–599 status, so the callback must return true for each status that your
application considers transient.
unrecoverable(error, message?, options?) explicitly marks any failure terminal.
Applications that resolve a different glide-mq copy than this package can pass
UnrecoverableError and RateLimitError constructors so thrown errors match the
application’s instanceof checks. Defaults remain this package’s glide-mq classes. The injected
terminal constructor must accept a required message: string parameter, matching glide-mq's own
UnrecoverableError; the injected rate-limit constructor takes no arguments.
import { UnrecoverableError, Worker } from 'glide-mq'
import { handleRateLimitedError, unrecoverable, wrapHttpForRetry } from '@vouchington/queue-errors'
unrecoverable(error, 'terminal', { UnrecoverableError })
wrapHttpForRetry(error, { UnrecoverableError, getStatus })
await handleRateLimitedError(error, worker, {
cooldownMs,
isRateLimited,
UnrecoverableError,
RateLimitError: Worker.RateLimitError,
})Provider rate limits
When a provider returns a rate limit, pause the worker for the application-selected cooldown and
throw GlideMQ's control-flow error so the current job is scheduled after the cooldown. GlideMQ 0.16
requeues the job without consuming a retry attempt, so cooldowns do not count against the job's
configured attempts.
import { handleRateLimitedError } from '@vouchington/queue-errors'
try {
await callProvider()
} catch (error) {
await handleRateLimitedError(error, worker, {
cooldownMs: retryAfterMs,
isRateLimited: (value) => getProviderStatus(value) === 429,
})
}cooldownMs must be a positive safe integer. The package does not choose provider names,
identifiers, throttling rules, or fallback policy. Provider exception names, SDK-specific metadata
extraction, and fixed cooldowns belong in an application adapter.
Deferral helpers
throwRateLimited, createRateLimitError, deferJobForRateLimit, and boundRateLimitDeferral requeue a job after a provider-stated wait without consuming an attempt. clampRateLimitDelayMs keeps the wait within minMs/maxMs (defaults 1 second to 15 minutes, defaultMs 60 seconds, itself clamped into that window), and boundRateLimitDeferral turns the signal back into its cause once the job is older than maxAgeMs (default 24 hours). deferPostgresConnectionTimeout defers a job while a pg-pool cannot supply a connection; messages and retryDelayMs are overridable. Reading Retry-After from a response and choosing which providers are throttled stay in the application.
