Skip to content

Thread cancellation through 10 PostgreSQL-target web reads (#4203) - #4373

Merged
erikdarlingdata merged 3 commits into
devfrom
fix/4203-web-read-cancellation-6
Sep 26, 2026
Merged

erikdarlingdata merged 3 commits into
devfrom
fix/4203-web-read-cancellation-6

Conversation

@erikdarlingdata

@erikdarlingdata erikdarlingdata commented Sep 26, 2026 •

Copy link
Copy Markdown
Owner

Refs #4203.

Why

Ten PostgreSQL-target /api/read reads (get_pg_buffer_usage, get_pg_extensions, get_pg_lock_stats, get_pg_server_config, get_pg_server_config_changes, get_pg_write_stats, get_pg_database_trend, get_pg_io_trend, get_pg_query_duration_trend, get_pg_wait_trend) ran their store queries to completion even after the browser abandoned the request, because their tool methods took no CancellationToken and their dispatch entries were on CancellationAllowlist.

What changes

Each of the ten [McpServerTool] methods in DarlingMcpPgServerStateTools.cs and DarlingMcpPgTrendTools.cs gains a trailing CancellationToken cancellationToken = default, threaded into every store call in its body (resolver, rollup/availability probes, reads, not-collected status checks). Each catch block is narrowed to when (ex is not OperationCanceledException). All ten storage-layer and shared-helper methods already accepted a CancellationToken with a default, so no signature changes were needed downstream; only the tool methods and DarlingWebEndpoints.cs's dispatch table needed updating. The ten names are removed from CancellationAllowlist and their dispatch entries now pass cancellationToken: c.RequestAborted.

Test plan

  • dotnet build Darling/PerformanceMonitor.Darling.Service/PerformanceMonitor.Darling.Service.csproj and dotnet build Darling/Darling.Tests/Darling.Tests.csproj -p:EnableWindowsTargeting=true: both 0 warnings / 0 errors.
  • WebReadCancellationPinTests (existing, generic, no changes needed) enforces this class of change directly off the code:
    • AConvertedReadEndpoint_ObservesCancellation_InsteadOfDialingTheStore is a [Theory] over every dispatch entry not on the allowlist (built from DarlingWebEndpoints.BuildReadDispatch().Keys.Except(CancellationAllowlist)) — before this change the ten tools were on the allowlist and excluded from the theory entirely; after this change they are in scope and each is asserted to throw OperationCanceledException against a dead store with an already-cancelled HttpContext.RequestAborted, not NpgsqlException. RED case: if one of the ten dispatch entries above had its cancellationToken: c.RequestAborted argument dropped while staying off the allowlist, its case would throw NpgsqlException (from actually dialing the dead port) instead of OperationCanceledException, and the theory case for that tool name fails.
    • EveryStoreReadingToolMethod_TakesACancellationToken_UnlessAllowlisted (reflection over [McpServerTool] methods with an NpgsqlDataSource parameter, on the read surface, not allowlisted) would fail listing any of the ten as an offender if its method had no CancellationToken parameter.
    • CancellationAllowlist_HasNoStaleEntry would fail if any of the ten were still on the allowlist now that their methods carry a token.
    • All three ran green locally is not verifiable here (Darling.Tests targets net10.0-windows, builds on macOS but cannot run) — listed unchecked; CI decides them. The pin's own design (see the theory's data source) is what would go RED on a regression, per above.
  • Windows-only test suite (Darling.Tests, net10.0-windows): builds 0/0 here, cannot run on macOS. CI decides.

For the coordinator

  • CancellationAllowlist count: down by 10 (the ten PostgreSQL-target reads named above).
  • No shared-helper signature changes: DarlingServerResolver.ResolveOrErrorAsync, DarlingEngineCapability.NotCollectedStatusAsync/PostgresTargetFactsAsync, DarlingRuntimePrecondition.StatusAsync, and every storage-layer reader touched already had a CancellationToken cancellationToken = default parameter; only the tool methods and the two using blocks (added System.Threading) and DarlingWebEndpoints.cs dispatch/allowlist changed.
  • A sibling slice runs in parallel on other tools in the same two files (DarlingWebEndpoints.cs's CancellationAllowlist and dispatch table); PR Thread cancellation through 7 Blocking web reads (#4203) #4360 also touches that allowlist. Textual conflict on merge is expected and is the PR tender's to resolve, per the brief.

CHANGELOG entry

SECTION: Fixed
ENTRY:

get_pg_buffer_usage, get_pg_extensions, get_pg_lock_stats,
get_pg_server_config, get_pg_server_config_changes, get_pg_write_stats,
get_pg_database_trend, get_pg_io_trend, get_pg_query_duration_trend and
get_pg_wait_trend now take a CancellationToken and pass it to every
store call, so an abandoned web request stops its query instead of
running to completion. Removes the ten from CancellationAllowlist.
@erikdarlingdata
erikdarlingdata marked this pull request as ready for review September 26, 2026 02:09
@erikdarlingdata
erikdarlingdata merged commit fd0bad2 into dev Sep 26, 2026
15 of 16 checks passed
@erikdarlingdata
erikdarlingdata deleted the fix/4203-web-read-cancellation-6 branch September 26, 2026 02:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant