Worker binary and job queue #4

Closed
opened 2026-08-26 09:13:10 +00:00 by GKaszewski · 0 comments
Owner

What to build

Implements ADR 0004. Background work moves out of tokio::spawn calls inside the server and into a dedicated worker binary, driven by a job queue with visible state.

The rule that makes this safe: no job may be enqueued unless a query over domain state can independently rediscover the same work. Losing a job then costs latency, never data, so the queue needs no transactional guarantees and saving a MoodEntry stays one small transaction that must simply succeed.

Everything downstream of that save is best-effort but traceable — status, attempt count, last error — so a failure can be retried deliberately rather than disappearing.

Three concrete prerequisites:

  • The in-process mpsc event channel cannot cross a process boundary. It is not the transport.
  • Shared wiring currently lives in the server crate and must move so both binaries build the same object graph.
  • The SQLite pool sets WAL and foreign keys but no busy_timeout. Two processes writing one file without it produces intermittent SQLITE_BUSY failures.

SQLite is the store of record. NATS, where available, is a relay for fan-out, never the source of truth.

Migrate the existing reminder scheduler and session cleanup into the worker as proof the split works end to end.

Acceptance criteria

  • A worker binary builds and runs independently of the server
  • Shared wiring is extracted so neither binary duplicates the object graph
  • busy_timeout is configured on the pool; concurrent writes from both processes succeed
  • Job records carry status, attempt count, and last error, and support ack/nack
  • Reminder scheduling and session cleanup run in the worker, not the server
  • A job that fails repeatedly stops retrying and remains visible rather than silently vanishing
  • Killing and restarting the worker mid-job loses no work that a sweep can rediscover
  • Sweeps are rate-bounded from configuration, not from constants

Blocked by

None - can start immediately.

## What to build Implements ADR 0004. Background work moves out of `tokio::spawn` calls inside the server and into a dedicated worker binary, driven by a job queue with visible state. The rule that makes this safe: **no job may be enqueued unless a query over domain state can independently rediscover the same work.** Losing a job then costs latency, never data, so the queue needs no transactional guarantees and saving a `MoodEntry` stays one small transaction that must simply succeed. Everything downstream of that save is best-effort but traceable — status, attempt count, last error — so a failure can be retried deliberately rather than disappearing. Three concrete prerequisites: - The in-process `mpsc` event channel cannot cross a process boundary. It is not the transport. - Shared wiring currently lives in the server crate and must move so both binaries build the same object graph. - The SQLite pool sets WAL and foreign keys but no `busy_timeout`. Two processes writing one file without it produces intermittent `SQLITE_BUSY` failures. SQLite is the store of record. NATS, where available, is a relay for fan-out, never the source of truth. Migrate the existing reminder scheduler and session cleanup into the worker as proof the split works end to end. ## Acceptance criteria - [ ] A worker binary builds and runs independently of the server - [ ] Shared wiring is extracted so neither binary duplicates the object graph - [ ] `busy_timeout` is configured on the pool; concurrent writes from both processes succeed - [ ] Job records carry status, attempt count, and last error, and support ack/nack - [ ] Reminder scheduling and session cleanup run in the worker, not the server - [ ] A job that fails repeatedly stops retrying and remains visible rather than silently vanishing - [ ] Killing and restarting the worker mid-job loses no work that a sweep can rediscover - [ ] Sweeps are rate-bounded from configuration, not from constants ## Blocked by None - can start immediately.
GKaszewski added the ready-for-human label 2026-08-26 09:13:10 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: GKaszewski/k-mood#4