Repository navigation
Give a held session's later probes their own throttle slot - #20
Merged
Merged
Conversation
The hold that stops a resumed subscription session's shadow counter being presented as spend lifts only once that session's own cost is observed moving with no windows — at least two observations, SUB_HOLD_SECS apart. Only the first of those was exempt from the shared throttle, via changes_shape; every later probe competed for a slot that is global across sessions. So the failure needed no unusual input, only a second busy session. A peer rendering on the same timer takes the slot every minute, the switched session is never observed moving, and the proof the hold waits for can never be assembled. The wait stops being a 45-minute one and becomes permanent: the status line shows `limits n/a` for the life of the session and real API-key spend never reaches the day total. Later probes from a held session now take a per-session slot too, bounded exactly as changes_shape is — one extra write per minute per session — and gated on the counter having actually moved.
This was referenced Aug 10, 2026
Merged
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
A session that switched billing mid-life could stay held forever rather than for
SUB_HOLD_SECS.The hold that stops a resumed subscription session's shadow counter being presented as spend lifts only once that session's own cost is observed moving with no windows — at least two observations, 45 minutes apart. Only the first was exempt from the throttle, via
changes_shape; every later probe competed for a slot that is global across sessions.So the failure needs no unusual input, only a second busy session. A peer rendering on the same timer takes the slot, the switched session is never observed moving, and the proof the hold waits for is never assembled. The status line then shows
limits n/afor the life of the session and real API-key spend never reaches the day total.Found in the wild on a machine running four concurrent sessions: the switched session had logged its windowed anchor and exactly one probe, then nothing for over an hour.
changes_shapeis — one extra write per minute per session — and gated on the counter having actually moved.Test plan
cargo fmt --check,cargo clippy --all-targets -- -D warnings,cargo build,cargo test --all(85 passed)a_held_sessions_later_probes_are_never_lost_to_the_shared_throttle— a peer contends for the slot every minute across the whole hold window; asserts the probes keep landing, that spend is counted again once movement is proven, and that the windowed anchor survived (so the release came from proof, not from retention evicting the anchor)!hold_probeterm fails the new test withgot 2— the anchor plus one probe, exactly the field signaturea_frozen_hold_probe_still_waits_its_turn— a frozen counter still writes nothing, so the exemption cannot become a back door. Pins the outcome rather than the mechanism, and says so: two guards produce it, and removing either alone leaves it greenMAX_ENTRIESso pruning cannot make the new test pass vacuously