Skip to content

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

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

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

Conversation

@erikdarlingdata

@erikdarlingdata erikdarlingdata commented Sep 26, 2026 •

Copy link
Copy Markdown
Owner

Refs #4203.

Why

The web /api/read surface abandons its request when the caller disconnects, but these 10 PostgreSQL-target MCP tools ran every store call to completion regardless — a slow query for a client that already left kept holding a connection and burning CPU for no reader. #4357 and #4359 established the pattern (trailing CancellationToken cancellationToken = default, threaded to every store call, c.RequestAborted at dispatch, removed from CancellationAllowlist); this applies it to the 10 single-tool PostgreSQL files in scope.

What changes

Each of these tool methods now takes a trailing CancellationToken cancellationToken = default, threads it through every store call (resolver, rollup/coverage reads, primary reads, capture/probe counts, NotCollectedStatusAsync/RuntimePrecondition.StatusAsync), narrows its catch block to when (ex is not OperationCanceledException), and is removed from CancellationAllowlist with its dispatch entry passing cancellationToken: c.RequestAborted:

  • get_pg_xmin_horizon (DarlingMcpPgXminTools.cs)
  • get_pg_wraparound_risk (DarlingMcpPgWraparoundTools.cs)
  • get_pg_session_states (DarlingMcpPgSessionStatesTools.cs)
  • get_pg_replication_stats (DarlingMcpPgReplicationStatsTools.cs)
  • get_pg_predicate_stats (DarlingMcpPgPredicateTools.cs)
  • get_pg_kernel_stats (DarlingMcpPgKernelStatsTools.cs)
  • get_pg_io_stats (DarlingMcpPgIoTools.cs)
  • get_pg_index_usage (DarlingMcpPgIndexUsageTools.cs)
  • get_pg_database_stats (DarlingMcpPgDatabaseTools.cs)
  • get_pg_autovacuum_health (DarlingMcpPgAutovacuumTools.cs)

All storage-layer reader methods called by these tools already accepted a CancellationToken cancellationToken = default parameter, so no storage-layer signature changes were needed — only the MCP tool layer and DarlingWebEndpoints.cs (dispatch table + CancellationAllowlist) changed. Two internal helper methods in the touched files (DarlingMcpPgDatabaseTools.EmptyAsync, DarlingMcpPgIndexUsageTools.EmptyAsync, DarlingMcpPgSessionStatesTools.EmptyAsync) gained a trailing CancellationToken cancellationToken = default parameter and now pass it to their own store calls.

Did NOT touch DarlingMcpPgIndexTools.cs, DarlingMcpPgLoggingAuditTools.cs, DarlingMcpPgLogEventTools.cs, DarlingMcpPgCpuUtilizationTools.cs or DarlingMcpPgBlockingTools.cs — out of scope for this batch.

Test plan

  • dotnet build Darling/PerformanceMonitor.Darling.Service/PerformanceMonitor.Darling.Service.csproj -p:EnableWindowsTargeting=true — 0 errors.
  • dotnet build Darling/Darling.Tests/Darling.Tests.csproj -p:EnableWindowsTargeting=true — 0 Warning(s), 0 Error(s).
  • Windows-only test suites (Darling.Tests, Lite.Tests) build here but cannot run on macOS — left unchecked for CI to decide.
  • PIN: the existing WebReadCancellationPinTests reflection ratchet (EveryStoreReadingToolMethod_TakesACancellationToken_UnlessAllowlisted, CancellationAllowlist_HasNoStaleEntry) walks every dispatch entry NOT on the allowlist and fails if it drops c.RequestAborted or if the target method lacks a CancellationToken parameter. Removing these 10 tools from the allowlist makes the ratchet enforce them going forward — RED case: any of these 10 dispatch entries omitting cancellationToken: c.RequestAborted, or the target method lacking the trailing CancellationToken parameter, now fails CancellationAllowlist_HasNoStaleEntry/EveryStoreReadingToolMethod_TakesACancellationToken_UnlessAllowlisted where it previously passed (silently) because the tool was allowlisted. No new pin needed — the ratchet already covers every tool leaving the allowlist.

CHANGELOG entry

SECTION: Fixed
ENTRY:

Known limits

get_pg_xmin_horizon, get_pg_wraparound_risk, get_pg_replication_stats,
get_pg_predicate_stats and get_pg_kernel_stats 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 five from
CancellationAllowlist.
get_pg_io_stats, get_pg_database_stats, get_pg_autovacuum_health and
get_pg_index_usage now take a CancellationToken and pass it to every
store call. Dispatch entries and allowlist removal follow in the next
commit alongside get_pg_session_states.
get_pg_session_states now takes a CancellationToken and passes it to
every store call. Wires the RequestAborted dispatch and removes all
10 slice tools from CancellationAllowlist: get_pg_xmin_horizon,
get_pg_wraparound_risk, get_pg_session_states, get_pg_replication_stats,
get_pg_predicate_stats, get_pg_kernel_stats, get_pg_io_stats,
get_pg_index_usage, get_pg_database_stats, get_pg_autovacuum_health.
@erikdarlingdata
erikdarlingdata marked this pull request as ready for review September 26, 2026 11:51
@erikdarlingdata
erikdarlingdata merged commit dd5a7a4 into dev Sep 26, 2026
15 of 16 checks passed
@erikdarlingdata
erikdarlingdata deleted the fix/4203-web-read-cancellation-11 branch September 26, 2026 11:51
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