Skip to content

Commit 3726981

Browse files
inventory69weblate
authored andcommitted
feat(sync): log every SyncWorker outcome to SyncDebugLogger
Previously only the "server unreachable / RETRY" path emitted a SyncDebugLogger entry, so the persistent log showed lots of STARTED lines from NetworkMonitor but never the matching SUCCESS / NO_CHANGES / FAILED outcomes from the worker itself. Add SyncDebugLogger.logTrigger() at every doWork() exit point: - SKIPPED: global cooldown active - SKIPPED: another sync already in progress - NO_CHANGES: pre-check found no unsynced changes - SKIPPED: blocked by sync gate (wifi-only / offline / no server) - STARTED: proceeding into syncService.syncNotes() - SUCCESS: syncNotes returned isSuccess=true (with synced count) - FAILED: syncNotes returned isSuccess=false (with errorMessage) - CANCELLED: CancellationException caught - FAILED: fatal exception caught No behaviour change \u2014 only observability. This closes the analysis gap where multiple "STARTED" lines from wifi-connect callbacks could not be correlated with the actual sync outcome (was it dropped by the mutex, finished as NO_CHANGES, or actually completed?).
1 parent 24ab57e commit 3726981

2 files changed

Lines changed: 58 additions & 5 deletions

File tree

