Skip to content

Commit

Permalink
GH-40 Rename reactive plugin to Coroutines routing component
Browse files Browse the repository at this point in the history
  • Loading branch information
dzikoysk committed Nov 11, 2023
1 parent ae2c810 commit 71b803e
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 61 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.javalin.community.routing.coroutines

import io.javalin.community.routing.coroutines.servlet.CoroutinesServlet
import io.javalin.community.routing.sortRoutes
import io.javalin.config.JavalinConfig
import io.javalin.http.Handler
import io.javalin.http.HandlerType
import io.javalin.router.InternalRouter
import io.javalin.router.RoutingApiInitializer
import java.util.function.Consumer

class Coroutines<ROUTE : SuspendedRoute<CONTEXT, RESPONSE>, CONTEXT, RESPONSE : Any>(
private val servlet: CoroutinesServlet<CONTEXT, RESPONSE>,
) : RoutingApiInitializer<CoroutinesRouting<ROUTE, CONTEXT, RESPONSE>> {

override fun initialize(cfg: JavalinConfig, internalRouter: InternalRouter, setup: Consumer<CoroutinesRouting<ROUTE, CONTEXT, RESPONSE>>) {
val coroutinesRouting = CoroutinesRouting<ROUTE, CONTEXT, RESPONSE>()
setup.accept(coroutinesRouting)

coroutinesRouting
.routes
.sortRoutes()
.map { it to Handler { ctx -> servlet.handle(ctx, it) } }
.forEach { (route, handler) -> internalRouter.addHttpHandler(HandlerType.valueOf(route.method.toString()), route.path, handler) }
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.javalin.community.routing.coroutines

import io.javalin.community.routing.Route

class CoroutinesRouting<ROUTE : SuspendedRoute<CONTEXT, RESPONSE>, CONTEXT, RESPONSE : Any> {

internal val routes = mutableListOf<ROUTE>()

fun route(route: ROUTE) {
routes.add(route)
}

fun routes(exampleEndpoint: SuspendedRoutes<ROUTE, CONTEXT, RESPONSE>): CoroutinesRouting<ROUTE, CONTEXT, RESPONSE> {
exampleEndpoint.routes().forEach { route(it) }
return this
}

}

fun <CONTEXT, RESPONSE : Any> CoroutinesRouting<SuspendedRoute<CONTEXT, RESPONSE>, CONTEXT, RESPONSE>.route(
method: Route,
path: String,
async: Boolean = true,
handler: suspend CONTEXT.() -> RESPONSE
) {
routes.add(SuspendedRoute(path, method, async, handler))
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ import io.javalin.community.routing.Route
import io.javalin.community.routing.Routed
import io.javalin.community.routing.Routes

class ReactiveRoute<CONTEXT, RESPONSE : Any>(
class SuspendedRoute<CONTEXT, RESPONSE : Any>(
override val path: String,
val method: Route,
val async: Boolean = true,
val handler: suspend CONTEXT.() -> RESPONSE
) : Routed

abstract class ReactiveRoutes<ROUTE : ReactiveRoute<CONTEXT, RESPONSE>, CONTEXT, RESPONSE : Any> : Routes<ROUTE, CONTEXT, RESPONSE> {
abstract class SuspendedRoutes<ROUTE : SuspendedRoute<CONTEXT, RESPONSE>, CONTEXT, RESPONSE : Any> : Routes<ROUTE, CONTEXT, RESPONSE> {

fun reactiveRoute(path: String, method: Route, async: Boolean = true, handler: suspend CONTEXT.() -> RESPONSE): ReactiveRoute<CONTEXT, RESPONSE> =
ReactiveRoute(
fun route(path: String, method: Route, async: Boolean = true, handler: suspend CONTEXT.() -> RESPONSE): SuspendedRoute<CONTEXT, RESPONSE> =
SuspendedRoute(
path = path,
method = method,
async = async,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.javalin.community.routing.coroutines.servlet

import io.javalin.community.routing.coroutines.ReactiveRoute
import io.javalin.community.routing.coroutines.SuspendedRoute
import io.javalin.http.Context
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineName
Expand All @@ -16,8 +16,8 @@ open class CoroutinesServlet<CONTEXT, RESPONSE : Any>(
name: String = "javalin-reactive-routing",
private val coroutinesEnabled: Boolean = true,
protected val dispatcher: CoroutineDispatcher,
protected val syncHandler: suspend (Context, ReactiveRoute<CONTEXT, RESPONSE>) -> RESPONSE,
protected val asyncHandler: suspend (Context, ReactiveRoute<CONTEXT, RESPONSE>, CompletableFuture<RESPONSE>) -> RESPONSE,
protected val syncHandler: suspend (Context, SuspendedRoute<CONTEXT, RESPONSE>) -> RESPONSE,
protected val asyncHandler: suspend (Context, SuspendedRoute<CONTEXT, RESPONSE>, CompletableFuture<RESPONSE>) -> RESPONSE,
private val responseConsumer: (suspend (Context, RESPONSE) -> Unit)? = null,
uncaughtExceptionConsumer: (CoroutineNameRepresentation, Throwable) -> Unit,
) {
Expand All @@ -28,7 +28,7 @@ open class CoroutinesServlet<CONTEXT, RESPONSE : Any>(
private val id = AtomicLong()
private val finished = AtomicLong()

fun handle(ctx: Context, route: ReactiveRoute<CONTEXT, RESPONSE>) {
fun handle(ctx: Context, route: SuspendedRoute<CONTEXT, RESPONSE>) {
id.incrementAndGet()

when {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package io.javalin.community.routing

import io.javalin.Javalin
import io.javalin.community.routing.coroutines.Coroutines
import io.javalin.community.routing.coroutines.route
import io.javalin.community.routing.coroutines.servlet.DefaultContextCoroutinesServlet
import io.javalin.testtools.JavalinTest
import java.util.concurrent.Executors
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package io.javalin.community.routing.examples
import io.javalin.Javalin
import io.javalin.community.routing.Route.GET
import io.javalin.community.routing.coroutines.Coroutines
import io.javalin.community.routing.coroutines.ReactiveRoute
import io.javalin.community.routing.coroutines.ReactiveRoutes
import io.javalin.community.routing.coroutines.SuspendedRoute
import io.javalin.community.routing.coroutines.SuspendedRoutes
import io.javalin.community.routing.coroutines.servlet.DefaultContextCoroutinesServlet
import io.javalin.http.Context
import java.lang.Thread.sleep
Expand All @@ -29,30 +29,30 @@ class CustomScope(val ctx: Context) : Context by ctx {
}

// Utility class representing group of reactive routes
abstract class ExampleRoutes : ReactiveRoutes<ReactiveRoute<CustomScope, Unit>, CustomScope, Unit>()
abstract class ExampleRoutes : SuspendedRoutes<SuspendedRoute<CustomScope, Unit>, CustomScope, Unit>()

// Endpoint (domain router)
class ExampleEndpoint(private val exampleService: ExampleService) : ExampleRoutes() {

// you can use suspend functions in coroutines context
// and as long as they're truly reactive, they won't freeze it
private val nonBlockingAsync = reactiveRoute("/async", GET) {
private val nonBlockingAsync = route("/async", GET) {
result(nonBlockingDelay("Non-blocking Async"))
}

// using truly-blocking functions in coroutines context will freeze thread anyway
private val blockingAsync = reactiveRoute("/async-blocking", GET) {
private val blockingAsync = route("/async-blocking", GET) {
result(blockingDelay("Blocking Async"))
}

// you can also use async = false, to run coroutine in sync context (runBlocking)
private val sync = reactiveRoute("/sync", GET, async = false) {
private val sync = route("/sync", GET, async = false) {
result(blockingDelay("Sync"))
}

// you can visit /stream in browser and see that despite single-threaded executor,
// you can make multiple concurrent requests and each request is handled
private val stream = reactiveRoute("/stream", GET) {
private val stream = route("/stream", GET) {
val id = exampleService.streamId.incrementAndGet()

while (true) {
Expand Down

0 comments on commit 71b803e

Please sign in to comment.