643
mutableState historyi.MutableState,
644
minVersionedTransition *persistencespb.VersionedTransition,
646
>
647
>
// NOTE: Not all callers of TaskRefresher goes through the closeTransaction process.
648
>
// If we were to regenerate tasks here by doing a state machine transition and return
649
>
// a TransitionOutput, then, we need to
650
>
// 1. Call taskGenerator.GenerateDirtySubStateMachineTasks explictly to make sure
651
>
// tasks are added to mutable state.
652
>
// 2. Make GenerateDirtySubStateMachineTasks idempotent, so that if the logic
653
>
// does go through closeTransaction, no duplicate tasks are generated.
654
>
// 3. Explicitly clear transition state for sub state machines when not going through
655
>
// closeTransaction path.
656
>
// 4. Sub state machine will be marked as dirty, causing task refresh being counted
657
>
// as a state transition. (if the logic does go through closeTransaction path,
658
>
// though we don't actually have such cases today)
659
>
// With the implementation below, we avoid the above complexities by directly generating
660
>
// tasks and adding them to mutable state immediately.
661
>
662
>
// Task refresher is only meant for regenerating tasks that has been generated before,
663
>
// in previous state transitions, so we can just call generateSubStateMachineTask
664
>
// which uses the last versioned transition.
665
>
// In replication case, task refresher should be called after applying the state from source
666
>
// cluster, which updated the transition history.
667
>
668
>
var nodesToRefresh []*hsm.Node
669
>
if err := mutableState.HSM().Walk(func(node *hsm.Node) error {
670
>
if node.Parent == nil {
671
>
// root node is mutable state and can't be refreshed
672
>
return nil
673
>
}
674
675
// Skip task generation if this state machine node has not been updated since minVersionedTransition.