-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Kotlin Coroutines in Quarkus #10162
Comments
cc @evanchooly |
We're working on a formal timeline but unofficially here's my short term plan:
As for coroutines in native mode, it's hard to tag that with a specific timeline because the interactions with graalvm make that one hard to gauge. It's likely that one will run in parallel with other tasks until we can crack that code. But I haven't yet dug in to it so it's all speculative at this point. The hope is to have some meetings this week. There's an issue to track the official roadmap if you want to follow along: #8194 |
Also, my unordered, unprioritized working list: area/kotlin |
@cescoffier can you CC Arthur so he can put some progress as he finds stuff on the native image compilation for Kotlin co-routines |
Does it make any conceptual sense that Vert.x has a Kotlin API generator, and whether we should extend this for Quarkus @cescoffier |
@Tas-Hur <-- That should be Arthur |
Hi, I checked out the fix that allows the compiler to solve issues with irreducible loops : oracle/graal@4662877 I am currently running some tests to have a better idea of how nesting loops and calling functions with several points of suspension influences the number of duplication. For now I have this basic scenario showing a linear relation between the maximum number of suspending calls and the value of MaxDuplicationFactor : MaxDuplicationFactor = 1 MaxDuplicationFactor = 2 MaxDuplicationFactor = 3 ... MaxDuplicationFactor = 10 |
webflux works with suspend fun now. maybe you can refer to it? |
Hello to all. Any updates on supporting Kotlin Coroutines ? |
The absence of support for Kotlin coroutines is really the only thing keeping my team from using Quarkus right now. Guess we gotta stick with Spring+WebFlux for a while... |
I believe Kotlin co-routines are supported in JVM mode. I don't see why they should not. Also, with the recent GraalVM changes, it may work in native (but I would be a bit more careful about that). Ping @evanchooly |
Yeah, coroutines should absolutely work in JVM mode. There were some significant hurdles the last time someone looked at native mode but I haven't had a chance just yet. It's on the list to revisit soon, though. Hopefully JetBrains and the graalvm team have worked out some of the issues. |
now dev mode might be another issue but I think that's literally the next item on my list to tackle. |
@evanchooly @cescoffier Kotlin Coroutines can be used in Quarkus JVM mode but If I am not mistaken there are some heavy limitations. For example: It is not possible to define Quarkus performance could be improved if threading could be controlled by the application code using Kotlin Coroutines fine grained mechanisms. Starting from a I think it would a huge improvement in Quarkus Kotlin experience if it would be possible to address these issues considering that these features are already available in Spring Boot or Micronaut. Nevertheless I have to thank you for your work so far in supporting Kotlin in Quarkus. |
Came across this issue. Be advised of https://medium.com/graalvm/graalvm-20-1-7ce7e89f066b. Works great in my testing so far. Had significant issues pre graal 20.1 |
@evanchooly @cescoffier Now that Mutiny has a nice integration with Kotlin Coroutines and we also got RestEasy Reactive is there a possibility to support RestEasy routes as suspending functions e.g. |
I really like the reactive routes and just For most cases, it's even simpler with mutiny-kotlin to just do a What do you (all) think about a @Route(path = "/greetings", methods = [HttpMethod.GET])
suspend fun greetings(ex: RoutingExchange) {
ex.ok("hello " + ex.getParam("name").orElse("world"))
} These methods would be launched on the vert.x coroutine dispatcher and would necessarily interact completely via the RoutingExchange. Or a solution some kind of similar to the routing DSL of Jetbrains Ktor what is really handy to work with - than the routes could directly be registered on vert.x routes. |
@heubeck Actually it would be even better if suspendable functions would supported in RestEasy Reactive which is like Reactive Routes but more high level and more declarative.
As it is build also on top of Quarkus Vertx Layer that should be feasible. |
@evanchooly is looking into adding proper Corroutine support into RESTEasy Reactive, so watch this space for updates :) |
@akoufa Until RESTEasy Reactive includes coroutines support. I used your guidance to create the following "scope" function to adapt resource methods. fun <T, R> T.resourceScope(block: suspend T.() -> R): Uni<R> =
GlobalScope.async(Infrastructure.getDefaultExecutor().asCoroutineDispatcher()) {
block.invoke(this@resourceScope)
}.asUni() It's used as... class TestCoroutineResource {
fun test(): Uni<String> = resourceScope {
...
}
} Is this considered to be efficient or is it dispatching to worker threads and waiting on them? Other than knowing the executor is the Mutiny default executor I have no idea if that's the executor Quarkus uses internally. |
Barring unforeseen events, Kotlin Coroutine support in RESTEasy Reactive will be present in the first Alpha of Quarkus 2.0 (see the linked PR for details). |
2 more CI jobs to finish and then I can merge. Hopefully in the next hour or so. |
@kdubb What do you think of the following? This should be much more efficient because we dont dispatch to worker threads and stay on the Vert.x event loop. import io.smallrye.mutiny.Uni
import io.smallrye.mutiny.coroutines.asUni
import io.vertx.core.Context
import io.vertx.core.Vertx
import kotlinx.coroutines.*
import java.util.concurrent.AbstractExecutorService
import java.util.concurrent.TimeUnit
import javax.enterprise.context.ApplicationScoped
import javax.inject.Inject
import javax.ws.rs.GET
import javax.ws.rs.Path
import javax.ws.rs.Produces
import javax.ws.rs.core.MediaType
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
class VertxCoroutineExecutor(
private val vertxContext: Context
) : AbstractExecutorService() {
override fun execute(command: Runnable) {
if (Vertx.currentContext() != vertxContext) {
vertxContext.runOnContext { command.run() }
} else {
command.run()
}
}
override fun shutdown(): Unit = throw UnsupportedOperationException()
override fun shutdownNow(): MutableList<Runnable> = throw UnsupportedOperationException()
override fun isShutdown(): Boolean = throw UnsupportedOperationException()
override fun isTerminated(): Boolean = throw UnsupportedOperationException()
override fun awaitTermination(timeout: Long, unit: TimeUnit): Boolean = throw UnsupportedOperationException()
}
@ApplicationScoped
class MyScope : CoroutineScope {
override val coroutineContext: CoroutineContext = SupervisorJob()
fun <T> asyncUni(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> T
): Uni<T> {
val vertxContext = checkNotNull(Vertx.currentContext())
val dispatcher = VertxCoroutineExecutor(vertxContext).asCoroutineDispatcher()
return async(context + dispatcher, start, block).asUni()
}
}
@ApplicationScoped
@Path("/")
class MyResource @Inject constructor(
private val scope: MyScope
) {
@GET
@Produces(MediaType.TEXT_PLAIN)
@Path("test")
fun test(): Uni<String> = scope.asyncUni {
"Hello ${Thread.currentThread().name}"
}
@GET
@Produces(MediaType.TEXT_PLAIN)
@Path("test2")
fun test2(): Uni<String> = scope.asyncUni {
callLongRunningTask()
}
private suspend fun callLongRunningTask() = withContext(Dispatchers.Default) { // In real applications this should be the managed executor service from Quarkus (see https://quarkus.io/guides/context-propagation#usage-example-for-completionstage).
delay(3000)
"Done!"
}
} |
Description
Hello to all. I am lately heavily using Quarkus together with Kotlin and I would like to ask you what the progress is, if any, regarding Kotlin Coroutines support in Quarkus APIs. Providing suspendable function APIs, like for example my other feature request, will improve the Quarkus experience for Kotlin developers. Together with the upcoming Hibernate Reactive this would allow us write synchronous-like non blocking code end to end. As Quarkus is based on Vert.x which already has superb Kotlin Coroutines support that is the way to go for Quarkus Kotlin developers. Also Kotlin Coroutines are a compile time construct which do not hinder adopting Project Loom in the future.
Nevertheless I was following the issues in GraalVM Repository and I think the blockers regarding native mode support should be fixed now: oracle/graal#366 oracle/graal#1330 .
The text was updated successfully, but these errors were encountered: