fix(quickfiler): make datamodel and dispatcher tests independent of wall-clock timing - #971
Merged
drmoisan merged 26 commits intoOct 2, 2026
Merged
Conversation
Parent parallel-orchestrator committed the child preparation work in its current state on a coordinator COMMIT NOW order. The commit holds the promoted entry, issue.md, spec.md and the plan file as the child left them. The plan may still be a scaffold. Preflight has not cleared. The parent authored no plan or specification content. Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
Research artifact stopped early for quota. Establishes defect A (BackgroundWorker pool-thread start forces wall-clock waits) and defect B (gate-free EnsureDispatcher seeding races the transaction test across parallel classes). Spec, plan and preflight remain. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NcieP6KJzhzgHkRh4F21Po
…depend-on-wall-clock-timing-950
…ision R2) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
…servation Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
… baseline Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
… baseline Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…depend-on-wall-clock-timing-950
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner
Author
|
AC17 final-head confirmation (coordinator ruling, option (a)).
Earlier runs recorded in |
1 of 5 tasks
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.
Summary
QfcDatamodelbackground worker through an injectableWorkerStarterseam; tests runDoWorksynchronously on the calling thread.QfcDatamodelinstance constructors assignworker => worker.RunWorkerAsync(), and the twoRunWorkerAsynccall sites inInitEmailQueuenow callWorkerStarter(worker).Transaction_SecondCallerCannotInstallUntilTheFirstRestores(R4) failure by pinning a non-nullUiThreaddispatcher baseline inside the transaction gate, closing a race with a gate-free writer in another test class under class-level parallelism.[DoNotParallelize], noWorkers=1, no lengthened timeouts, and noThread.Sleep/Task.Delaywaits were introduced; the repository runsettings are unchanged.Why
Several QuickFiler.Test tests failed intermittently under load and stopped unrelated executor gates and the required CI check. Research identified two root causes:
QfcDatamodelLivenessTests,QfcDatamodelTeardownTestsandQfcInitEmailQueueZeroBatchTestsblocked on five-secondSpinWait.SpinUntilandTask.Waitcalls becauseInitEmailQueuestarted its worker on a thread-pool thread the test could not control.UiThreadDispatcherFixture.EnsureDispatcher()writes the process-wideUiThread._dispatcherstatic without taking the transaction gate, racing the theme tests inQfcItemController_FocusAndThemeTestsunderWorkers=0/Scope=ClassLevel.What Changed
Production
QuickFiler/Controllers/QfcDatamodel.cs: new documentedinternal Action<BackgroundWorker> WorkerStarter { get; set; }(mirrors the existingRemainingEmailLoaderconvention; null onGetUninitializedObjectinstances, so a misconfigured test fails fast instead of starting a thread). Assigned in both constructors; replaces bothRunWorkerAsynccall sites.Tests
QuickFiler.Test/Controllers/QfcDatamodelLivenessTests.cs,QfcDatamodelTeardownTests.cs,QfcInitEmailQueueZeroBatchTests.cs: assign a synchronous starter (test-sideBackgroundWorkersubclass exposingOnDoWork) and, where a continuation must be observed after release, a test-owned drainableSynchronizationContext. All wall-clock waits removed.QuickFiler.Test/Controllers/QfcItemController.UiThreadDispatcherFixtureTests.cs: R4 opens ausingoverQfcItemControllerTestSupport.EnsureUiThreadDispatcher()after transaction A acquires the gate and before theoriginalread; both assertions kept; the R4 doc comment now names the gate-free writer as the cause and states the residual-writer invariant.Docs / evidence
docs/features/active/2026-09-30-quickfiler-tests-depend-on-wall-clock-timing-950/: spec, plan, research, baseline / regression / QA-gate evidence, negative-control records, and the policy, code-review and feature audits.Architecture / How It Fits Together
InitEmailQueuesets_remainingLoadActive = trueand then callsWorkerStarter(worker). In production the starter isRunWorkerAsync(), so control flow is identical to before. In tests the starter raisesDoWorksynchronously, so the producer's progress is driven by the test rather than by the thread pool, and each assertion observes a deterministic state.Verification
Completed (local, recorded in the feature folder evidence):
dotnet tool run csharpier check .: pass.msbuild TaskMaster.sln /t:Rebuild ... /p:EnableNETAnalyzers=true /p:EnforceCodeStyleInBuild=true: pass.msbuild TaskMaster.sln /t:Rebuild ... /p:TreatWarningsAsErrors=true: pass.Pending:
spec.md.Backward Compatibility / Migration Notes
None. The seam is
internal, and the default starter preserves the previous behavior.Risks and Mitigations
QfcDatamodelconstruction path that bypasses both constructors would leaveWorkerStarternull. Mitigation: it fails fast with aNullReferenceExceptionatInitEmailQueue, which matches the existingRemainingEmailLoaderbehavior.Review Guide
QuickFiler/Controllers/QfcDatamodel.cs(16 lines).QfcItemController.UiThreadDispatcherFixtureTests.cs(R4 pin and doc comment).spec.mdandfeature-audit.2026-10-02T14-30.mdin the feature folder.Follow-ups
Routed by the coordinator; none filed from this branch.
QuickFiler.Test/TestSupport/when the test csproj is next edited._remainingLoadActivedoc comment inQfcDatamodel.QueueProcessing.csto nameWorkerStarter.QfcDatamodel.cs(495 of 500 lines).SynchronousBackgroundWorkerinstances in the liveness and zero-batch tests.try/finallyaroundtransactionAin R4.FocusAndThemeTeststheme tests hold their ensure scope (theme-test dispatcher exposure).artifacts/csharp/coverage.xmlabsent in agent worktrees (recurring).GitHub Auto-close
🤖 Generated with Claude Code