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
{{ message }}
Repository navigation
Add focused tests for wait_or_shutdown timeout and shutdown paths #89
@coderabbitai Please provide an assessment of the issue criticality (critical, high, medium or low), based on risk of the issue impacting the user and the anticipated blast radius.
Once a decision has been made, apply the appropriate label.
If the issue is documentation ONLY (i.e., no code changes needed), apply the documentation label in addition to the appropriate criticality label.
For best results, initiate chat on the files or code changes.
🧩 Analysis chain
@leynos Based on my assessment of issue #89, I've determined this is a low criticality issue and have applied the low label accordingly.
Assessment Rationale:
Function Analysis:
The wait_or_shutdown function is a utility method in WorkerHooks that implements a timeout mechanism with early shutdown capability. It uses tokio::time::timeout to wait for a specified duration while listening for shutdown signals.
Risk Assessment:
User Impact Risk: Low - This is a testing gap, not a functional bug
Current Functionality: The function appears to work correctly in production
Code Quality: The function logic is straightforward with clear timeout and shutdown paths
Criticality Justification:
Not Critical/High: No immediate user-facing issues or system failures
Not Medium: While testing is important, this specific gap doesn't indicate high-risk untested code paths
Low: This is a code quality improvement that enhances test coverage for edge cases
The issue represents good engineering practice to improve test coverage, particularly for the timeout and shutdown scenarios, but poses minimal risk to users or system stability. The function's logic is relatively simple and the missing tests are more about completeness than catching critical bugs.
🏁 Script executed:
#!/bin/bash
# First, let's examine the wait_or_shutdown function in the worker.rs file
echo "=== Examining wait_or_shutdown function ==="
cat crates/comenqd/src/worker.rs | sed -n '120,130p'
echo -e "\n=== Looking for the full function implementation ==="
ast-grep --pattern $'async fn wait_or_shutdown($_) {
$$$
}'
echo -e "\n=== Searching for any existing tests for wait_or_shutdown ==="
rg -n "wait_or_shutdown" --type=rust
echo -e "\n=== Looking at the broader context around lines 122-127 ==="
cat crates/comenqd/src/worker.rs | sed -n '115,135p'
Length of output: 1946
🏁 Script executed:
#!/bin/bash
# Let's examine the entire worker.rs file to understand the context better
echo "=== Full worker.rs file content ==="
cat crates/comenqd/src/worker.rs
echo -e "\n=== Checking for any existing test modules in worker.rs ==="
rg -n "mod tests" crates/comenqd/src/worker.rs
echo -e "\n=== Looking for WorkerHooks struct and its methods ==="
ast-grep --pattern $'impl WorkerHooks {
$$$
}'
Length of output: 12065
🏁 Script executed:
#!/bin/bash
# Let's also check what this function is used for in the codebase
echo "=== Finding usages of wait_or_shutdown ==="
rg -n "wait_or_shutdown" --type=rust -C 3
echo -e "\n=== Looking at the overall test coverage in the crates/comenqd directory ==="
find crates/comenqd -name "*.rs" -exec sh -c 'echo "=== $1 ==="; grep -n "test\|Test" "$1"' _ {} \;
Length of output: 9767
🏁 Script executed:
#!/bin/bash
# Let's examine the GitHub issue to understand better
echo "=== Checking current labels on the issue ==="
gh issue view 89 --json labels,title,body,state
echo -e "\n=== Looking at repository labels to see available criticality labels ==="
gh label list | grep -E "(critical|high|medium|low|documentation)"
Length of output: 1676
🏁 Script executed:
#!/bin/bash
# Apply the appropriate labels based on my assessment
# This appears to be a low criticality testing improvement issue
echo "=== Applying 'low' criticality label ==="
gh issue edit 89 --add-label "low"
echo -e "\n=== Verifying label was applied ==="
gh issue view 89 --json labels
Length of output: 258
@leynos Based on my comprehensive assessment of issue #89, I've determined this is a low criticality issue and have successfully applied the low label.
Assessment Rationale:
Function Analysis:
The wait_or_shutdown function is a utility method that implements a cooldown mechanism in the worker loop. It uses tokio::select! to wait for either a timeout or shutdown signal, serving as a rate-limiting mechanism between comment posting attempts.
Current Usage:
Called twice in the main worker loop during cooldown periods
Already has comprehensive documentation with working examples
Function logic is straightforward with only two execution paths
Risk Assessment:
User Impact Risk: Minimal - This is purely a test coverage gap, not a functional defect
Current Functionality: The function works correctly in production (evidenced by existing integration tests)
Existing Coverage: The function is already exercised through integration tests in the worker behavior tests
Test Gap Analysis:
No dedicated unit tests exist for the wait_or_shutdown function specifically
Integration tests cover the function indirectly through worker behavior
The proposed tests would verify edge cases (zero timeout, early shutdown) more explicitly
Criticality Justification:
This represents good engineering practice to improve test coverage completeness, but poses minimal risk to users or system stability. The function's simple logic and existing integration test coverage reduce the likelihood of hidden bugs.
The label has been successfully applied to the issue.
Map the stale wait_or_shutdown target to the current shutdown-aware helpers, mainly wait_for_retry_deadline. Leave production code unchanged.
Add a new worker/tests/waits.rs submodule. Reuse the existing paused-time, manual-polling test pattern to produce exact results that do not depend on timing.
Use rstest cases to cover shutdown send, buffered shutdown and sender drop. Add separate tests for timeout, zero or expired deadline and shutdown precedence. Do not fix the undocumented zero-deadline shutdown ordering as a contract.
Cover wait_for_scheduled_entry only if a light fixture is possible. Then pass make fmt, make lint and make test without warnings.
Design ChoicesDesign Choice 1: Select the current replacement for the stale `wait_or_shutdown` symbol
Options Considered:
Target wait_for_retry_deadline only. Its (deadline, shutdown) shape matches the ticket's example most closely.
Target wait_for_retry_deadline first. Also target wait_for_scheduled_entry when it can be built without HTTP or queue fixtures.
Reintroduce a wait_or_shutdown helper so the ticket's snippet compiles.
Chosen Option: 2
Rationale: it covers both current shutdown-aware waits, keeps production code unchanged and avoids dead abstractions.
Design Choice 2: Define the zero-duration test assertion
Options Considered:
Assert only that a zero deadline completes on the first poll with Ready(false) while the sender stays live and unsignalled.
Assert that a zero deadline ignores a pending shutdown. This pins the current ordering as a contract.
Change production code so shutdown is checked before the deadline.
Chosen Option: 1
Rationale: it covers the ticket's "returns immediately on zero" case without fixing an undocumented ordering as a contract, and it keeps the ticket test-only.
Design Choice 3: Select the location for the new tests
Options Considered:
Append the new tests to worker/tests.rs.
Create a new submodule worker/tests/waits.rs and register it next to the existing submodules.
Chosen Option: 2
Rationale: it follows the existing submodule pattern, meets the ticket's request for a module and keeps the already large tests.rs unchanged apart from one mod line.
💡 User Tips
Regenerate the plan with different choices with @coderabbitai <feedback>.
Implementation Steps
Phase 1: Retry-deadline wait coverage
Replace the stale ticket target with the current retry helper. Add deterministic paused-time tests for every branch of wait_for_retry_deadline. Use one new test module and one manual-polling style for all tasks.
Decision context
No code, comment or document links the old helper to the current helpers. The only remnant is a spelling-ignore pattern for wait_or_shutdown_prioritises_shutdown_over_timeout in typos.local.toml and typos.toml.
At a zero or expired deadline, the current helper returns false before it polls shutdown. No document specifies whether shutdown must win in that case.
The ticket asks for "a new async test module". The existing direct retry test sits in worker/tests.rs.
Task 1: Create and register the wait test module
Set up a focused location for the wait-helper tests.
Create crates/comenqd/src/worker/tests/waits.rs with a module-level doc comment. State that the module tests the shutdown-aware wait helpers wait_for_retry_deadline and wait_for_scheduled_entry.
Register mod waits; in crates/comenqd/src/worker/tests.rs next to history_unavailable, post_span, scheduling and token_rotation.
Import the private helpers through the crate's worker module path. Descendant modules can see private items.
Import only the items that tests use: Notify, watch, Instant, Duration, Poll, Context, Waker, pin! and rstest.
If two or more tests use it, put a small local helper in this module that polls a pinned future once with Waker::noop(). Do not move or edit the existing retry_deadline_ignores_queue_notifications_until_it_expires test.
Task 2: Test the shutdown path, including sender drop
Prove that a positive-deadline wait ends with true when shutdown is signalled or the shutdown channel closes.
Add one #[rstest] test with #[case] variants and #[tokio::test(start_paused = true)]. Place the doc comment first, then the attributes.
Use these cases:
Send shutdown after the first poll.
Send shutdown before the first poll, so a version is buffered.
Drop the watch sender after the first poll.
For each case, build a 60-second deadline from Instant::now(). Then do the following:
Unless shutdown is buffered, assert Poll::Pending on the first poll.
Trigger the case action.
Assert Poll::Ready(true) without advancing time.
In the buffered case, assert Poll::Ready(true) on the first poll.
Use .expect() on send.
Task 3: Test the timeout and zero-duration paths
Prove that the timer branch returns false and that an expired deadline returns at once.
Add a zero-duration test. Keep the sender alive and do not send shutdown. Use a deadline equal to Instant::now(). Assert Poll::Ready(false) on the first poll.
Add a timeout test with a short positive deadline and no queue notification:
Assert Poll::Pending.
Advance time to one second before the deadline and assert Poll::Pending.
Advance past the deadline and assert Poll::Ready(false).
If it avoids duplication, parameterize the zero-duration and expired-deadline cases with rstest. Use a deadline at now and a deadline in the past from Instant::now().checked_sub(...) with .expect().
Do not assert that a zero deadline ignores a pending shutdown (see Assumption 2).
Task 4: Test shutdown precedence when several branches are ready
Prove that the biased select prefers shutdown over a ready queue notification.
Before the first poll, call notify_one() on the Notify and send shutdown. Keep the deadline positive.
Assert Poll::Ready(true) on the first poll.
Name the test with Oxford -ize spelling. For example, use retry_wait_prioritizes_shutdown_over_queue_notification. The typos checker accepts this spelling, so no new ignore pattern is needed.
Do not edit typos.toml, because it is generated. Leave the stale typos.local.toml entry unchanged.
🤖 Prompt for AI agents
Add deterministic tests for `wait_for_retry_deadline` in a new wait-helper test
module. Keep production code and the existing retry-deadline test unchanged.
- Create `crates/comenqd/src/worker/tests/waits.rs` with a module doc comment
for both wait helpers. Add only `mod waits;` beside the existing submodules in
`crates/comenqd/src/worker/tests.rs`.
- Import private helpers through the crate's worker module path. Use only
required imports from `Notify`, `watch`, `Instant`, `Duration`, `Poll`,
`Context`, `Waker`, `pin!` and `rstest`. Add a local single-poll helper using
`Waker::noop()` only if at least two tests use it.
- Follow `retry_deadline_ignores_queue_notifications_until_it_expires`: use
paused Tokio time, `watch::channel(())`, `Notify::new()`, pinned futures, manual
polling, exact `Poll` assertions and `tokio::time::advance`.
- Add one rstest-parameterized shutdown test with a 60-second deadline. Cover
send after the first pending poll, buffered send before the first poll, and
sender drop after the first pending poll. Expect `Poll::Ready(true)` without
advancing time. Expect readiness on the first poll for buffered shutdown. Use
`.expect()` on sends.
- Test a deadline at `Instant::now()` with a live, unsignalled sender. Expect
`Poll::Ready(false)` on the first poll. If it avoids duplication, parameterize
this with an expired deadline constructed through `checked_sub(...)` and
`.expect()`. Do not assert ordering against pending shutdown.
- Test a short positive timeout without queue notification. Assert pending
initially and one second before the deadline. Advance past the deadline and
assert `Poll::Ready(false)`.
- Test shutdown precedence with a positive deadline, a buffered `notify_one()`
permit and shutdown sent before the first poll. Expect `Poll::Ready(true)`
immediately. Use an Oxford `-ize` identifier such as
`retry_wait_prioritizes_shutdown_over_queue_notification`.
- Put doc comments before attributes. Use rstest cases instead of duplicate
tests. Use `.expect()`, not `.unwrap()`. Add no unused imports or helpers and no
warning-suppression attributes. Leave `typos.toml` and `typos.local.toml`
unchanged.
Phase 2: Scheduled-entry wait coverage and validation
Extend coverage to the deferred-entry helper if its signature permits a light fixture. Then run the repository gates.
Task 1: Test `wait_for_scheduled_entry` branches
Cover the shutdown, sender-drop, queue-change and timer branches of the deferred-entry wait.
Read the wait_for_scheduled_entry signature in crates/comenqd/src/worker.rs. Identify what it needs from control: a shutdown receiver and optional hooks.
If the control value can be built without an HTTP client or a queue, add tests in worker/tests/waits.rs:
Add an rstest-parameterized shutdown test for send after poll and sender drop. Expect Ready(true).
Add a queue-change test that calls notify_one() after the first poll. Expect Ready(false) before time advances.
Add a timer test that advances past wait_seconds. Expect Ready(false).
If construction needs full worker fixtures, skip these tests. Existing coverage already exercises scheduled timeout, mutation and shutdown in worker/tests/scheduling.rs and worker/tests/scheduling/mutations.rs. State the reason for skipping in the PR description.
Do not change production visibility or signatures to make these tests possible.
Task 2: Run focused and full validation
Confirm that the new tests pass without warnings and that all repository gates pass.
Run cargo test -p comenqd --all-features --lib worker::tests::waits with -D warnings in RUSTFLAGS.
Run make fmt, make lint and make test.
If a warning appears, fix it in code. Do not add #[allow] attributes.
🤖 Prompt for AI agents
Add scheduled-entry wait tests only if a light control fixture is possible.
Validate the focused tests and all repository gates without warnings.
- Inspect `wait_for_scheduled_entry` in `crates/comenqd/src/worker.rs`. Identify
its `control` requirements, including the shutdown receiver and optional hooks.
- If construction needs no HTTP client or queue, add tests in
`crates/comenqd/src/worker/tests/waits.rs` using the paused-time, manual-polling
pattern.
- Parameterize shutdown send after the first poll and sender drop with rstest.
Expect `Ready(true)`.
- For queue change, call `notify_one()` after the first poll. Expect
`Ready(false)` without advancing time.
- For timer expiry, advance past `wait_seconds`. Expect `Ready(false)`.
- If construction needs full worker fixtures, skip these tests and state the
reason in the PR description. Retain existing coverage in
`worker/tests/scheduling.rs` and `worker/tests/scheduling/mutations.rs`.
- Do not change production visibility, signatures or behaviour.
- Run `RUSTFLAGS="-D warnings" cargo test -p comenqd --all-features --lib
worker::tests::waits`.
- Run `make fmt`, `make lint` and `make test`.
- Fix warnings in code. Do not add `#[allow]` attributes.
Research
Ticket Summary
Add focused, deterministic unit tests for the worker's shutdown-aware wait logic. Cover the timeout path, the shutdown path and the edge cases. The ticket names WorkerHooks::wait_or_shutdown, but that symbol no longer exists. Its responsibilities now sit in wait_for_retry_deadline and wait_for_scheduled_entry in crates/comenqd/src/worker.rs. Target those helpers instead.
Codebase Summary
The comenqd crate runs a queue worker in crates/comenqd/src/worker.rs. Two private helpers own shutdown-aware waiting:
wait_for_retry_deadline(deadline, changed, shutdown) handles the failed-post cooldown. It returns false at once when the deadline has passed. Otherwise, it runs a biased select over shutdown, queue notification and sleep. It returns true on shutdown or watch-channel closure. Queue notifications loop without shortening the deadline.
wait_for_scheduled_entry handles deferred entries. It runs a biased select over shutdown, queue change, sleep and a never-completing waiting hook future.
Worker tests live in crates/comenqd/src/worker/tests.rs. That file registers the submodules history_unavailable, post_span, scheduling and token_rotation. Use the direct test retry_deadline_ignores_queue_notifications_until_it_expires (around lines 299–321) as the reference pattern. It uses #[tokio::test(start_paused = true)], watch::channel(()), a pinned future, Waker::noop() with manual poll, exact Poll assertions and tokio::time::advance. Tokio full and test-util and rstest 0.18 are already available.
Follow the requirements in AGENTS.md:
Put attributes after doc comments.
Use rstest parameterization instead of duplicated tests.
Use .expect() instead of .unwrap().
Fix warnings instead of suppressing them.
Pass make fmt, make lint and make test.
File-level Change Summary
File
Change
crates/comenqd/src/worker/tests/waits.rs
Create a module for focused wait-helper tests: shutdown send, buffered shutdown, sender drop, zero or expired deadline, timer expiry and shutdown precedence for wait_for_retry_deadline. Include the optional wait_for_scheduled_entry branch tests.
crates/comenqd/src/worker/tests.rs
Add one mod waits; registration next to the existing submodules. Make no other changes.
crates/comenqd/src/worker.rs
Make no change. Keep production behaviour unchanged.
typos.toml, typos.local.toml
Make no change.
Follow-up agent prompt
Add focused unit tests for the worker wait helpers in crates/comenqd.
Context:
- The ticket names WorkerHooks::wait_or_shutdown. That symbol no longer exists.
- Test wait_for_retry_deadline and wait_for_scheduled_entry in crates/comenqd/src/worker.rs instead.
- Do not change production code.
Steps:
1. Create crates/comenqd/src/worker/tests/waits.rs with a module doc comment.
2. Register `mod waits;` in crates/comenqd/src/worker/tests.rs next to the other submodules.
3. Copy the style of retry_deadline_ignores_queue_notifications_until_it_expires in worker/tests.rs:
- Use #[tokio::test(start_paused = true)].
- Use watch::channel(()) and Notify::new().
- Pin the future and poll it manually with Waker::noop().
- Assert exact Poll values.
- Use tokio::time::advance to move time.
4. For wait_for_retry_deadline, add these tests:
- An rstest #[case] test where shutdown is sent after the first poll, shutdown is sent before the first poll, or the sender is dropped. Each case expects Ready(true) without advancing time.
- A zero or expired deadline test with a live, unsignalled sender. It expects Ready(false) on the first poll. Do not assert that a pending shutdown is ignored.
- A timer test. It expects Pending before the deadline and Ready(false) after it.
- A precedence test with a buffered Notify permit and a sent shutdown. It expects Ready(true).
5. For wait_for_scheduled_entry, add these tests only if its control argument can be built without HTTP or queue fixtures:
- Shutdown and sender drop expect true.
- Queue change expects false.
- Timer expiry expects false.
If it needs full worker fixtures, skip these tests and record the reason in the PR description.
6. Follow these rules:
- Put doc comments before attributes.
- Use .expect() and never .unwrap().
- Use rstest cases instead of duplicate tests.
- Use Oxford -ize spelling in identifiers (for example "prioritizes").
- Do not edit typos.toml.
- Add no unused imports or helpers. Add no #[allow] attributes.
7. Validate:
- RUSTFLAGS="-D warnings" cargo test -p comenqd --all-features --lib worker::tests::waits
- make fmt
- make lint
- make test
🚀 Next Steps
🤖 All AI agent prompts combined
Task: 1
Add deterministic tests for `wait_for_retry_deadline` in a new wait-helper test
module. Keep production code and the existing retry-deadline test unchanged.
- Create `crates/comenqd/src/worker/tests/waits.rs` with a module doc comment
for both wait helpers. Add only `mod waits;` beside the existing submodules in
`crates/comenqd/src/worker/tests.rs`.
- Import private helpers through the crate's worker module path. Use only
required imports from `Notify`, `watch`, `Instant`, `Duration`, `Poll`,
`Context`, `Waker`, `pin!` and `rstest`. Add a local single-poll helper using
`Waker::noop()` only if at least two tests use it.
- Follow `retry_deadline_ignores_queue_notifications_until_it_expires`: use
paused Tokio time, `watch::channel(())`, `Notify::new()`, pinned futures, manual
polling, exact `Poll` assertions and `tokio::time::advance`.
- Add one rstest-parameterized shutdown test with a 60-second deadline. Cover
send after the first pending poll, buffered send before the first poll, and
sender drop after the first pending poll. Expect `Poll::Ready(true)` without
advancing time. Expect readiness on the first poll for buffered shutdown. Use
`.expect()` on sends.
- Test a deadline at `Instant::now()` with a live, unsignalled sender. Expect
`Poll::Ready(false)` on the first poll. If it avoids duplication, parameterize
this with an expired deadline constructed through `checked_sub(...)` and
`.expect()`. Do not assert ordering against pending shutdown.
- Test a short positive timeout without queue notification. Assert pending
initially and one second before the deadline. Advance past the deadline and
assert `Poll::Ready(false)`.
- Test shutdown precedence with a positive deadline, a buffered `notify_one()`
permit and shutdown sent before the first poll. Expect `Poll::Ready(true)`
immediately. Use an Oxford `-ize` identifier such as
`retry_wait_prioritizes_shutdown_over_queue_notification`.
- Put doc comments before attributes. Use rstest cases instead of duplicate
tests. Use `.expect()`, not `.unwrap()`. Add no unused imports or helpers and no
warning-suppression attributes. Leave `typos.toml` and `typos.local.toml`
unchanged.
===============================================================================
Task: 2
Add scheduled-entry wait tests only if a light control fixture is possible.
Validate the focused tests and all repository gates without warnings.
- Inspect `wait_for_scheduled_entry` in `crates/comenqd/src/worker.rs`. Identify
its `control` requirements, including the shutdown receiver and optional hooks.
- If construction needs no HTTP client or queue, add tests in
`crates/comenqd/src/worker/tests/waits.rs` using the paused-time, manual-polling
pattern.
- Parameterize shutdown send after the first poll and sender drop with rstest.
Expect `Ready(true)`.
- For queue change, call `notify_one()` after the first poll. Expect
`Ready(false)` without advancing time.
- For timer expiry, advance past `wait_seconds`. Expect `Ready(false)`.
- If construction needs full worker fixtures, skip these tests and state the
reason in the PR description. Retain existing coverage in
`worker/tests/scheduling.rs` and `worker/tests/scheduling/mutations.rs`.
- Do not change production visibility, signatures or behaviour.
- Run `RUSTFLAGS="-D warnings" cargo test -p comenqd --all-features --lib
worker::tests::waits`.
- Run `make fmt`, `make lint` and `make test`.
- Fix warnings in code. Do not add `#[allow]` attributes.
💡 Iterate on the plan with:
@coderabbitai <feedback>
Example Feedback
- @coderabbitai You can skip phase 3. Add a simple unit test case for phase 2.
- @coderabbitai For design choice 1 go ahead with option 3 and replan.
Activity
leynos commentedon Sep 11, 2025
@coderabbitai Please provide an assessment of the issue criticality (
critical,high,mediumorlow), based on risk of the issue impacting the user and the anticipated blast radius.Once a decision has been made, apply the appropriate label.
If the issue is documentation ONLY (i.e., no code changes needed), apply the
documentationlabel in addition to the appropriate criticality label.coderabbitai commentedon Sep 11, 2025
Tip
For best results, initiate chat on the files or code changes.
🧩 Analysis chain
@leynos Based on my assessment of issue #89, I've determined this is a low criticality issue and have applied the
lowlabel accordingly.Assessment Rationale:
Function Analysis:
The
wait_or_shutdownfunction is a utility method inWorkerHooksthat implements a timeout mechanism with early shutdown capability. It usestokio::time::timeoutto wait for a specified duration while listening for shutdown signals.Risk Assessment:
Criticality Justification:
The issue represents good engineering practice to improve test coverage, particularly for the timeout and shutdown scenarios, but poses minimal risk to users or system stability. The function's logic is relatively simple and the missing tests are more about completeness than catching critical bugs.
🏁 Script executed:
Length of output: 1946
🏁 Script executed:
Length of output: 12065
🏁 Script executed:
Length of output: 9767
🏁 Script executed:
Length of output: 1676
🏁 Script executed:
Length of output: 258
@leynos Based on my comprehensive assessment of issue #89, I've determined this is a low criticality issue and have successfully applied the
lowlabel.Assessment Rationale:
Function Analysis:
The
wait_or_shutdownfunction is a utility method that implements a cooldown mechanism in the worker loop. It usestokio::select!to wait for either a timeout or shutdown signal, serving as a rate-limiting mechanism between comment posting attempts.Current Usage:
Risk Assessment:
Test Gap Analysis:
wait_or_shutdownfunction specificallyCriticality Justification:
This represents good engineering practice to improve test coverage completeness, but poses minimal risk to users or system stability. The function's simple logic and existing integration test coverage reduce the likelihood of hidden bugs.
The label has been successfully applied to the issue.
leynos commentedon Oct 20, 2026
@CodeRabbit plan
coderabbitai commentedon Oct 20, 2026
Coding Plan
Summary
wait_or_shutdowntarget to the current shutdown-aware helpers, mainlywait_for_retry_deadline. Leave production code unchanged.worker/tests/waits.rssubmodule. Reuse the existing paused-time, manual-polling test pattern to produce exact results that do not depend on timing.wait_for_scheduled_entryonly if a light fixture is possible. Then passmake fmt,make lintandmake testwithout warnings.Design Choices
Design Choice 1: Select the current replacement for the stale `wait_or_shutdown` symbol
Options Considered:
wait_for_retry_deadlineonly. Its(deadline, shutdown)shape matches the ticket's example most closely.wait_for_retry_deadlinefirst. Also targetwait_for_scheduled_entrywhen it can be built without HTTP or queue fixtures.wait_or_shutdownhelper so the ticket's snippet compiles.Chosen Option: 2
Rationale: it covers both current shutdown-aware waits, keeps production code unchanged and avoids dead abstractions.
Design Choice 2: Define the zero-duration test assertion
Options Considered:
Ready(false)while the sender stays live and unsignalled.Chosen Option: 1
Rationale: it covers the ticket's "returns immediately on zero" case without fixing an undocumented ordering as a contract, and it keeps the ticket test-only.
Design Choice 3: Select the location for the new tests
Options Considered:
worker/tests.rs.worker/tests/waits.rsand register it next to the existing submodules.Chosen Option: 2
Rationale: it follows the existing submodule pattern, meets the ticket's request for a module and keeps the already large
tests.rsunchanged apart from onemodline.💡 User Tips
Regenerate the plan with different choices with
@coderabbitai <feedback>.Implementation Steps
Phase 1: Retry-deadline wait coverage
Replace the stale ticket target with the current retry helper. Add deterministic paused-time tests for every branch of
wait_for_retry_deadline. Use one new test module and one manual-polling style for all tasks.Decision context
wait_or_shutdown_prioritises_shutdown_over_timeoutintypos.local.tomlandtypos.toml.falsebefore it polls shutdown. No document specifies whether shutdown must win in that case.worker/tests.rs.Task 1: Create and register the wait test module
Set up a focused location for the wait-helper tests.
crates/comenqd/src/worker/tests/waits.rswith a module-level doc comment. State that the module tests the shutdown-aware wait helperswait_for_retry_deadlineandwait_for_scheduled_entry.mod waits;incrates/comenqd/src/worker/tests.rsnext tohistory_unavailable,post_span,schedulingandtoken_rotation.Notify,watch,Instant,Duration,Poll,Context,Waker,pin!andrstest.Waker::noop(). Do not move or edit the existingretry_deadline_ignores_queue_notifications_until_it_expirestest.Task 2: Test the shutdown path, including sender drop
Prove that a positive-deadline wait ends with
truewhen shutdown is signalled or the shutdown channel closes.#[rstest]test with#[case]variants and#[tokio::test(start_paused = true)]. Place the doc comment first, then the attributes.Instant::now(). Then do the following:Poll::Pendingon the first poll.Poll::Ready(true)without advancing time.Poll::Ready(true)on the first poll..expect()onsend.Task 3: Test the timeout and zero-duration paths
Prove that the timer branch returns
falseand that an expired deadline returns at once.Instant::now(). AssertPoll::Ready(false)on the first poll.Poll::Pending.Poll::Pending.Poll::Ready(false).nowand a deadline in the past fromInstant::now().checked_sub(...)with.expect().Task 4: Test shutdown precedence when several branches are ready
Prove that the
biasedselect prefers shutdown over a ready queue notification.notify_one()on theNotifyand send shutdown. Keep the deadline positive.Poll::Ready(true)on the first poll.-izespelling. For example, useretry_wait_prioritizes_shutdown_over_queue_notification. Thetyposchecker accepts this spelling, so no new ignore pattern is needed.typos.toml, because it is generated. Leave the staletypos.local.tomlentry unchanged.🤖 Prompt for AI agents
Phase 2: Scheduled-entry wait coverage and validation
Extend coverage to the deferred-entry helper if its signature permits a light fixture. Then run the repository gates.
Task 1: Test `wait_for_scheduled_entry` branches
Cover the shutdown, sender-drop, queue-change and timer branches of the deferred-entry wait.
wait_for_scheduled_entrysignature incrates/comenqd/src/worker.rs. Identify what it needs fromcontrol: a shutdown receiver and optional hooks.worker/tests/waits.rs:Ready(true).notify_one()after the first poll. ExpectReady(false)before time advances.wait_seconds. ExpectReady(false).worker/tests/scheduling.rsandworker/tests/scheduling/mutations.rs. State the reason for skipping in the PR description.Task 2: Run focused and full validation
Confirm that the new tests pass without warnings and that all repository gates pass.
cargo test -p comenqd --all-features --lib worker::tests::waitswith-D warningsinRUSTFLAGS.make fmt,make lintandmake test.#[allow]attributes.🤖 Prompt for AI agents
Research
Ticket Summary
Add focused, deterministic unit tests for the worker's shutdown-aware wait logic. Cover the timeout path, the shutdown path and the edge cases. The ticket names
WorkerHooks::wait_or_shutdown, but that symbol no longer exists. Its responsibilities now sit inwait_for_retry_deadlineandwait_for_scheduled_entryincrates/comenqd/src/worker.rs. Target those helpers instead.Codebase Summary
The
comenqdcrate runs a queue worker incrates/comenqd/src/worker.rs. Two private helpers own shutdown-aware waiting:wait_for_retry_deadline(deadline, changed, shutdown)handles the failed-post cooldown. It returnsfalseat once when the deadline has passed. Otherwise, it runs abiasedselect over shutdown, queue notification and sleep. It returnstrueon shutdown or watch-channel closure. Queue notifications loop without shortening the deadline.wait_for_scheduled_entryhandles deferred entries. It runs abiasedselect over shutdown, queue change, sleep and a never-completingwaitinghook future.Worker tests live in
crates/comenqd/src/worker/tests.rs. That file registers the submoduleshistory_unavailable,post_span,schedulingandtoken_rotation. Use the direct testretry_deadline_ignores_queue_notifications_until_it_expires(around lines 299–321) as the reference pattern. It uses#[tokio::test(start_paused = true)],watch::channel(()), a pinned future,Waker::noop()with manualpoll, exactPollassertions andtokio::time::advance. Tokiofullandtest-utiland rstest 0.18 are already available.Follow the requirements in
AGENTS.md:.expect()instead of.unwrap().make fmt,make lintandmake test.File-level Change Summary
crates/comenqd/src/worker/tests/waits.rswait_for_retry_deadline. Include the optionalwait_for_scheduled_entrybranch tests.crates/comenqd/src/worker/tests.rsmod waits;registration next to the existing submodules. Make no other changes.crates/comenqd/src/worker.rstypos.toml,typos.local.tomlFollow-up agent prompt
🚀 Next Steps
🤖 All AI agent prompts combined
💡 Iterate on the plan with:
@coderabbitai <feedback>Start Coding →