Skip to content

Commit

Permalink
Fix race when a new class is added
Browse files Browse the repository at this point in the history
The class needs to be in the classpath before the reload
request is sent.
  • Loading branch information
sellmair committed Dec 18, 2024
1 parent e71a020 commit 8e804e5
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,12 @@ class TransactionScope(
}
}

suspend fun sync() {
val ping = OrchestrationMessage.Ping()
ping.send()
awaitAck(ping)
}

suspend fun awaitAck(message: OrchestrationMessage) {
/*
There is no ACK for an ACK, and there is also no ACk for a shutdown request.
Expand All @@ -127,16 +133,20 @@ class TransactionScope(
val reloadRequest = skipToMessage<ReloadClassesRequest>()
val reloadResult = skipToMessage<ReloadClassesResult>()
if (!reloadResult.isSuccess) {
fail("Failed to reload classes: ${reloadResult.errorMessage}")
fail("Failed to reload classes: ${reloadResult.errorMessage}", Throwable(reloadResult.errorMessage).apply {
stackTrace = reloadResult.errorStacktrace?.toTypedArray().orEmpty()
})
}

val rendered = skipToMessage<UIRendered>()
assertEquals(reloadRequest.messageId, rendered.reloadRequestId)
sync()
}

suspend infix fun initialSourceCode(source: String): Path {
val file = writeCode(source = source)
launchApplicationAndWait()
sync()
return file
}

Expand Down Expand Up @@ -176,7 +186,3 @@ class TransactionScope(
return resolvedFile
}
}

fun awaitAck(message: OrchestrationMessage): suspend TransactionScope.() -> Unit = {
this.awaitAck(message)
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ internal fun reload(
val daos = DataOutputStream(baos)
clazz.classFile.write(daos)

ClassDefinition(Class.forName(clazz.name), baos.toByteArray())
ClassDefinition(originalClass ?: Class.forName(clazz.name), baos.toByteArray())
}

instrumentation.redefineClasses(*definitions.toTypedArray())
Expand All @@ -78,4 +78,3 @@ internal fun reload(
definition.reinitializeStaticsIfNecessary()
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.jetbrains.compose.reload.agent


import org.jetbrains.compose.reload.core.createLogger
import org.jetbrains.compose.reload.core.withLinearClosure
import org.jetbrains.compose.reload.orchestration.OrchestrationMessage
import org.jetbrains.compose.reload.orchestration.invokeWhenReceived
import java.io.File
Expand Down Expand Up @@ -35,7 +36,9 @@ internal fun launchReloadClassesRequestHandler(instrumentation: Instrumentation)
if (result.isFailure) {
logger.orchestration("Failed to reload classes", result.exceptionOrNull())
OrchestrationMessage.ReloadClassesResult(
request.messageId, false, result.exceptionOrNull()?.message
request.messageId, false, result.exceptionOrNull()?.message,
result.exceptionOrNull()?.withLinearClosure { throwable -> throwable.cause }.orEmpty()
.flatMap { throwable -> throwable.stackTrace.toList() }
).send()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.jetbrains.compose.reload
import org.gradle.api.DefaultTask
import org.gradle.api.Project
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.Directory
import org.gradle.api.tasks.*
import org.gradle.kotlin.dsl.property
import org.gradle.kotlin.dsl.withType
Expand All @@ -13,10 +14,14 @@ import org.jetbrains.compose.reload.orchestration.OrchestrationClientRole.Compil
import org.jetbrains.compose.reload.orchestration.OrchestrationMessage
import org.jetbrains.compose.reload.orchestration.OrchestrationMessage.ReloadClassesRequest
import org.jetbrains.compose.reload.orchestration.OrchestrationMessage.ReloadClassesRequest.ChangeType
import org.jetbrains.compose.reload.orchestration.asBlockingQueue
import org.jetbrains.compose.reload.orchestration.connectOrchestrationClient
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import java.io.File
import java.util.concurrent.TimeUnit
import kotlin.system.exitProcess
import kotlin.time.Duration.Companion.nanoseconds
import kotlin.time.Duration.Companion.seconds


internal fun Project.setupComposeReloadHotClasspathTasks() {
Expand All @@ -36,12 +41,11 @@ internal fun Project.setupComposeReloadHotClasspathTasks() {
internal fun Project.setupComposeReloadHotClasspathTask(compilation: KotlinCompilation<*>): TaskProvider<ComposeReloadHotClasspathTask> {
val name = composeReloadHotClasspathTaskName(compilation)
if (name in tasks.names) return tasks.named(name, ComposeReloadHotClasspathTask::class.java)
val hotRuntimeClasses = compilation.hotRuntimeClasspath
val hotApplicationClasses = compilation.hotApplicationClasspath

return tasks.register(name, ComposeReloadHotClasspathTask::class.java) { task ->
task.classpath.from(hotRuntimeClasses)
task.finalizedBy(hotApplicationClasses)
task.classpath.from(hotApplicationClasses)
task.dependsOn(hotApplicationClasses)
}
}

Expand All @@ -60,7 +64,7 @@ internal open class ComposeReloadHotClasspathTask : DefaultTask() {
@get:Incremental
val classpath: ConfigurableFileCollection = project.objects.fileCollection()

@Internal
@get:Internal
val agentPort = project.objects.property<Int>()

@TaskAction
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ public sealed class OrchestrationMessage : Serializable {
public data class ReloadClassesResult(
val reloadRequestId: UUID,
val isSuccess: Boolean,
val errorMessage: String? = null
val errorMessage: String? = null,
val errorStacktrace: List<StackTraceElement>? = null,
) : OrchestrationMessage()

/**
Expand Down

0 comments on commit 8e804e5

Please sign in to comment.