ENT-4601 Public API to run external operations from a flow (#5833)

Deprecate FlowAsyncOperation and reimplement public versions FlowExternalOperation and FlowExternalAsyncOperation.

await added to FlowLogic to allow easy calling from both Java and Kotlin. There are two overrides of await (one for FlowExternalOperation and FlowExternalAsyncOperation).

Implementations of FlowExternalOperation return a result (written as blocking code) from their execute function. This operation will then be executed using a thread provided by the externalOperationExecutor.

Implementations of FlowExternalAsyncOperation return a future from their execute function. This operation must be executed on a newly spawned thread or one provided by a thread pool. It is up to developers to handle threading in this scenario.

The default thread pool (externalOperationExecutor) can be configured through the flowExternalOperationThreadPoolSize node config.

The current implementation leaves FlowAsyncOperation alone, meaning that any developers that have used it (even though it is internal) won't need to change their apps. If this was not concern I would delete it completely and replumb the state machine code. Instead, it has been marked with @DoNotImplement and executeAsync is annotated with @Deprecated
This commit is contained in:
Dan Newton
2020-01-22 09:27:17 +00:00
committed by Rick Parker
parent 0978500a9a
commit 4bae045a58
29 changed files with 2235 additions and 129 deletions

View File

@ -1,38 +1,31 @@
package net.corda.docs.kotlin.tutorial.flowstatemachines
import co.paralleluniverse.fibers.Suspendable
import net.corda.core.concurrent.CordaFuture
import net.corda.core.flows.FlowExternalAsyncOperation
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.StartableByRPC
import net.corda.core.internal.FlowAsyncOperation
import net.corda.core.internal.concurrent.doneFuture
import net.corda.core.internal.concurrent.openFuture
import net.corda.core.internal.executeAsync
import java.util.concurrent.CompletableFuture
// DOCSTART SummingOperation
class SummingOperation(val a: Int, val b: Int) : FlowAsyncOperation<Int> {
override fun execute(deduplicationId: String): CordaFuture<Int> {
return doneFuture(a + b)
class SummingOperation(val a: Int, val b: Int) : FlowExternalAsyncOperation<Int> {
override fun execute(deduplicationId: String): CompletableFuture<Int> {
return CompletableFuture.completedFuture(a + b)
}
}
// DOCEND SummingOperation
// DOCSTART SummingOperationThrowing
class SummingOperationThrowing(val a: Int, val b: Int) : FlowAsyncOperation<Int> {
override fun execute(deduplicationId: String): CordaFuture<Int> {
class SummingOperationThrowing(val a: Int, val b: Int) : FlowExternalAsyncOperation<Int> {
override fun execute(deduplicationId: String): CompletableFuture<Int> {
throw IllegalStateException("You shouldn't be calling me")
}
}
// DOCEND SummingOperationThrowing
// DOCSTART ExampleSummingFlow
@StartableByRPC
class ExampleSummingFlow : FlowLogic<Int>() {
@Suspendable
override fun call(): Int {
val answer = executeAsync(SummingOperation(1, 2))
val answer = await(SummingOperation(1, 2))
return answer // hopefully 3
}
}
// DOCEND ExampleSummingFlow