fix(routing): avoid deadlock when exclusion log throttle expires - #1154
Conversation
|
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (1)
Included review availability: Your plan provides up to 2 included reviews per hour; 1 remains after this review. 📝 WalkthroughWalkthrough
ChangesExclusion log throttling
Priority: ➖ Normal — Schedule this routing deadlock fix because an expired exclusion-log throttle can block request workers before provider dispatch. Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: ⚪ Minimal · up to Exclusion-log throttling now updates timestamps atomically, preventing request-worker stalls when an exclusion interval expires. The change preserves the throttle behavior and is ready to merge. 🚥 Pre-merge checks | ✅ 5 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (5 passed)
Full details: E2e Test Quality ReviewExplanation Blocking issue: the added regression tests are unit tests in Resolution Add an E2E test that sends requests through the proxy with a cooled routing target and a surviving provider. Cover the post-throttle-expiry request path with a watchdog, assert that the request completes and reaches the surviving provider, and verify the expected single exclusion log under concurrent requests. Use a test-controlled interval or clock if needed to avoid a 60-second test delay.
✨ Finishing Touches🧪 Generate unit tests (beta)
Warning Git: CodeRabbit could not clone the repository, so clone-backed analysis was skipped and this review may be incomplete. Verify repository clone access, such as SSH credentials, before requesting another full review. If clone access is intentionally unavailable, use Comment |
|
@jarvis9443 @nic-6443 — could you review this routing deadlock fix? Repeated target exclusions can permanently block request workers once the 60-second logging throttle expires, before provider dispatch or the upstream timeout. The regression reproduces the original deadlock, the fix and concurrent/suppression tests pass, and all 1,209 proxy unit tests pass. The CLA clarification questions on #1047 also remain open. Thanks! |
jarvis9443
left a comment
There was a problem hiding this comment.
Verified independently, approving.
On main, should_log_exclusion keeps the DashMap::get() read guard alive as the match scrutinee temporary into the fallback arm that calls insert() on the same shard; dashmap 6.1.0's shard lock is a non-reentrant RwLock, so the first exclusion after the 60s window expires parks that worker forever, and every later write to the same shard parks behind it. Applying only your tests onto main's implementation reproduces it (the expiry test times out, the concurrency test sees 3 writers instead of 1); both pass on this branch. I also swept every DashMap/DashSet use in the workspace and this was the only get-then-mutate-under-guard site, so nothing else needs the same treatment.
The red e2e (work-stealing) leg failed on metric-label-selection-e2e startup validation with an assertion text identical to a failure on an unrelated branch yesterday, i.e. a known flake; re-running it.
|
Merged as 7d6d14b — thanks for the thorough report and the fix; it will ship in the next release. |
Anytime, I look forward to contributing more over time! Thank you for creating this project and all of your hard work! |
When a routing target is excluded repeatedly, the first exclusion after its 60-second log throttle expires can block the request worker indefinitely before provider dispatch. In
should_log_exclusion, theDashMap::get()guard used as the match scrutinee remains alive in the fallback arm, whereinsert()attempts to acquire the same shard's write lock. This also prevents the request from reaching the upstream timeout and can accumulate blocked workers during an outage.Use
DashMap::entry()to check and update the timestamp under one guard. This removes the lock upgrade and ensures concurrent callers emit at most one exclusion log per group/model/reason per interval. Routing order, cooldown settings, and public interfaces remain unchanged.Validation:
cargo fmt --all -- --checkandgit diff --checkpass.Summary by CodeRabbit
Bug Fixes
Tests