commit cf666c58b22632fe256db9e9d566de6d26444bd1
parent 93846a924abeb02a1c3c82f332ce058596f713a5
Author: Michael Camilleri <[email protected]>
Date: Thu, 14 May 2026 12:21:43 +0900
Clear last sync error when its phase succeeds again
The diagnostics panel could be pinned to a transient failure (e.g. an OpLock
that the recovery path retried successfully) because SyncMonitor.recordSuccess
only updated lastSuccessAt and left the lastError* fields intact. With
PendingChanges=0 and Engine Running=Yes alongside a stale Last Error line, the
reported state misrepresented current health.
recordSuccess now clears the stored error when the succeeding phase matches
lastErrorPhase. Scoping by phase means a recovered push does not mask an
ongoing fetch failure (or vice versa).
Co-Authored-By: Claude Opus 4.7 <[email protected]>
Diffstat:
1 file changed, 7 insertions(+), 0 deletions(-)
diff --git a/Crossmate/Services/DebuggingMonitors.swift b/Crossmate/Services/DebuggingMonitors.swift
@@ -200,6 +200,13 @@ final class SyncMonitor {
func recordSuccess(_ phase: String) {
lastSuccessAt = Date()
+ // Once the phase that last errored runs to completion, the stored
+ // error is stale — the engine has recovered. Clear it so the
+ // diagnostics panel reflects current health instead of pinning to
+ // a transient failure (e.g. an OpLock that retried successfully).
+ if lastErrorPhase == phase {
+ clearLastError()
+ }
append(level: "info", "\(phase) succeeded")
}