Files
beenvoice/apps/worker/README.md
T

1.4 KiB

Beenvoice worker

The worker is a separate Bun process backed by the same PostgreSQL database as the web app. It follows the Racetix worker model: a durable database outbox, a lightweight scheduler, and horizontally safe polling with FOR UPDATE SKIP LOCKED.

It generates due recurring invoices and delivers scheduled invoice emails. New asynchronous workflows should enqueue a typed job through apps/web/src/server/jobs/queue.ts and add a handler in src/index.ts.

Jobs have an idempotency key, scheduled run time, bounded exponential retries, and stale-lock recovery. Multiple worker replicas can run safely. Timer elapsed time is still derived from startedAt; the worker should only send time-clock reminders, never increment a counter every second.

Scheduled sends store an absolute UTC instant plus the IANA timezone selected by the client. The worker calls the app's secret-protected internal delivery endpoint through APP_INTERNAL_URL; that endpoint passes the job idempotency key to Resend, so a retry cannot send the same invoice twice.

# Uses the web app's .env/.env.local files
bun run dev

# Production environment is injected by Docker Compose/Coolify
bun run start

WORKER_POLL_MS defaults to 2000 and WORKER_SCHEDULE_MS defaults to 60000. APP_INTERNAL_URL defaults to http://app:3000 in Compose, and CRON_SECRET authenticates worker requests to the app.