Repository navigation
Lite: a cancelled analysis request stops instead of reading to the end - #4561
Merged
Merged
Conversation
Lite's four on-demand analysis methods (CollectAndScoreFactsAsync, CollectConfigAuditFactsAsync, ComparePeriodsAsync, and the private LookUpDispersionAsync) now take a CancellationToken, threaded through AnalysisContext.CancellationToken the way the DuckDB fact collector and baseline provider already read it. The three MCP tool callers (analyze_server, compare_analysis, audit_config) pass their own token through get_analysis_facts, compare_analysis, and audit_config. Each method's fault catch now excludes OperationCanceledException, so a cancelled read reaches the caller as a cancellation instead of an empty result logged as a fault -- the same #4203 rule Darling's twin already follows.
…aller A config-change attribution request that had already been cancelled still ran both comparison-period reads to the end, because the internal call to ComparePeriodsAsync inside AnalysisService omitted the CancellationToken that was already in scope on the line above it. Extends the source-census pin covering the four on-demand analysis methods with a fact that every production call of those methods under Lite/ passes a CancellationToken argument, so a future caller that forgets the token fails the same way.
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.
Why
A cancelled Lite MCP analysis request (a client that gave up, or an abandoned tool call)
used to keep reading DuckDB to the end. Darling's twin service already honours its
caller's cancellation on the same four methods; Lite's did not.
What changes
Lite/Analysis/AnalysisService.cs:CollectAndScoreFactsAsync,CollectConfigAuditFactsAsync,ComparePeriodsAsync, and theprivate
LookUpDispersionAsynceach take aCancellationToken cancellationToken = default,set onto
AnalysisContext.CancellationToken(or forwarded toBaselineProvider.GetBaselineAsync),which the DuckDB fact collector and baseline provider already observe on every store read.
catch (Exception ex)now excludesOperationCanceledException(when (ex is not OperationCanceledException)), so a cancelledread reaches the caller as a cancellation instead of an empty result logged as an error —
the same rule Darling's
CollectConfigAuditFactsAsyncalready states for the same reason.AttributeConfigChangesAsyncnow passescontext.CancellationTokento its
ComparePeriodsAsynccall, the same token it already checks withThrowIfCancellationRequested()on the line above; a cancelled config-change attributionrequest used to run both comparison-period reads to the end anyway. Every other production
call of the four on-demand methods under
Lite/already passed the token.Lite/Mcp/McpAnalysisTools.cs:GetAnalysisFacts(get_analysis_facts),CompareAnalysis(compare_analysis), andAuditConfig(audit_config) each take aCancellationToken cancellationToken = defaultparameter and pass it through to theAnalysisServicecall they make. Their outercatch (Exception ex)blocks also excludeOperationCanceledExceptionnow that a cancellation can actually surface there.Test plan
Census pin (Darling.Tests, runs on macOS): a new
LiteAnalysisServiceCancellationSourceTestsreadsLite/Analysis/AnalysisService.csas text(no project reference to Lite) and asserts each of the four methods' signature carries a
CancellationTokenand that the one fault catch inside each method's body excludesOperationCanceledException.origin/dev(f8508b5):Total: 5, Errors: 0, Failed: 5(the pre-fix source hasneither the parameter nor the filter).
AnalysisWindowEmptyRuleParityTests,AnalysisFactsReadRunsDetectorParityTests, andAsOfWindowAnchorTests:Total: 39, Errors: 0, Failed: 0.The same class also carries a new fact,
EveryProductionCallOfTheFourOnDemandMethods_ PassesACancellationTokenArgument: it scans every.csfile underLite/for a call of thefour on-demand methods and asserts the call's argument text contains a
CancellationToken.Lite/Analysis/AnalysisService.cs: call of ComparePeriodsAsync at offset 62746 has no CancellationToken argument.Total: 5, Errors: 0, Failed: 0.Mutation: removed the
when (ex is not OperationCanceledException)filter fromCollectAndScoreFactsAsync's catch, rebuilt — the census pin went RED(
Total: 4, Errors: 0, Failed: 1, theCollectAndScoreFactsAsynccase) — then reverted andrebuilt back to GREEN.
Lite.Tests pins (Windows-only; CI judges these): a new
LiteAnalysisCancellationTestsclass gives each of the three public
AnalysisServicemethods a pre-cancelledCancellationTokenSourceand assertsAssert.ThrowsAnyAsync<OperationCanceledException>. Onthe pre-fix code this file does not compile (the methods had no
cancellationTokenparameterto pass), so its RED is a compile failure, not a runtime one. It builds clean (0 warnings) on
this branch;
dotnet Lite.Tests.dllcannot run in-process on macOS (discovery dies onWindowsBase), so CI is the first runtime judge of these three tests.
Builds, 0 warnings on each:
Lite/PerformanceMonitorLite.csproj,Lite.Tests/Lite.Tests.csproj,Darling/Darling.Tests/Darling.Tests.csproj(Release,-p:EnableWindowsTargeting=true), anddeprecated/Dashboard.Tests/Dashboard.Tests.csproj(build-only, untouched — its ownAnalysisService/McpAnalysisToolscopies indeprecated/Dashboardare a separate, olderclass hierarchy and were not touched).
xUnit1051does not fire because both test projects'.csprojalready suppress it (<NoWarn>...;xUnit1051</NoWarn>) with a standing commentexplaining why (a per-call-site style nag across hundreds of short-lived test calls).
CHANGELOG
SECTION: Fixed
ENTRY: - Lite's MCP analysis tools stop reading when the client cancels the request ([#4561]) - A cancelled
get_analysis_facts,compare_analysisoraudit_configrequest, and the config-change attribution behind it, now stops reading DuckDB and returns as cancelled, instead of reading to the end and logging an error. Darling's analysis tools already did this.REF: [#4561]: #4561