Index pending-probe deadlines and process managed timeout transitions through a global bounded work budget, preventing large timeout backlogs from monopolizing a ManagedClientTask poll.
Timeout processing now round-robins across due targets while preserving timeout-before-receive ordering, including partial batches during active and draining states, so overdue replies remain EchoLoss followed by LateReply rather than being misclassified as normal replies. Public timeout polling remains exhaustive, and the deadline index stays exactly bounded by the existing pending-probe limit.
Adds deterministic coverage for per-poll bounds, multi-target fairness, partial-batch receive ordering, drain behavior, cursor pruning, deadline-index consistency, and preserved exhaustive client semantics.
Index pending-probe deadlines and process managed timeout transitions through a global bounded work budget, preventing large timeout backlogs from monopolizing a ManagedClientTask poll.
Timeout processing now round-robins across due targets while preserving timeout-before-receive ordering, including partial batches during active and draining states, so overdue replies remain EchoLoss followed by LateReply rather than being misclassified as normal replies. Public timeout polling remains exhaustive, and the deadline index stays exactly bounded by the existing pending-probe limit.
Adds deterministic coverage for per-poll bounds, multi-target fairness, partial-batch receive ordering, drain behavior, cursor pruning, deadline-index consistency, and preserved exhaustive client semantics.
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
### 💡 Codex Review
Here are some automated review suggestions for this pull request.
**Reviewed commit:** `4632e310d7`
<details> <summary>ℹ️ About Codex in GitHub</summary>
<br/>
[Your team has set up Codex to review pull requests in this repo](https://chatgpt.com/codex/cloud/settings/general). Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
</details>
When a managed task contains more than TIMEOUT_WORK_BUDGET targets, every task poll still scans all target_len entries and, if many are overdue, stores all their indexes before processing only 128 expirations. Because max_live_target_generations is configurable without an upper bound, a large timeout backlog causes repeated O(number-of-targets) scans and allocations across many self-woken polls, defeating the cooperative work budget and potentially monopolizing a current-thread Tokio runtime. Persist the discovery cursor/backlog and inspect only a bounded number of targets per poll, as the existing target and send passes do.
Useful? React with 👍 / 👎.
**<sub><sub></sub></sub> Bound timeout target discovery work**
When a managed task contains more than `TIMEOUT_WORK_BUDGET` targets, every task poll still scans all `target_len` entries and, if many are overdue, stores all their indexes before processing only 128 expirations. Because `max_live_target_generations` is configurable without an upper bound, a large timeout backlog causes repeated O(number-of-targets) scans and allocations across many self-woken polls, defeating the cooperative work budget and potentially monopolizing a current-thread Tokio runtime. Persist the discovery cursor/backlog and inspect only a bounded number of targets per poll, as the existing target and send passes do.
Useful? React with 👍 / 👎.
When more than 128 targets have simultaneous expirations, this pass leaves some overdue targets active, but its immediate result does not prevent the send pass later in the same poll. If one of those targets is selected by send_cursor while its pending map is full—for example, max_pending_probes = 1 with its sole probe already expired—poll_send_probe reports PendingLimitExceeded and the managed target fails even though processing its already-due timeout on the next poll would free the slot. Track which targets still have due timeout work or defer sending while any selected target's timeout deadline is overdue.
Useful? React with 👍 / 👎.
**<sub><sub></sub></sub> Skip sends for targets with unprocessed timeouts**
When more than 128 targets have simultaneous expirations, this pass leaves some overdue targets active, but its `immediate` result does not prevent the send pass later in the same poll. If one of those targets is selected by `send_cursor` while its pending map is full—for example, `max_pending_probes = 1` with its sole probe already expired—`poll_send_probe` reports `PendingLimitExceeded` and the managed target fails even though processing its already-due timeout on the next poll would free the slot. Track which targets still have due timeout work or defer sending while any selected target's timeout deadline is overdue.
Useful? React with 👍 / 👎.
When the deadline index needs a new B-tree node, deadlines.insert allocates during commit_insert, but preflight_insert only fallibly reserves the hash map. This commit runs after the UDP send has already been accepted, so allocation failure now aborts or panics instead of returning ClientError::AllocationFailed before transmission, breaking the transactional send path that reserves storage during preflight. Use an index with fallible capacity reservation and reserve it alongside the map before allowing the send.
Useful? React with 👍 / 👎.
**<sub><sub></sub></sub> Keep probe commits allocation-free**
When the deadline index needs a new B-tree node, `deadlines.insert` allocates during `commit_insert`, but `preflight_insert` only fallibly reserves the hash map. This commit runs after the UDP send has already been accepted, so allocation failure now aborts or panics instead of returning `ClientError::AllocationFailed` before transmission, breaking the transactional send path that reserves storage during preflight. Use an index with fallible capacity reservation and reserve it alongside the map before allowing the send.
Useful? React with 👍 / 👎.
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
### 💡 Codex Review
Here are some automated review suggestions for this pull request.
**Reviewed commit:** `ab9912b3d5`
<details> <summary>ℹ️ About Codex in GitHub</summary>
<br/>
[Your team has set up Codex to review pull requests in this repo](https://chatgpt.com/codex/cloud/settings/general). Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
</details>
When targets.len() > TIMEOUT_WORK_BUDGET and one sparsely located target has multiple overdue probes, advancing timeout_cursor unconditionally after processing only one probe postpones that target's next expiration until a complete target sweep. more_due merely triggers another poll; each intervening poll also calls next_deadline, which scans every target, so a sparse backlog can require O(N / TIMEOUT_WORK_BUDGET) polls and repeated O(N) scans per loss, severely delaying timeout events and drain completion. Preserve or requeue indexes whose TimeoutStep::more_due is true while still round-robining among backlogged targets. Fresh evidence beyond the earlier timeout-discovery comment is that the current fix still advances the cursor despite the returned backlog signal.
Useful? React with 👍 / 👎.
**<sub><sub></sub></sub> Requeue targets that still have due timeouts**
When `targets.len() > TIMEOUT_WORK_BUDGET` and one sparsely located target has multiple overdue probes, advancing `timeout_cursor` unconditionally after processing only one probe postpones that target's next expiration until a complete target sweep. `more_due` merely triggers another poll; each intervening poll also calls `next_deadline`, which scans every target, so a sparse backlog can require `O(N / TIMEOUT_WORK_BUDGET)` polls and repeated `O(N)` scans per loss, severely delaying timeout events and drain completion. Preserve or requeue indexes whose `TimeoutStep::more_due` is true while still round-robining among backlogged targets. Fresh evidence beyond the earlier timeout-discovery comment is that the current fix still advances the cursor despite the returned backlog signal.
Useful? React with 👍 / 👎.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Index pending-probe deadlines and process managed timeout transitions through a global bounded work budget, preventing large timeout backlogs from monopolizing a ManagedClientTask poll.
Timeout processing now round-robins across due targets while preserving timeout-before-receive ordering, including partial batches during active and draining states, so overdue replies remain EchoLoss followed by LateReply rather than being misclassified as normal replies. Public timeout polling remains exhaustive, and the deadline index stays exactly bounded by the existing pending-probe limit.
Adds deterministic coverage for per-poll bounds, multi-target fairness, partial-batch receive ordering, drain behavior, cursor pruning, deadline-index consistency, and preserved exhaustive client semantics.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit:
4632e310d7ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
When a managed task contains more than
TIMEOUT_WORK_BUDGETtargets, every task poll still scans alltarget_lenentries and, if many are overdue, stores all their indexes before processing only 128 expirations. Becausemax_live_target_generationsis configurable without an upper bound, a large timeout backlog causes repeated O(number-of-targets) scans and allocations across many self-woken polls, defeating the cooperative work budget and potentially monopolizing a current-thread Tokio runtime. Persist the discovery cursor/backlog and inspect only a bounded number of targets per poll, as the existing target and send passes do.Useful? React with 👍 / 👎.
When more than 128 targets have simultaneous expirations, this pass leaves some overdue targets active, but its
immediateresult does not prevent the send pass later in the same poll. If one of those targets is selected bysend_cursorwhile its pending map is full—for example,max_pending_probes = 1with its sole probe already expired—poll_send_probereportsPendingLimitExceededand the managed target fails even though processing its already-due timeout on the next poll would free the slot. Track which targets still have due timeout work or defer sending while any selected target's timeout deadline is overdue.Useful? React with 👍 / 👎.
@@ -46,0 +64,4 @@if let Some(previous) = previous {let previous = self.map.get_mut(&previous)When the deadline index needs a new B-tree node,
deadlines.insertallocates duringcommit_insert, butpreflight_insertonly fallibly reserves the hash map. This commit runs after the UDP send has already been accepted, so allocation failure now aborts or panics instead of returningClientError::AllocationFailedbefore transmission, breaking the transactional send path that reserves storage during preflight. Use an index with fallible capacity reservation and reserve it alongside the map before allowing the send.Useful? React with 👍 / 👎.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit:
ab9912b3d5ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
@@ -1731,0 +1875,4 @@}}Err(error) => {self.targets[index].counters.packets_sent = client.packets_sent();When
targets.len() > TIMEOUT_WORK_BUDGETand one sparsely located target has multiple overdue probes, advancingtimeout_cursorunconditionally after processing only one probe postpones that target's next expiration until a complete target sweep.more_duemerely triggers another poll; each intervening poll also callsnext_deadline, which scans every target, so a sparse backlog can requireO(N / TIMEOUT_WORK_BUDGET)polls and repeatedO(N)scans per loss, severely delaying timeout events and drain completion. Preserve or requeue indexes whoseTimeoutStep::more_dueis true while still round-robining among backlogged targets. Fresh evidence beyond the earlier timeout-discovery comment is that the current fix still advances the cursor despite the returned backlog signal.Useful? React with 👍 / 👎.