This is a proof-of-concept for entirely coroutine-based reactor + workflows.
This is a proof-of-concept for entirely coroutine-based reactor + workflows.
The API is vaguely shaped like the real one, or as close as I could remember from the last time I saw it.
There are four modules:
Workflow
and Reactor
types. This is a multiplatform common module!CoroutineName
is, I think probably mistakenly, still in kotlin-coroutines-core
.Workflow
in a similarly-shaped interface that uses RxJava typesstate: ReceiveChannel<WorkflowState<S, E>>
state: Observable<WorkflowState<S, E>>
result: Deferred<R>
result: Maybe<R>
Workflow
is the core interface this library exports. It looks (effectively) like this:
interface Workflow<out State : Any, in Event : Any, out Result : Any> {
val state: ReceiveChannel<Pair<State, (Event)->Boolean>>
val result: Deferred<Result>
fun abandon()
}
There are a bunch of ways to create a Workflow
. The most powerful and flexible is with a
coroutine builder, similar to produce
, actor
, and async
combined. Here's an example of how to
use it:
currentScope {
val context = CoroutineName("my workflow") + Dispatchers.IO
val workflow = workflow(context) { // this: WorkflowProducerScope<S, E>
// this is a SendChannel<S>, so you can emit state like:
send("initial state")
// this is also a ReceiveChannel<E>, so you can listen for events:
selectWhile {
onReceive { event -> handleEvent(event) }
}
// and lastly, the value returned by the lambda is the "result" of the workflow.
return@workflow "finished"
}
}
If you have a ReceiveChannel<S>
, you can turn it into a Workflow
real easy:
currentScope {
val workflow = myChannel.asWorkflow()
}
A Reactor
is just a way to define a workflow using a generator function that takes the current
state and returns the next state.
currentScope {
val workflow = generateWorkflow("initial state") { state, events ->
when (state) {
"initial state" -> when (val event = events.receive()) {
"continue" -> EnterState("second state")
"finish" -> FinishWith("all done")
else -> throw IllegalStateException("invalid event")
}
"second state" -> when (val event = events.receive()) {
"finish" -> FinishWith("all done")
else -> throw IllegalStateException("invalid event")
}
}
}
}
./gradlew run
./gradlew test