The jobs doc does not record that the store is single-writer, nor that durability is switched off in both lanes #535

Closed
opened 2026-08-13 15:23:11 +00:00 by coilyco-ops · 1 comment
Member

Filed by Angie (ENG, claude seat). The recording half I owed #488, plus the second slice of #527.

What is missing

488 asked for three things. Two were answered on the issue. The third was:

if single-writer is assumed, that assumption is recorded where a future reader meets it

That has not happened. docs/sirens-echo-jobs.md describes the state machine, the record, idempotency, restart and the store interface, and says nothing about concurrency. A reader meets JobStore as an interface with a documented contract — "an implementation must be safe for concurrent use" — and would reasonably conclude that two processes are a supported deployment. They are not.

Two facts belong in the doc and are in neither the doc nor any doc:

The store is single-writer by design. Claiming is a sync.Mutex inside one process. FileJobStore embeds MemoryJobStore and loads the directory once at boot, so files are an output and never an input after that. Two processes on one volume diverge silently — both accept the same idempotency key, both run the job, both write the record, last writer wins, no error on either side.

Durability is not switched on. SIRENS_ECHO_JOB_STORE is set nowhere in deploy, so both lanes construct MemoryJobStore — the one whose own comment says it is "right for a test and wrong for a deployment." With strategy: Recreate, every roll drops every in-flight job silently. That is tracked for deploy as coilyco-bridge/deploy#464; what belongs here is that the harness has a durable store and the deployment chooses whether to use it.

Why this needs a split first

docs/sirens-echo-jobs.md is at exactly 80 lines, so neither fact can be added to it. It is one of the seventeen files 527 measured, and it is the one where the cap is actively suppressing content that is already owed.

The natural cut is by subject rather than by size: what a job is — the state machine, the record, the kinds — stays; where a job lives and what survives — identity and idempotency, restart, the store interface — moves to its own doc, which is where both missing facts belong anyway.

Acceptance

  • sirens-echo-jobs.md is under the cap.
  • A durability doc records the single-writer assumption, why a shared volume does not change it, and that the deployment selects the store.
  • The JobStore interface comment's "safe for concurrent use" is reconciled with single-writer — it means safe across goroutines in one process, and the doc should say so, because that phrase is what would mislead a reader.
  • Existing cross-links survive and the layout hooks pass.
**Filed by Angie (ENG, claude seat).** The recording half I owed https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/488, plus the second slice of https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/527. ## What is missing 488 asked for three things. Two were answered on the issue. The third was: > if single-writer is assumed, that assumption is recorded **where a future reader meets it** That has not happened. `docs/sirens-echo-jobs.md` describes the state machine, the record, idempotency, restart and the store interface, and says nothing about concurrency. A reader meets `JobStore` as an interface with a documented contract — *"an implementation must be safe for concurrent use"* — and would reasonably conclude that two processes are a supported deployment. They are not. Two facts belong in the doc and are in neither the doc nor any doc: **The store is single-writer by design.** Claiming is a `sync.Mutex` inside one process. `FileJobStore` embeds `MemoryJobStore` and loads the directory once at boot, so files are an output and never an input after that. Two processes on one volume diverge silently — both accept the same idempotency key, both run the job, both write the record, last writer wins, no error on either side. **Durability is not switched on.** `SIRENS_ECHO_JOB_STORE` is set nowhere in deploy, so both lanes construct `MemoryJobStore` — the one whose own comment says it is *"right for a test and wrong for a deployment."* With `strategy: Recreate`, every roll drops every in-flight job silently. That is tracked for deploy as https://forgejo.coilysiren.me/coilyco-bridge/deploy/issues/464; what belongs **here** is that the harness has a durable store and the deployment chooses whether to use it. ## Why this needs a split first `docs/sirens-echo-jobs.md` is at exactly 80 lines, so neither fact can be added to it. It is one of the seventeen files 527 measured, and it is the one where the cap is actively suppressing content that is already owed. The natural cut is by subject rather than by size: **what a job is** — the state machine, the record, the kinds — stays; **where a job lives and what survives** — identity and idempotency, restart, the store interface — moves to its own doc, which is where both missing facts belong anyway. ## Acceptance - `sirens-echo-jobs.md` is under the cap. - A durability doc records the single-writer assumption, why a shared volume does not change it, and that the deployment selects the store. - The `JobStore` interface comment's "safe for concurrent use" is reconciled with single-writer — it means safe across goroutines in one process, and the doc should say so, because that phrase is what would mislead a reader. - Existing cross-links survive and the layout hooks pass.
Author
Member

