Decay unmatched order-response buffer and exempt benign acks (fixes #218)#234
Merged
Conversation
0c076b1 began feeding every order-response whose request_id did not match a pending place into `unmatched_order_responses`, freezing the maker once the buffer passed 256 entries. The buffer never decayed and had stable benign sources — the reduce-only inventory-exit ack (its submission id was discarded, never registered as pending), late acks for places already dropped by `pending.retain`, and cancel acks — so any long live session grew the count monotonically until it hit the cap and falsely failed closed, cancelling all quotes and reconnecting. - Age unmatched entries out by cycle (UNMATCHED_ORDER_RESPONSE_TTL_CYCLES) so bounded-rate benign responses can no longer grow the buffer without limit; only a sustained flood of genuinely-uncorrelated responses within the window still overflows and fails closed. - Register the inventory-exit submission id into `pending` (sentinel level so it never reserves a quote slot) so its async ack correlates instead of counting as unmatched. - Add a long-session regression test proving the buffer stays bounded and never freezes under a steady stream of benign unmatched responses, while a same-cycle flood still fails closed. Fixes #218 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
wjllance
force-pushed
the
fix-218-unmatched-buffer-decay
branch
from
July 13, 2026 07:37
b97eb54 to
527001b
Compare
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
0c076b1started routing every order-response whoserequest_iddid not match a pending place intounmatched_order_responses, freezing the maker (cancel all quotes + reconnect) once the buffer exceeded 256 entries. The buffer never decayed, and it had stable benign sources, so any long live session grew the count monotonically until it hit the cap and falsely failed closed:cycle.rs) used.await?and discarded its submission id, so its async ack was never registered as pending and always counted as unmatched.pending.retain(|p| cycle - p.cycle <= 2).request_idwith no matching pending place.Changes
standx-maker/src/runtime.rs): unmatched entries are now stamped with the cycle they arrived and aged out afterUNMATCHED_ORDER_RESPONSE_TTL_CYCLES(8). Bounded-rate benign responses can no longer grow the buffer without limit; only a sustained flood of genuinely-uncorrelated responses within the window still overflows and fails closed, preserving the real protection.standx-cli/src/commands/maker/cycle.rs): the exit submission id is registered intopendingwith a sentinel level (so it never reserves a real quote slot) so its async ack correlates as matched. A reduce-only market order never rests, so reconciliation drops it whenpendingages out.OrderResponseUnmatchednow carries the currentcycle(standx-cli/src/commands/maker/runtime.rs).Auth acks are consumed inside
OrderResponseStream::connect()and never reach the channel, so they were already exempt.Test plan
cargo fmt -- --check— no diffcargo clippy --workspace --all-targets -- -D warnings— cleancargo test -p standx-makerandcargo test -p standx-cli— passbenign_unmatched_responses_decay_over_a_long_sessiondrives 10,000 cycles of steady benign unmatched responses and asserts the buffer stays bounded and never freezes; the existingunmatched_response_overflow_fails_closedtest confirms a same-cycle flood still fails closed.Fixes #218
🤖 Generated with Claude Code