Repository navigation
Thread cancellation through 10 store/fleet web reads (#4203) - #4402
Merged
Merged
Conversation
get_store_query_stats, get_store_metrics, get_store_log, get_collector_stall_probes, get_plan_xml, get_oversized_plan_backlog, get_fleet_overview, get_sweep_reports, get_collector_cost and get_pg_blocking now take a CancellationToken and pass it down to every store call (resolver, rollup availability, not-collected status, direct reads), so an abandoned web request stops its query instead of running to completion. Removes all ten from CancellationAllowlist. get_store_host stays on the allowlist: its GetOrGatherAsync signature makes threading the caller's token in a larger change than this slice, so it is left for a follow-up.
…t exclusion and updated call text)
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.
Refs #4203.
Why
/api/read/{tool}requests that abandon (client disconnect, timeout) should stop their store query instead of running it to completion. #4357/#4359 established the pattern; this converts 10 of the 11 tools in this batch.What changes
get_store_query_stats,get_store_metrics,get_store_log,get_collector_stall_probes,get_plan_xml,get_oversized_plan_backlog,get_fleet_overview,get_sweep_reports,get_collector_cost,get_pg_blocking— each tool method now takes a trailingCancellationToken cancellationToken = default, passes it to every store call (resolver, reader helpers, not-collected probes), and narrows its catch block towhen (ex is not OperationCanceledException). All ten are removed fromDarlingWebEndpoints.CancellationAllowlist, and their dispatch entries inBuildReadDispatchnow passc.RequestAborted(orcancellationToken: c.RequestAbortedwhere named).get_store_host(the 11th tool in scope) is left unconverted and still allowlisted: its read runs throughStoreHostProfileCache.GetOrGatherAsync, whose gather delegate is wrapped in its own fixed-deadlineCancellationTokenSource. Linking the caller's token in required either aCreateLinkedTokenSourceinside the delegate (tried, but it makesWebReadCancellationPinTests.CancellationAllowlist_HasNoStaleEntryfail — that test asserts an allowlisted tool's method must NOT already carry aCancellationTokenparameter, so a method converted but kept on the allowlist is itself a violation) or removing it from the allowlist plus building aPostgresConfig-carrying harness case (the test's defaultBuildReadDispatch()call passes noPostgresConfig, soget_store_hostshort-circuits to"unavailable"before it ever reaches the store, and the cancellation assertion can never observe anything on it). Neither fit this change's scope.DarlingMcpStoreHostTools.cswas reverted to dev's shape. A follow-up should either extend the pin harness with a populatedPostgresConfigcase, or give the cache's own deadline logic a way to observe the caller's token without changing the test's shape.Test plan
dotnet build Darling/Darling.Tests/Darling.Tests.csproj -p:EnableWindowsTargeting=true(both Debug and Release): 0 Warning(s), 0 Error(s).dotnet build Lite.Tests/Lite.Tests.csproj -p:EnableWindowsTargeting=true: 0 Warning(s), 0 Error(s).CancellationAllowlist, soWebReadCancellationPinTests.ConvertedDispatchEntries()never generated a theory case for any of them — the cancellation-observed assertion never ran against these ten. Removing the allowlist entries makes the reflection ratchet (EveryStoreReadingToolMethod_TakesACancellationToken_UnlessAllowlistedandCancellationAllowlist_HasNoStaleEntry) enforce them now that they're off it.Darling.Tests.dllin-process (strippedMicrosoft.WindowsDesktop.Appfrom the Release runtimeconfig, no rig/database needed for this class):dotnet Darling.Tests.dll -class Darling.Tests.WebReadCancellationPinTests→ Total: 101, Errors: 0, Failed: 0, Skipped: 0.PgTargetMcpSurfaceTests,McpServiceParameterDiSeatCensusTests,EngineCapabilityMissTests,RuntimePreconditionMissTests(all touching this area): Total: 4, Errors: 0, Failed: 0.CHANGELOG entry
SECTION: Fixed
ENTRY:
get_store_query_stats,get_store_metrics,get_store_log,get_collector_stall_probes,get_plan_xml,get_oversized_plan_backlog,get_fleet_overview,get_sweep_reports,get_collector_costandget_pg_blockingkept running their store query to completion after a/api/readclient disconnected or timed out, because their dispatch entries and tool methods never threaded the request'sCancellationTokenthrough to the query. Each now takes the token and passes it to every store call, so an abandoned request stops promptly instead of finishing unread.REF:
[Thread cancellation through 10 store/fleet web reads (#4203) #4402]: Thread cancellation through 10 store/fleet web reads (#4203) #4402
Known limits
CancellationAllowlistcount on dev: 42; after this PR: 32 (10 removed;get_store_hoststays, unconverted — see "What changes" above for why).cancellationTokenparameter through (every reader method touched here already had one defaulted todefault); no other caller's compile surface changed.DarlingWebEndpoints.cstoo — expect a textual merge conflict at merge time.get_store_hostdeferred) — a small follow-up, not a separate issue (it's a few hours at most, tied to this same allowlist/pin mechanism).