Repository navigation
Drive LatestWinsPrefetchScheduler debounce from an injected clock - #114
Merged
Merged
Conversation
LatestWinsScheduler_HoverStormStartsOnlyFinalPrediction slept 150 ms on real time and expected a 30 ms debounce to have fired. On a loaded CI runner (run 41157408754) the timer fired late and the test saw 0 starts. The scheduler now takes a TimeProvider (TimeProvider.System by default, so the app's timer behaviour is unchanged) and its tests drive a FakeTimeProvider instead of sleeping: - Both LatestWinsScheduler_* tests and the transport-level LatestWinsHoverStorm test, which had the same wall-clock debounce, advance the clock explicitly. - TimerCountingTimeProvider counts debounce timers as they fire. Advance runs timer callbacks inline, but the code after Task.Delay resumes on the thread pool, so "nothing else started" is asserted on the fired count, which is exact when Advance returns. - Mutation checks: removing the cancel of a superseded prediction fails both hover-storm tests, and removing the cancel in Cancel() fails the route-departure test. Adds Microsoft.Extensions.TimeProvider.Testing 10.10.0 to the test project; the lock file gains only that entry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
zhuowcui
approved these changes
Oct 31, 2026
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.
Problem
AdaptivePrefetchPolicyTests.LatestWinsScheduler_HoverStormStartsOnlyFinalPredictionscheduled 100 predictions with a 30 ms debounce, slept 150 ms of real time, and then expected exactly one start. On a loaded runner the timer fired after the sleep and the test failed withExpected: 1, Actual: 0. Seen in run 41157408754, job "Native AOT contract and unit tests". The flake is onmainand unrelated to the MarkdownRenderer work.Change
Production:
LatestWinsPrefetchSchedulertakes aTimeProvider. The parameterless constructor, which every view model uses, passesTimeProvider.System. The debounce is nowTask.Delay(debounce, _timeProvider, token), which forTimeProvider.Systemuses the same timer-queue path as the oldTask.Delay(debounce, token). App behaviour is unchanged.Tests: these three tests now drive a
FakeTimeProviderand no longer sleep on real time:LatestWinsScheduler_HoverStormStartsOnlyFinalPredictionLatestWinsScheduler_RouteDepartureCancelsPendingAndActivePredictionPhase0RequestTransportTests.LatestWinsHoverStorm_DoesNotAccumulateQueuedNetworkRequestsThe third test had the same real 30 ms debounce. A stall during its 100-item loop could let an early item start.
TimerCountingTimeProvider(inTestSupport) counts debounce timers as they fire.Advanceruns timer callbacks on the calling thread, but code awaitingTask.Delayon a fake clock resumes later on the thread pool. "Only the final prediction's debounce elapsed" and "the cancelled debounce never elapsed" are therefore asserted on that count, which is exact whenAdvancereturns. Waits for a positive signal useAsyncTestWait.HangGuard.Package:
Microsoft.Extensions.TimeProvider.Testing10.10.0 is added to the test project. It has no dependencies on net10.0, andpackages.lock.jsongains only that entry. A locked restore passes.No assertion was weakened. The hover-storm tests now also check that nothing fires 1 ms before the debounce.
Verification
CancelSafely(supersededPending)fails both hover-storm tests. RemovingCancelSafely(pending)inCancel()fails the route-departure test. Both fail every time.LatestWinstests passed. They ran while the full suite looped in parallel and busy loops loaded all 24 cores.VNextShellHomeServiceTests.PullRequestNavigationCache_CancelledScheduledPrefetchDoesNotFetch(expectedCancelled, gotSuccess). That test coversPullRequestNavigationCache, which does not use this scheduler. It is left for a separate fix.JitHub.WinUIbuilds in Debug x64.🤖 Generated with Claude Code