per-client services preloading. Use proper ClientId, separate registration and preloading

GitOrigin-RevId: 205c4f4a99acee7c31f69f380873b11a63cf26d3
This commit is contained in:
Alexander.Kirsanov
2021-06-28 14:09:00 +03:00
committed by intellij-monorepo-bot
parent 8e6a421c0f
commit 6a175a0ae9
5 changed files with 65 additions and 41 deletions

View File

@@ -11,6 +11,7 @@ import com.intellij.serviceContainer.ComponentManagerImpl
import com.intellij.serviceContainer.PrecomputedExtensionModel
import com.intellij.serviceContainer.throwAlreadyDisposedError
import org.jetbrains.annotations.ApiStatus
import java.util.concurrent.CompletableFuture
@ApiStatus.Internal
abstract class ClientAwareComponentManager @JvmOverloads constructor(
@@ -61,7 +62,7 @@ abstract class ClientAwareComponentManager @JvmOverloads constructor(
listenerCallbacks: List<Runnable>?) {
super.registerComponents(plugins, app, precomputedExtensionModel, listenerCallbacks)
val sessionsManager = super.getService(ClientSessionsManager::class.java) ?: return
val sessionsManager = super.getService(ClientSessionsManager::class.java)!!
for (session in sessionsManager.getSessions(true)) {
(session as? ClientSessionImpl)?.registerComponents(plugins, app, precomputedExtensionModel, listenerCallbacks)
}
@@ -70,12 +71,33 @@ abstract class ClientAwareComponentManager @JvmOverloads constructor(
override fun unloadServices(services: List<ServiceDescriptor>, pluginId: PluginId) {
super.unloadServices(services, pluginId)
val sessionsManager = super.getService(ClientSessionsManager::class.java) ?: return
val sessionsManager = super.getService(ClientSessionsManager::class.java)!!
for (session in sessionsManager.getSessions(true)) {
(session as? ClientSessionImpl)?.unloadServices(services, pluginId)
}
}
override fun preloadServices(plugins: List<IdeaPluginDescriptorImpl>,
activityPrefix: String,
onlyIfAwait: Boolean): Pair<CompletableFuture<Void?>, CompletableFuture<Void?>> {
val (asyncPreloadFuture, syncPreloadFuture) = super.preloadServices(plugins, activityPrefix, onlyIfAwait)
val sessionsManager = super.getService(ClientSessionsManager::class.java)!!
val asyncPreloadFutures = mutableListOf<CompletableFuture<Void?>>()
val syncPreloadFutures = mutableListOf<CompletableFuture<Void?>>()
for (session in sessionsManager.getSessions(true)) {
session as? ClientSessionImpl ?: continue
val (sessionAsyncPreloadFuture, sessionSyncPreloadFuture) = session.preloadServices(plugins, activityPrefix, onlyIfAwait)
asyncPreloadFutures.add(sessionAsyncPreloadFuture)
syncPreloadFutures.add(sessionSyncPreloadFuture)
}
return Pair(
CompletableFuture.allOf(asyncPreloadFuture, *asyncPreloadFutures.toTypedArray()),
CompletableFuture.allOf(syncPreloadFuture, *syncPreloadFutures.toTypedArray())
)
}
override fun isPreInitialized(component: Any): Boolean {
return super.isPreInitialized(component) || component is ClientSessionsManager<*>
}

View File

@@ -40,29 +40,33 @@ abstract class ClientSessionImpl(
override val isLightServiceSupported = false
override val isMessageBusSupported = false
open fun init() {
assert(containerState.get() == ContainerState.PRE_INIT)
init {
registerServiceInstance(ClientSession::class.java, this, fakeCorePluginDescriptor)
}
if (!isLocal) {
// registration for local session happens in ClientAwareComponentManager#registerComponents
registerComponents(
PluginManagerCore.getLoadedPlugins(null),
ApplicationManager.getApplication(),
null,
null
)
}
fun registerServices() {
registerComponents(
PluginManagerCore.getLoadedPlugins(null),
ApplicationManager.getApplication(),
null,
null
)
}
fun preloadServices() {
assert(containerState.get() == ContainerState.PRE_INIT)
preloadServices(
PluginManagerCore.getLoadedPlugins(null),
container = this,
activityPrefix = "client ",
onlyIfAwait = false
).join()
assert(containerState.compareAndSet(ContainerState.PRE_INIT, ContainerState.COMPONENT_CREATED))
}
override fun instantiateService(service: ServiceDescriptor) {
ClientId.withClientId(clientId) {
preloadServices(
PluginManagerCore.getLoadedPlugins(null),
container = this,
activityPrefix = "client ",
onlyIfAwait = false
)
// per-client components aren't supported
//createComponents(null)
assert(containerState.compareAndSet(ContainerState.PRE_INIT, ContainerState.COMPONENT_CREATED))
super.instantiateService(service)
}
}
@@ -177,9 +181,8 @@ open class ClientAppSessionImpl(
return pluginDescriptor.appContainerDescriptor
}
override fun init() {
init {
registerServiceInstance(ClientAppSession::class.java, this, fakeCorePluginDescriptor)
super.init()
}
}
@@ -193,10 +196,9 @@ open class ClientProjectSessionImpl(
return pluginDescriptor.projectContainerDescriptor
}
override fun init() {
init {
registerServiceInstance(ClientProjectSession::class.java, this, fakeCorePluginDescriptor)
registerServiceInstance(Project::class.java, project, fakeCorePluginDescriptor)
super.init()
}
override val appSession: ClientAppSession

View File

@@ -66,7 +66,6 @@ sealed class ClientSessionsManager<T : ClientSession> {
Disposer.register(disposable) {
sessions.remove(clientId)
}
(session as? ClientSessionImpl)?.init()
}
}

View File

@@ -103,13 +103,10 @@
<applicationService serviceImplementation="com.intellij.openapi.keymap.impl.ModifierKeyDoubleClickHandler" preload="await"/>
<!-- register local sessions and preload per-client services-->
<applicationService serviceInterface="com.intellij.openapi.client.ClientSessionsManager"
serviceImplementation="com.intellij.openapi.client.ClientAppSessionsManager"
preload="await"/>
serviceImplementation="com.intellij.openapi.client.ClientAppSessionsManager"/>
<projectService serviceInterface="com.intellij.openapi.client.ClientSessionsManager"
serviceImplementation="com.intellij.openapi.client.ClientProjectSessionsManager"
preload="await"/>
serviceImplementation="com.intellij.openapi.client.ClientProjectSessionsManager"/>
<projectService serviceInterface="com.intellij.openapi.fileEditor.ex.IdeDocumentHistory"
serviceImplementation="com.intellij.openapi.fileEditor.impl.IdeDocumentHistoryImpl" preload="await"/>

View File

@@ -1004,7 +1004,7 @@ abstract class ComponentManagerImpl @JvmOverloads constructor(
open fun activityNamePrefix(): String? = null
@ApiStatus.Internal
fun preloadServices(plugins: List<IdeaPluginDescriptorImpl>,
open fun preloadServices(plugins: List<IdeaPluginDescriptorImpl>,
activityPrefix: String,
onlyIfAwait: Boolean = false): Pair<CompletableFuture<Void?>, CompletableFuture<Void?>> {
val asyncPreloadedServices = mutableListOf<ForkJoinTask<*>>()
@@ -1049,15 +1049,8 @@ abstract class ComponentManagerImpl @JvmOverloads constructor(
return@task
}
val adapter = componentKeyToAdapter.get(service.getInterface()) as ServiceComponentAdapter? ?: return@task
try {
val instance = adapter.getInstance<Any>(this, null)
if (instance != null) {
val implClass = instance.javaClass
if (Modifier.isFinal(implClass.modifiers)) {
serviceInstanceHotCache.putIfAbsent(implClass, instance)
}
}
instantiateService(service)
}
catch (ignore: AlreadyDisposedException) {
}
@@ -1083,6 +1076,17 @@ abstract class ComponentManagerImpl @JvmOverloads constructor(
)
}
protected open fun instantiateService(service: ServiceDescriptor) {
val adapter = componentKeyToAdapter.get(service.getInterface()) as ServiceComponentAdapter? ?: return
val instance = adapter.getInstance<Any>(this, null)
if (instance != null) {
val implClass = instance.javaClass
if (Modifier.isFinal(implClass.modifiers)) {
serviceInstanceHotCache.putIfAbsent(implClass, instance)
}
}
}
override fun isDisposed(): Boolean {
return containerState.get() >= ContainerState.DISPOSE_IN_PROGRESS
}