Last active
August 26, 2021 03:37
-
-
Save edreyer/dbef4856c728b7cab33b7f57719d25fb to your computer and use it in GitHub Desktop.
Kotlin UseCase impl
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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