fix(sync-health): checkNow() now runs regardless of start() (#95)

checkNow() previously delegated to _runAll(), which gated each
account on the _running flag (only true after start() is called).
This meant the manual "Verify sync health" action silently did nothing
if start() had not yet been called, or in any context where the
periodic runner was not active (e.g. widget tests).

Fix: checkNow() now iterates accounts directly and calls
_runForAccount() with force:true, bypassing the _running guard.
The guard is still respected during periodic runs for graceful
shutdown.

Adds three unit tests that reproduce the bug and verify the fix.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Thomas SharedInbox
2026-05-15 19:54:39 +02:00
co-authored by Claude Sonnet 4.6
parent 8d715218c6
commit 4a25d831fb
2 changed files with 214 additions and 3 deletions
+10 -3
View File
@@ -50,7 +50,7 @@ class ReliabilityRunner {
}
}
Future<void> _runForAccount(String accountId) async {
Future<void> _runForAccount(String accountId, {bool force = false}) async {
try {
final mailboxes = await _mailboxes.observeMailboxes(accountId).first;
var totalMissingLocally = 0;
@@ -59,7 +59,7 @@ class ReliabilityRunner {
final details = <String, dynamic>{};
for (final mailbox in mailboxes) {
if (!_running) break;
if (!force && !_running) break;
final result = await _emails.verifySyncReliability(
accountId,
mailbox.path,
@@ -103,7 +103,14 @@ class ReliabilityRunner {
}
/// Forces a reliability check for all accounts immediately.
///
/// Works regardless of whether [start] has been called, so the UI can
/// trigger a manual check at any time without depending on the periodic
/// runner being active.
Future<void> checkNow() async {
await _runAll();
final accounts = await _accounts.observeAccounts().first;
for (final account in accounts) {
await _runForAccount(account.id, force: true);
}
}
}