Skip to content

Two worker slots stay free for jobs that make no model call, so a sync runs even while model work holds every other slot - #1349

Merged
WaylandYang merged 1 commit into
deeplethe:devfrom
QuintinBotes:feat/no-chat-lane
Oct 21, 2026
Merged

WaylandYang merged 1 commit into
deeplethe:devfrom
QuintinBotes:feat/no-chat-lane

Conversation

@QuintinBotes

Copy link
Copy Markdown
Contributor

Closes #1300: the reserved lane, the second of the two PRs agreed there. The first was #1324.

Why

#1324 orders the claim so that work which makes no chat call goes first. Ordering only decides who gets the next free slot, though. An extraction waiting for its model permit still holds its worker slot, and on a slow local model every slot is often held that way. A sync then waits for one of those extractions to finish, however far ahead of them it stands in the queue.

What changes

  • jobs::NO_CHAT_LANE = 2. Once all worker_concurrency regular slots are taken, run_worker may still claim up to two more jobs, and only those with job_priority(kind) = 0: the same list as Intake jobs are claimed before model work, so a sync no longer waits behind the extraction backlog #1324, so there is one list, not two. Each job returns its slot to the side it was claimed on (in_lane is counted apart from running). worker_concurrency now bounds model work, plus two slots reserved for intake jobs, as agreed in A sync or a new document waits behind the whole extraction backlog: jobs are claimed strictly by run_at #1300.
  • claim_one(pool, no_chat_only). The lane's restriction is written into the SQL as a literal rather than a bound parameter. With a literal, EXPLAIN shows it as an index condition on jobs_priority_claim_idx, so a lane claim stops at the end of the priority-0 rows. As a bound parameter it would be a row filter, scanning every queued extraction every 200 ms while the regular slots are full.
  • When the lane finds nothing, the loop sleeps 200 ms, as it already did when saturated, so a freed regular slot is noticed as quickly as before.
  • Wording. The settings hint for background workers (en.ts and zh.ts) and the doc comment on DeploymentReq::worker_concurrency now say it bounds model work, plus two slots reserved for intake jobs. In docs/, worker_concurrency only appears in ADR 0006, which records the state at the time, so I've left it unchanged.

Known limits

Test

tests/a_sync_runs_while_model_work_holds_every_slot.rs runs a real run_worker, so it is a binary of its own, with a line in tests/store/main.rs. The handler accepts only its own two marked jobs and fails anything else, as human_phrase_materialization_delivery does.

  • With worker_concurrency at 1, an extract_document takes the only regular slot and never returns, standing in for an extraction waiting on the model.
  • A sync_source queued after it must still run within ten seconds.
  • With NO_CHAT_LANE = 0 the test fails: the sync waited behind the extraction: Err(Elapsed(())).

How it was checked

On an M1 Max (macOS), at the PR head on top of dev f2e2a47:

  • cargo fmt --all --check: passes.
  • cargo clippy --workspace --all-targets -- -D warnings: no issues.
  • cargo test --workspace --no-fail-fast with UTOPIA_DATABASE_URL pointing at a database created and migrated for this branch alone: 1,646 passed, 0 failed, 6 ignored.
  • pnpm build and pnpm test in web/: build passes, 307 tests pass.

Before review

  • Every commit is signed off (git commit -s)
  • cargo fmt --all --check, cargo clippy --workspace --all-targets -- -D warnings and cargo test --workspace pass
  • For changes under web/: pnpm build and pnpm test pass
  • SQL under crates/utopia-store/ was tested with UTOPIA_DATABASE_URL set (those tests skip without it)
  • UI strings are in both web/src/i18n/en.ts and zh.ts

…c runs even while model work holds every other slot

Signed-off-by: Quintin Botes <quintinbotes@outlook.com>
@WaylandYang
WaylandYang merged commit f2d2997 into deeplethe:dev Oct 21, 2026
6 checks passed
gedaiu added a commit to re-cinq/utopia that referenced this pull request Oct 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants