[Daemon] Improve daemon connection algorithm
Before this change, the logic was to find the most suitable daemon and try connecting to it in a loop, ignoring the fact that it could be dying. Now, instead of trying to connect to the daemon dying daemon in a loop, we will make only 1 attemp and then skip if it's already dying. ^KT-55322 In Progress
This commit is contained in:
committed by
Space Team
parent
44d6807aba
commit
8ceee3e8b9
@@ -1,6 +1,3 @@
|
|||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
|
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask
|
|
||||||
|
|
||||||
description = "Kotlin Daemon Client"
|
description = "Kotlin Daemon Client"
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
@@ -32,16 +29,7 @@ dependencies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType<KotlinCompilationTask<*>> {
|
configureKotlinCompileTasksGradleCompatibility()
|
||||||
compilerOptions {
|
|
||||||
// This module is being run from within Gradle, older versions of which only have older kotlin-stdlib in the runtime classpath.
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
apiVersion.set(KotlinVersion.KOTLIN_1_4)
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
languageVersion.set(KotlinVersion.KOTLIN_1_4)
|
|
||||||
freeCompilerArgs.add("-Xsuppress-version-warnings")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
"main" { projectDefault() }
|
"main" { projectDefault() }
|
||||||
|
|||||||
+50
-29
@@ -101,36 +101,45 @@ object KotlinCompilerClient {
|
|||||||
autostart: Boolean,
|
autostart: Boolean,
|
||||||
leaseSession: Boolean,
|
leaseSession: Boolean,
|
||||||
sessionAliveFlagFile: File? = null,
|
sessionAliveFlagFile: File? = null,
|
||||||
): CompileServiceSession? = connectLoop(reportingTargets, autostart) { isLastAttempt ->
|
): CompileServiceSession? {
|
||||||
|
val ignoredDaemonSessionFiles = mutableSetOf<File>()
|
||||||
|
return connectLoop(reportingTargets, autostart) { isLastAttempt ->
|
||||||
|
|
||||||
fun CompileService.leaseImpl(): CompileServiceSession? {
|
fun CompileService.tryToLeaseSession(): CompileServiceSession? {
|
||||||
// the newJVMOptions could be checked here for additional parameters, if needed
|
// the newJVMOptions could be checked here for additional parameters, if needed
|
||||||
registerClient(clientAliveFlagFile.absolutePath)
|
registerClient(clientAliveFlagFile.absolutePath)
|
||||||
reportingTargets.report(DaemonReportCategory.DEBUG, "connected to the daemon")
|
reportingTargets.report(DaemonReportCategory.DEBUG, "connected to the daemon")
|
||||||
|
|
||||||
if (!leaseSession) return CompileServiceSession(this, CompileService.NO_SESSION)
|
if (!leaseSession) return CompileServiceSession(this, CompileService.NO_SESSION)
|
||||||
|
|
||||||
return leaseCompileSession(sessionAliveFlagFile?.absolutePath).takeUnless { it is CompileService.CallResult.Dying }?.let {
|
return leaseCompileSession(sessionAliveFlagFile?.absolutePath).takeUnless { it is CompileService.CallResult.Dying }?.let {
|
||||||
CompileServiceSession(this, it.get())
|
CompileServiceSession(this, it.get())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ensureServerHostnameIsSetUp()
|
ensureServerHostnameIsSetUp()
|
||||||
val (service, newJVMOptions) = tryFindSuitableDaemonOrNewOpts(
|
val result = tryFindSuitableDaemonOrNewOpts(
|
||||||
File(daemonOptions.runFilesPath),
|
File(daemonOptions.runFilesPath),
|
||||||
compilerId,
|
compilerId,
|
||||||
daemonJVMOptions
|
daemonJVMOptions,
|
||||||
) { cat, msg -> reportingTargets.report(cat, msg) }
|
ignoredDaemonSessionFiles,
|
||||||
|
) { cat, msg -> reportingTargets.report(cat, msg) }
|
||||||
if (service != null) {
|
|
||||||
service.leaseImpl()
|
when (result) {
|
||||||
} else {
|
is DaemonSearchResult.Found -> result.compileService.tryToLeaseSession().also {
|
||||||
if (!isLastAttempt && autostart) {
|
// the null value here means that the daemon is already dying,
|
||||||
if (startDaemon(compilerId, newJVMOptions, daemonOptions, reportingTargets)) {
|
// so we shall query other daemons or start a new one
|
||||||
reportingTargets.report(DaemonReportCategory.DEBUG, "new daemon started, trying to find it")
|
if (it == null) ignoredDaemonSessionFiles.add(result.runFileMarker)
|
||||||
|
}
|
||||||
|
is DaemonSearchResult.NotFound -> {
|
||||||
|
if (!isLastAttempt && autostart) {
|
||||||
|
if (startDaemon(compilerId, result.requiredJvmOptions, daemonOptions, reportingTargets)) {
|
||||||
|
reportingTargets.report(DaemonReportCategory.DEBUG, "new daemon started, trying to find it")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,16 +393,28 @@ object KotlinCompilerClient {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private sealed interface DaemonSearchResult {
|
||||||
|
class Found(
|
||||||
|
val compileService: CompileService,
|
||||||
|
val runFileMarker: File,
|
||||||
|
) : DaemonSearchResult
|
||||||
|
|
||||||
|
class NotFound(
|
||||||
|
val requiredJvmOptions: DaemonJVMOptions,
|
||||||
|
) : DaemonSearchResult
|
||||||
|
}
|
||||||
|
|
||||||
private fun tryFindSuitableDaemonOrNewOpts(
|
private fun tryFindSuitableDaemonOrNewOpts(
|
||||||
registryDir: File,
|
registryDir: File,
|
||||||
compilerId: CompilerId,
|
compilerId: CompilerId,
|
||||||
daemonJVMOptions: DaemonJVMOptions,
|
daemonJVMOptions: DaemonJVMOptions,
|
||||||
|
ignoredDaemonSessionFiles: Set<File>,
|
||||||
report: (DaemonReportCategory, String) -> Unit,
|
report: (DaemonReportCategory, String) -> Unit,
|
||||||
): Pair<CompileService?, DaemonJVMOptions> {
|
): DaemonSearchResult {
|
||||||
registryDir.mkdirs()
|
registryDir.mkdirs()
|
||||||
val timestampMarker = Files.createTempFile(registryDir.toPath(), "kotlin-daemon-client-tsmarker", null).toFile()
|
val timestampMarker = Files.createTempFile(registryDir.toPath(), "kotlin-daemon-client-tsmarker", null).toFile()
|
||||||
val aliveWithMetadata = try {
|
val aliveWithMetadata = try {
|
||||||
walkDaemons(registryDir, compilerId, timestampMarker, report = report).toList()
|
walkDaemons(registryDir, compilerId, timestampMarker, report = report, filter = { file, _ -> file !in ignoredDaemonSessionFiles }).toList()
|
||||||
} finally {
|
} finally {
|
||||||
timestampMarker.delete()
|
timestampMarker.delete()
|
||||||
}
|
}
|
||||||
@@ -403,10 +424,10 @@ object KotlinCompilerClient {
|
|||||||
val optsCopy = daemonJVMOptions.copy()
|
val optsCopy = daemonJVMOptions.copy()
|
||||||
// if required options fit into fattest running daemon - return the daemon and required options with memory params set to actual ones in the daemon
|
// if required options fit into fattest running daemon - return the daemon and required options with memory params set to actual ones in the daemon
|
||||||
return aliveWithMetadata.maxWithOrNull(comparator)?.takeIf { daemonJVMOptions memorywiseFitsInto it.jvmOptions }?.let {
|
return aliveWithMetadata.maxWithOrNull(comparator)?.takeIf { daemonJVMOptions memorywiseFitsInto it.jvmOptions }?.let {
|
||||||
Pair(it.daemon, optsCopy.updateMemoryUpperBounds(it.jvmOptions))
|
DaemonSearchResult.Found(it.daemon, it.runFile)
|
||||||
}
|
}
|
||||||
// else combine all options from running daemon to get fattest option for a new daemon to run
|
// else combine all options from running daemon to get fattest option for a new daemon to run
|
||||||
?: Pair(null, aliveWithMetadata.fold(optsCopy) { opts, d -> opts.updateMemoryUpperBounds(d.jvmOptions) })
|
?: DaemonSearchResult.NotFound(aliveWithMetadata.fold(optsCopy) { opts, d -> opts.updateMemoryUpperBounds(d.jvmOptions) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -39,7 +39,7 @@ interface CompileService : Remote {
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val NO_SESSION: Int = 0
|
const val NO_SESSION: Int = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class CallResult<out R> : Serializable {
|
sealed class CallResult<out R> : Serializable {
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.daemon
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.daemon.client.KotlinCompilerClient
|
import org.jetbrains.kotlin.daemon.client.KotlinCompilerClient
|
||||||
import org.jetbrains.kotlin.daemon.common.CompileService
|
import org.jetbrains.kotlin.daemon.common.CompileService
|
||||||
import org.junit.jupiter.api.Disabled
|
|
||||||
import org.junit.jupiter.api.DisplayName
|
import org.junit.jupiter.api.DisplayName
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -36,7 +35,6 @@ class LastSessionDaemonTest : BaseDaemonSessionTest() {
|
|||||||
assertEquals(0, exitCode)
|
assertEquals(0, exitCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Disabled("KT-55322")
|
|
||||||
@DisplayName("can lease a session when the daemon in the LastSession state") // either by starting a new daemon or returning it to the Alive state
|
@DisplayName("can lease a session when the daemon in the LastSession state") // either by starting a new daemon or returning it to the Alive state
|
||||||
@Test
|
@Test
|
||||||
fun canLeaseNewSession() {
|
fun canLeaseNewSession() {
|
||||||
|
|||||||
Reference in New Issue
Block a user