You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Drive the Tasks debounce and DebouncedSave timers with TimeProvider so tests stop sleeping #726
TasksDesktopState and DebouncedSave schedule work on System.Threading.Timer with hard-coded delays and no TimeProvider. The tests that cover them can only wait: about 25 seconds of Task.Delay per full run, all inside a serialised collection, and one test deliberately races a 750 ms window, which is the flake history behind issue #211. Found in the 2026-09-27 repository review.
Context
Production:
src/Modules/Tasks/Backlog.Modules.Tasks.UI/TasksDesktopState.cs lines 63 to 73, 121 and 2672 (new Timer(state => OnDebounceElapsed(row, (Timer)state!))), with 750, 900 and 2000 ms constants.
src/Core/Backlog.UI.Components/Feedback/DebouncedSave.cs line 117.
Tests that sleep because of it:
tests/Backlog.Desktop.UI.UnitTests/TasksDesktopStateLifetimeTests.cs lines 50, 75, 98 to 101, 146, 179: six Task.Delay(1500) plus one Task.Delay(700) timed "right up against the 750 ms".
tests/Backlog.Desktop.UI.UnitTests/TasksSaveStateBandTests.cs lines 61, 85, 245: about 2.6 s each.
tests/Backlog.Desktop.UI.UnitTests/DevbookChapterEditorTests.cs line 148.
tests/Backlog.UI.Components.UnitTests/.../DebouncedSaveTests.cs lines 42 to 102.
Eight test projects already reference Microsoft.Extensions.TimeProvider.Testing, and FakeTimeProvider is used in 45 test files, so the pattern exists.
Inject TimeProvider into TasksDesktopState and DebouncedSave (default TimeProvider.System for the hosts) and create timers through timeProvider.CreateTimer.
Rewrite the listed tests to FakeTimeProvider.Advance(...) past each threshold, so each asserts a deterministic order instead of a sleep.
While in DebouncedSave.cs lines 84 to 90 and 130 to 153, keep the in-flight debounced save in a field and have SaveNowAsync await it before starting the immediate save, so two _save() calls can no longer overlap on the same document. Add a test that a SaveNowAsync issued while a debounced save is mid-flight results in exactly one concurrent write.
Activity
JSdotNet commentedon Sep 29, 2026
The issue sweep opened a draft pull request for this issue: #802. Read its What could not be proved section before marking it ready.