SIGN IN SIGN UP

feat: flip default to at-least-once, add dead-letter events and purge()

Default mode is now transactional: false (at-least-once) — the conventional
job-queue behavior. Pass transactional: true explicitly for exactly-once
semantics. The createQueue overloads are updated to match.

Default maxAttempts is now 5 (was null/unlimited), so a poison pill is
dead-lettered instead of retrying forever.

Dead-letter tracking:
- Terminal failures (attempts exhausted, claim-time enforcement) now write
  deadLetteredAt to the record and emit a "dead" event alongside "jobError",
  giving users a distinct signal to route to alerting or DLQ storage.
- DequeueOutcome carries a deadLettered boolean so callers can distinguish
  transient from terminal failures.

New purge(options) method: bulk-deletes finished rows older than a cutoff,
with optional deadLetteredOnly flag. Pairs with the partial index — purging
finished rows keeps the indexed working set small.

New transactionWarningTimeout option: in transactional mode, a background
timer fires a console.warn if the worker holds its dequeue transaction
longer than the threshold (default: 50% of transactionTimeout). This
catches workers that use a separate connection (worker_threads, external
services) and should use transactional: false instead.

Update createEmailQueue test helper to pin transactional: true so existing
transactional-mode tests are unaffected by the default change.
O
Olivier Louvignes committed
ce15010a48ce8c0de025a204b60d38dfcafdd92e
Parent: e722e63