mirror of
https://github.com/corda/corda.git
synced 2024-12-24 07:06:44 +00:00
Merge pull request #106 from corda/mike-thread-affinity-for-smm
Additional thread affinity for the StateMachineManager.
This commit is contained in:
commit
875efbfa11
@ -58,6 +58,7 @@ interface ServiceHub {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Will check [logicType] and [args] against a whitelist and if acceptable then construct and initiate the flow.
|
* Will check [logicType] and [args] against a whitelist and if acceptable then construct and initiate the flow.
|
||||||
|
* Note that you must be on the server thread to call this method.
|
||||||
*
|
*
|
||||||
* @throws IllegalFlowLogicException or IllegalArgumentException if there are problems with the [logicType] or [args].
|
* @throws IllegalFlowLogicException or IllegalArgumentException if there are problems with the [logicType] or [args].
|
||||||
*/
|
*/
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
package net.corda.flows
|
package net.corda.flows
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture
|
import com.google.common.util.concurrent.ListenableFuture
|
||||||
import net.corda.testing.BOC
|
|
||||||
import net.corda.testing.BOC_KEY
|
|
||||||
import net.corda.flows.IssuerFlow.IssuanceRequester
|
|
||||||
import net.corda.core.contracts.Amount
|
import net.corda.core.contracts.Amount
|
||||||
import net.corda.core.contracts.DOLLARS
|
import net.corda.core.contracts.DOLLARS
|
||||||
import net.corda.core.contracts.PartyAndReference
|
import net.corda.core.contracts.PartyAndReference
|
||||||
@ -14,10 +11,8 @@ import net.corda.core.serialization.OpaqueBytes
|
|||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
import net.corda.core.utilities.DUMMY_NOTARY
|
import net.corda.core.utilities.DUMMY_NOTARY
|
||||||
import net.corda.core.utilities.DUMMY_NOTARY_KEY
|
import net.corda.core.utilities.DUMMY_NOTARY_KEY
|
||||||
import net.corda.testing.MEGA_CORP
|
import net.corda.flows.IssuerFlow.IssuanceRequester
|
||||||
import net.corda.testing.MEGA_CORP_KEY
|
import net.corda.testing.*
|
||||||
import net.corda.testing.initiateSingleShotFlow
|
|
||||||
import net.corda.testing.ledger
|
|
||||||
import net.corda.testing.node.MockNetwork
|
import net.corda.testing.node.MockNetwork
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -62,7 +57,7 @@ class IssuerFlowTest {
|
|||||||
}.map { it.fsm }
|
}.map { it.fsm }
|
||||||
|
|
||||||
val issueRequest = IssuanceRequester(amount, issueToPartyAndRef.party, issueToPartyAndRef.reference, bankOfCordaNode.info.legalIdentity)
|
val issueRequest = IssuanceRequester(amount, issueToPartyAndRef.party, issueToPartyAndRef.reference, bankOfCordaNode.info.legalIdentity)
|
||||||
val issueRequestResultFuture = bankClientNode.smm.add(issueRequest).resultFuture
|
val issueRequestResultFuture = bankClientNode.services.startFlow(issueRequest).resultFuture
|
||||||
|
|
||||||
return IssuerFlowTest.RunResult(issuerFuture, issueRequestResultFuture)
|
return IssuerFlowTest.RunResult(issuerFuture, issueRequestResultFuture)
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import com.google.common.util.concurrent.ListenableFuture
|
|||||||
import com.google.common.util.concurrent.MoreExecutors
|
import com.google.common.util.concurrent.MoreExecutors
|
||||||
import com.google.common.util.concurrent.SettableFuture
|
import com.google.common.util.concurrent.SettableFuture
|
||||||
import net.corda.core.*
|
import net.corda.core.*
|
||||||
import net.corda.core.contracts.Amount
|
|
||||||
import net.corda.core.crypto.Party
|
import net.corda.core.crypto.Party
|
||||||
import net.corda.core.crypto.X509Utilities
|
import net.corda.core.crypto.X509Utilities
|
||||||
import net.corda.core.flows.FlowLogic
|
import net.corda.core.flows.FlowLogic
|
||||||
@ -17,12 +16,14 @@ import net.corda.core.messaging.SingleMessageRecipient
|
|||||||
import net.corda.core.node.*
|
import net.corda.core.node.*
|
||||||
import net.corda.core.node.services.*
|
import net.corda.core.node.services.*
|
||||||
import net.corda.core.node.services.NetworkMapCache.MapChange
|
import net.corda.core.node.services.NetworkMapCache.MapChange
|
||||||
import net.corda.core.serialization.OpaqueBytes
|
|
||||||
import net.corda.core.serialization.SingletonSerializeAsToken
|
import net.corda.core.serialization.SingletonSerializeAsToken
|
||||||
import net.corda.core.serialization.deserialize
|
import net.corda.core.serialization.deserialize
|
||||||
import net.corda.core.serialization.serialize
|
import net.corda.core.serialization.serialize
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
import net.corda.flows.*
|
import net.corda.flows.CashCommand
|
||||||
|
import net.corda.flows.CashFlow
|
||||||
|
import net.corda.flows.FinalityFlow
|
||||||
|
import net.corda.flows.sendRequest
|
||||||
import net.corda.node.api.APIServer
|
import net.corda.node.api.APIServer
|
||||||
import net.corda.node.services.api.*
|
import net.corda.node.services.api.*
|
||||||
import net.corda.node.services.config.NodeConfiguration
|
import net.corda.node.services.config.NodeConfiguration
|
||||||
@ -123,7 +124,9 @@ abstract class AbstractNode(open val configuration: NodeConfiguration, val netwo
|
|||||||
override val monitoringService: MonitoringService = MonitoringService(MetricRegistry())
|
override val monitoringService: MonitoringService = MonitoringService(MetricRegistry())
|
||||||
override val flowLogicRefFactory: FlowLogicRefFactory get() = flowLogicFactory
|
override val flowLogicRefFactory: FlowLogicRefFactory get() = flowLogicFactory
|
||||||
|
|
||||||
override fun <T> startFlow(logic: FlowLogic<T>): FlowStateMachine<T> = smm.add(logic)
|
override fun <T> startFlow(logic: FlowLogic<T>): FlowStateMachine<T> {
|
||||||
|
return serverThread.fetchFrom { smm.add(logic) }
|
||||||
|
}
|
||||||
|
|
||||||
override fun registerFlowInitiator(markerClass: KClass<*>, flowFactory: (Party) -> FlowLogic<*>) {
|
override fun registerFlowInitiator(markerClass: KClass<*>, flowFactory: (Party) -> FlowLogic<*>) {
|
||||||
require(markerClass !in flowFactories) { "${markerClass.java.name} has already been used to register a flow" }
|
require(markerClass !in flowFactories) { "${markerClass.java.name} has already been used to register a flow" }
|
||||||
|
@ -64,9 +64,7 @@ abstract class ServiceHubInternal : PluginServiceHub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: borrowing this method from service manager work in another branch. It's required to avoid circular dependency
|
* Starts an already constructed flow. Note that you must be on the server thread to call this method.
|
||||||
* between SMM and the scheduler. That particular problem should also be resolved by the service manager work
|
|
||||||
* itself, at which point this method would not be needed (by the scheduler).
|
|
||||||
*/
|
*/
|
||||||
abstract fun <T> startFlow(logic: FlowLogic<T>): FlowStateMachine<T>
|
abstract fun <T> startFlow(logic: FlowLogic<T>): FlowStateMachine<T>
|
||||||
|
|
||||||
|
@ -381,8 +381,11 @@ class StateMachineManager(val serviceHub: ServiceHubInternal,
|
|||||||
* Kicks off a brand new state machine of the given class.
|
* Kicks off a brand new state machine of the given class.
|
||||||
* The state machine will be persisted when it suspends, with automated restart if the StateMachineManager is
|
* The state machine will be persisted when it suspends, with automated restart if the StateMachineManager is
|
||||||
* restarted with checkpointed state machines in the storage service.
|
* restarted with checkpointed state machines in the storage service.
|
||||||
|
*
|
||||||
|
* Note that you must be on the [executor] thread.
|
||||||
*/
|
*/
|
||||||
fun <T> add(logic: FlowLogic<T>): FlowStateMachine<T> {
|
fun <T> add(logic: FlowLogic<T>): FlowStateMachine<T> {
|
||||||
|
executor.checkOnThread()
|
||||||
// We swap out the parent transaction context as using this frequently leads to a deadlock as we wait
|
// We swap out the parent transaction context as using this frequently leads to a deadlock as we wait
|
||||||
// on the flow completion future inside that context. The problem is that any progress checkpoints are
|
// on the flow completion future inside that context. The problem is that any progress checkpoints are
|
||||||
// unable to acquire the table lock and move forward till the calling transaction finishes.
|
// unable to acquire the table lock and move forward till the calling transaction finishes.
|
||||||
|
@ -59,7 +59,6 @@ import kotlin.test.assertTrue
|
|||||||
* We assume that Alice and Bob already found each other via some market, and have agreed the details already.
|
* We assume that Alice and Bob already found each other via some market, and have agreed the details already.
|
||||||
*/
|
*/
|
||||||
class TwoPartyTradeFlowTests {
|
class TwoPartyTradeFlowTests {
|
||||||
|
|
||||||
lateinit var net: MockNetwork
|
lateinit var net: MockNetwork
|
||||||
lateinit var notaryNode: MockNetwork.MockNode
|
lateinit var notaryNode: MockNetwork.MockNode
|
||||||
lateinit var aliceNode: MockNetwork.MockNode
|
lateinit var aliceNode: MockNetwork.MockNode
|
||||||
@ -418,7 +417,7 @@ class TwoPartyTradeFlowTests {
|
|||||||
Buyer(otherParty, notaryNode.info.notaryIdentity, 1000.DOLLARS, CommercialPaper.State::class.java)
|
Buyer(otherParty, notaryNode.info.notaryIdentity, 1000.DOLLARS, CommercialPaper.State::class.java)
|
||||||
}.map { it.fsm }
|
}.map { it.fsm }
|
||||||
val seller = Seller(bobNode.info.legalIdentity, notaryNode.info, assetToSell, 1000.DOLLARS, ALICE_KEY)
|
val seller = Seller(bobNode.info.legalIdentity, notaryNode.info, assetToSell, 1000.DOLLARS, ALICE_KEY)
|
||||||
val sellerResultFuture = aliceNode.smm.add(seller).resultFuture
|
val sellerResultFuture = aliceNode.services.startFlow(seller).resultFuture
|
||||||
return RunResult(buyerFuture, sellerResultFuture, seller.fsm.id)
|
return RunResult(buyerFuture, sellerResultFuture, seller.fsm.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +79,9 @@ open class MockServiceHubInternal(
|
|||||||
|
|
||||||
override fun recordTransactions(txs: Iterable<SignedTransaction>) = recordTransactionsInternal(txStorageService, txs)
|
override fun recordTransactions(txs: Iterable<SignedTransaction>) = recordTransactionsInternal(txStorageService, txs)
|
||||||
|
|
||||||
override fun <T> startFlow(logic: FlowLogic<T>): FlowStateMachine<T> = smm.add(logic)
|
override fun <T> startFlow(logic: FlowLogic<T>): FlowStateMachine<T> {
|
||||||
|
return smm.executor.fetchFrom { smm.add(logic) }
|
||||||
|
}
|
||||||
|
|
||||||
override fun registerFlowInitiator(markerClass: KClass<*>, flowFactory: (Party) -> FlowLogic<*>) {
|
override fun registerFlowInitiator(markerClass: KClass<*>, flowFactory: (Party) -> FlowLogic<*>) {
|
||||||
flowFactories[markerClass.java] = flowFactory
|
flowFactories[markerClass.java] = flowFactory
|
||||||
|
@ -38,7 +38,6 @@ import java.util.concurrent.TimeUnit
|
|||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class NodeSchedulerServiceTest : SingletonSerializeAsToken() {
|
class NodeSchedulerServiceTest : SingletonSerializeAsToken() {
|
||||||
|
|
||||||
val realClock: Clock = Clock.systemUTC()
|
val realClock: Clock = Clock.systemUTC()
|
||||||
val stoppedClock = Clock.fixed(realClock.instant(), realClock.zone)
|
val stoppedClock = Clock.fixed(realClock.instant(), realClock.zone)
|
||||||
val testClock = TestClock(stoppedClock)
|
val testClock = TestClock(stoppedClock)
|
||||||
|
@ -39,7 +39,6 @@ import kotlin.test.assertEquals
|
|||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class StateMachineManagerTests {
|
class StateMachineManagerTests {
|
||||||
|
|
||||||
private val net = MockNetwork(servicePeerAllocationStrategy = InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin())
|
private val net = MockNetwork(servicePeerAllocationStrategy = InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin())
|
||||||
private val sessionTransfers = ArrayList<SessionTransfer>()
|
private val sessionTransfers = ArrayList<SessionTransfer>()
|
||||||
private lateinit var node1: MockNode
|
private lateinit var node1: MockNode
|
||||||
@ -69,7 +68,7 @@ class StateMachineManagerTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `newly added flow is preserved on restart`() {
|
fun `newly added flow is preserved on restart`() {
|
||||||
node1.smm.add(NoOpFlow(nonTerminating = true))
|
node1.services.startFlow(NoOpFlow(nonTerminating = true))
|
||||||
node1.acceptableLiveFiberCountOnStop = 1
|
node1.acceptableLiveFiberCountOnStop = 1
|
||||||
val restoredFlow = node1.restartAndGetRestoredFlow<NoOpFlow>()
|
val restoredFlow = node1.restartAndGetRestoredFlow<NoOpFlow>()
|
||||||
assertThat(restoredFlow.flowStarted).isTrue()
|
assertThat(restoredFlow.flowStarted).isTrue()
|
||||||
@ -82,7 +81,7 @@ class StateMachineManagerTests {
|
|||||||
@Suspendable
|
@Suspendable
|
||||||
override fun call() = Unit
|
override fun call() = Unit
|
||||||
}
|
}
|
||||||
node1.smm.add(flow)
|
node1.services.startFlow(flow)
|
||||||
assertThat(flow.lazyTime).isNotNull()
|
assertThat(flow.lazyTime).isNotNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +89,7 @@ class StateMachineManagerTests {
|
|||||||
fun `flow restarted just after receiving payload`() {
|
fun `flow restarted just after receiving payload`() {
|
||||||
node2.services.registerFlowInitiator(SendFlow::class) { ReceiveThenSuspendFlow(it) }
|
node2.services.registerFlowInitiator(SendFlow::class) { ReceiveThenSuspendFlow(it) }
|
||||||
val payload = random63BitValue()
|
val payload = random63BitValue()
|
||||||
node1.smm.add(SendFlow(payload, node2.info.legalIdentity))
|
node1.services.startFlow(SendFlow(payload, node2.info.legalIdentity))
|
||||||
|
|
||||||
// We push through just enough messages to get only the payload sent
|
// We push through just enough messages to get only the payload sent
|
||||||
node2.pumpReceive()
|
node2.pumpReceive()
|
||||||
@ -106,7 +105,7 @@ class StateMachineManagerTests {
|
|||||||
fun `flow added before network map does run after init`() {
|
fun `flow added before network map does run after init`() {
|
||||||
val node3 = net.createNode(node1.info.address) //create vanilla node
|
val node3 = net.createNode(node1.info.address) //create vanilla node
|
||||||
val flow = NoOpFlow()
|
val flow = NoOpFlow()
|
||||||
node3.smm.add(flow)
|
node3.services.startFlow(flow)
|
||||||
assertEquals(false, flow.flowStarted) // Not started yet as no network activity has been allowed yet
|
assertEquals(false, flow.flowStarted) // Not started yet as no network activity has been allowed yet
|
||||||
net.runNetwork() // Allow network map messages to flow
|
net.runNetwork() // Allow network map messages to flow
|
||||||
assertEquals(true, flow.flowStarted) // Now we should have run the flow
|
assertEquals(true, flow.flowStarted) // Now we should have run the flow
|
||||||
@ -116,7 +115,7 @@ class StateMachineManagerTests {
|
|||||||
fun `flow added before network map will be init checkpointed`() {
|
fun `flow added before network map will be init checkpointed`() {
|
||||||
var node3 = net.createNode(node1.info.address) //create vanilla node
|
var node3 = net.createNode(node1.info.address) //create vanilla node
|
||||||
val flow = NoOpFlow()
|
val flow = NoOpFlow()
|
||||||
node3.smm.add(flow)
|
node3.services.startFlow(flow)
|
||||||
assertEquals(false, flow.flowStarted) // Not started yet as no network activity has been allowed yet
|
assertEquals(false, flow.flowStarted) // Not started yet as no network activity has been allowed yet
|
||||||
node3.disableDBCloseOnStop()
|
node3.disableDBCloseOnStop()
|
||||||
node3.stop()
|
node3.stop()
|
||||||
@ -141,7 +140,7 @@ class StateMachineManagerTests {
|
|||||||
fun `flow loaded from checkpoint will respond to messages from before start`() {
|
fun `flow loaded from checkpoint will respond to messages from before start`() {
|
||||||
val payload = random63BitValue()
|
val payload = random63BitValue()
|
||||||
node1.services.registerFlowInitiator(ReceiveThenSuspendFlow::class) { SendFlow(payload, it) }
|
node1.services.registerFlowInitiator(ReceiveThenSuspendFlow::class) { SendFlow(payload, it) }
|
||||||
node2.smm.add(ReceiveThenSuspendFlow(node1.info.legalIdentity)) // Prepare checkpointed receive flow
|
node2.services.startFlow(ReceiveThenSuspendFlow(node1.info.legalIdentity)) // Prepare checkpointed receive flow
|
||||||
// Make sure the add() has finished initial processing.
|
// Make sure the add() has finished initial processing.
|
||||||
node2.smm.executor.flush()
|
node2.smm.executor.flush()
|
||||||
node2.disableDBCloseOnStop()
|
node2.disableDBCloseOnStop()
|
||||||
@ -163,7 +162,7 @@ class StateMachineManagerTests {
|
|||||||
net.runNetwork()
|
net.runNetwork()
|
||||||
|
|
||||||
// Kick off first send and receive
|
// Kick off first send and receive
|
||||||
node2.smm.add(PingPongFlow(node3.info.legalIdentity, payload))
|
node2.services.startFlow(PingPongFlow(node3.info.legalIdentity, payload))
|
||||||
databaseTransaction(node2.database) {
|
databaseTransaction(node2.database) {
|
||||||
assertEquals(1, node2.checkpointStorage.checkpoints().size)
|
assertEquals(1, node2.checkpointStorage.checkpoints().size)
|
||||||
}
|
}
|
||||||
@ -207,7 +206,7 @@ class StateMachineManagerTests {
|
|||||||
node2.services.registerFlowInitiator(SendFlow::class) { ReceiveThenSuspendFlow(it) }
|
node2.services.registerFlowInitiator(SendFlow::class) { ReceiveThenSuspendFlow(it) }
|
||||||
node3.services.registerFlowInitiator(SendFlow::class) { ReceiveThenSuspendFlow(it) }
|
node3.services.registerFlowInitiator(SendFlow::class) { ReceiveThenSuspendFlow(it) }
|
||||||
val payload = random63BitValue()
|
val payload = random63BitValue()
|
||||||
node1.smm.add(SendFlow(payload, node2.info.legalIdentity, node3.info.legalIdentity))
|
node1.services.startFlow(SendFlow(payload, node2.info.legalIdentity, node3.info.legalIdentity))
|
||||||
net.runNetwork()
|
net.runNetwork()
|
||||||
val node2Flow = node2.getSingleFlow<ReceiveThenSuspendFlow>().first
|
val node2Flow = node2.getSingleFlow<ReceiveThenSuspendFlow>().first
|
||||||
val node3Flow = node3.getSingleFlow<ReceiveThenSuspendFlow>().first
|
val node3Flow = node3.getSingleFlow<ReceiveThenSuspendFlow>().first
|
||||||
@ -241,7 +240,7 @@ class StateMachineManagerTests {
|
|||||||
node2.services.registerFlowInitiator(ReceiveThenSuspendFlow::class) { SendFlow(node2Payload, it) }
|
node2.services.registerFlowInitiator(ReceiveThenSuspendFlow::class) { SendFlow(node2Payload, it) }
|
||||||
node3.services.registerFlowInitiator(ReceiveThenSuspendFlow::class) { SendFlow(node3Payload, it) }
|
node3.services.registerFlowInitiator(ReceiveThenSuspendFlow::class) { SendFlow(node3Payload, it) }
|
||||||
val multiReceiveFlow = ReceiveThenSuspendFlow(node2.info.legalIdentity, node3.info.legalIdentity)
|
val multiReceiveFlow = ReceiveThenSuspendFlow(node2.info.legalIdentity, node3.info.legalIdentity)
|
||||||
node1.smm.add(multiReceiveFlow)
|
node1.services.startFlow(multiReceiveFlow)
|
||||||
node1.acceptableLiveFiberCountOnStop = 1
|
node1.acceptableLiveFiberCountOnStop = 1
|
||||||
net.runNetwork()
|
net.runNetwork()
|
||||||
assertThat(multiReceiveFlow.receivedPayloads[0]).isEqualTo(node2Payload)
|
assertThat(multiReceiveFlow.receivedPayloads[0]).isEqualTo(node2Payload)
|
||||||
@ -265,7 +264,7 @@ class StateMachineManagerTests {
|
|||||||
@Test
|
@Test
|
||||||
fun `both sides do a send as their first IO request`() {
|
fun `both sides do a send as their first IO request`() {
|
||||||
node2.services.registerFlowInitiator(PingPongFlow::class) { PingPongFlow(it, 20L) }
|
node2.services.registerFlowInitiator(PingPongFlow::class) { PingPongFlow(it, 20L) }
|
||||||
node1.smm.add(PingPongFlow(node2.info.legalIdentity, 10L))
|
node1.services.startFlow(PingPongFlow(node2.info.legalIdentity, 10L))
|
||||||
net.runNetwork()
|
net.runNetwork()
|
||||||
|
|
||||||
assertSessionTransfers(
|
assertSessionTransfers(
|
||||||
@ -332,7 +331,7 @@ class StateMachineManagerTests {
|
|||||||
@Test
|
@Test
|
||||||
fun `exception thrown on other side`() {
|
fun `exception thrown on other side`() {
|
||||||
node2.services.registerFlowInitiator(ReceiveThenSuspendFlow::class) { ExceptionFlow }
|
node2.services.registerFlowInitiator(ReceiveThenSuspendFlow::class) { ExceptionFlow }
|
||||||
val future = node1.smm.add(ReceiveThenSuspendFlow(node2.info.legalIdentity)).resultFuture
|
val future = node1.services.startFlow(ReceiveThenSuspendFlow(node2.info.legalIdentity)).resultFuture
|
||||||
net.runNetwork()
|
net.runNetwork()
|
||||||
assertThatThrownBy { future.getOrThrow() }.isInstanceOf(FlowSessionException::class.java)
|
assertThatThrownBy { future.getOrThrow() }.isInstanceOf(FlowSessionException::class.java)
|
||||||
assertSessionTransfers(
|
assertSessionTransfers(
|
||||||
@ -413,7 +412,6 @@ class StateMachineManagerTests {
|
|||||||
|
|
||||||
|
|
||||||
private class NoOpFlow(val nonTerminating: Boolean = false) : FlowLogic<Unit>() {
|
private class NoOpFlow(val nonTerminating: Boolean = false) : FlowLogic<Unit>() {
|
||||||
|
|
||||||
@Transient var flowStarted = false
|
@Transient var flowStarted = false
|
||||||
|
|
||||||
@Suspendable
|
@Suspendable
|
||||||
@ -427,7 +425,6 @@ class StateMachineManagerTests {
|
|||||||
|
|
||||||
|
|
||||||
private class SendFlow(val payload: Any, vararg val otherParties: Party) : FlowLogic<Unit>() {
|
private class SendFlow(val payload: Any, vararg val otherParties: Party) : FlowLogic<Unit>() {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
require(otherParties.isNotEmpty())
|
require(otherParties.isNotEmpty())
|
||||||
}
|
}
|
||||||
@ -438,7 +435,6 @@ class StateMachineManagerTests {
|
|||||||
|
|
||||||
|
|
||||||
private class ReceiveThenSuspendFlow(vararg val otherParties: Party) : FlowLogic<Unit>() {
|
private class ReceiveThenSuspendFlow(vararg val otherParties: Party) : FlowLogic<Unit>() {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
require(otherParties.isNotEmpty())
|
require(otherParties.isNotEmpty())
|
||||||
}
|
}
|
||||||
@ -453,7 +449,6 @@ class StateMachineManagerTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class PingPongFlow(val otherParty: Party, val payload: Long) : FlowLogic<Unit>() {
|
private class PingPongFlow(val otherParty: Party, val payload: Long) : FlowLogic<Unit>() {
|
||||||
|
|
||||||
@Transient var receivedPayload: Long? = null
|
@Transient var receivedPayload: Long? = null
|
||||||
@Transient var receivedPayload2: Long? = null
|
@Transient var receivedPayload2: Long? = null
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user