mirror of
https://github.com/corda/corda.git
synced 2024-12-23 14:52:29 +00:00
Enable RPC start of Flows that return nothing (eg. Void). (#1374)
* Enable RPC start of Flows that return nothing (eg. Void). * Fix blocking test (caused by not running mockNetwork). Improve execution times by moving redundant setup() initialisation to only tests that use it.
This commit is contained in:
parent
954ed69102
commit
a286f7553b
@ -194,14 +194,14 @@ interface CordaRPCOps : RPCOps {
|
|||||||
* Start the given flow with the given arguments. [logicType] must be annotated with [net.corda.core.flows.StartableByRPC].
|
* Start the given flow with the given arguments. [logicType] must be annotated with [net.corda.core.flows.StartableByRPC].
|
||||||
*/
|
*/
|
||||||
@RPCReturnsObservables
|
@RPCReturnsObservables
|
||||||
fun <T : Any> startFlowDynamic(logicType: Class<out FlowLogic<T>>, vararg args: Any?): FlowHandle<T>
|
fun <T> startFlowDynamic(logicType: Class<out FlowLogic<T>>, vararg args: Any?): FlowHandle<T>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start the given flow with the given arguments, returning an [Observable] with a single observation of the
|
* Start the given flow with the given arguments, returning an [Observable] with a single observation of the
|
||||||
* result of running the flow. [logicType] must be annotated with [net.corda.core.flows.StartableByRPC].
|
* result of running the flow. [logicType] must be annotated with [net.corda.core.flows.StartableByRPC].
|
||||||
*/
|
*/
|
||||||
@RPCReturnsObservables
|
@RPCReturnsObservables
|
||||||
fun <T : Any> startTrackedFlowDynamic(logicType: Class<out FlowLogic<T>>, vararg args: Any?): FlowProgressHandle<T>
|
fun <T> startTrackedFlowDynamic(logicType: Class<out FlowLogic<T>>, vararg args: Any?): FlowProgressHandle<T>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns Node's identity, assuming this will not change while the node is running.
|
* Returns Node's identity, assuming this will not change while the node is running.
|
||||||
@ -327,25 +327,25 @@ inline fun <reified T : ContractState> CordaRPCOps.vaultTrackBy(criteria: QueryC
|
|||||||
* Note that the passed in constructor function is only used for unification of other type parameters and reification of
|
* Note that the passed in constructor function is only used for unification of other type parameters and reification of
|
||||||
* the Class instance of the flow. This could be changed to use the constructor function directly.
|
* the Class instance of the flow. This could be changed to use the constructor function directly.
|
||||||
*/
|
*/
|
||||||
inline fun <T : Any, reified R : FlowLogic<T>> CordaRPCOps.startFlow(
|
inline fun <T, reified R : FlowLogic<T>> CordaRPCOps.startFlow(
|
||||||
@Suppress("UNUSED_PARAMETER")
|
@Suppress("UNUSED_PARAMETER")
|
||||||
flowConstructor: () -> R
|
flowConstructor: () -> R
|
||||||
): FlowHandle<T> = startFlowDynamic(R::class.java)
|
): FlowHandle<T> = startFlowDynamic(R::class.java)
|
||||||
|
|
||||||
inline fun <T : Any, A, reified R : FlowLogic<T>> CordaRPCOps.startFlow(
|
inline fun <T, A, reified R : FlowLogic<T>> CordaRPCOps.startFlow(
|
||||||
@Suppress("UNUSED_PARAMETER")
|
@Suppress("UNUSED_PARAMETER")
|
||||||
flowConstructor: (A) -> R,
|
flowConstructor: (A) -> R,
|
||||||
arg0: A
|
arg0: A
|
||||||
): FlowHandle<T> = startFlowDynamic(R::class.java, arg0)
|
): FlowHandle<T> = startFlowDynamic(R::class.java, arg0)
|
||||||
|
|
||||||
inline fun <T : Any, A, B, reified R : FlowLogic<T>> CordaRPCOps.startFlow(
|
inline fun <T, A, B, reified R : FlowLogic<T>> CordaRPCOps.startFlow(
|
||||||
@Suppress("UNUSED_PARAMETER")
|
@Suppress("UNUSED_PARAMETER")
|
||||||
flowConstructor: (A, B) -> R,
|
flowConstructor: (A, B) -> R,
|
||||||
arg0: A,
|
arg0: A,
|
||||||
arg1: B
|
arg1: B
|
||||||
): FlowHandle<T> = startFlowDynamic(R::class.java, arg0, arg1)
|
): FlowHandle<T> = startFlowDynamic(R::class.java, arg0, arg1)
|
||||||
|
|
||||||
inline fun <T : Any, A, B, C, reified R : FlowLogic<T>> CordaRPCOps.startFlow(
|
inline fun <T, A, B, C, reified R : FlowLogic<T>> CordaRPCOps.startFlow(
|
||||||
@Suppress("UNUSED_PARAMETER")
|
@Suppress("UNUSED_PARAMETER")
|
||||||
flowConstructor: (A, B, C) -> R,
|
flowConstructor: (A, B, C) -> R,
|
||||||
arg0: A,
|
arg0: A,
|
||||||
@ -353,7 +353,7 @@ inline fun <T : Any, A, B, C, reified R : FlowLogic<T>> CordaRPCOps.startFlow(
|
|||||||
arg2: C
|
arg2: C
|
||||||
): FlowHandle<T> = startFlowDynamic(R::class.java, arg0, arg1, arg2)
|
): FlowHandle<T> = startFlowDynamic(R::class.java, arg0, arg1, arg2)
|
||||||
|
|
||||||
inline fun <T : Any, A, B, C, D, reified R : FlowLogic<T>> CordaRPCOps.startFlow(
|
inline fun <T, A, B, C, D, reified R : FlowLogic<T>> CordaRPCOps.startFlow(
|
||||||
@Suppress("UNUSED_PARAMETER")
|
@Suppress("UNUSED_PARAMETER")
|
||||||
flowConstructor: (A, B, C, D) -> R,
|
flowConstructor: (A, B, C, D) -> R,
|
||||||
arg0: A,
|
arg0: A,
|
||||||
@ -362,7 +362,7 @@ inline fun <T : Any, A, B, C, D, reified R : FlowLogic<T>> CordaRPCOps.startFlow
|
|||||||
arg3: D
|
arg3: D
|
||||||
): FlowHandle<T> = startFlowDynamic(R::class.java, arg0, arg1, arg2, arg3)
|
): FlowHandle<T> = startFlowDynamic(R::class.java, arg0, arg1, arg2, arg3)
|
||||||
|
|
||||||
inline fun <T : Any, A, B, C, D, E, reified R : FlowLogic<T>> CordaRPCOps.startFlow(
|
inline fun <T, A, B, C, D, E, reified R : FlowLogic<T>> CordaRPCOps.startFlow(
|
||||||
@Suppress("UNUSED_PARAMETER")
|
@Suppress("UNUSED_PARAMETER")
|
||||||
flowConstructor: (A, B, C, D, E) -> R,
|
flowConstructor: (A, B, C, D, E) -> R,
|
||||||
arg0: A,
|
arg0: A,
|
||||||
@ -372,7 +372,7 @@ inline fun <T : Any, A, B, C, D, E, reified R : FlowLogic<T>> CordaRPCOps.startF
|
|||||||
arg4: E
|
arg4: E
|
||||||
): FlowHandle<T> = startFlowDynamic(R::class.java, arg0, arg1, arg2, arg3, arg4)
|
): FlowHandle<T> = startFlowDynamic(R::class.java, arg0, arg1, arg2, arg3, arg4)
|
||||||
|
|
||||||
inline fun <T : Any, A, B, C, D, E, F, reified R : FlowLogic<T>> CordaRPCOps.startFlow(
|
inline fun <T, A, B, C, D, E, F, reified R : FlowLogic<T>> CordaRPCOps.startFlow(
|
||||||
@Suppress("UNUSED_PARAMETER")
|
@Suppress("UNUSED_PARAMETER")
|
||||||
flowConstructor: (A, B, C, D, E, F) -> R,
|
flowConstructor: (A, B, C, D, E, F) -> R,
|
||||||
arg0: A,
|
arg0: A,
|
||||||
@ -387,20 +387,20 @@ inline fun <T : Any, A, B, C, D, E, F, reified R : FlowLogic<T>> CordaRPCOps.sta
|
|||||||
* Same again, except this time with progress-tracking enabled.
|
* Same again, except this time with progress-tracking enabled.
|
||||||
*/
|
*/
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
inline fun <T : Any, reified R : FlowLogic<T>> CordaRPCOps.startTrackedFlow(
|
inline fun <T, reified R : FlowLogic<T>> CordaRPCOps.startTrackedFlow(
|
||||||
@Suppress("unused_parameter")
|
@Suppress("unused_parameter")
|
||||||
flowConstructor: () -> R
|
flowConstructor: () -> R
|
||||||
): FlowProgressHandle<T> = startTrackedFlowDynamic(R::class.java)
|
): FlowProgressHandle<T> = startTrackedFlowDynamic(R::class.java)
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
inline fun <T : Any, A, reified R : FlowLogic<T>> CordaRPCOps.startTrackedFlow(
|
inline fun <T, A, reified R : FlowLogic<T>> CordaRPCOps.startTrackedFlow(
|
||||||
@Suppress("unused_parameter")
|
@Suppress("unused_parameter")
|
||||||
flowConstructor: (A) -> R,
|
flowConstructor: (A) -> R,
|
||||||
arg0: A
|
arg0: A
|
||||||
): FlowProgressHandle<T> = startTrackedFlowDynamic(R::class.java, arg0)
|
): FlowProgressHandle<T> = startTrackedFlowDynamic(R::class.java, arg0)
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
inline fun <T : Any, A, B, reified R : FlowLogic<T>> CordaRPCOps.startTrackedFlow(
|
inline fun <T, A, B, reified R : FlowLogic<T>> CordaRPCOps.startTrackedFlow(
|
||||||
@Suppress("unused_parameter")
|
@Suppress("unused_parameter")
|
||||||
flowConstructor: (A, B) -> R,
|
flowConstructor: (A, B) -> R,
|
||||||
arg0: A,
|
arg0: A,
|
||||||
@ -408,7 +408,7 @@ inline fun <T : Any, A, B, reified R : FlowLogic<T>> CordaRPCOps.startTrackedFlo
|
|||||||
): FlowProgressHandle<T> = startTrackedFlowDynamic(R::class.java, arg0, arg1)
|
): FlowProgressHandle<T> = startTrackedFlowDynamic(R::class.java, arg0, arg1)
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
inline fun <T : Any, A, B, C, reified R : FlowLogic<T>> CordaRPCOps.startTrackedFlow(
|
inline fun <T, A, B, C, reified R : FlowLogic<T>> CordaRPCOps.startTrackedFlow(
|
||||||
@Suppress("unused_parameter")
|
@Suppress("unused_parameter")
|
||||||
flowConstructor: (A, B, C) -> R,
|
flowConstructor: (A, B, C) -> R,
|
||||||
arg0: A,
|
arg0: A,
|
||||||
@ -417,7 +417,7 @@ inline fun <T : Any, A, B, C, reified R : FlowLogic<T>> CordaRPCOps.startTracked
|
|||||||
): FlowProgressHandle<T> = startTrackedFlowDynamic(R::class.java, arg0, arg1, arg2)
|
): FlowProgressHandle<T> = startTrackedFlowDynamic(R::class.java, arg0, arg1, arg2)
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
inline fun <T : Any, A, B, C, D, reified R : FlowLogic<T>> CordaRPCOps.startTrackedFlow(
|
inline fun <T, A, B, C, D, reified R : FlowLogic<T>> CordaRPCOps.startTrackedFlow(
|
||||||
@Suppress("unused_parameter")
|
@Suppress("unused_parameter")
|
||||||
flowConstructor: (A, B, C, D) -> R,
|
flowConstructor: (A, B, C, D) -> R,
|
||||||
arg0: A,
|
arg0: A,
|
||||||
@ -427,7 +427,7 @@ inline fun <T : Any, A, B, C, D, reified R : FlowLogic<T>> CordaRPCOps.startTrac
|
|||||||
): FlowProgressHandle<T> = startTrackedFlowDynamic(R::class.java, arg0, arg1, arg2, arg3)
|
): FlowProgressHandle<T> = startTrackedFlowDynamic(R::class.java, arg0, arg1, arg2, arg3)
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
inline fun <T : Any, A, B, C, D, E, reified R : FlowLogic<T>> CordaRPCOps.startTrackedFlow(
|
inline fun <T, A, B, C, D, E, reified R : FlowLogic<T>> CordaRPCOps.startTrackedFlow(
|
||||||
@Suppress("unused_parameter")
|
@Suppress("unused_parameter")
|
||||||
flowConstructor: (A, B, C, D, E) -> R,
|
flowConstructor: (A, B, C, D, E) -> R,
|
||||||
arg0: A,
|
arg0: A,
|
||||||
@ -438,7 +438,7 @@ inline fun <T : Any, A, B, C, D, E, reified R : FlowLogic<T>> CordaRPCOps.startT
|
|||||||
): FlowProgressHandle<T> = startTrackedFlowDynamic(R::class.java, arg0, arg1, arg2, arg3, arg4)
|
): FlowProgressHandle<T> = startTrackedFlowDynamic(R::class.java, arg0, arg1, arg2, arg3, arg4)
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
inline fun <T : Any, A, B, C, D, E, F, reified R : FlowLogic<T>> CordaRPCOps.startTrackedFlow(
|
inline fun <T, A, B, C, D, E, F, reified R : FlowLogic<T>> CordaRPCOps.startTrackedFlow(
|
||||||
@Suppress("unused_parameter")
|
@Suppress("unused_parameter")
|
||||||
flowConstructor: (A, B, C, D, E, F) -> R,
|
flowConstructor: (A, B, C, D, E, F) -> R,
|
||||||
arg0: A,
|
arg0: A,
|
||||||
|
@ -127,7 +127,7 @@ class CordaRPCOpsImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun <T : Any> startTrackedFlowDynamic(logicType: Class<out FlowLogic<T>>, vararg args: Any?): FlowProgressHandle<T> {
|
override fun <T> startTrackedFlowDynamic(logicType: Class<out FlowLogic<T>>, vararg args: Any?): FlowProgressHandle<T> {
|
||||||
val stateMachine = startFlow(logicType, args)
|
val stateMachine = startFlow(logicType, args)
|
||||||
return FlowProgressHandleImpl(
|
return FlowProgressHandleImpl(
|
||||||
id = stateMachine.id,
|
id = stateMachine.id,
|
||||||
@ -136,12 +136,12 @@ class CordaRPCOpsImpl(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun <T : Any> startFlowDynamic(logicType: Class<out FlowLogic<T>>, vararg args: Any?): FlowHandle<T> {
|
override fun <T> startFlowDynamic(logicType: Class<out FlowLogic<T>>, vararg args: Any?): FlowHandle<T> {
|
||||||
val stateMachine = startFlow(logicType, args)
|
val stateMachine = startFlow(logicType, args)
|
||||||
return FlowHandleImpl(id = stateMachine.id, returnValue = stateMachine.resultFuture)
|
return FlowHandleImpl(id = stateMachine.id, returnValue = stateMachine.resultFuture)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <T : Any> startFlow(logicType: Class<out FlowLogic<T>>, args: Array<out Any?>): FlowStateMachineImpl<T> {
|
private fun <T> startFlow(logicType: Class<out FlowLogic<T>>, args: Array<out Any?>): FlowStateMachineImpl<T> {
|
||||||
require(logicType.isAnnotationPresent(StartableByRPC::class.java)) { "${logicType.name} was not designed for RPC" }
|
require(logicType.isAnnotationPresent(StartableByRPC::class.java)) { "${logicType.name} was not designed for RPC" }
|
||||||
val rpcContext = getRpcContext()
|
val rpcContext = getRpcContext()
|
||||||
rpcContext.requirePermission(startFlowPermission(logicType))
|
rpcContext.requirePermission(startFlowPermission(logicType))
|
||||||
|
@ -126,7 +126,7 @@ interface ServiceHubInternal : PluginServiceHub {
|
|||||||
* @throws net.corda.core.flows.IllegalFlowLogicException or IllegalArgumentException if there are problems with the
|
* @throws net.corda.core.flows.IllegalFlowLogicException or IllegalArgumentException if there are problems with the
|
||||||
* [logicType] or [args].
|
* [logicType] or [args].
|
||||||
*/
|
*/
|
||||||
fun <T : Any> invokeFlowAsync(
|
fun <T> invokeFlowAsync(
|
||||||
logicType: Class<out FlowLogic<T>>,
|
logicType: Class<out FlowLogic<T>>,
|
||||||
flowInitiator: FlowInitiator,
|
flowInitiator: FlowInitiator,
|
||||||
vararg args: Any?): FlowStateMachineImpl<T> {
|
vararg args: Any?): FlowStateMachineImpl<T> {
|
||||||
|
@ -7,6 +7,7 @@ import net.corda.core.contracts.Issued
|
|||||||
import net.corda.core.crypto.isFulfilledBy
|
import net.corda.core.crypto.isFulfilledBy
|
||||||
import net.corda.core.crypto.keys
|
import net.corda.core.crypto.keys
|
||||||
import net.corda.core.flows.FlowLogic
|
import net.corda.core.flows.FlowLogic
|
||||||
|
import net.corda.core.flows.StartableByRPC
|
||||||
import net.corda.core.flows.StateMachineRunId
|
import net.corda.core.flows.StateMachineRunId
|
||||||
import net.corda.core.messaging.*
|
import net.corda.core.messaging.*
|
||||||
import net.corda.core.node.services.ServiceInfo
|
import net.corda.core.node.services.ServiceInfo
|
||||||
@ -44,6 +45,7 @@ import rx.Observable
|
|||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertFalse
|
import kotlin.test.assertFalse
|
||||||
|
import kotlin.test.assertNull
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class CordaRPCOpsImplTest {
|
class CordaRPCOpsImplTest {
|
||||||
@ -71,12 +73,6 @@ class CordaRPCOpsImplTest {
|
|||||||
startFlowPermission<CashIssueFlow>(),
|
startFlowPermission<CashIssueFlow>(),
|
||||||
startFlowPermission<CashPaymentFlow>()
|
startFlowPermission<CashPaymentFlow>()
|
||||||
))))
|
))))
|
||||||
|
|
||||||
aliceNode.database.transaction {
|
|
||||||
stateMachineUpdates = rpc.stateMachinesFeed().updates
|
|
||||||
transactions = rpc.verifiedTransactionsFeed().updates
|
|
||||||
vaultTrackCash = rpc.vaultTrackBy<Cash.State>().updates
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
@ -86,6 +82,11 @@ class CordaRPCOpsImplTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `cash issue accepted`() {
|
fun `cash issue accepted`() {
|
||||||
|
aliceNode.database.transaction {
|
||||||
|
stateMachineUpdates = rpc.stateMachinesFeed().updates
|
||||||
|
vaultTrackCash = rpc.vaultTrackBy<Cash.State>().updates
|
||||||
|
}
|
||||||
|
|
||||||
val quantity = 1000L
|
val quantity = 1000L
|
||||||
val ref = OpaqueBytes(ByteArray(1) { 1 })
|
val ref = OpaqueBytes(ByteArray(1) { 1 })
|
||||||
|
|
||||||
@ -131,6 +132,12 @@ class CordaRPCOpsImplTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `issue and move`() {
|
fun `issue and move`() {
|
||||||
|
aliceNode.database.transaction {
|
||||||
|
stateMachineUpdates = rpc.stateMachinesFeed().updates
|
||||||
|
transactions = rpc.verifiedTransactionsFeed().updates
|
||||||
|
vaultTrackCash = rpc.vaultTrackBy<Cash.State>().updates
|
||||||
|
}
|
||||||
|
|
||||||
val anonymous = false
|
val anonymous = false
|
||||||
val result = rpc.startFlow(::CashIssueFlow,
|
val result = rpc.startFlow(::CashIssueFlow,
|
||||||
100.DOLLARS,
|
100.DOLLARS,
|
||||||
@ -248,4 +255,20 @@ class CordaRPCOpsImplTest {
|
|||||||
@Suspendable
|
@Suspendable
|
||||||
override fun call() = Unit
|
override fun call() = Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `attempt to start RPC flow with void return`() {
|
||||||
|
CURRENT_RPC_CONTEXT.set(RpcContext(User("user", "pwd", permissions = setOf(
|
||||||
|
startFlowPermission<VoidRPCFlow>()
|
||||||
|
))))
|
||||||
|
val result = rpc.startFlow(::VoidRPCFlow)
|
||||||
|
mockNet.runNetwork()
|
||||||
|
assertNull(result.returnValue.getOrThrow())
|
||||||
|
}
|
||||||
|
|
||||||
|
@StartableByRPC
|
||||||
|
class VoidRPCFlow : FlowLogic<Void?>() {
|
||||||
|
@Suspendable
|
||||||
|
override fun call() : Void? = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user