tell the user when a sync fails

The failure was only recorded as SyncStatus.Failed, which nothing shows, so a
bad username or an unreachable server folded silently. It goes through the same
toast the rest of the data layer uses, with the server's own message.
This commit is contained in:
austinried
2026-10-04 00:30:04 +00:00
parent cdbecb9a9d
commit 5cbe4c6839
3 changed files with 17 additions and 3 deletions
@@ -29,6 +29,7 @@ class SyncManager(
private val db: SubtracksDatabase,
private val sourceRepository: SourceRepository,
private val queueRepository: QueueRepository,
private val showMessage: (String) -> Unit = {},
) {
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
private val requests = Channel<Unit>(Channel.CONFLATED)
@@ -56,7 +57,9 @@ class SyncManager(
throw cancellation
} catch (failure: Exception) {
Log.w(TAG, "Sync failed", failure)
SyncStatus.Failed(failure.message ?: "Sync failed")
val message = failure.message ?: "unknown error"
showMessage("Sync failed: $message")
SyncStatus.Failed(message)
}
queueRepository.invalidateLibraryCache()
_status.value = result
@@ -57,7 +57,7 @@ fun appModule(
single<ServerActionSink> { NetworkServerActionSink(get()) }
single { LibraryRepository(get(), get(), get(), toast) }
single<ArtworkSeedStore> { ArtworkSeedRepository(get()) }
single { SyncManager(get(), get(), get()) }
single { SyncManager(get(), get(), get(), showMessage = toast) }
single { QueueRepository(get()) }
single { ArtworkStore(downloadsRoot(context)) }
single<ArtworkFetcher> { OkHttpArtworkFetcher(get()) }
@@ -21,6 +21,7 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import java.io.File
import java.util.concurrent.CopyOnWriteArrayList
@RunWith(AndroidJUnit4::class)
class SyncManagerTest {
@@ -28,6 +29,7 @@ class SyncManagerTest {
private lateinit var sourceRepository: SourceRepository
private lateinit var queueRepository: QueueRepository
private lateinit var manager: SyncManager
private val messages = CopyOnWriteArrayList<String>()
@Before
fun setUp() {
@@ -39,7 +41,7 @@ class SyncManagerTest {
.build()
sourceRepository = SourceRepository(db, OkHttpClient(), fakeUserPreferences(), ArtworkStore(File(context.cacheDir, "art")))
queueRepository = QueueRepository(db)
manager = SyncManager(db, sourceRepository, queueRepository)
manager = SyncManager(db, sourceRepository, queueRepository, showMessage = { messages += it })
}
@After
@@ -48,6 +50,15 @@ class SyncManagerTest {
db.close()
}
@Test
fun aFailedSyncTellsTheUser() =
runBlocking {
manager.requestSync()
withTimeout(10_000) { manager.status.first { it is SyncStatus.Failed } }
assertEquals(listOf("Sync failed: No server configured"), messages)
}
@Test
fun aFailedSyncStillInvalidatesTheLibraryCache() =
runBlocking {