Skip to content

Instantly share code, notes, and snippets.

@edreyer
Last active August 26, 2021 03:37
Show Gist options
  • Save edreyer/dbef4856c728b7cab33b7f57719d25fb to your computer and use it in GitHub Desktop.
Save edreyer/dbef4856c728b7cab33b7f57719d25fb to your computer and use it in GitHub Desktop.
Kotlin UseCase impl
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.reactive.asFlow
import kotlinx.coroutines.reactor.awaitSingle
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
typealias Workflow<R> = suspend () -> Result<R>
typealias MonoWorkflow<R> = suspend () -> Mono<R>
typealias FluxWorkflow<R> = suspend () -> Flux<R>
typealias UseCase<R> = Workflow<R>
typealias MonoUseCase<R> = MonoWorkflow<R>
typealias FluxUseCase<R> = FluxWorkflow<R>
/* Basic impl */
suspend fun <R : Any> runWorkflow(workflow: Workflow<R>): Result<R> = coroutineScope {
async {
workflow.invoke()
}.await()
}
/* Impl converting Reactive Mono to coroutine */
suspend fun <R : Any> runAsync(workflow: MonoWorkflow<R>): R = coroutineScope {
async {
workflow.invoke().awaitSingle()
}.await()
}
/* Impl converting Reactive Flux to coroutine */
suspend fun <R : Any> runAsyncFlow(workflow: FluxWorkflow<R>): Flow<R> = coroutineScope {
async {
workflow.invoke()
}.await().asFlow()
}
// Example
object main {
val name = "Bob Loblaw"
val sayHelloUseCase: MonoUseCase<String> = {
// complex use case closing over 'name'
Mono.just("Hello, $name")
}
// what a controller method might look like
// Notice that the return type is String, not Mono<String>
// kotlin reactive extensions make that disappear, keeping the code simpler
@GetMapping(value = ["/sayHello"])
suspend fun sayHello(): String = runAsync(sayHelloUseCase)
// could look like this too
@GetMapping(value = ["/sayHello2"])
suspend fun sayHello2(): String = runAsync {
Mono.just("Hello, $name")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment