Conversation
Thread an optional AbortSignal through the model-cache single-flight so caller cancellation reaches the fetcher layer. Each flight owns a refcounted AbortController: the shared network request is aborted only when the last waiter leaves, the in-flight entry is released synchronously at last-waiter abort, and a joiner arriving after the release starts a fresh fetch. Every fetch routed through the single-flight carries a bounded 15 s timeout that manifests as an abort. Fetchers whose HTTP client natively supports cancellation (axios signal, fetch signal) cancel the network request on the last-waiter abort; SDK-bound fetchers (poe, LM Studio client calls) honor cancellation at their await boundaries by releasing the shared entry and stopping their waiters. Fixes Zoo-Code-Org#1615
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository: Zoo-Code-Org/Zoo-Code/.coderabbit.yaml Review profile: ASSERTIVE Plan: Advanced Run ID: 📒 Files selected for processing (1)
Included review availability: Your plan provides up to 4 included reviews per hour; 2 remain after this review. 📜 Recent review details🧰 Additional context used📓 Path-based instructions (5)Treat model, provider, MCP, path, command, and tool data as untrusted.⚙️ CodeRabbit configuration file Files:
Require regression coverage at the lowest valid harness with behavior-focused assertions, including relevant negative, error, false/unset, and boundary cases.⚙️ CodeRabbit configuration file Files:
Check strict typing and exhaustive behavior across normal, boundary, error, cancellation, retry, and compatibility paths.⚙️ CodeRabbit configuration file Files:
Verify extension/webview contracts, cancellation and error propagation, VS Code lifecycle correctness, and behavior under retries and partial failure.⚙️ CodeRabbit configuration file Files:
Act as an adversarial second-opinion reviewer.⚙️ CodeRabbit configuration file Files:
🔇 Additional comments (1)
📝 SummarySummary by CodeRabbit
WalkthroughThe change adds optional abort-signal support across model-catalog fetchers. The model cache now coordinates cancellable single-flight requests with bounded timeouts, waiter tracking, and immediate release. Tests cover provider propagation, abort errors, fallback ordering, fan-out requests, and shared-flight lifecycle behavior. ChangesModel catalog cancellation
Priority: ➖ Normal Estimated code review effort: 4 (Complex) | ~60 minutes Change: Bug fix · Severity of issue fixed: Medium Sequence Diagram(s)sequenceDiagram
participant Caller
participant ModelCache
participant ProviderFetcher
participant HTTPClient
Caller->>ModelCache: Request models with AbortSignal
ModelCache->>ProviderFetcher: Dispatch shared fetch with signal
ProviderFetcher->>HTTPClient: Start cancellable catalog request
Caller->>ModelCache: Abort signal
ModelCache->>ProviderFetcher: Abort when the last waiter leaves
ProviderFetcher->>HTTPClient: Cancel request where supported
ModelCache-->>Caller: Reject with AbortError
Caution Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional.
❌ Failed checks (1 error, 2 warnings)
✅ Passed checks (5 passed)
Full details: Out of Scope Changes checkExplanation The issue explicitly excludes auth-scoped fetches. This PR adds caller-signal handling and tests for the direct Full details: Regression EvidenceExplanation The changed auth-scoped Resolution Add a model-cache test for auth-scoped Full details: Lifecycle Resource CleanupExplanation The changed single-flight path retains resources after early cancellation and can duplicate provider work. Resolution Dispose the per-flight timeout on early release. Use an explicitly clearable timer, or otherwise provide a cancellation/disposal path that removes the timeout listener and releases the timer when the last waiter leaves. For Poe and LM Studio, either add cancellation support to the underlying SDK operation or keep the non-cancellable operation tracked until it settles and prevent a replacement flight from starting duplicate provider work.
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Review statusThanks for contributing. This comment tracks the review sequence and the next action. Current step: Address automated review findings and push fixes. After fixes are pushed and required CI passes, automated review restarts. Review-state labels are managed by this workflow; do not edit them manually. |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Cover the three cancellation branches in getPoeModels: a pre-aborted signal rejects with AbortError before the SDK call, an abort observed while the SDK call is pending rejects instead of resolving a catalog, and an SDK rejection after caller cancellation rethrows AbortError instead of returning an empty catalog. Addresses the pre-merge Regression Evidence check asking for focused negative-path tests for the changed Poe cancellation behavior.
What
Caller cancellation now reaches the model-catalog fetcher layer.
getModelsandrefreshModelsaccept an optionalAbortSignal, which is threaded through the model-cache single-flight to whichever fetcher is dispatched. Before, every caller joined one non-cancellable shared promise: a caller that gave up left the HTTP request and the in-flight entry running until the request settled.How
AbortController. The network request aborts only when the last waiter leaves; a partial abort detaches that waiter and leaves the fetch running.signal,fetchsignal) cancel the request at the network level. SDK-bound fetchers (poe, the LM Studio client calls) expose no cancellation surface, so they honor cancellation at their await boundaries: the shared entry is released and waiters stop waiting.Heads-up
The uniform 15 s single-flight timeout replaces per-fetcher bounds on single-flight-served fetchers: litellm from 5 s to 15 s, kenari/nanogpt/opencode-go/deepseek/moonshot from 10 s to 15 s. The auth-scoped fetchers (zoo-gateway, kimi-code) keep their own bounds; the per-model OpenRouter endpoints path is unchanged.
Tests
44 new tests: 15 single-flight behavior tests (refcounting, release-on-abort, fresh joiner, timeout) plus per-fetcher abort tests across the touched providers. Provider surface: 1880 passed, 0 failed.
Closes #1615