Skip to content

Implement pausing for submissions#132

Draft
SemMulder wants to merge 4 commits into
masterfrom
sm/allow-pausing-submissions
Draft

Implement pausing for submissions#132
SemMulder wants to merge 4 commits into
masterfrom
sm/allow-pausing-submissions

Conversation

@SemMulder

Copy link
Copy Markdown
Contributor

Introduce submissions_paused and chunks_paused tables (alongside the existing submissions_{completed,failed,cancelled} and chunks_{completed,failed} tables).

Pausing a submission atomically moves it from submissionssubmissions_paused and its remaining chunks from chunkschunks_paused. Because paused chunks are no longer in the chunks table, the consumer dispatcher naturally skips them without any changes to the dispatch query.

Unpausing reverses the move and notifies waiting consumers.

Paused submissions can also be inserted directly in the paused state (via the new paused: bool field on InsertSubmission); in that case notify_on_insert is intentionally not fired.

Paused submissions are cancellable; cancel_submission now handles the case where the submission is found in submissions_paused.

@SemMulder
SemMulder force-pushed the sm/allow-pausing-submissions branch from a9f5556 to bcd4161 Compare July 15, 2026 15:32
@SemMulder

Copy link
Copy Markdown
Contributor Author

TODO: How to deal with reserved chunks when pausing?

@SemMulder
SemMulder force-pushed the sm/allow-pausing-submissions branch from b09f93b to 7e7052d Compare July 17, 2026 14:24
@SemMulder

SemMulder commented Jul 17, 2026

Copy link
Copy Markdown
Contributor Author

TODO: How to deal with reserved chunks when pausing?

Discussed this with @ReinierMaas yesterday, we tried to make it work s.t. chunk completions for cancelled and paused submissions would still be processed. However, implementing that proved to be difficult:

  • What if the completed chunk was the last one? Would the submission status then progress from cancelled/paused to completed?
  • There were a lot of subtleties that needed to be thought through around multiple consumers that could be working on the same chunk.

After struggling with it for a while, I thought it would be easier to invoke the idempotency assumption we have for how consumers process chunks, and just ignore the completion in case the submission is cancelled or paused. This results in less edge-cases and simpler code in the end, at the cost of slightly higher compute cost. But I think it's worth the trade-off: there are enough edge-cases in the codebase as it is :).

@ReinierMaas, let me know if you disagree ;).

Introduce `submissions_paused` and `chunks_paused` tables
(alongside the existing `submissions_{completed,failed,cancelled}` and
`chunks_{completed,failed}` tables).

Pausing a submission atomically moves it from `submissions` →
`submissions_paused` and its remaining chunks from `chunks` →
`chunks_paused`. Because paused chunks are no longer in the `chunks`
table, the consumer dispatcher naturally skips them without any changes
to the dispatch query.

Unpausing reverses the move and notifies waiting consumers.

Paused submissions can also be inserted directly in the paused state
(via the new `paused: bool` field on `InsertSubmission`); in that
case `notify_on_insert` is intentionally not fired.

Paused submissions are cancellable; `cancel_submission` now handles
the case where the submission is found in `submissions_paused`.
@SemMulder
SemMulder force-pushed the sm/allow-pausing-submissions branch from 990a5d2 to 71ace4e Compare July 17, 2026 15:26
pass


class ChunkNotFoundError(IncorrectUsageError):

@SemMulder SemMulder Jul 17, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Note that ChunkNotFoundError can be dropped since it is (and was) dead code.

)
.await
})
.await;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Note that we were silently dropping errors here before, which went unnoticed because of the underscore prefix of _chunk_size.

})
.await;

counter!(crate::prometheus::SUBMISSIONS_TOTAL_COUNTER).increment(1);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

TODO: Increment SUBMISSIONS_PAUSED_COUNTER.

Comment on lines +2137 to +2158
#[sqlx::test]
/// Test that a submission inserted directly in the paused state stays paused
/// (unlike empty non-paused submissions which are auto-completed).
pub async fn insert_paused_submission_stays_paused(db: sqlx::SqlitePool) {
let db = WriterPool::new(db);
let mut conn = db.writer_conn().await.unwrap();
insert_submission_from_chunks(
None,
vec![Some("foo".into()), Some("bar".into())],
None,
StrategicMetadataMap::default(),
ChunkSize::default(),
true,
&mut conn,
)
.await
.expect("insertion failed");

assert_matches!(count_submissions(&mut conn).await, Ok(0));
assert_matches!(count_submissions_paused(&mut conn).await, Ok(1));
assert_matches!(count_submissions_completed(&mut conn).await, Ok(0));
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

TODO: Drop this test, it doesn't add much compared to the tests above.

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