问题
Is it possible to initiate a flow session from a flow that is annoted with InitiatedBy to a flow which is also annoted with InitiatedBy?
For example:
@InitiatingFlow
Class FlowA
@InitiatedBy(FlowA.class)
Class FlowB
@InitiatedBy(FlowB.class)
Class FlowC
is it possible to achieve sequence of flow session like: A->B->C ?
回答1:
Yes, this is possible, as follows:
@InitiatingFlow
@StartableByRPC
class Initiator(val firstCounterparty: Party, val secondCounterparty: Party) : FlowLogic<Int>() {
override val progressTracker = ProgressTracker()
@Suspendable
override fun call(): Int {
val flowSession = initiateFlow(firstCounterparty)
flowSession.send(secondCounterparty)
return flowSession.receive<Int>().unwrap { it }
}
}
@InitiatingFlow
@InitiatedBy(Initiator::class)
class Responder(val flowSession: FlowSession) : FlowLogic<Unit>() {
@Suspendable
override fun call() {
val secondCounterparty = flowSession.receive<Party>().unwrap { it }
val newFlowSession = initiateFlow(secondCounterparty)
val int = newFlowSession.receive<Int>().unwrap { it }
flowSession.send(int)
}
}
@InitiatingFlow
@InitiatedBy(Responder::class)
class ResponderResponder(val flowSession: FlowSession) : FlowLogic<Unit>() {
@Suspendable
override fun call() {
flowSession.send(3)
}
}
However, there is one major caveat. In Corda 3.x, you can't have two FlowSession
s with the same counterparty in the same flow. So either you need to disallow the case where A -> B -> A, as follows:
@InitiatingFlow
@StartableByRPC
class Initiator(val firstCounterparty: Party, val secondCounterparty: Party) : FlowLogic<Int>() {
override val progressTracker = ProgressTracker()
@Suspendable
override fun call(): Int {
if (secondCounterparty == ourIdentity) {
throw FlowException("In Corda 3.x, you can't have two flow sessions with the same party.")
}
val flowSession = initiateFlow(firstCounterparty)
flowSession.send(secondCounterparty)
return flowSession.receive<Int>().unwrap { it }
}
}
@InitiatingFlow
@InitiatedBy(Initiator::class)
class Responder(val flowSession: FlowSession) : FlowLogic<Unit>() {
@Suspendable
override fun call() {
val secondCounterparty = flowSession.receive<Party>().unwrap { it }
if (secondCounterparty == flowSession.counterparty) {
throw FlowException("In Corda 3.x, you can't have two flow sessions with the same party.")
}
val newFlowSession = initiateFlow(secondCounterparty)
val int = newFlowSession.receive<Int>().unwrap { it }
flowSession.send(int)
}
}
@InitiatingFlow
@InitiatedBy(Responder::class)
class ResponderResponder(val flowSession: FlowSession) : FlowLogic<Unit>() {
@Suspendable
override fun call() {
flowSession.send(3)
}
}
Or you need to drop into an InitiatingFlow
subflow in Responder
before starting the flow that starts ResponderResponder
, as follows:
@InitiatingFlow
@StartableByRPC
class Initiator(val firstCounterparty: Party, val secondCounterparty: Party) : FlowLogic<Int>() {
override val progressTracker = ProgressTracker()
@Suspendable
override fun call(): Int {
val flowSession = initiateFlow(firstCounterparty)
flowSession.send(secondCounterparty)
return flowSession.receive<Int>().unwrap { it }
}
}
@InitiatingFlow
@InitiatedBy(Initiator::class)
class Responder(val flowSession: FlowSession) : FlowLogic<Unit>() {
@Suspendable
override fun call() {
val secondCounterparty = flowSession.receive<Party>().unwrap { it }
val int = subFlow(ResponderInitiator(secondCounterparty))
flowSession.send(int)
}
}
@InitiatingFlow
class ResponderInitiator(val counterparty: Party) : FlowLogic<Int>() {
@Suspendable
override fun call(): Int {
val flowSession = initiateFlow(counterparty)
return flowSession.receive<Int>().unwrap { it }
}
}
@InitiatingFlow
@InitiatedBy(ResponderInitiator::class)
class ResponderResponder(val flowSession: FlowSession) : FlowLogic<Unit>() {
@Suspendable
override fun call() {
flowSession.send(3)
}
}
来源:https://stackoverflow.com/questions/53447038/initiating-a-flow-session-from-a-flow-that-is-annoted-with-initiatedby-to-a-flow