crossmate

A collaborative crossword app for iOS
Log | Files | Refs | LICENSE

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:
MCrossmate/Services/DebuggingMonitors.swift | 7+++++++
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") }