Awesome-omni-skill this-sample-workflow-execute-3-steps-in-sequence
Apply for this-sample-workflow-execute-3-steps-in-sequence. --- description: globs:
install
source · Clone the upstream repo
git clone https://github.com/diegosouzapw/awesome-omni-skill
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/fullstack-web/this-sample-workflow-execute-3-steps-in-sequence" ~/.claude/skills/diegosouzapw-awesome-omni-skill-this-sample-workflow-execute-3-steps-in-sequence && rm -rf "$T"
manifest:
skills/fullstack-web/this-sample-workflow-execute-3-steps-in-sequence/SKILL.mdsource content
This sample workflow execute 3 steps in sequence.
description: globs: alwaysApply: false
This file provides rules and context for generating or understanding Go code related to a custom Domain Specific Language (DSL) for defining Temporal workflows within this project.
DSL Overview:
This project uses a specific Go-based DSL to define Temporal workflows declaratively. The core idea is to represent workflow logic using nested structures rather than imperative Go code directly within the workflow function.
Core DSL Structures (Defined in
package):dsl
: The top-level structure representing the entire workflow definition.Workflow
: Initial variables available to the workflow. These act as the initial state or input.Variables map[string]string
: The starting point of the workflow logic (can be a single activity, a sequence, or parallel steps).Root Statement
: A building block representing a single step or a composite structure. AStatement
can contain one of the following:Statement
: Represents a call to a Temporal Activity.Activity *ActivityInvocation
: Represents a series of statements executed sequentially.Sequence *Sequence
: Represents a set of statements executed in parallel.Parallel *Parallel
: Contains a sliceSequence
which are executed one after another.Elements []*Statement
: Contains a sliceParallel
which are executed concurrently. The parallel execution waits for all branches to complete. If one branch errors, others are cancelled.Branches []*Statement
: Defines how to invoke a specific Temporal Activity.ActivityInvocation
: The registered name of the Temporal Activity to call.Name string
: A list of variable names (keys from theArguments []string
map) whose values should be passed as arguments to the activity.bindings
: The name of the variable (key in theResult string
map) where the activity's result should be stored.bindings
Execution Flow (
):SimpleDSLWorkflow
- The entry point for workflows defined using this DSL is the
function:SimpleDSLWorkflow
.func SimpleDSLWorkflow(ctx workflow.Context, dslWorkflow Workflow) ([]byte, error) - It initializes a
map from thebindings
.dslWorkflow.Variables - It sets default
(e.g.,workflow.ActivityOptions
).StartToCloseTimeout - It uses
for logging.workflow.GetLogger(ctx) - It recursively calls the
method on theexecute
statement, passing theRoot
andctx
map.bindings
Data Flow (
):bindings
- The
acts as the shared state or memory for the workflow execution.bindings map[string]string - Initial values come from
.Workflow.Variables
specifies which values fromActivityInvocation.Arguments
to use as input for an activity.bindings
specifies the key inActivityInvocation.Result
where the activity's return value should be stored.bindings- The
helper function retrieves argument values from themakeInput
map based on the names listed inbindings
.ActivityInvocation.Arguments
Concurrency (
execution):Parallel
- The
method usesParallel.execute
to launch each branch concurrently.workflow.Go - It uses
andworkflow.NewSelector
to wait for branches to complete.Future.Get
is used to cancel pending branches if one branch encounters an error.workflow.WithCancel
Working with the DSL:
- When asked to create or modify workflows, structure the logic using the
,Workflow
,Statement
,Sequence
, andParallel
types.ActivityInvocation - Define the flow of execution by nesting
andSequence
structures withinParallel
s.Statement - Specify activity calls using
, ensuringActivityInvocation
,Name
, andArguments
are correctly defined based on the available activities and the desired data flow through theResult
map.bindings - Remember that the actual activity implementation exists separately (see
) and is invoked by name.activities.mdc
package dsl import ( "time" "go.temporal.io/sdk/workflow" ) type ( // Workflow is the type used to express the workflow definition. Variables are a map of valuables. Variables can be // used as input to Activity. Workflow struct { Variables map[string]string Root Statement } // Statement is the building block of dsl workflow. A Statement can be a simple ActivityInvocation or it // could be a Sequence or Parallel. Statement struct { Activity *ActivityInvocation Sequence *Sequence Parallel *Parallel } // Sequence consist of a collection of Statements that runs in sequential. Sequence struct { Elements []*Statement } // Parallel can be a collection of Statements that runs in parallel. Parallel struct { Branches []*Statement } // ActivityInvocation is used to express invoking an Activity. The Arguments defined expected arguments as input to // the Activity, the result specify the name of variable that it will store the result as which can then be used as // arguments to subsequent ActivityInvocation. ActivityInvocation struct { Name string Arguments []string Result string } executable interface { execute(ctx workflow.Context, bindings map[string]string) error } ) // SimpleDSLWorkflow workflow definition func SimpleDSLWorkflow(ctx workflow.Context, dslWorkflow Workflow) ([]byte, error) { bindings := make(map[string]string) //workflowcheck:ignore Only iterates for building another map for k, v := range dslWorkflow.Variables { bindings[k] = v } ao := workflow.ActivityOptions{ StartToCloseTimeout: 10 * time.Second, } ctx = workflow.WithActivityOptions(ctx, ao) logger := workflow.GetLogger(ctx) err := dslWorkflow.Root.execute(ctx, bindings) if err != nil { logger.Error("DSL Workflow failed.", "Error", err) return nil, err } logger.Info("DSL Workflow completed.") return nil, err } func (b *Statement) execute(ctx workflow.Context, bindings map[string]string) error { if b.Parallel != nil { err := b.Parallel.execute(ctx, bindings) if err != nil { return err } } if b.Sequence != nil { err := b.Sequence.execute(ctx, bindings) if err != nil { return err } } if b.Activity != nil { err := b.Activity.execute(ctx, bindings) if err != nil { return err } } return nil } func (a ActivityInvocation) execute(ctx workflow.Context, bindings map[string]string) error { inputParam := makeInput(a.Arguments, bindings) var result string err := workflow.ExecuteActivity(ctx, a.Name, inputParam).Get(ctx, &result) if err != nil { return err } if a.Result != "" { bindings[a.Result] = result } return nil } func (s Sequence) execute(ctx workflow.Context, bindings map[string]string) error { for _, a := range s.Elements { err := a.execute(ctx, bindings) if err != nil { return err } } return nil } func (p Parallel) execute(ctx workflow.Context, bindings map[string]string) error { // // You can use the context passed in to activity as a way to cancel the activity like standard GO way. // Cancelling a parent context will cancel all the derived contexts as well. // // In the parallel block, we want to execute all of them in parallel and wait for all of them. // if one activity fails then we want to cancel all the rest of them as well. childCtx, cancelHandler := workflow.WithCancel(ctx) selector := workflow.NewSelector(ctx) var activityErr error for _, s := range p.Branches { f := executeAsync(s, childCtx, bindings) selector.AddFuture(f, func(f workflow.Future) { err := f.Get(ctx, nil) if err != nil { // cancel all pending activities cancelHandler() activityErr = err } }) } for i := 0; i < len(p.Branches); i++ { selector.Select(ctx) // this will wait for one branch if activityErr != nil { return activityErr } } return nil } func executeAsync(exe executable, ctx workflow.Context, bindings map[string]string) workflow.Future { future, settable := workflow.NewFuture(ctx) workflow.Go(ctx, func(ctx workflow.Context) { err := exe.execute(ctx, bindings) settable.Set(nil, err) }) return future } func makeInput(argNames []string, argsMap map[string]string) []string { var args []string for _, arg := range argNames { args = append(args, argsMap[arg]) } return args }
Example Workflows:
Here are some example workflow implementations:
- Serial workflow:
# This sample workflow execute 3 steps in sequence. # 1) sampleActivity1, takes arg1 as input, and put result as result1. # 2) sampleActivity2, takes result1 as input, and put result as result2. # 3) sampleActivity3, takes args2 and result2 as input, and put result as result3. variables: arg1: value1 arg2: value2 root: sequence: elements: - activity: name: SampleActivity1 arguments: - arg1 result: result1 - activity: name: SampleActivity2 arguments: - result1 result: result2 - activity: name: SampleActivity3 arguments: - arg2 - result2 result: result3
- Parallel workflow:
# This sample workflow execute 3 steps in sequence. # 1) activity1, takes arg1 as input, and put result as result1. # 2) it runs a parallel block which runs below sequence branches in parallel # 2.1) sequence 1 # 2.1.1) activity2, takes result1 as input, and put result as result2 # 2.1.2) activity3, takes arg2 and result2 as input, and put result as result3 # 2.2) sequence 2 # 2.2.1) activity4, takes result1 as input, and put result as result4 # 2.2.2) activity5, takes arg3 and result4 as input, and put result as result5 # 3) activity1, takes result3 and result5 as input, and put result as result6. variables: arg1: value1 arg2: value2 arg3: value3 root: sequence: elements: - activity: name: SampleActivity1 arguments: - arg1 result: result1 - parallel: branches: - sequence: elements: - activity: name: SampleActivity2 arguments: - result1 result: result2 - activity: name: SampleActivity3 arguments: - arg2 - result2 result: result3 - sequence: elements: - activity: name: SampleActivity4 arguments: - result1 result: result4 - activity: name: SampleActivity5 arguments: - arg3 - result4 result: result5 - activity: name: SampleActivity1 arguments: - result3 - result5 result: result6