From f9f6d12c1d4043be39e22db218c2ac00da730d85 Mon Sep 17 00:00:00 2001 From: Yiqun Zhang Date: Tue, 13 Aug 2024 13:58:45 +0800 Subject: [PATCH] :bug: Fix DesktopSyncManager exit exception issue --- .../com/crosspaste/sync/DesktopSyncManager.kt | 134 +++++++++--------- 1 file changed, 69 insertions(+), 65 deletions(-) diff --git a/composeApp/src/desktopMain/kotlin/com/crosspaste/sync/DesktopSyncManager.kt b/composeApp/src/desktopMain/kotlin/com/crosspaste/sync/DesktopSyncManager.kt index 13383dee..df50abb3 100644 --- a/composeApp/src/desktopMain/kotlin/com/crosspaste/sync/DesktopSyncManager.kt +++ b/composeApp/src/desktopMain/kotlin/com/crosspaste/sync/DesktopSyncManager.kt @@ -24,6 +24,7 @@ import io.realm.kotlin.notifications.UpdatedResults import kotlinx.coroutines.CoroutineName import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.delay import kotlinx.coroutines.launch @@ -62,76 +63,79 @@ class DesktopSyncManager( override var refreshing by mutableStateOf(false) - init { - realTimeSyncScope.launch(CoroutineName("SyncManagerListenChanger")) { - val syncRuntimeInfos = syncRuntimeInfoDao.getAllSyncRuntimeInfos() - internalSyncHandlers.putAll( - syncRuntimeInfos.map { syncRuntimeInfo -> - syncRuntimeInfo.appInstanceId to - DesktopSyncHandler( - syncRuntimeInfo, - tokenCache, - telnetUtils, - syncInfoFactory, - syncClientApi, - signalProtocolStore, - signalProcessorCache, - syncRuntimeInfoDao, - signalDao, - realTimeSyncScope, - ) - }, - ) - withContext(mainDispatcher) { - realTimeSyncRuntimeInfos.addAll(syncRuntimeInfos) - refreshWaitToVerifySyncRuntimeInfo() - deviceManager.refresh() - resolveSyncs() - } - val syncRuntimeInfosFlow = syncRuntimeInfos.asFlow() - syncRuntimeInfosFlow.collect { changes: ResultsChange -> - when (changes) { - is UpdatedResults -> { - for (deletion in changes.deletions) { - val deletionSyncRuntimeInfo = realTimeSyncRuntimeInfos[deletion] - internalSyncHandlers.remove(deletionSyncRuntimeInfo.appInstanceId)!! - .clearContext() - } + private val syncManagerListenJob: Job - for (insertion in changes.insertions) { - val insertionSyncRuntimeInfo = changes.list[insertion] - internalSyncHandlers[insertionSyncRuntimeInfo.appInstanceId] = - DesktopSyncHandler( - insertionSyncRuntimeInfo, - tokenCache, - telnetUtils, - syncInfoFactory, - syncClientApi, - signalProtocolStore, - signalProcessorCache, - syncRuntimeInfoDao, - signalDao, - realTimeSyncScope, - ) + init { + syncManagerListenJob = + realTimeSyncScope.launch(CoroutineName("SyncManagerListenChanger")) { + val syncRuntimeInfos = syncRuntimeInfoDao.getAllSyncRuntimeInfos() + internalSyncHandlers.putAll( + syncRuntimeInfos.map { syncRuntimeInfo -> + syncRuntimeInfo.appInstanceId to + DesktopSyncHandler( + syncRuntimeInfo, + tokenCache, + telnetUtils, + syncInfoFactory, + syncClientApi, + signalProtocolStore, + signalProcessorCache, + syncRuntimeInfoDao, + signalDao, + realTimeSyncScope, + ) + }, + ) + withContext(mainDispatcher) { + realTimeSyncRuntimeInfos.addAll(syncRuntimeInfos) + refreshWaitToVerifySyncRuntimeInfo() + deviceManager.refresh() + resolveSyncs() + } + val syncRuntimeInfosFlow = syncRuntimeInfos.asFlow() + syncRuntimeInfosFlow.collect { changes: ResultsChange -> + when (changes) { + is UpdatedResults -> { + for (deletion in changes.deletions) { + val deletionSyncRuntimeInfo = realTimeSyncRuntimeInfos[deletion] + internalSyncHandlers.remove(deletionSyncRuntimeInfo.appInstanceId)!! + .clearContext() + } + + for (insertion in changes.insertions) { + val insertionSyncRuntimeInfo = changes.list[insertion] + internalSyncHandlers[insertionSyncRuntimeInfo.appInstanceId] = + DesktopSyncHandler( + insertionSyncRuntimeInfo, + tokenCache, + telnetUtils, + syncInfoFactory, + syncClientApi, + signalProtocolStore, + signalProcessorCache, + syncRuntimeInfoDao, + signalDao, + realTimeSyncScope, + ) + } + + // When the synchronization parameters change, + // we will force resolve, so we do not need to process it redundantly here + // for (change in changes.changes) { } + + withContext(Dispatchers.Main) { + realTimeSyncRuntimeInfos.clear() + realTimeSyncRuntimeInfos.addAll(changes.list) + refreshWaitToVerifySyncRuntimeInfo() + deviceManager.refresh() + } } - - // When the synchronization parameters change, - // we will force resolve, so we do not need to process it redundantly here - // for (change in changes.changes) { } - - withContext(Dispatchers.Main) { - realTimeSyncRuntimeInfos.clear() - realTimeSyncRuntimeInfos.addAll(changes.list) - refreshWaitToVerifySyncRuntimeInfo() - deviceManager.refresh() + else -> { + // types other than UpdatedResults are not changes -- ignore them } } - else -> { - // types other than UpdatedResults are not changes -- ignore them - } } } - } } override fun refreshWaitToVerifySyncRuntimeInfo() { @@ -198,7 +202,7 @@ class DesktopSyncManager( } override fun notifyExit() { - realTimeJob.cancel() + syncManagerListenJob.cancel() internalSyncHandlers.values.forEach { syncHandler -> // Ensure that the notification is completed before exiting runBlocking { syncHandler.notifyExit() }