diff --git a/plugins/settings-sync/src/com/intellij/settingsSync/SettingsSyncBridge.kt b/plugins/settings-sync/src/com/intellij/settingsSync/SettingsSyncBridge.kt index 8cc734c6dfc5..e40370d42332 100644 --- a/plugins/settings-sync/src/com/intellij/settingsSync/SettingsSyncBridge.kt +++ b/plugins/settings-sync/src/com/intellij/settingsSync/SettingsSyncBridge.kt @@ -6,6 +6,7 @@ import com.intellij.openapi.Disposable import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.diagnostic.logger import com.intellij.openapi.progress.runBlockingCancellable +import com.intellij.platform.util.progress.withProgressText import com.intellij.settingsSync.SettingsSyncBridge.PushRequestMode.* import com.intellij.settingsSync.statistics.SettingsSyncEventsStatistics import com.intellij.util.containers.ContainerUtil @@ -39,6 +40,10 @@ class SettingsSyncBridge( @Volatile private var queueJob: Job? = null + val isInitialized + get() = queueJob != null + + private val eventsLock = ReentrantLock() private val settingsChangeListener = object : SettingsSyncEventListener { @@ -76,24 +81,27 @@ class SettingsSyncBridge( internal fun initialize(initMode: InitMode) { coroutineScope.launch { - try { - settingsLog.initialize() + withProgressText(SettingsSyncBundle.message(initMode.messageKey)) { + try { + settingsLog.initialize() - // the queue is not activated initially => events will be collected but not processed until we perform all initialization tasks - SettingsSyncEvents.getInstance().addListener(settingsChangeListener) - ideMediator.activateStreamProvider() + // the queue is not activated initially => events will be collected but not processed until we perform all initialization tasks + SettingsSyncEvents.getInstance().addListener(settingsChangeListener) + ideMediator.activateStreamProvider() - applyInitialChanges(initMode) + applyInitialChanges(initMode) - startQueue() - } - catch (ex: Exception) { - stopSyncingAndRollback(null, ex) + startQueue() + } + catch (ex: Exception) { + stopSyncingAndRollback(null, ex) + } } } } private fun startQueue() { + LOG.info("Starting settings sync queue") queueJob = coroutineScope.launch { while (true) { processPendingEvents() @@ -197,11 +205,18 @@ class SettingsSyncBridge( }) } - internal sealed class InitMode { - object JustInit : InitMode() - class TakeFromServer(val cloudEvent: SyncSettingsEvent.CloudChange) : InitMode() - class MigrateFromOldStorage(val migration: SettingsSyncMigration) : InitMode() - object PushToServer : InitMode() + internal sealed class InitMode(val messageKey: String) { + object JustInit + : InitMode("enable.sync.check.server.data.progress") + + class TakeFromServer(val cloudEvent: SyncSettingsEvent.CloudChange) + : InitMode("enable.sync.get.from.server.progress") + + class MigrateFromOldStorage(val migration: SettingsSyncMigration) + : InitMode("enable.sync.check.server.data.progress") + + object PushToServer + : InitMode("enable.sync.push.to.server.progress") } private suspend fun processExclusiveEvent(event: SyncSettingsEvent.ExclusiveEvent) { @@ -239,7 +254,7 @@ class SettingsSyncBridge( var mergeAndPushAfterProcessingEvents = true while (pendingEvents.isNotEmpty()) { val event = pendingEvents.removeAt(0) - LOG.debug("Processing event $event") + LOG.info("Processing event $event") when (event) { is SyncSettingsEvent.IdeChange -> { settingsLog.applyIdeState(event.snapshot, "Local changes made in the IDE") diff --git a/plugins/settings-sync/src/com/intellij/settingsSync/config/SettingsSyncEnabler.kt b/plugins/settings-sync/src/com/intellij/settingsSync/config/SettingsSyncEnabler.kt index bcd5f3c8ed90..c8071c5ccda5 100644 --- a/plugins/settings-sync/src/com/intellij/settingsSync/config/SettingsSyncEnabler.kt +++ b/plugins/settings-sync/src/com/intellij/settingsSync/config/SettingsSyncEnabler.kt @@ -2,11 +2,16 @@ package com.intellij.settingsSync.config import com.intellij.configurationStore.saveSettings import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.components.Service +import com.intellij.openapi.components.service import com.intellij.openapi.progress.ProgressIndicator import com.intellij.openapi.progress.Task import com.intellij.openapi.progress.runBlockingCancellable +import com.intellij.openapi.util.NlsContexts +import com.intellij.platform.util.progress.withProgressText import com.intellij.settingsSync.* import com.intellij.util.EventDispatcher +import kotlinx.coroutines.* import java.util.* internal class SettingsSyncEnabler { @@ -64,12 +69,7 @@ internal class SettingsSyncEnabler { fun pushSettingsToServer() { val settingsSyncControls = SettingsSyncMain.getInstance().controls - object : Task.Modal(null, SettingsSyncBundle.message("enable.sync.push.to.server.progress"), false) { - override fun run(indicator: ProgressIndicator) { - // todo initialization must be modal but pushing to server can be made later - settingsSyncControls.bridge.initialize(SettingsSyncBridge.InitMode.PushToServer) - } - }.queue() + settingsSyncControls.bridge.initialize(SettingsSyncBridge.InitMode.PushToServer) } diff --git a/plugins/settings-sync/src/com/intellij/settingsSync/performanceTesting/EnableSettingsSyncCommand.kt b/plugins/settings-sync/src/com/intellij/settingsSync/performanceTesting/EnableSettingsSyncCommand.kt index 36cb1690a3af..07286062b051 100644 --- a/plugins/settings-sync/src/com/intellij/settingsSync/performanceTesting/EnableSettingsSyncCommand.kt +++ b/plugins/settings-sync/src/com/intellij/settingsSync/performanceTesting/EnableSettingsSyncCommand.kt @@ -6,11 +6,9 @@ import com.intellij.openapi.ui.playback.commands.PlaybackCommandCoroutineAdapter import com.intellij.settingsSync.* import com.intellij.settingsSync.config.SettingsSyncEnabler import com.jetbrains.performancePlugin.commands.Waiter -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.delay -import kotlinx.coroutines.withContext +import kotlinx.coroutines.* import org.jetbrains.annotations.NonNls +import java.util.concurrent.TimeUnit enum class EnableSettingSyncOptions { GET, PUSH, NONE @@ -67,15 +65,28 @@ class EnableSettingsSyncCommand(text: @NonNls String, line: Int) : PlaybackComma }) settingsSyncEnabler.checkServerState() serverRespondedOnCheck.await() + + var startTime = System.currentTimeMillis() + while (!SettingsSyncMain.getInstance().controls.bridge.isInitialized) { + delay(50) + if (System.currentTimeMillis() - startTime > TimeUnit.SECONDS.toMillis(5)) { + throw Exception("Settings Sync initialization timeout exceeded") + } + } + if(SettingsSyncLocalSettings.getInstance().isCrossIdeSyncEnabled != isCrossIdeSync){ SettingsSyncLocalSettings.getInstance().isCrossIdeSyncEnabled = isCrossIdeSync SettingsSyncEvents.getInstance().fireSettingsChanged(SyncSettingsEvent.CrossIdeSyncStateChanged(isCrossIdeSync)) } //there is no event that cross-ide sync was enabled, so we need to check that file appears and wait a bit :( - Waiter.checkCondition { - CloudConfigServerCommunicator().isFileExists(CROSS_IDE_SYNC_MARKER_FILE) == isCrossIdeSync + startTime = System.currentTimeMillis() + while (CloudConfigServerCommunicator().isFileExists(CROSS_IDE_SYNC_MARKER_FILE) != isCrossIdeSync) { + delay(500) + if (System.currentTimeMillis() - startTime > TimeUnit.SECONDS.toMillis(5)) { + val fileExists = CloudConfigServerCommunicator().isFileExists(CROSS_IDE_SYNC_MARKER_FILE) + throw Exception("Cross-IDE sync marker file was not updated in 5 seconds. File exists=$fileExists, expected=$isCrossIdeSync") + } } - delay(5000L) } } } \ No newline at end of file