M9 — Device diagnostics & debug reporting (connectivity + UPnP desync) #104

Merged
bvandeusen merged 5 commits from dev into main 2026-06-29 19:24:16 -04:00
Showing only changes of commit 8a58f07237 - Show all commits
@@ -70,8 +70,10 @@ class DiagnosticsUploader @Inject constructor(
/** Coalesces concurrent triggers via tryLock — a drain in flight wins. */
private suspend fun drainSafe() {
if (authStore.sessionCookie.value.isNullOrEmpty()) return
val clientId = authStore.clientId.value ?: return
val clientId = authStore.clientId.value
// Signed out / no client id yet → nothing to do. Single guard keeps
// the return count within the detekt gate.
if (authStore.sessionCookie.value.isNullOrEmpty() || clientId == null) return
if (!mutex.tryLock()) return
try {
drain(clientId)
@@ -81,13 +83,14 @@ class DiagnosticsUploader @Inject constructor(
}
private suspend fun drain(clientId: String) {
while (true) {
var more = true
while (more) {
val batch = runCatching { dao.takeBatch(BATCH_SIZE) }.getOrNull().orEmpty()
if (batch.isEmpty()) return
val sent = runCatching { upload(clientId, batch) }.isSuccess
if (!sent) return // leave rows for the next trigger
runCatching { dao.deleteByIds(batch.map { it.id }) }
if (batch.size < BATCH_SIZE) return
val sent = batch.isNotEmpty() && runCatching { upload(clientId, batch) }.isSuccess
if (sent) runCatching { dao.deleteByIds(batch.map { it.id }) }
// Keep going only while a full batch sent cleanly; otherwise stop
// (empty buffer, or a failure to retry on the next trigger).
more = sent && batch.size >= BATCH_SIZE
}
}