Skip to content

Fix #39: mirror an unchanged poll status with one conditional update - #93

Open
corgab wants to merge 2 commits into
mainfrom
fix/39-skip-unchanged-poll-writes
Open

Fix #39: mirror an unchanged poll status with one conditional update#93
corgab wants to merge 2 commits into
mainfrom
fix/39-skip-unchanged-poll-writes

Conversation

@corgab

@corgab corgab commented Sep 8, 2026

Copy link
Copy Markdown
Owner

Summary

PollQuantumTask::persist() ran on every non-terminal poll: a SELECT of the quantum_tasks row followed by save(). Measured on main with the query log, the second poll of an unchanged RUNNING task issues exactly one SELECT and no UPDATE: Eloquent already skips the write when nothing is dirty, so the amplification the issue describes is one read per poll rather than one write. That is still up to 720 avoidable queries per task at the default polling budget.

Plan

Make the intermediate-status path a single conditional UPDATE keyed on the task ARN and on the status being different, so an unchanged poll is one statement that touches no row and moves no updated_at, and a changed status is written without reading the row first. Keep the model path for terminal transitions, which also record counts, errors and timestamps.

Changes

  • PollQuantumTask::persist(): when neither counts nor an error are given, QuantumTask::query()->where('task_arn', ...)->where('status', '!=', $status->value)->update(['status' => ...]) (Eloquent stamps updated_at itself); otherwise the existing load-and-save path.
  • Documented trade-off: the intermediate update goes straight to the query builder, so QuantumTask model observers no longer see CREATED/QUEUED/RUNNING changes, only the terminal transition. Docblock and README say so and point at CircuitCompleted or the table for earlier states. Keeping those events would require the per-poll SELECT this PR removes.

No config change, no new dependencies, no change to what ends up in the table.

Tests

PersistenceTest: a second poll with the same status runs exactly one query, it is an UPDATE, and updated_at does not move (time is advanced between the polls to prove it); a status change from QUEUED to RUNNING is recorded with a single query and no preceding SELECT. The first test fails on main (the query is a SELECT), and the existing intermediate-status and terminal-state tests keep passing.

Local: pint passed, pest 793 tests passed.

Closes #39

Every non-terminal poll read the quantum_tasks row and saved it back;
Eloquent already skipped the UPDATE when nothing changed, but the SELECT
ran on each of the up to 720 polls of a queued task. A status-only update
is now a single conditional UPDATE keyed on the task ARN and the previous
status, so an unchanged poll costs one query and writes no row, and
updated_at only moves when the status does. Terminal transitions keep the
model path, which also records counts, errors and timestamps.

Closes #39
…rs skip model events

Builder::update() already adds updated_at, so the explicit value only tied
the job to the column name. The docblock and README now say that the
status-only update bypasses the QuantumTask model events, while terminal
transitions still fire them.
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.

[jobs] PollQuantumTask::persist() writes to the database on every unchanged poll

1 participant