SettingsSynchronizer - don't implement several EP as one class

GitOrigin-RevId: 806103ac2e63f103a558a8ccf93c307763282901
This commit is contained in:
Vladimir Krivosheev
2023-07-24 03:10:49 +02:00
committed by intellij-monorepo-bot
parent fbe7cfb413
commit 9b5bf1a2be
5 changed files with 80 additions and 73 deletions

View File

@@ -13,7 +13,7 @@ import git4idea.GitVcs
import git4idea.log.showExternalGitLogInToolwindow
import java.util.function.Supplier
class SettingsSyncHistoryAction : DumbAwareAction() {
private class SettingsSyncHistoryAction : DumbAwareAction() {
override fun actionPerformed(e: AnActionEvent) {
val project = e.project!!
val settingsSyncStorage = SettingsSyncMain.getInstance().controls.settingsSyncStorage

View File

@@ -21,7 +21,7 @@
<applicationService serviceImplementation="com.intellij.settingsSync.notification.NotificationServiceImpl"
serviceInterface="com.intellij.settingsSync.notification.NotificationService"/>
<!--suppress PluginXmlDynamicPlugin -->
<applicationInitializedListener implementation="com.intellij.settingsSync.SettingsSynchronizer"/>
<applicationInitializedListener implementation="com.intellij.settingsSync.SettingsSynchronizerApplicationInitializedListener"/>
<applicationConfigurable id="settings.sync"
key="title.settings.sync"
bundle="messages.SettingsSyncBundle"

View File

@@ -2,17 +2,12 @@ package com.intellij.settingsSync
import com.intellij.concurrency.ConcurrentCollectionFactory
import com.intellij.configurationStore.*
import com.intellij.configurationStore.schemeManager.SchemeManagerFactoryBase
import com.intellij.configurationStore.schemeManager.SchemeManagerImpl
import com.intellij.openapi.application.PathManager.OPTIONS_DIRECTORY
import com.intellij.openapi.application.invokeAndWaitIfNeeded
import com.intellij.openapi.components.RoamingType
import com.intellij.openapi.components.StateStorage
import com.intellij.openapi.diagnostic.Attachment
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.editor.colors.EditorColorsManager
import com.intellij.openapi.editor.colors.impl.EditorColorsManagerImpl
import com.intellij.openapi.options.SchemeManagerFactory
import com.intellij.openapi.util.registry.Registry
import com.intellij.settingsSync.SettingsSnapshot.MetaInfo
import com.intellij.settingsSync.notification.NotificationService
@@ -300,7 +295,7 @@ internal class SettingsSyncIdeMediatorImpl(private val componentStore: Component
private fun getOrCreateLock(fileSpec: String) = fileSpecsToLocks.computeIfAbsent(fileSpec) { ReentrantReadWriteLock() }
companion object {
val LOG = logger<SettingsSyncIdeMediatorImpl>()
private val LOG = logger<SettingsSyncIdeMediatorImpl>()
internal fun <T: Any> findProviderById(id: String, state: T): SettingsProvider<T>? {
val provider = SettingsProvider.SETTINGS_PROVIDER_EP.findFirstSafe(Predicate { it.id == id })

View File

@@ -6,6 +6,7 @@ import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.PathManager
import com.intellij.openapi.components.Service
import com.intellij.openapi.components.service
import com.intellij.openapi.components.serviceIfCreated
import com.intellij.openapi.components.stateStore
import com.intellij.settingsSync.auth.SettingsSyncAuthService
import com.intellij.util.SystemProperties
@@ -19,25 +20,24 @@ fun isSettingsSyncEnabledByKey(): Boolean = SystemProperties.getBooleanProperty(
internal fun isSettingsSyncEnabledInSettings(): Boolean = SettingsSyncSettings.getInstance().syncEnabled
internal const val SETTINGS_SYNC_STORAGE_FOLDER = "settingsSync"
internal const val SETTINGS_SYNC_STORAGE_FOLDER: String = "settingsSync"
@ApiStatus.Internal
@Service
class SettingsSyncMain : Disposable {
val controls: SettingsSyncControls
private val componentStore: ComponentStoreImpl
init {
val application = ApplicationManager.getApplication()
val appConfigPath = PathManager.getConfigDir()
val settingsSyncStorage = appConfigPath.resolve(SETTINGS_SYNC_STORAGE_FOLDER)
val remoteCommunicator = CloudConfigServerCommunicator()
componentStore = application.stateStore as ComponentStoreImpl
val ideMediator = SettingsSyncIdeMediatorImpl(componentStore, appConfigPath, enabledCondition = {
val componentStore = ApplicationManager.getApplication().stateStore as ComponentStoreImpl
val ideMediator = SettingsSyncIdeMediatorImpl(componentStore = componentStore, rootConfig = appConfigPath, enabledCondition = {
isSettingsSyncEnabledByKey() && isAvailable() && isSettingsSyncEnabledInSettings()
})
controls = init(this, settingsSyncStorage, appConfigPath, remoteCommunicator, ideMediator)
controls = init(parentDisposable = this,
settingsSyncStorage = appConfigPath.resolve(SETTINGS_SYNC_STORAGE_FOLDER),
appConfigPath = appConfigPath,
remoteCommunicator = CloudConfigServerCommunicator(),
ideMediator = ideMediator)
}
override fun dispose() {
@@ -50,9 +50,8 @@ class SettingsSyncMain : Disposable {
}
companion object {
fun isAvailable(): Boolean {
return ApplicationManager.getApplication().getServiceIfCreated(SettingsSyncMain::class.java) != null
return ApplicationManager.getApplication().serviceIfCreated<SettingsSyncMain>() != null
}
fun getInstance(): SettingsSyncMain = service<SettingsSyncMain>()

View File

@@ -4,8 +4,11 @@ import com.intellij.ide.ApplicationInitializedListener
import com.intellij.openapi.application.ApplicationActivationListener
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.PathManager
import com.intellij.openapi.components.Service
import com.intellij.openapi.components.service
import com.intellij.openapi.components.serviceAsync
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.extensions.ExtensionNotApplicableException
import com.intellij.openapi.extensions.ExtensionPointName
import com.intellij.openapi.progress.blockingContext
import com.intellij.openapi.util.registry.Registry
@@ -22,23 +25,36 @@ private val LOG = logger<SettingsSynchronizer>()
private val MIGRATION_EP = ExtensionPointName<SettingsSyncMigration>("com.intellij.settingsSyncMigration")
internal class SettingsSynchronizer : ApplicationInitializedListener, ApplicationActivationListener, SettingsSyncEventListener {
private val executorService = AppExecutorUtil.createBoundedScheduledExecutorService("Settings Sync Update", 1)
private val autoSyncDelay: Long
get() = Registry.intValue("settingsSync.autoSync.frequency.sec", 60).toLong()
private var scheduledFuture: ScheduledFuture<*>? = null // accessed only from the EDT
private class SettingsSynchronizerApplicationInitializedListener : ApplicationInitializedListener {
init {
if (ApplicationManager.getApplication().isHeadlessEnvironment || !isSettingsSyncEnabledByKey()) {
throw ExtensionNotApplicableException.create()
}
}
override suspend fun execute(asyncScope: CoroutineScope) {
if (ApplicationManager.getApplication().isHeadlessEnvironment || !isSettingsSyncEnabledByKey()) {
return
}
asyncScope.launch {
SettingsSyncEvents.getInstance().addListener(this@SettingsSynchronizer)
val settingsSyncEventListener = object : SettingsSyncEventListener {
override fun categoriesStateChanged() {
SettingsSyncEvents.getInstance().fireSettingsChanged(SyncSettingsEvent.LogCurrentSettings)
}
override fun enabledStateChanged(syncEnabled: Boolean) {
if (syncEnabled) {
SettingsSyncEvents.getInstance().addListener(this)
// the actual start of the sync is handled inside SettingsSyncEnabler
}
else {
SettingsSyncEvents.getInstance().removeListener(this)
service<SettingsSynchronizerState>().stopSyncingByTimer()
SettingsSyncMain.getInstance().disableSyncing()
}
}
}
SettingsSyncEvents.getInstance().addListener(settingsSyncEventListener)
if (isSettingsSyncEnabledInSettings()) {
initializeSyncing(SettingsSyncBridge.InitMode.JustInit)
initializeSyncing(SettingsSyncBridge.InitMode.JustInit, settingsSyncEventListener)
return@launch
}
@@ -47,23 +63,56 @@ internal class SettingsSynchronizer : ApplicationInitializedListener, Applicatio
val migration = MIGRATION_EP.extensionList.firstOrNull { it.isLocalDataAvailable(PathManager.getConfigDir()) }
if (migration != null) {
LOG.info("Found migration from an old storage via ${migration.javaClass.simpleName}")
initializeSyncing(SettingsSyncBridge.InitMode.MigrateFromOldStorage(migration))
initializeSyncing(SettingsSyncBridge.InitMode.MigrateFromOldStorage(migration), settingsSyncEventListener)
SettingsSyncEventsStatistics.MIGRATED_FROM_OLD_PLUGIN.log()
}
else {
migrateIfNeeded(executorService)
migrateIfNeeded(service<SettingsSynchronizerState>().executorService)
}
}
}
}
}
private suspend fun initializeSyncing(initMode: SettingsSyncBridge.InitMode, settingsSyncEventListener: SettingsSyncEventListener) {
LOG.info("Initializing settings sync")
val settingsSyncMain = serviceAsync<SettingsSyncMain>()
blockingContext {
settingsSyncMain.controls.bridge.initialize(initMode)
val settingsSyncEvents = SettingsSyncEvents.getInstance()
settingsSyncEvents.addListener(settingsSyncEventListener)
settingsSyncEvents.fireSettingsChanged(SyncSettingsEvent.SyncRequest)
LocalHostNameProvider.initialize()
}
}
@Service
private class SettingsSynchronizerState {
@JvmField val executorService = AppExecutorUtil.createBoundedScheduledExecutorService("Settings Sync Update", 1)
// accessed only from the EDT
@JvmField var scheduledFuture: ScheduledFuture<*>? = null
@RequiresEdt
fun stopSyncingByTimer() {
if (scheduledFuture != null) {
scheduledFuture!!.cancel(true)
scheduledFuture = null
}
}
}
private class SettingsSynchronizer : ApplicationActivationListener {
private val autoSyncDelay: Long
get() = Registry.intValue("settingsSync.autoSync.frequency.sec", 60).toLong()
override fun applicationActivated(ideFrame: IdeFrame) {
if (!isSettingsSyncEnabledByKey() || !isSettingsSyncEnabledInSettings() || !SettingsSyncMain.isAvailable()) {
return
}
if (autoSyncDelay > 0 && scheduledFuture == null) {
scheduledFuture = setupSyncingByTimer()
if (autoSyncDelay > 0 && service<SettingsSynchronizerState>().scheduledFuture == null) {
service<SettingsSynchronizerState>().scheduledFuture = setupSyncingByTimer()
}
if (Registry.`is`("settingsSync.autoSync.on.focus", true)) {
@@ -72,53 +121,17 @@ internal class SettingsSynchronizer : ApplicationInitializedListener, Applicatio
}
override fun applicationDeactivated(ideFrame: IdeFrame) {
stopSyncingByTimer()
}
private suspend fun initializeSyncing(initMode: SettingsSyncBridge.InitMode) {
LOG.info("Initializing settings sync")
val settingsSyncMain = serviceAsync<SettingsSyncMain>()
blockingContext {
settingsSyncMain.controls.bridge.initialize(initMode)
val settingsSyncEvents = SettingsSyncEvents.getInstance()
settingsSyncEvents.addListener(this)
settingsSyncEvents.fireSettingsChanged(SyncSettingsEvent.SyncRequest)
LocalHostNameProvider.initialize()
}
}
override fun enabledStateChanged(syncEnabled: Boolean) {
if (syncEnabled) {
SettingsSyncEvents.getInstance().addListener(this)
// the actual start of the sync is handled inside SettingsSyncEnabler
}
else {
SettingsSyncEvents.getInstance().removeListener(this)
stopSyncingByTimer()
SettingsSyncMain.getInstance().disableSyncing()
}
}
override fun categoriesStateChanged() {
SettingsSyncEvents.getInstance().fireSettingsChanged(SyncSettingsEvent.LogCurrentSettings)
service<SettingsSynchronizerState>().stopSyncingByTimer()
}
@RequiresEdt
private fun setupSyncingByTimer(): ScheduledFuture<*> {
val delay = autoSyncDelay
return executorService.scheduleWithFixedDelay(Runnable {
return service<SettingsSynchronizerState>().executorService.scheduleWithFixedDelay(Runnable {
LOG.debug("Syncing settings by timer")
fireSettingsChanged()
}, delay, delay, TimeUnit.SECONDS)
}
@RequiresEdt
private fun stopSyncingByTimer() {
if (scheduledFuture != null) {
scheduledFuture!!.cancel(true)
scheduledFuture = null
}
}
}
internal fun fireSettingsChanged() {