You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
wait=False now uses quick_operation_timeout_seconds instead of a literal 0 for it’s deadline to ensure operations aren’t just instantly failing without a chance to execute
wait=True waits for a terminal state such as RUNNING
Use python scripts/pq_wait_test.py --url <server> --username <username> to exercise the new behavior.
The reason will be displayed to describe this comment to others. Learn more.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.
If a restart is requested while the existing attempt is in ACQUIRING_WORKER (init=0), that attempt can still progress through INITIALIZING (init=2) to RUNNING (init=2) before the restart takes effect. The changed timestamp makes this watcher accept RUNNING even though _old_run_gone is still False. Consequently, wait=True can return the previous attempt's outcome before the replacement starts. Track the pre-existing startup separately and require evidence of a replacement before accepting its outcome. Add this sequence as a regression test.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Settlement handling can misreport lifecycle outcomes, and temporary log creation permits symlink-based file truncation.
No open issues 🎉
4 previously missed issues
In code that hasn't changed since last review
Create log files atomically in the private temporary directory
scripts/pq_wait_test.py:458
The log path is outside the private temporary directory and is predictable from that directory's visible name. Another local user can create a symlink there while the password prompt is open. On systems permitting that symlink traversal, open(..., "w") truncates the target with the invoking user's permissions. Allocate the log atomically with tempfile.mkstemp(), which also creates it with private permissions.
A new attempt ending in KILLED never satisfies _start_settled, even with a different initialization timestamp, so start/restart reports a timeout instead of the settled outcome. client/_protobuf.py:72 already classifies KILLED as terminal. Include it in the ended statuses, add a predicate test, and update the documented start/restart outcome lists.
KILLED is missing from the stopped statuses, although client/_protobuf.py:72 classifies it as terminal. If a worker ends in that state while stopping, _stop_settled stays false and reports a timeout despite termination. Include KILLED and add a stop-predicate test for that outcome.
Prevent stale runs from satisfying replacement-run settlement
A changed initialization timestamp does not always identify a replacement run. If the initial snapshot is ACQUIRING_WORKER with timestamp 0, the previous run can initialize before the restart is processed. A delayed RUNNING or FAILED snapshot from that run then has a nonzero timestamp and satisfies this predicate, ending the wait before the replacement settles. Use a reliable attempt identifier or a synchronized stop/new-attempt boundary, and add a regression case where the previous run initializes during submission.
Both _START_ENDED_STATUSES and _STOPPED_STATUSES omit KILLED, which client/_protobuf.py:72 classifies as terminal. If a new start/restart attempt ends in KILLED, or a stop leaves the PQ in that state, the corresponding predicate never settles and wait=True reports a timeout despite the worker having terminated. Include KILLED in both sets, add regression cases for both predicates, and update the documented outcome lists.
The reason will be displayed to describe this comment to others. Learn more.
Per Claude: the CLI can time out before the server does. The extra 60s doesn't cover a first call that has to authenticate (60–120s) and subscribe (30s). Fix: add auth_timeout_seconds + subscribe_timeout_seconds to the CLI timeout.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Unsafe log creation permits symlink attacks that truncate user-writable files, while omitted KILLED statuses cause settled start, restart, and stop operations to wait until timeout.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
New behavior for waiting:
wait=Falsenow usesquick_operation_timeout_secondsinstead of a literal 0 for it’s deadline to ensure operations aren’t just instantly failing without a chance to executewait=Truewaits for a terminal state such as RUNNINGUse
python scripts/pq_wait_test.py --url <server> --username <username>to exercise the new behavior.