Retries and timeouts
Configure durable backoff and cooperative attempt limits.
Retry.never, Retry.fixed, Retry.linear and Retry.exponential produce
validated callback-free policy data. The policy is persisted with the Job;
Retry.custom remains process-local and is evaluated only by the Worker.
import * as z from 'zod'
import { Codec, JobEncodeFailure, Queue, Retry } from 'better-effect-mq'
import { Schema as CoreSchema } from 'better-effect-schema'
import { Schema } from 'better-effect-schema/zod'
const Jobs = Queue.define('billing')
const ChargeCardPayloadSchema = z.object({ paymentId: z.string().min(1) })
class ChargeCardPayload extends Schema.Class<ChargeCardPayload>('app/ChargeCardPayload')(
ChargeCardPayloadSchema
) {}
const ChargeCardPayloadCodec = Codec.standardSchema({
schema: ChargeCardPayload,
encode: (value) =>
CoreSchema.encode(ChargeCardPayload, value).mapError(
(error) => new JobEncodeFailure({ message: error.message, code: 'schema-encode' })
)
})
const ChargeCard = Jobs.job('charge-card', {
version: 1,
payload: ChargeCardPayloadCodec,
result: Codec.void,
failure: Codec.standardSchema({ schema: z.object({ code: z.string().min(1) }) }),
defaults: {
attempts: 4,
backoff: Retry.exponential({
initialDelayMs: 100,
factor: 2,
maxDelayMs: 5_000,
maxAttempts: 4
}),
timeoutMs: 30_000
},
retryable: ({ code }) => code !== 'card-blocked'
})attempts includes the first delivery. A typed Result.err is retryable only
when the Job policy says so; Job.unrecoverable(value) marks an object failure
as terminal. Defects retry by default and can be disabled with
retryDefects: false. Decode and encode failures are terminal because the
Worker cannot safely invoke the handler or persist its result.
Timeouts abort the attempt cooperatively with JobTimeoutError. The Worker
checks the deadline at the settlement submission gate, but a Promise that
ignores its signal may continue running outside the supervisor. External APIs
must use their own timeout and idempotency controls.
Retry and failure data are bounded JSON-safe DTOs. Causes, stacks, arbitrary
exceptions and sensitive payloads do not become persisted failure fields.
Use Zod 4 through better-effect-schema with Codec.standardSchema for
boundary validation. The trusted JSON escape hatch
is reserved for values that are already JSON-safe and need no runtime schema;
it is not the default boundary codec.