Skip to content

refactor(work): run pause and resume as one writer job - #4139

Merged
ScriptedAlchemy merged 1 commit into
masterfrom
refactor/storage-run-control-jobs
Oct 16, 2026
Merged

ScriptedAlchemy merged 1 commit into
masterfrom
refactor/storage-run-control-jobs

Conversation

@ScriptedAlchemy

@ScriptedAlchemy ScriptedAlchemy commented Oct 16, 2026 •

Copy link
Copy Markdown
Owner

Summary

Step 5 of the storage redesign (docs/plans/storage/README.md), second slice. Pause and resume of a Work run now run as one writer job.

Before this change, a pause made three separate trips to storage: the run's frontier on a reader, the workflow journal replay through a begin_deferred writer transaction, and the compare-and-swap publication in its own interactive transaction. Every trip parked the request thread, which is why Work requests ran under off_native_worker. Now RegisteredWorkApplicationServicesV1::pause_run and resume_run run the unchanged WorkRunControlService decision inside WorkSqliteStorage::transact. The frontier read, the journal read, the decision and the publication commit together or not at all, and the awaiting task parks no thread. offer_work_blocked_interval_receipts still runs after the commit.

This is the shape the rest of step 5 follows. The decision stays a synchronous contracts function, and it runs on the writer thread over a storage scoped to that job's transaction.

  • WorkRunControlTransitionPort (contracts) holds the three methods a transition uses. It has no Send + Sync bound, so WorkSqliteJobStorage, which borrows the job transaction, can implement it. The rest of WorkRunControlStoragePort is unchanged.
  • WorkSqliteJobStorage holds no ExactSqlHandle. A job therefore cannot call back into the writer thread that runs it.
  • The handle path and the job path share every SQL body, through RegisteredWorkQuery (now also implemented for ExactSqlJobTransaction) and a new RegisteredWorkWrite.
  • The handle-based transition stays for its one remaining caller, synchronize_fan_out_run_controls (synchronous workflow fan-out). It goes when that path migrates.

Test plan

  • work_run_control_jobs::pause_and_resume_awaited_on_a_native_worker_park_no_native_thread (application_suite): pause then resume on a native worker leave the native writer-wait and reader-wait counters unchanged. Putting back the old synchronous call in pause_run fails it (writer waits left 11), and so does the same change in resume_run.
  • work_run_control_storage::a_run_control_job_publishes_with_its_frontier_read_or_not_at_all (rusqlite_suite): a job that publishes and then refuses leaves no control row, and an accepted job commits it. Committing regardless of the verdict fails it.
  • bazel test --config=clippy for rusqlite-runtime unit_test and rusqlite_suite, contracts unit_test and contracts_suite, application unit_test and application_suite, and daemon-service unit_test
  • rustfmt_check_2024 for each touched crate
  • //crates/tracedecay:daemon_suite, :mcp_suite, :session_suite, :unit_test in CI

Refs #4052


Devin Review

PauseRun and ResumeRun now run the contracts run-control service inside one ExactSqlHandle::transact job over WorkSqliteJobStorage, a Work storage that holds the job transaction and no handle. The frontier read, the workflow journal read and the CAS publication commit together, and the awaiting task parks no native thread.

The pause/resume reads and publication move to a WorkRunControlTransitionPort without a Send + Sync bound so the job-scoped storage can implement it. Their bodies, the workflow schema check and the run journal replay are shared between the handle and job paths through RegisteredWorkQuery and a new RegisteredWorkWrite trait. The handle-based transition stays for the workflow fan-out run-control sync, which is still synchronous.
@changeset-bot

changeset-bot Bot commented Oct 16, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 71f9667

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Devin Review: 1 flag

Not posted on this PR by your GitHub settings — view it in Devin Review. (Configure)

Devin Review

@ScriptedAlchemy
ScriptedAlchemy merged commit 7282324 into master Oct 16, 2026
10 of 20 checks passed
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.

1 participant