mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[startup] IJPL-163158 Startup: postpone built-in server init till the end of startup of the platform
GitOrigin-RevId: 5e8c06e6563b597290512f557cdc60a37a51fbec
This commit is contained in:
committed by
intellij-monorepo-bot
parent
eac533a20d
commit
035ab04b1c
@@ -16,7 +16,8 @@
|
||||
</extensionPoints>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<applicationService serviceInterface="org.jetbrains.ide.BuiltInServerManager" serviceImplementation="org.jetbrains.ide.BuiltInServerManagerImpl" preload="true"/>
|
||||
<applicationService serviceInterface="org.jetbrains.ide.BuiltInServerManager" serviceImplementation="org.jetbrains.ide.BuiltInServerManagerImpl"/>
|
||||
<applicationActivity implementation="org.jetbrains.ide.BuiltInServerManagerLauncher"/>
|
||||
|
||||
<applicationService serviceImplementation="org.jetbrains.builtInWebServer.BuiltInServerOptions"/>
|
||||
<xdebugger.configurableProvider implementation="org.jetbrains.builtInWebServer.BuiltInServerOptions$BuiltInServerDebuggerConfigurableProvider"/>
|
||||
@@ -27,7 +28,7 @@
|
||||
<httpRequestHandler implementation="org.jetbrains.ide.InstallPluginService"/>
|
||||
<httpRequestHandler implementation="org.jetbrains.ide.UploadLogsService"/>
|
||||
|
||||
<applicationService serviceImplementation="org.jetbrains.ide.ToolboxRestServiceConfig" preload="true"/>
|
||||
<applicationActivity implementation="org.jetbrains.ide.ToolboxRestLauncher"/>
|
||||
<httpRequestHandler implementation="org.jetbrains.ide.ToolboxRestService"/>
|
||||
<toolboxServiceHandler implementation="org.jetbrains.ide.ToolboxUpdateNotificationHandler"/>
|
||||
<toolboxServiceHandler implementation="org.jetbrains.ide.ToolboxRestartNotificationHandler"/>
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.ide
|
||||
|
||||
import com.intellij.ide.ApplicationActivity
|
||||
import com.intellij.notification.Notification
|
||||
import com.intellij.notification.NotificationType
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.ApplicationNamesInfo
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.components.serviceAsync
|
||||
import com.intellij.openapi.diagnostic.logger
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.util.registry.RegistryManager
|
||||
import com.intellij.util.SystemProperties
|
||||
import com.intellij.util.Url
|
||||
import com.intellij.util.Urls
|
||||
@@ -30,6 +33,12 @@ import java.net.NetworkInterface
|
||||
import java.net.URLConnection
|
||||
import java.util.*
|
||||
|
||||
private const val PORTS_COUNT = 20
|
||||
private const val PROPERTY_RPC_PORT = "rpc.port"
|
||||
private const val PROPERTY_DISABLED = "idea.builtin.server.disabled"
|
||||
|
||||
private val LOG = logger<BuiltInServerManager>()
|
||||
|
||||
class BuiltInServerManagerImpl(private val coroutineScope: CoroutineScope) : BuiltInServerManager() {
|
||||
private val authService = service<BuiltInWebServerAuth>()
|
||||
private var serverStartFuture: Job? = null
|
||||
@@ -46,19 +55,15 @@ class BuiltInServerManagerImpl(private val coroutineScope: CoroutineScope) : Bui
|
||||
val app = ApplicationManager.getApplication()
|
||||
serverStartFuture = when {
|
||||
app.isUnitTestMode -> null
|
||||
else -> coroutineScope.launch(Dispatchers.IO) { startServerInPooledThread() }
|
||||
else -> coroutineScope.launch(Dispatchers.IO) {
|
||||
startServerInPooledThread()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun createClientBootstrap(): Bootstrap = NettyUtil.nioClientBootstrap(server!!.childEventLoopGroup)
|
||||
|
||||
companion object {
|
||||
private const val PORTS_COUNT = 20
|
||||
private const val PROPERTY_RPC_PORT = "rpc.port"
|
||||
private const val PROPERTY_DISABLED = "idea.builtin.server.disabled"
|
||||
|
||||
private val LOG = logger<BuiltInServerManager>()
|
||||
|
||||
internal const val NOTIFICATION_GROUP = "Built-in Server"
|
||||
|
||||
@JvmStatic
|
||||
@@ -119,6 +124,9 @@ class BuiltInServerManagerImpl(private val coroutineScope: CoroutineScope) : Bui
|
||||
return
|
||||
}
|
||||
|
||||
// extensions may use registry to enable/disable URL handlers
|
||||
RegistryManager.getInstanceAsync().awaitRegistryLoad()
|
||||
|
||||
try {
|
||||
server = BuiltInServer.start(firstPort = getDefaultPort(), portsCount = PORTS_COUNT, tryAnyPort = true)
|
||||
bindCustomPorts(server!!)
|
||||
@@ -171,3 +179,12 @@ class BuiltInServerManagerImpl(private val coroutineScope: CoroutineScope) : Bui
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instead of preloading too early, we explicitly start the server at the end of the application boot sequence.
|
||||
*/
|
||||
internal class BuiltInServerManagerLauncher : ApplicationActivity {
|
||||
override suspend fun execute() {
|
||||
serviceAsync<BuiltInServerManager>()
|
||||
}
|
||||
}
|
||||
@@ -4,17 +4,23 @@ package org.jetbrains.ide
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonParser
|
||||
import com.intellij.ide.ApplicationActivity
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.diagnostic.logger
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.components.serviceAsync
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.util.AwaitCancellationAndInvoke
|
||||
import com.intellij.util.asSafely
|
||||
import com.intellij.util.awaitCancellationAndInvoke
|
||||
import com.intellij.util.concurrency.AppExecutorUtil
|
||||
import com.intellij.util.io.delete
|
||||
import io.netty.buffer.Unpooled
|
||||
import io.netty.channel.ChannelHandlerContext
|
||||
import io.netty.channel.ChannelOption
|
||||
import io.netty.handler.codec.http.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import org.jetbrains.io.addCommonHeaders
|
||||
import java.nio.file.Files
|
||||
@@ -63,7 +69,7 @@ interface ToolboxServiceHandler<T> {
|
||||
/**
|
||||
* Check if a given HTTP method is supported by this specific handler
|
||||
*/
|
||||
fun isMethodSupported(method: HttpMethod) = method == HttpMethod.POST
|
||||
fun isMethodSupported(method: HttpMethod): Boolean = method == HttpMethod.POST
|
||||
}
|
||||
|
||||
private fun findToolboxHandlerByUri(requestUri: String): ToolboxServiceHandler<*>? = toolboxHandlerEP.findFirstSafe {
|
||||
@@ -87,19 +93,27 @@ private fun <T> wrapHandler(handler: ToolboxServiceHandler<T>, request: JsonElem
|
||||
}
|
||||
}
|
||||
|
||||
internal class ToolboxRestServiceConfig : Disposable {
|
||||
override fun dispose() = Unit
|
||||
internal class ToolboxRestLauncher : ApplicationActivity {
|
||||
override suspend fun execute() {
|
||||
serviceAsync<ToolboxRestServiceConfig>()
|
||||
}
|
||||
}
|
||||
|
||||
@Service(Service.Level.APP)
|
||||
@OptIn(AwaitCancellationAndInvoke::class)
|
||||
internal class ToolboxRestServiceConfig(cs: CoroutineScope) {
|
||||
init {
|
||||
val toolboxPortFilePath = System.getProperty("toolbox.notification.portFile")
|
||||
if (toolboxPortFilePath != null) {
|
||||
AppExecutorUtil.getAppExecutorService().submit {
|
||||
val server = BuiltInServerManager.getInstance()
|
||||
cs.launch {
|
||||
val server = serviceAsync<BuiltInServerManager>()
|
||||
val port = server.waitForStart().port
|
||||
val portFile = Path.of(toolboxPortFilePath)
|
||||
|
||||
runCatching { Files.createDirectories(portFile.parent) }
|
||||
runCatching { portFile.writeText("$port") }
|
||||
Disposer.register(this) {
|
||||
|
||||
cs.awaitCancellationAndInvoke {
|
||||
runCatching { portFile.delete() }
|
||||
}
|
||||
}
|
||||
@@ -108,10 +122,6 @@ internal class ToolboxRestServiceConfig : Disposable {
|
||||
}
|
||||
|
||||
internal class ToolboxRestService : RestService() {
|
||||
internal companion object {
|
||||
private val LOG = logger<ToolboxRestService>()
|
||||
}
|
||||
|
||||
override fun getServiceName() = "toolbox"
|
||||
|
||||
override fun isSupported(request: FullHttpRequest): Boolean {
|
||||
|
||||
Reference in New Issue
Block a user