build_step.go (24 lines of code) (raw):

package flow // StepBuilder allows to build the internal Steps when adding into Workflow. // // type StepImpl struct {} // func (s *StepImpl) Unwrap() []flow.Steper { return /* internal steps */ } // func (s *StepImpl) Do(ctx context.Context) error { /* ... */ } // func (s *StepImpl) BuildStep() { /* build internal steps */ } // // workflow.Add( // flow.Step(new(StepImpl)), // here will call StepImpl.BuildStep() once implicitly // ) type StepBuilder struct{ built Set[Steper] } // BuildStep calls BuildStep() method of the Steper if it's implemented, // and ensure it's called only once for each Steper. func (sb *StepBuilder) BuildStep(s Steper) { if sb.built == nil { sb.built = make(Set[Steper]) } Traverse(s, func(s Steper, walked []Steper) TraverseDecision { if sb.built.Has(s) { return TraverseEndBranch // already built } if _, ok := s.(interface{ BuildStep(Steper) }); ok { return TraverseEndBranch // it's a sub-workflow, let it manage its own steps } if b, ok := s.(interface{ BuildStep() }); ok { if r, ok := s.(interface{ Reset() }); ok { r.Reset() // reset the step before building } b.BuildStep() sb.built.Add(s) return TraverseEndBranch // not necessary to go deeper } return TraverseContinue }) }