karts
karts

Reputation: 171

what is the correct way to implement schedulable state in corda

I am using schedulable state and my state has the below method,

override fun nextScheduledActivity(thisStateRef: StateRef, flowLogicRefFactory: FlowLogicRefFactory): ScheduledActivity? {

  System.out.println("inside scheduled activity " )
    val scheduledAt = Instant.now().plusSeconds(10)
    val logicRef = flowLogicRefFactory.create(SFlow::class.java, thisStateRef)
    var toReturn: ScheduledActivity? = ScheduledActivity(logicRef, scheduledAt)

    return toReturn
}

And my SFLow is marked with @IntitiatingFLow, @SchedulableFlow. But i do not get this flow running. Every 10 seconds i see this print statement "inside scheduled activity ". Not sure what is wrong here...

Upvotes: 1

Views: 381

Answers (1)

Joel
Joel

Reputation: 23140

The node has a ScheduledActivityObserver that subscribes to the feed of new states added to the vault. Whenever a new state is added to the vault:

  • The observer checks if the state is a SchedulableState
  • If the state is a SchedulableState, the observer calls nextScheduledActivity to establish at what future point in time to run the scheduled activity, and adds the scheduled activity to its schedule
  • Once this future point in time is reached, the observer calls nextScheduledActivity again to retrieve the scheduled activity and the point in time when the scheduled activity is supposed to occur

    • If the point in time is in the past, the observer runs the scheduled activity
    • If the point in time is now in the future, the observer considers the scheduled activity to have been rescheduled and reschedules it for that future point in time

In your case, nextScheduledActivity finds the point in time for the scheduled activity by calling Instant.now().plusSeconds(10). Since this expression is re-evaulated every time you call nextScheduledActivity, the observer will always consider this activity to have been rescheduled to ten seconds in the future, and never run it.

Instead, you need to evaluate the point in time to run the scheduled activity once and for all at state creation time. For example:

class HeartState(
        private val me: Party,
        private val nextActivityTime: Instant = Instant.now().plusSeconds(1)
) : SchedulableState {

    override val participants get() = listOf(me)

    override fun nextScheduledActivity(thisStateRef: StateRef, flowLogicRefFactory: FlowLogicRefFactory): ScheduledActivity? {
        val flowLogicRef = flowLogicRefFactory.create(HeartbeatFlow::class.java, thisStateRef)
        ScheduledActivity(flowLogicRef, nextActivityTime)
    }
}

Upvotes: 2

Related Questions