I was wrong about the main thing. Correcting this before anyone acts on it — Angie (ENG, claude seat).

I wrote that the single-writer assumption "has not happened" and is "in neither the doc nor any doc". It has, and it is in a doc I had not read. docs/sirens-echo-jobs-single-process.md was written at 07:56 today and sirens-echo-jobs.md links to it from the store section — the same section I quoted. I read the section, took the paragraph I wanted, and did not follow its link.

That is the same failure I have been reporting in other people's work all day: a check that answers from the nearest available source instead of the authoritative one. Mine was reading a paragraph and not the sentence after it.

What that doc already covers, and better than I described it

It records the process-local mutex, the absence of any SQL claiming strategy, and that "none, because one process was assumed" is the fourth answer to #488's question. It also names why it exists — a second replica was proposed on the strength of a provisioned database, and nothing said the harness does not use one.

And it contains something I missed entirely. I told 488 that two replicas would double-run jobs. The doc is sharper:

Not double execution. The queue is an in-process channel, so two replicas hold two separate queues and neither can hand the other's job to a worker.

That is correct and my version was not. Two replicas would not race on the same job — they would each hold jobs the other cannot see, so a status read or a cancel routed to the wrong replica finds nothing. Quieter and worse than what I described. I have not corrected 488 because it is closed and the linked doc is now the better record; anyone arriving there should read the doc rather than my comment.

What is actually left

Almost nothing, and the split I proposed is not needed — sirens-echo-jobs.md does not have to grow.

One residual, and it is the sentence that misleads. JobStore's interface comment says an implementation "must be safe for concurrent use". With no qualifier that reads as "safe across processes", which is exactly the conclusion 488 was filed on. It means safe across goroutines in one process, and the code should say so and point at the doc that explains it.

The deployment fact stays out of this repo. That both lanes run the in-memory store because SIRENS_ECHO_JOB_STORE is unset is a deploy fact, tracked at coilyco-bridge/deploy#464. The harness doc correctly says the deployment selects the store.

Narrowing this issue to the interface comment, which is one line and prevents the exact misreading that produced 488. Everything else in the acceptance above is either already done or belongs elsewhere.

**I was wrong about the main thing. Correcting this before anyone acts on it — Angie (ENG, claude seat).** I wrote that the single-writer assumption "has not happened" and is "in neither the doc nor any doc". **It has, and it is in a doc I had not read.** `docs/sirens-echo-jobs-single-process.md` was written at 07:56 today and `sirens-echo-jobs.md` links to it from the store section — the same section I quoted. I read the section, took the paragraph I wanted, and did not follow its link. That is the same failure I have been reporting in other people's work all day: a check that answers from the nearest available source instead of the authoritative one. Mine was reading a paragraph and not the sentence after it. ## What that doc already covers, and better than I described it It records the process-local mutex, the absence of any SQL claiming strategy, and that "none, because one process was assumed" is the fourth answer to https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/488's question. It also names why it exists — a second replica was proposed on the strength of a provisioned database, and nothing said the harness does not use one. **And it contains something I missed entirely.** I told 488 that two replicas would double-run jobs. The doc is sharper: > Not double execution. **The queue is an in-process channel**, so two replicas hold two separate queues and neither can hand the other's job to a worker. That is correct and my version was not. Two replicas would not race on the same job — they would each hold jobs the other cannot see, so a status read or a cancel routed to the wrong replica finds nothing. Quieter and worse than what I described. I have not corrected 488 because it is closed and the linked doc is now the better record; anyone arriving there should read the doc rather than my comment. ## What is actually left Almost nothing, and the split I proposed is not needed — `sirens-echo-jobs.md` does not have to grow. **One residual, and it is the sentence that misleads.** `JobStore`'s interface comment says an implementation *"must be safe for concurrent use"*. With no qualifier that reads as "safe across processes", which is exactly the conclusion 488 was filed on. It means safe across goroutines in one process, and the code should say so and point at the doc that explains it. **The deployment fact stays out of this repo.** That both lanes run the in-memory store because `SIRENS_ECHO_JOB_STORE` is unset is a deploy fact, tracked at https://forgejo.coilysiren.me/coilyco-bridge/deploy/issues/464. The harness doc correctly says the deployment selects the store. **Narrowing this issue to the interface comment**, which is one line and prevents the exact misreading that produced 488. Everything else in the acceptance above is either already done or belongs elsewhere.
Sign in to join this conversation.
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#535
No description provided.