diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/core/sync/SyncManager.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/core/sync/SyncManager.kt index 5b8e22e20..1e5f393d9 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/core/sync/SyncManager.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/core/sync/SyncManager.kt @@ -55,11 +55,11 @@ object SyncManager { .onFailure { log.e(it) { "Library pull failed" } } } launch { - runCatching { WatchProgressRepository.pullFromServer(profileId) } + runCatching { WatchProgressRepository.forceSnapshotRefreshFromServer(profileId) } .onFailure { log.e(it) { "WatchProgress pull failed" } } } launch { - runCatching { WatchedRepository.pullFromServer(profileId) } + runCatching { WatchedRepository.forceSnapshotRefreshFromServer(profileId) } .onFailure { log.e(it) { "Watched pull failed" } } } launch { diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/watched/WatchedRepository.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/watched/WatchedRepository.kt index a3a1a35fb..62a0e7f7d 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/watched/WatchedRepository.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/watched/WatchedRepository.kt @@ -12,6 +12,7 @@ import com.nuvio.app.features.watching.sync.SupabaseWatchedSyncAdapter import com.nuvio.app.features.watching.sync.TraktWatchedSyncAdapter import com.nuvio.app.features.watching.sync.WatchedDeltaEvent import com.nuvio.app.features.watching.sync.WatchedSyncAdapter +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob @@ -171,6 +172,60 @@ object WatchedRepository { } } + suspend fun forceSnapshotRefreshFromServer(profileId: Int) { + TraktAuthRepository.ensureLoaded() + TraktSettingsRepository.ensureLoaded() + val operationGeneration = activeOperationGeneration(profileId) ?: run { + log.d { "Skipping watched snapshot pull for inactive profile $profileId" } + return + } + val pullStartedEpochMs = WatchedClock.nowEpochMs() + val localBeforePull = itemsByKey.values + .map(WatchedItem::normalizedMarkedAt) + .toList() + val lastPushEpochMs = lastSuccessfulPushEpochMs + runCatching { + if (shouldUseTraktWatchedSync()) { + pullFullFromAdapter( + adapter = TraktWatchedSyncAdapter, + profileId = profileId, + localBeforePull = localBeforePull, + lastPushEpochMs = lastPushEpochMs, + pullStartedEpochMs = pullStartedEpochMs, + resetDeltaState = true, + operationGeneration = operationGeneration, + ) + return@runCatching + } + + val cursorBeforeSnapshot = try { + syncAdapter.getDeltaCursor(profileId) + } catch (error: CancellationException) { + throw error + } catch (_: Throwable) { + null + } + pullFullFromAdapter( + adapter = syncAdapter, + profileId = profileId, + localBeforePull = localBeforePull, + lastPushEpochMs = lastPushEpochMs, + pullStartedEpochMs = pullStartedEpochMs, + resetDeltaState = cursorBeforeSnapshot == null, + operationGeneration = operationGeneration, + ) + if (!isActiveOperation(profileId, operationGeneration)) return@runCatching + if (cursorBeforeSnapshot != null) { + deltaCursorEventId = cursorBeforeSnapshot + deltaInitialized = true + persist() + } + }.onFailure { e -> + if (e is CancellationException) throw e + log.e(e) { "Failed to pull watched items snapshot from server" } + } + } + private suspend fun pullFullFromAdapter( adapter: WatchedSyncAdapter, profileId: Int,