[external-systems] allow to specify custom delay before auto-reloading changes from build scripts

Set to 0 for Amper which doesn't need a delay: AMPER-674.

GitOrigin-RevId: 689f5bddeaf918d84a8d2aff41243ea471372022
This commit is contained in:
Kirill Likhodedov
2024-10-08 13:45:31 +02:00
committed by intellij-monorepo-bot
parent db7891da87
commit 0da8cd8e43
2 changed files with 36 additions and 10 deletions

View File

@@ -5,6 +5,7 @@ import com.intellij.openapi.Disposable
import com.intellij.openapi.externalSystem.autoimport.ExternalSystemSettingsFilesModificationContext.Event
import com.intellij.openapi.externalSystem.autoimport.ExternalSystemSettingsFilesModificationContext.ReloadStatus
import org.jetbrains.annotations.ApiStatus
import kotlin.time.Duration
interface ExternalSystemProjectAware {
@@ -21,6 +22,21 @@ interface ExternalSystemProjectAware {
fun reloadProject(context: ExternalSystemProjectReloadContext)
/**
* Internal. Please see implementation limitations.
*
* This property defines a delay for the "smart" project sync request.
* Usually, the "smart" sync is requested after changes in the [settingsFiles].
*
* Note: All external systems sync events are dispatched and merged by the same [com.intellij.util.ui.update.MergingUpdateQueue].
* Therefore, this value can be overridden by the greater [smartProjectReloadDelay].
* For example, between default (3 seconds) and zero delays will be chosen the default delay.
*
* A null value means default [smartProjectReloadDelay] that is equals to 3 seconds.
*/
@get:ApiStatus.Internal
val smartProjectReloadDelay: Duration? get() = null
/**
* Experimental. Please see implementation limitations.
*

View File

@@ -41,6 +41,13 @@ import java.util.*
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.atomic.AtomicReference
import kotlin.streams.asStream
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
private val MERGING_TIME_SPAN = 300.milliseconds
private val MERGING_TIME_SPAN_MS = MERGING_TIME_SPAN.inWholeMilliseconds
private val DEFAULT_SMART_PROJECT_RELOAD_DELAY = 3.seconds
@ApiStatus.Internal
@State(name = "ExternalSystemProjectTracker", storages = [Storage(CACHE_FILE)])
@@ -60,7 +67,7 @@ class AutoImportProjectTracker(
private val projectChangeOperation = AtomicOperationTrace(name = "Project change operation")
private val projectReloadOperation = AtomicOperationTrace(name = "Project reload operation")
private val isProjectLookupActivateProperty = AtomicBooleanProperty(false)
private val dispatcher = MergingUpdateQueue("AutoImportProjectTracker.dispatcher", 300, true, null, serviceDisposable)
private val dispatcher = MergingUpdateQueue("AutoImportProjectTracker.dispatcher", MERGING_TIME_SPAN_MS.toInt(), true, null, serviceDisposable)
private val backgroundExecutor = AppExecutorUtil.createBoundedApplicationPoolExecutor("AutoImportProjectTracker.backgroundExecutor", 1)
private fun createProjectChangesListener() =
@@ -103,17 +110,20 @@ class AutoImportProjectTracker(
schedule(priority = 1, dispatchIterations = 1) { processChanges() }
}
/**
* ```
* dispatcher.mergingTimeSpan = 300 ms
* dispatchIterations = 9
* We already dispatched processChanges
* So delay is equal to (1 + 9) * 300 ms = 3000 ms = 3 s
* ```
*/
private fun scheduleDelayedSmartProjectReload() {
LOG.debug("Schedule delayed project reload")
schedule(priority = 2, dispatchIterations = 9) { reloadProject(explicitReload = false) }
// See AutoImportProjectTracker.scheduleChangeProcessing for details
val smartProjectReloadDelay = projectDataMap.values.maxOfOrNull {
it.projectAware.smartProjectReloadDelay ?: DEFAULT_SMART_PROJECT_RELOAD_DELAY
} ?: DEFAULT_SMART_PROJECT_RELOAD_DELAY
// We already dispatched processChanges with the MERGING_TIME_SPAN delay
// See AutoImportProjectTracker.scheduleChangeProcessing for details
val smartProjectReloadDispatcherIterations = ((smartProjectReloadDelay - MERGING_TIME_SPAN) / MERGING_TIME_SPAN).toInt()
// smartProjectReloadDispatcherIterations can be negative if smartProjectReloadDelay is less than MERGING_TIME_SPAN
val dispatchIterations = maxOf(smartProjectReloadDispatcherIterations, 1)
schedule(priority = 2, dispatchIterations = dispatchIterations) { reloadProject(explicitReload = false) }
}
private val currentActivity = AtomicReference<ProjectInitializationDiagnosticService.ActivityTracker?>()