Saiprasad
Saiprasad

Reputation: 11

Automatically trigger a flow when state attribute changes at the counterparty

I have party A which has created one transaction and added a participant Party B. The state created in the transaction is shared with Party B. There are state properties like FirstName, LastName and Status. Party B changes the status to green and then the transaction is completed and recorded to vault of Party B and Party A.

The same process is followed between Party A and Party C. The same process is followed between Party A and Party D.

           ------Party B
         /
Party A /-------Party C
        \
         \------Party D

I have a use case wherein Party B, Party C, Party D can change the status in the state to Green. As soon as all the status becomes green, i want to initiate a flow at Party A.

What is the best way to implement this in Corda?

Upvotes: 1

Views: 387

Answers (1)

Joel
Joel

Reputation: 23210

There are two ways to do this:

Using a Corda service:

A service is a long-lived object in the node that is created when the node is initialised and allows state and functionality to be shared across flows.

We could define our service as follows. It will increment a counter whenever a flag is raised, and trigger a flow once the flag has been raised three times:

@CordaService
class FlagService(private val services: AppServiceHub) : SingletonSerializeAsToken() {
    var flagCount = 0

    fun incrementFlagCount() {
        flagCount++

        if (flagCount == 3) {
            val flagsRaisedFlow = FlagsRaised()
            services.startFlow(flagsRaisedFlow)
        }
    }
}

This flow that the service will start once the flag has been raised three times is as follows:

@InitiatingFlow
@StartableByService
class FlagsRaised : FlowLogic<Unit>() {
    @Suspendable
    override fun call() {
        logger.info("FlagsRaised flow called.")
        // TODO: Flow activity after all flags are raised.
    }
}

Parties B, C and D raise a flag using the following flow:

@InitiatingFlow
@StartableByRPC
class Initiator(val counterparty: Party) : FlowLogic<Unit>() {
    @Suspendable
    override fun call() {
        // TODO: Other flow activity before flag is raised.
        val session = initiateFlow(counterparty)
        session.send(true)
    }
}

Party A responds by invoking the following flow, which retrieves the FlagService and calls incrementFlagCount:

@InitiatedBy(Initiator::class)
class Responder(val counterpartySession: FlowSession) : FlowLogic<Unit>() {
    @Suspendable
    override fun call() {
        counterpartySession.receive<Boolean>()
        val flagService = serviceHub.cordaService(FlagService::class.java)
        flagService.incrementFlagCount()
    }
}

By checking at the end of each flow:

We could also simply check after each flag is raised whether all three flags have been raised. If they have, we start a subflow:

@InitiatingFlow
@StartableByRPC
class Initiator(val counterparty: Party) : FlowLogic<Unit>() {
    @Suspendable
    override fun call() {
        // TODO: Other flow activity before flag is raised.
        val session = initiateFlow(counterparty)
        session.send(true)
    }
}

@InitiatedBy(Initiator::class)
class Responder(val counterpartySession: FlowSession) : FlowLogic<Unit>() {
    @Suspendable
    override fun call() {
        counterpartySession.receive<Boolean>()
        val allFlagsRaised =
                TODO("Check (e.g. using the vault) whether all three flags have been raised.")
        if (allFlagsRaised) {
            subFlow(FlagsRaised())
        }
    }
}

Upvotes: 2

Related Questions