β€Žandroid/app/build.gradle.ktsβ€Ž

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ android {
2020
applicationId = "dev.dettmer.simplenotes"
2121
minSdk = 24
2222
targetSdk = 36
23-
versionCode = 31 // πŸ†• v2.3.1
24-
versionName = "2.3.1" // πŸ†• v2.3.1
23+
versionCode = 32 // πŸ†• v2.3.2 - Sync Debug
24+
versionName = "2.4.0" // πŸ†• v2.3.2 - Sync Debug
2525

2626
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
2727
// πŸ†• v2.2.0: Enable by default for the diagnostic phase β€” flip to false before release.

β€Žandroid/app/src/main/java/dev/dettmer/simplenotes/sync/SyncWorker.ktβ€Ž

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,12 @@ class SyncWorker(context: Context, params: WorkerParameters) : CoroutineWorker(c
129129
// Globaler Cooldown-Check (nicht fΓΌr Bypass-Syncs)
130130
if (!bypassesGlobalCooldown && !SyncStateManager.canSyncGlobally(prefs)) {
131131
Logger.d(TAG, "⏭️ SyncWorker: Global sync cooldown active - skipping")
132+
SyncDebugLogger.logTrigger(
133+
triggerType = tagOrUnknown(),
134+
outcome = SyncDebugLogger.Outcome.SKIPPED,
135+
reason = "global cooldown active",
136+
networkState = SyncDebugLogger.snapshotNetwork(applicationContext)
137+
)
132138
if (BuildConfig.DEBUG) {
133139
Logger.d(TAG, "βœ… SyncWorker.doWork() SUCCESS (cooldown)")
134140
Logger.d(TAG, "═══════════════════════════════════════")
@@ -138,6 +144,12 @@ class SyncWorker(context: Context, params: WorkerParameters) : CoroutineWorker(c
138144

139145
if (!SyncStateManager.tryStartSync("worker-${tags.firstOrNull() ?: "unknown"}", silent = true)) {
140146
Logger.d(TAG, "⏭️ SyncWorker: Another sync already in progress - skipping")
147+
SyncDebugLogger.logTrigger(
148+
triggerType = tagOrUnknown(),
149+
outcome = SyncDebugLogger.Outcome.SKIPPED,
150+
reason = "another sync in progress",
151+
networkState = SyncDebugLogger.snapshotNetwork(applicationContext)
152+
)
141153
if (BuildConfig.DEBUG) {
142154
Logger.d(TAG, "βœ… SyncWorker.doWork() SUCCESS (already syncing)")
143155
Logger.d(TAG, "═══════════════════════════════════════")
@@ -157,6 +169,11 @@ class SyncWorker(context: Context, params: WorkerParameters) : CoroutineWorker(c
157169
if (!syncService.hasUnsyncedChanges()) {
158170
Logger.d(TAG, "⏭️ No local changes - skipping sync (performance optimization)")
159171
Logger.d(TAG, " Saves battery, network traffic, and server load")
172+
SyncDebugLogger.logTrigger(
173+
triggerType = tagOrUnknown(),
174+
outcome = SyncDebugLogger.Outcome.NO_CHANGES,
175+
networkState = SyncDebugLogger.snapshotNetwork(applicationContext)
176+
)
160177

161178
// πŸ†• v2.4.0 (FIX-SSBE-005): Visibility-aware Termination
162179
// markCompleted() prΓΌft silent-Flag: silent=true β†’ IDLE, promoted β†’ COMPLETED
@@ -184,6 +201,15 @@ class SyncWorker(context: Context, params: WorkerParameters) : CoroutineWorker(c
184201
} else {
185202
Logger.d(TAG, "⏭️ Sync blocked by gate: ${gateResult.blockReason ?: "offline/no server"}")
186203
}
204+
SyncDebugLogger.logTrigger(
205+
triggerType = tagOrUnknown(),
206+
outcome = SyncDebugLogger.Outcome.SKIPPED,
207+
reason = "gate: " + when {
208+
gateResult.isBlockedByWifiOnly -> "wifi-only, not on wifi"
209+
else -> gateResult.blockReason ?: "offline/no server"
210+
},
211+
networkState = SyncDebugLogger.snapshotNetwork(applicationContext)
212+
)
187213

188214
// πŸ†• v2.4.0 (FIX-SSBE-006): Visibility-aware Termination
189215
// Zeigt Fehler im Banner wenn der Sync promoted wurde (silent=false)
@@ -259,7 +285,12 @@ class SyncWorker(context: Context, params: WorkerParameters) : CoroutineWorker(c
259285
Logger.d(TAG, "πŸ“ Step 6: Server reachable - proceeding with sync")
260286
Logger.d(TAG, " SyncService: $syncService")
261287
}
262-
288+
// πŸ†• v2.2.0: Sync wird jetzt wirklich ausgefΓΌhrt β€” STARTED-Outcome
289+
SyncDebugLogger.logTrigger(
290+
triggerType = tagOrUnknown(),
291+
outcome = SyncDebugLogger.Outcome.STARTED,
292+
networkState = SyncDebugLogger.snapshotNetwork(applicationContext)
293+
)
263294
// Try-catch um syncNotes
264295
val result = try {
265296
if (BuildConfig.DEBUG) {
@@ -290,7 +321,12 @@ class SyncWorker(context: Context, params: WorkerParameters) : CoroutineWorker(c
290321
Logger.d(TAG, "πŸ“ Step 8: Success path")
291322
}
292323
Logger.i(TAG, "βœ… Sync successful: ${result.syncedCount} notes")
293-
324+
SyncDebugLogger.logTrigger(
325+
triggerType = tagOrUnknown(),
326+
outcome = SyncDebugLogger.Outcome.SUCCESS,
327+
reason = "synced=${result.syncedCount}",
328+
networkState = SyncDebugLogger.snapshotNetwork(applicationContext)
329+
)
294330
// πŸ†• v1.8.1 (IMPL_08): SyncStateManager aktualisieren
295331
SyncStateManager.markCompleted()
296332

@@ -332,7 +368,12 @@ class SyncWorker(context: Context, params: WorkerParameters) : CoroutineWorker(c
332368
Logger.d(TAG, "πŸ“ Step 8: Failure path")
333369
}
334370
Logger.e(TAG, "❌ Sync failed: ${result.errorMessage}")
335-
371+
SyncDebugLogger.logTrigger(
372+
triggerType = tagOrUnknown(),
373+
outcome = SyncDebugLogger.Outcome.FAILED,
374+
reason = result.errorMessage ?: "unknown",
375+
networkState = SyncDebugLogger.snapshotNetwork(applicationContext)
376+
)
336377
// πŸ†• v1.8.1 (IMPL_08): SyncStateManager aktualisieren
337378
SyncStateManager.markError(result.errorMessage)
338379

@@ -353,6 +394,12 @@ class SyncWorker(context: Context, params: WorkerParameters) : CoroutineWorker(c
353394
} catch (e: CancellationException) {
354395
// πŸ›‘οΈ v1.8.2 (IMPL_14): State reset β€” verhindert "Sync already in progress" Deadlock
355396
SyncStateManager.reset()
397+
SyncDebugLogger.logTrigger(
398+
triggerType = tagOrUnknown(),
399+
outcome = SyncDebugLogger.Outcome.CANCELLED,
400+
reason = e.message,
401+
networkState = SyncDebugLogger.snapshotNetwork(applicationContext)
402+
)
356403

357404
// πŸ†• v1.10.0-P2: Detailed stop reason logging + quota/standby tracking
358405
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
@@ -385,6 +432,12 @@ class SyncWorker(context: Context, params: WorkerParameters) : CoroutineWorker(c
385432
Logger.e(TAG, "Exception type: ${e.javaClass.name}")
386433
Logger.e(TAG, "Exception message: ${e.message}")
387434
Logger.e(TAG, "Stack trace:", e)
435+
SyncDebugLogger.logTrigger(
436+
triggerType = tagOrUnknown(),
437+
outcome = SyncDebugLogger.Outcome.FAILED,
438+
reason = "exception: ${e.javaClass.simpleName}: ${e.message}",
439+
networkState = SyncDebugLogger.snapshotNetwork(applicationContext)
440+
)
388441

389442
// πŸ†• v1.8.2: State cleanup β€” verhindert "Sync already in progress" Deadlock
390443
SyncStateManager.markError(e.message)

0 commit comments

Comments
Β (0)