docs(jobs): write down that the job system is single-process #514

Merged
coilyco-ops merged 1 commit from docs/jobs-are-single-process into main 2026-08-13 14:54:53 +00:00
Member

closes #488

The filer asked which claiming strategy the Postgres job store uses, and said plainly they had not read this repository. I have.

There is no Postgres job store

Two implementations: MemoryJobStore and FileJobStore. No SQL anywhere in internal/ or cmd/ — no database/sql, no driver, no FOR UPDATE SKIP LOCKED, no advisory lock, no atomic UPDATE … RETURNING. I grepped for each.

So the question has a fourth answer: none, because one process was assumed. The claim is a transition guarded by a process-local sync.Mutex.

The double execution they feared cannot happen that way

The queue is an in-process Go channel. Two replicas hold two separate queues; neither can hand the other's job to a worker, because there is no shared queue to hand it from.

The real failures are quieter, which is why they are worth writing down:

  • a job is visible only to the process that accepted its submission, so a status read or cancel routed to the other replica finds nothing
  • two processes sharing a directory guard nothing between them — concurrent transitions on one id interleave, and the rename makes it last-writer-wins

Their actual ask

It is the assumption that needs to be written down rather than held implicitly.

Done, and it is stronger than single-writer: single-process, across the store, the queue, and the worker pool. The new doc also lists what would have to change first, so "provision a database" is not mistaken for "this is ready for two replicas".

ward exec gate green: build, policy-check, vet, test, test-skips, pre-commit.

closes #488 The filer asked which claiming strategy the Postgres job store uses, and said plainly they had not read this repository. I have. ## There is no Postgres job store Two implementations: `MemoryJobStore` and `FileJobStore`. **No SQL anywhere** in `internal/` or `cmd/` — no `database/sql`, no driver, no `FOR UPDATE SKIP LOCKED`, no advisory lock, no atomic `UPDATE … RETURNING`. I grepped for each. So the question has a fourth answer: **none, because one process was assumed.** The claim is a transition guarded by a process-local `sync.Mutex`. ## The double execution they feared cannot happen that way **The queue is an in-process Go channel.** Two replicas hold two separate queues; neither can hand the other's job to a worker, because there is no shared queue to hand it from. The real failures are quieter, which is why they are worth writing down: - a job is visible only to the process that accepted its submission, so a status read or cancel routed to the other replica finds nothing - two processes sharing a directory guard nothing between them — concurrent transitions on one id interleave, and the rename makes it last-writer-wins ## Their actual ask > It is the assumption that needs to be written down rather than held implicitly. Done, and it is stronger than single-writer: **single-process**, across the store, the queue, and the worker pool. The new doc also lists what would have to change first, so "provision a database" is not mistaken for "this is ready for two replicas". `ward exec gate` green: build, policy-check, vet, test, test-skips, pre-commit.
docs(jobs): write down that the job system is single-process
All checks were successful
ci / image-build (pull_request) Successful in 21s
ci / test (pull_request) Successful in 32s
ci / publish-echo-image (pull_request) Has been skipped
ci / publish-observed (pull_request) Has been skipped
e4de0c3fa8
Someone proposed a second replica on the strength of the deployment
provisioning a database per lane, and asked which claiming strategy the
Postgres job store uses. There is no Postgres job store. No SQL anywhere in
internal or cmd, no driver, no FOR UPDATE SKIP LOCKED, no advisory lock.

So the answer to which strategy is the fourth option, none, because one process
was assumed. The claim is a transition guarded by a process-local mutex.

The double execution they worried about cannot happen the way they described
it, because the queue is an in-process channel: two replicas hold two queues
and neither can hand the other's job to a worker. The real failures are
quieter. A job is visible only to the process that accepted its submission, so
a cancel routed elsewhere finds nothing, and two processes sharing a directory
guard nothing between them.

They asked for the assumption to be written down rather than held implicitly,
and it is stronger than single-writer: single-process, in the store, the queue,
and the worker pool.

closes #488

Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-gaming/sirens-echo!514
No description provided.