### Start Workflow Execution (Go) Source: https://github.com/sicko7947/workflow-go/blob/main/PROJECT_INDEX.md Provides an example of initiating the execution of a defined workflow. This function takes a context, the workflow definition, and initial input to start the process. ```Go engine.StartWorkflow(ctx, wf, input) ``` -------------------------------- ### Run Simple Math and Conditional Workflows in Go Source: https://github.com/sicko7947/workflow-go/blob/main/example/README.md Demonstrates how to import and run the Simple Math and Conditional workflows using the Workflow-Go engine. It shows the creation of the engine, workflow definitions, input data, and starting workflow executions with context. ```go import ( "context" "github.com/sicko7947/workflow-go/engine" "github.com/sicko7947/workflow-go/store" "github.com/sicko7947/workflow-go/example/simple_math" "github.com/sicko7947/workflow-go/example/conditional" ) func main() { // Create engine (uses defaults: stdout logger, DefaultEngineConfig) eng := engine.NewEngine(store.NewMemoryStore()) // Run simple math workflow mathWf, _ := simple_math.NewSimpleMathWorkflow() mathInput := simple_math.WorkflowInput{Val1: 10, Val2: 5, Mult: 2} runID1, _ := eng.StartWorkflow(context.Background(), mathWf, mathInput) // Run conditional workflow condWf, _ := conditional.NewConditionalWorkflow() condInput := conditional.ConditionalInput{ Value: 10, EnableDoubling: true, EnableFormatting: true, } runID2, _ := eng.StartWorkflow(context.Background(), condWf, condInput) } ``` -------------------------------- ### Start Conditional Workflow Examples (Go) Source: https://github.com/sicko7947/workflow-go/blob/main/example/conditional/README.md Initiates the conditional workflow with different input flags to demonstrate various execution paths. It shows how to enable or skip doubling and formatting steps based on boolean inputs. ```go import ( "context" "github.com/sicko7947/workflow-go/engine" "github.com/sicko7947/workflow-go/store" "github.com/sicko7947/workflow-go/example/conditional" ) func main() { // Create engine eng := engine.NewEngine(store.NewMemoryStore()) // Create conditional workflow wf, _ := conditional.NewConditionalWorkflow() // Example 1: Enable both steps input1 := conditional.ConditionalInput{ Value: 10, EnableDoubling: true, EnableFormatting: true, } runID1, _ := eng.StartWorkflow(context.Background(), wf, input1) // Result: Value doubled to 20, formatted output // Example 2: Skip doubling input2 := conditional.ConditionalInput{ Value: 10, EnableDoubling: false, // Step skipped! EnableFormatting: true, } runID2, _ := eng.StartWorkflow(context.Background(), wf, input2) // Result: Default output used, formatted // Example 3: Skip both conditional steps input3 := conditional.ConditionalInput{ Value: 10, EnableDoubling: false, EnableFormatting: false, } runID3, _ := eng.StartWorkflow(context.Background(), wf, input3) // Result: Both steps skipped, default values used } ``` -------------------------------- ### Simple Math Workflow Example Structure Source: https://github.com/sicko7947/workflow-go/blob/main/example/README.md Illustrates the typical file structure for a Workflow-Go example, including input/output types, step implementations, workflow definition, and an orchestrator. ```bash example/ ├── / │ ├── README.md # Detailed documentation │ ├── types.go # Input/output type definitions │ ├── steps.go # Step implementations │ ├── workflow.go # Workflow builder function │ └── orchestrator.go # Workflow orchestrator (encapsulates engine + workflow) └── README.md # This file - examples overview ``` -------------------------------- ### Use Orchestrator for Structured Workflow Execution Source: https://github.com/sicko7947/workflow-go/blob/main/example/simple_math/README.md Illustrates how to use the workflow-go orchestrator for a more structured workflow management. It shows creating an orchestrator with a logger and store, starting a workflow, retrieving its status, and canceling it. ```go import ( "context" "github.com/rs/zerolog" "github.com/sicko7947/workflow-go/engine" "github.com/sicko7947/workflow-go/store" "github.com/sicko7947/workflow-go/example/simple_math" ) func main() { logger := zerolog.New(os.Stdout).With().Timestamp().Logger() store := store.NewMemoryStore() // Create orchestrator (encapsulates workflow + engine) orch, _ := simple_math.NewOrchestrator( store, logger, engine.DefaultEngineConfig, ) // Start workflow input := simple_math.WorkflowInput{Val1: 10, Val2: 5, Mult: 2} runID, _ := orch.StartWorkflow(context.Background(), input) // Get status status, _ := orch.GetWorkflowStatus(context.Background(), runID) fmt.Printf("Status: %s, Output: %+v\n", status.Status, status.Output) // Cancel if needed _ = orch.CancelWorkflow(context.Background(), runID) } ``` -------------------------------- ### Execute Conditional Workflow Example Source: https://context7.com/sicko7947/workflow-go/llms.txt Demonstrates the execution of a conditional workflow. It initializes a memory store and an engine, starts a workflow with specific inputs (enabling doubling but disabling formatting), and then retrieves and prints the workflow's status. The output indicates that the 'Double' step was executed while the 'Format' step was skipped due to the input conditions. ```go package main import ( "context" "fmt" "github.com/sicko7947/workflow-go/engine" "github.com/sicko7947/workflow-go/store" ) // Assuming NewConditionalWorkflow and ConditionalInput are defined elsewhere in the project // func NewConditionalWorkflow() (*workflow.Workflow, error) // type ConditionalInput struct { // Value int // EnableDoubling bool // EnableFormatting bool // } // Example execution func ExecuteConditionalWorkflow() { store := store.NewMemoryStore() eng := engine.NewEngine(store) wf, _ := NewConditionalWorkflow() // Placeholder for actual workflow creation // Test with doubling enabled, formatting disabled runID, _ := eng.StartWorkflow( context.Background(), wf, ConditionalInput{ Value: 10, EnableDoubling: true, EnableFormatting: false, }, ) run, _ := eng.GetRun(context.Background(), runID) fmt.Printf("Workflow Status: %s\n", run.Status) // Output: Workflow Status: COMPLETED // Note: Double step executed, format step skipped } ``` -------------------------------- ### Execute Simple Math Workflow using Engine Source: https://github.com/sicko7947/workflow-go/blob/main/example/simple_math/README.md Demonstrates how to create an engine, define a simple math workflow, and execute it with specific input values. It shows the basic usage of the workflow engine for sequential step execution and data passing. ```go import ( "context" "github.com/sicko7947/workflow-go/engine" "github.com/sicko7947/workflow-go/store" "github.com/sicko7947/workflow-go/example/simple_math" ) func main() { // Create engine with default logger and config eng := engine.NewEngine(store.NewMemoryStore()) // Create workflow wf, _ := simple_math.NewSimpleMathWorkflow() // Execute input := simple_math.WorkflowInput{ Val1: 10, Val2: 5, Mult: 2, } runID, _ := eng.StartWorkflow(context.Background(), wf, input) // Result: (10 + 5) * 2 = 30 } ``` -------------------------------- ### Execute and Monitor a Workflow (Go) Source: https://github.com/sicko7947/workflow-go/blob/main/README.md Shows the process of executing a defined workflow using the `engine` package. It covers setting up the state store, creating the engine, starting the workflow with input and tags, and retrieving its status. ```go import ( "context" "github.com/rs/zerolog" "github.com/sicko7947/workflow-go/engine" "github.com/sicko7947/workflow-go/store" ) func main() { // Create store store := store.NewMemoryStore() // Create engine with default logger and config eng := engine.NewEngine(store) // Or with custom logger and config // logger := zerolog.New(os.Stdout).With().Timestamp().Logger() // eng := engine.NewEngine(store, // engine.WithLogger(logger), // engine.WithConfig(engine.DefaultEngineConfig), // ) // Create workflow wf, err := NewCalculationWorkflow() if err != nil { logger.Fatal().Err(err).Msg("Failed to create workflow") } // Start workflow ctx := context.Background() runID, err := eng.StartWorkflow( ctx, wf, CalculationInput{A: 10, B: 5}, workflow.WithTags(map[string]string{ "type": "calculation", }), ) if err != nil { logger.Fatal().Err(err).Msg("Failed to start workflow") } logger.Info().Str("run_id", runID).Msg("Workflow started") // Get workflow status run, err := eng.GetRun(ctx, runID) if err != nil { logger.Fatal().Err(err).Msg("Failed to get workflow status") } logger.Info(). Str("status", string(run.Status)). Float64("progress", run.Progress). Msg("Workflow status") } ``` -------------------------------- ### Install Workflow-Go Package Source: https://github.com/sicko7947/workflow-go/blob/main/PROJECT_INDEX.md Add the workflow-go library to your Go project dependencies. This command fetches the latest version of the package and updates your go.mod and go.sum files. ```bash go get github.com/sicko7947/workflow-go ``` -------------------------------- ### Build and Execute Sequential Workflow in Go Source: https://context7.com/sicko7947/workflow-go/llms.txt This code demonstrates building a sequential workflow using the fluent builder API provided by workflow-go. It configures the workflow with a description, version, and execution settings, then chains the previously defined steps. Finally, it shows how to execute the workflow with an in-memory store and a logger, starting the workflow, and retrieving its status. Dependencies include the 'workflow-go' library and 'zerolog'. ```go // Build workflow using fluent builder API func NewSimpleMathWorkflow() (*workflow.Workflow, error) { wf, err := builder.NewWorkflow("simple_math", "Simple Math Workflow"). WithDescription("A simple workflow to test the engine"). WithVersion("1.0"). WithConfig(workflow.ExecutionConfig{ MaxRetries: 3, RetryDelayMs: 3000, TimeoutSeconds: 3, }). Sequence( NewAddStep(), NewMultiplyStep(), NewFormatStep(), ). Build() if err != nil { return nil, fmt.Errorf("failed to build workflow: %w", err) } return wf, nil } // Execute the workflow func main() { // Create logger logger := zerolog.New(os.Stdout).With().Timestamp().Logger() // Create in-memory store store := store.NewMemoryStore() // Create engine eng := engine.NewEngine(store, engine.WithLogger(logger), engine.WithConfig(engine.EngineConfig{ MaxConcurrentWorkflows: 10, DefaultTimeout: 5 * time.Minute, }), ) // Create workflow wf, err := NewSimpleMathWorkflow() if err != nil { logger.Fatal().Err(err).Msg("Failed to create workflow") } // Start workflow ctx := context.Background() runID, err := eng.StartWorkflow( ctx, wf, WorkflowInput{Val1: 10, Val2: 5, Mult: 3}, workflow.WithTags(map[string]string{"type": "calculation"}), ) if err != nil { logger.Fatal().Err(err).Msg("Failed to start workflow") } logger.Info().Str("run_id", runID).Msg("Workflow started") // Get workflow status run, err := eng.GetRun(ctx, runID) if err != nil { logger.Fatal().Err(err).Msg("Failed to get workflow status") } fmt.Printf("Status: %s, Progress: %.0f%%\n", run.Status, run.Progress*100) // Output: Status: COMPLETED, Progress: 100% } ``` -------------------------------- ### Registering Workflows in Workflow Go Application Source: https://context7.com/sicko7947/workflow-go/llms.txt This Go code snippet demonstrates how to initialize a Workflow Go application. It sets up an in-memory store and a new engine, then registers two sample workflows: 'order_processing' and 'simple_math'. Finally, it starts an HTTP server to expose the workflows via a REST API. ```go package main import ( "fmt" "net/http" "github.com/sicko7947/workflow-go/engine" "github.com/sicko7947/workflow-go/store" ) func main() { store := store.NewMemoryStore() eng := engine.NewEngine(store) api := NewWorkflowAPI(eng) // Register workflows orderWorkflow, _ := NewOrderProcessingWorkflow() api.RegisterWorkflow("order_processing", orderWorkflow) mathWorkflow, _ := NewSimpleMathWorkflow() api.RegisterWorkflow("simple_math", mathWorkflow) fmt.Println("Starting workflow API server on :8080") http.ListenAndServe(":8080", api.Routes()) } ``` -------------------------------- ### Setup Production Engine with DynamoDB in Go Source: https://context7.com/sicko7947/workflow-go/llms.txt Configures and initializes the workflow engine with persistent storage using AWS DynamoDB for production environments. It loads AWS configuration, creates a DynamoDB client and store, and sets up a production-level logger. Dependencies include AWS SDK for Go, zerolog, and the workflow-go engine and store packages. Outputs a configured engine instance or an error. ```go package main import ( "context" "os" "fmt" "time" "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/dynamodb" "github.com/rs/zerolog" "github.com/sicko7947/workflow-go/engine" "github.com/sicko7947/workflow-go/store" ) func SetupProductionEngine() (*engine.Engine, error) { // Load AWS configuration cfg, err := config.LoadDefaultConfig(context.Background()) if err != nil { return nil, fmt.Errorf("failed to load AWS config: %w", err) } // Create DynamoDB client client := dynamodb.NewFromConfig(cfg) // Create DynamoDB store dynamoStore, err := store.NewDynamoDBStore(client, "workflow_executions") if err != nil { return nil, fmt.Errorf("failed to create DynamoDB store: %w", err) } // Create production logger with appropriate level logger := zerolog.New(os.Stdout). With(). Timestamp(). Str("service", "workflow-engine"). Str("environment", "production"). Logger(). Level(zerolog.InfoLevel) // Create engine with production configuration eng := engine.NewEngine(dynamoStore, engine.WithLogger(logger), engine.WithConfig(engine.EngineConfig{ MaxConcurrentWorkflows: 50, DefaultTimeout: 10 * time.Minute, }), ) return eng, nil } ``` -------------------------------- ### POST /workflows/{workflowID}/runs Source: https://context7.com/sicko7947/workflow-go/llms.txt Starts a new execution of a specified workflow. Accepts an optional JSON payload for workflow input. ```APIDOC ## POST /workflows/{workflowID}/runs ### Description Starts a new execution of a specified workflow. Accepts an optional JSON payload for workflow input. ### Method POST ### Endpoint /workflows/{workflowID}/runs #### Path Parameters - **workflowID** (string) - Required - The ID of the workflow to start. #### Request Body - **input** (object) - Optional - A JSON object representing the input data for the workflow. ### Request Example ```json { "key": "value" } ``` ### Response #### Success Response (200) - **run_id** (string) - The ID of the newly started workflow run. #### Response Example ```json { "run_id": "a1b2c3d4-e5f6-7890-1234-567890abcdef" } ``` #### Error Response (404) - Workflow not found. #### Error Response (400) - Invalid request body. ``` -------------------------------- ### Setup Development Engine with In-Memory Store in Go Source: https://context7.com/sicko7947/workflow-go/llms.txt Initializes the workflow engine using an in-memory store for development and testing. It configures a debug-level logger and sets a lower concurrency limit and timeout. This approach avoids external dependencies like DynamoDB during development. Outputs a configured engine instance. ```go package main import ( "os" "github.com/rs/zerolog" "github.com/sicko7947/workflow-go/engine" "github.com/sicko7947/workflow-go/store" "time" ) // For development, use in-memory store func SetupDevelopmentEngine() *engine.Engine { logger := zerolog.New(os.Stdout). With(). Timestamp(). Logger(). Level(zerolog.DebugLevel) memStore := store.NewMemoryStore() return engine.NewEngine(memStore, engine.WithLogger(logger), engine.WithConfig(engine.EngineConfig{ MaxConcurrentWorkflows: 10, DefaultTimeout: 5 * time.Minute, }), ) } ``` -------------------------------- ### Step-Level Conditional Execution with Default Values (Go) Source: https://github.com/sicko7947/workflow-go/blob/main/example/conditional/README.md Presents an alternative method for handling conditional steps by wrapping a base step within a `NewConditionalStep`. This allows specifying a condition and a default output value directly at the step level. ```go baseStep := workflow.NewStep("process", "Process", handler) defaultOutput := &ProcessOutput{Status: "skipped"} conditionalStep := workflow.NewConditionalStep(baseStep, condition, defaultOutput) builder.ThenStep(conditionalStep) ``` -------------------------------- ### Workflow State Management for Conditions (Go) Source: https://github.com/sicko7947/workflow-go/blob/main/example/conditional/README.md Illustrates setting boolean flags within the workflow's runtime state, which are later used to control conditional step execution. This enables dynamic decision-making during workflow processing. ```go ctx.State.Set("enable_doubling", input.EnableDoubling) ctx.State.Set("enable_formatting", input.EnableFormatting) ``` -------------------------------- ### Define Type-Safe Workflow Steps in Go Source: https://context7.com/sicko7947/workflow-go/llms.txt This code defines input and output structures for workflow steps, enabling type safety. It includes examples for 'Add', 'Multiply', and 'Format' steps, showcasing how to create generic steps with custom handlers and optional configurations like retries and timeouts. Dependencies include the 'workflow-go' library. ```go package main import ( "context" "fmt" "time" workflow "github.com/sicko7947/workflow-go" "github.com/sicko7947/workflow-go/builder" "github.com/sicko7947/workflow-go/engine" "github.com/sicko7947/workflow-go/store" "github.com/rs/zerolog" "os" ) // Define step input/output types type WorkflowInput struct { Val1 int `json:"val1"` Val2 int `json:"val2"` Mult int `json:"mult"` } type AddOutput struct { Value int `json:"value"` Mult int `json:"mult"` } type MultiplyOutput struct { Value int `json:"value"` } type FormatOutput struct { Message string `json:"message"` } // Create type-safe steps with handlers func NewAddStep() *workflow.Step[WorkflowInput, AddOutput] { return workflow.NewStep( "add", "Add Numbers", func(ctx *workflow.StepContext, input WorkflowInput) (AddOutput, error) { sum := input.Val1 + input.Val2 ctx.Logger.Info().Int("val1", input.Val1).Int("val2", input.Val2).Int("sum", sum).Msg("Adding numbers") return AddOutput{Value: sum, Mult: input.Mult}, nil }, ) } func NewMultiplyStep() *workflow.Step[AddOutput, MultiplyOutput] { return workflow.NewStep( "multiply", "Multiply Result", func(ctx *workflow.StepContext, input AddOutput) (MultiplyOutput, error) { prod := input.Value * input.Mult ctx.Logger.Info().Int("value", input.Value).Int("mult", input.Mult).Int("product", prod).Msg("Multiplying result") return MultiplyOutput{Value: prod}, nil }, workflow.WithRetries(5), workflow.WithBackoff(workflow.BackoffExponential), workflow.WithTimeout(5*time.Second), ) } func NewFormatStep() *workflow.Step[MultiplyOutput, FormatOutput] { return workflow.NewStep( "format", "Format Output", func(ctx *workflow.StepContext, input MultiplyOutput) (FormatOutput, error) { msg := fmt.Sprintf("The final result is %d", input.Value) ctx.Logger.Info().Str("message", msg).Msg("Formatting output") return FormatOutput{Message: msg}, nil }, ) } ``` -------------------------------- ### Workflow Execution Flow in Go Source: https://github.com/sicko7947/workflow-go/blob/main/README.md Provides a high-level overview of the workflow execution process. It outlines the key stages, starting from initiating a workflow run, traversing the execution graph, executing individual steps with retries, storing outputs, and finally completing the workflow. This illustrates the orchestration managed by the engine. ```go 1. StartWorkflow() → Create WorkflowRun 2. Engine.executeWorkflow() → Traverse execution graph 3. For each step: - Create StepExecution - Execute handler with retries - Store output - Update progress 4. Complete workflow → Update final status ``` -------------------------------- ### Conditional Step Execution in Go Source: https://github.com/sicko7947/workflow-go/blob/main/README.md Illustrates how to execute workflow steps based on a runtime condition. This allows for dynamic workflow paths. The example shows both builder-level and step-level APIs for defining conditional logic, where a step only runs if the provided condition function returns true. A default output can be specified for cases where the step is skipped. ```go // Define a condition function condition := func(ctx *workflow.StepContext) (bool, error) { // Access state or previous step outputs var shouldProcess bool ctx.State.Get("should_process", &shouldProcess) return shouldProcess, nil } // Builder-level API (recommended) processStep := workflow.NewStep("process", "Process Data", processHandler) memungkinkan, wf, err := builder.NewWorkflow("conditional-workflow", "Conditional Workflow"). ThenStep(checkStep). ThenStepIf(processStep, condition, nil). // ← Builder-level conditional ThenStep(finalStep). Build() // Alternative: Step-level API (for type-safe default values) baseStep := workflow.NewStep("process", "Process Data", processHandler) defaultOutput := &ProcessOutput{Status: "skipped"} conditionalStep := workflow.NewConditionalStep(baseStep, condition, defaultOutput) memungkinkan, wf, err := builder.NewWorkflow("conditional-workflow", "Conditional Workflow"). ThenStep(checkStep). ThenStep(conditionalStep). Build() ``` -------------------------------- ### Go: Conditional Workflow Execution with workflow-go Source: https://context7.com/sicko7947/workflow-go/llms.txt This Go code defines steps for a workflow that execute conditionally based on flags stored in the workflow's state. It includes steps for setup, doubling a value, and conditionally formatting the result. The workflow uses `ThenStepIf` to control the execution of steps based on custom condition functions. ```go package main import ( "fmt" "github.com/sicko7947/workflow-go" "github.com/sicko7947/workflow-go/builder" ) type ConditionalInput struct { Value int `json:"value"` EnableDoubling bool `json:"enable_doubling"` EnableFormatting bool `json:"enable_formatting"` } type DoubleInput struct { Value int `json:"value"` } type DoubleOutput struct { Value int `json:"value"` Doubled bool `json:"doubled"` Message string `json:"message"` } type ConditionalFormatInput struct { Value int `json:"value"` Doubled bool `json:"doubled"` Message string `json:"message"` } type ConditionalFormatOutput struct { Value int `json:"value"` Formatted string `json:"formatted"` Doubled bool `json:"doubled"` } func NewSetupStep() *workflow.Step[ConditionalInput, DoubleInput] { return workflow.NewStep( "setup", "Setup Conditional Flags", func(ctx *workflow.StepContext, input ConditionalInput) (DoubleInput, error) { // Store flags in state for condition evaluation ctx.State.Set("enable_doubling", input.EnableDoubling) ctx.State.Set("enable_formatting", input.EnableFormatting) ctx.Logger.Info(). Bool("enable_doubling", input.EnableDoubling). Bool("enable_formatting", input.EnableFormatting). Msg("Conditional flags set in state") return DoubleInput{Value: input.Value}, nil }, ) } func NewDoubleStep() *workflow.Step[DoubleInput, DoubleOutput] { return workflow.NewStep( "double", "Double the Value", func(ctx *workflow.StepContext, input DoubleInput) (DoubleOutput, error) { doubled := input.Value * 2 ctx.Logger.Info(). Int("original", input.Value). Int("doubled", doubled). Msg("Doubling value") return DoubleOutput{ Value: doubled, Doubled: true, Message: fmt.Sprintf("Doubled %d to %d", input.Value, doubled), }, nil }, ) } func NewConditionalFormatStep() *workflow.Step[ConditionalFormatInput, ConditionalFormatOutput] { return workflow.NewStep( "conditional_format", "Format Result Conditionally", func(ctx *workflow.StepContext, input ConditionalFormatInput) (ConditionalFormatOutput, error) { formatted := fmt.Sprintf("Final value: %d (doubled: %v)", input.Value, input.Doubled) if input.Message != "" { formatted = fmt.Sprintf("%s | %s", formatted, input.Message) } ctx.Logger.Info().Str("formatted", formatted).Msg("Formatting conditional result") return ConditionalFormatOutput{ Value: input.Value, Formatted: formatted, Doubled: input.Doubled, }, }, ) } func NewConditionalWorkflow() (*workflow.Workflow, error) { // Define condition functions that evaluate workflow state shouldDouble := func(ctx *workflow.StepContext) (bool, error) { var enableDoubling bool if err := ctx.State.Get("enable_doubling", &enableDoubling); err != nil { ctx.Logger.Warn().Err(err).Msg("Failed to get enable_doubling from state, defaulting to false") return false, nil } ctx.Logger.Info().Bool("enable_doubling", enableDoubling).Msg("Evaluating doubling condition") return enableDoubling, nil } shouldFormat := func(ctx *workflow.StepContext) (bool, error) { var enableFormatting bool if err := ctx.State.Get("enable_formatting", &enableFormatting); err != nil { ctx.Logger.Warn().Err(err).Msg("Failed to get enable_formatting from state, defaulting to false") return false, nil } ctx.Logger.Info().Bool("enable_formatting", enableFormatting).Msg("Evaluating formatting condition") return enableFormatting, nil } // Define default output when doubling is skipped doubleDefault := &DoubleOutput{ Value: 0, Doubled: false, Message: "Doubling was skipped", } // Build workflow with conditional steps using ThenStepIf wf, err := builder.NewWorkflow("conditional_example", "Conditional Execution Example"). WithDescription("Demonstrates conditional step execution with ThenStepIf"). WithVersion("1.0"). WithConfig(workflow.ExecutionConfig{ MaxRetries: 2, RetryDelayMs: 1000, TimeoutSeconds: 10, }). ThenStep(NewSetupStep()). ThenStepIf(NewDoubleStep(), shouldDouble, doubleDefault). ThenStepIf(NewConditionalFormatStep(), shouldFormat, nil). Build() return wf, err } ``` -------------------------------- ### Create and Execute a Simple Workflow in Go Source: https://github.com/sicko7947/workflow-go/blob/main/PROJECT_INDEX.md Demonstrates how to define a simple sequential workflow with a single step, build the workflow, and then execute it using the workflow engine. It includes setting up the necessary components like the store and logger. ```go import ( workflow "github.com/sicko7947/workflow-go" "github.com/sicko7947/workflow-go/builder" "github.com/sicko7947/workflow-go/engine" "github.com/sicko7947/workflow-go/store" "context" "os" "github.com/rs/zerolog" ) // Define step step := workflow.NewStep( "hello", "Say Hello", func(ctx *workflow.StepContext, input string) (string, error) { return "Hello, " + input, nil }, ) // Build workflow wf, _ := builder.NewWorkflow("greeting", "Greeting Workflow"). Sequence(step). Build() // Execute store := store.NewMemoryStore() logger := zerolog.New(os.Stdout) eng := engine.NewEngine(store, logger, engine.DefaultEngineConfig) runID, _ := eng.StartWorkflow(context.Background(), wf, "World") ``` -------------------------------- ### Order Processing Orchestrator Implementation in Go Source: https://context7.com/sicko7947/workflow-go/llms.txt Defines an `OrderProcessingOrchestrator` struct that encapsulates workflow logic for processing orders. It initializes the workflow engine, provides methods to start, get status, cancel, and list order processing workflows. Dependencies include the 'workflow-go' library and 'zerolog' for logging. ```go package main import ( "context" "encoding/json" "fmt" "github.com/rs/zerolog" "github.com/sicko7947/workflow-go" "github.com/sicko7947/workflow-go/engine" ) type OrderProcessingOrchestrator struct { workflow *workflow.Workflow engine *engine.Engine logger zerolog.Logger } func NewOrderProcessingOrchestrator( store workflow.WorkflowStore, logger zerolog.Logger, config engine.EngineConfig, ) (*OrderProcessingOrchestrator, error) { // Create order processing workflow wf, err := NewOrderProcessingWorkflow() if err != nil { return nil, fmt.Errorf("failed to create order processing workflow: %w", err) } // Create engine with logger and config eng := engine.NewEngine(store, engine.WithLogger(logger), engine.WithConfig(config), ) return &OrderProcessingOrchestrator{ workflow: wf, engine: eng, logger: logger, }, nil } func (o *OrderProcessingOrchestrator) ProcessOrder( ctx context.Context, orderID string, customerID string, items []OrderItem, ) (string, error) { o.logger.Info(). Str("order_id", orderID). Str("customer_id", customerID). Int("items_count", len(items)). Msg("Starting order processing workflow") input := OrderInput{ OrderID: orderID, CustomerID: customerID, Items: items, } // Start workflow with metadata runID, err := o.engine.StartWorkflow( ctx, o.workflow, input, workflow.WithResourceID(orderID), workflow.WithTags(map[string]string{ "order_id": orderID, "customer_id": customerID, "type": "order_processing", }), workflow.WithTriggerType("api"), workflow.WithTriggerSource("order-service"), ) if err != nil { return "", fmt.Errorf("failed to start order processing workflow: %w", err) } o.logger.Info(). Str("run_id", runID). Str("order_id", orderID). Msg("Order processing workflow started successfully") return runID, nil } func (o *OrderProcessingOrchestrator) GetOrderStatus( ctx context.Context, runID string, ) (*OrderStatus, error) { // Get workflow run run, err := o.engine.GetRun(ctx, runID) if err != nil { return nil, fmt.Errorf("failed to get workflow run: %w", err) } // Get step executions for detailed progress stepExecs, err := o.engine.GetStepExecutions(ctx, runID) if err != nil { return nil, fmt.Errorf("failed to get step executions: %w", err) } status := &OrderStatus{ RunID: run.RunID, OrderID: run.ResourceID, Status: string(run.Status), Progress: run.Progress, CreatedAt: run.CreatedAt, CompletedAt: run.CompletedAt, StepExecutions: stepExecs, } // Parse output if completed if run.Status == workflow.RunStatusCompleted && len(run.Output) > 0 { var output OrderProcessingOutput if err := json.Unmarshal(run.Output, &output); err == nil { status.Output = &output } } return status, nil } func (o *OrderProcessingOrchestrator) CancelOrder(ctx context.Context, runID string) error { o.logger.Info().Str("run_id", runID).Msg("Cancelling order processing workflow") return o.engine.Cancel(ctx, runID) } func (o *OrderProcessingOrchestrator) ListOrdersByStatus( ctx context.Context, status workflow.RunStatus, limit int, ) ([]*workflow.WorkflowRun, error) { filter := workflow.RunFilter{ WorkflowID: o.workflow.ID, Status: status, Limit: limit, } return o.engine.ListRuns(ctx, filter) } type OrderItem struct { SKU string `json:"sku"` Quantity int `json:"quantity"` Price float64 `json:"price"` } type OrderInput struct { OrderID string `json:"order_id"` CustomerID string `json:"customer_id"` Items []OrderItem `json:"items"` } type OrderProcessingOutput struct { OrderID string `json:"order_id"` Status string `json:"status"` TotalAmount float64 `json:"total_amount"` InvoiceNumber string `json:"invoice_number"` } type OrderStatus struct { RunID string `json:"run_id"` OrderID string `json:"order_id"` Status string `json:"status"` Progress float64 `json:"progress"` CreatedAt time.Time `json:"created_at"` CompletedAt *time.Time `json:"completed_at,omitempty"` StepExecutions []*workflow.StepExecution `json:"step_executions,omitempty"` Output *OrderProcessingOutput `json:"output,omitempty"` } ``` -------------------------------- ### Create Workflow Engine (Go) Source: https://github.com/sicko7947/workflow-go/blob/main/PROJECT_INDEX.md Shows how to instantiate a new workflow engine. The engine requires dependencies such as a store implementation, a logger, and configuration parameters to manage workflow execution. ```Go engine.NewEngine(store, logger, config) ``` -------------------------------- ### Go HTTP API for Workflow Orchestration Source: https://context7.com/sicko7947/workflow-go/llms.txt Implements a RESTful API using Go and the chi router to manage workflow executions. It supports starting, getting status, listing runs, and cancelling workflows. Dependencies include 'net/http', 'encoding/json', 'time', and specific chi and workflow-go packages. It handles JSON request bodies and responses, returning appropriate HTTP status codes. ```go package main import ( "context" "encoding/json" "net/http" "time" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" "github.com/sicko7947/workflow-go" "github.com/sicko7947/workflow-go/engine" ) type WorkflowAPI struct { engine *engine.Engine workflows map[string]*workflow.Workflow } func NewWorkflowAPI(eng *engine.Engine) *WorkflowAPI { return &WorkflowAPI{ engine: eng, workflows: make(map[string]*workflow.Workflow), } } func (api *WorkflowAPI) RegisterWorkflow(id string, wf *workflow.Workflow) { api.workflows[id] = wf } func (api *WorkflowAPI) Routes() chi.Router { r := chi.NewRouter() r.Use(middleware.Logger) r.Use(middleware.Recoverer) r.Use(middleware.Timeout(60 * time.Second)) r.Post("/workflows/{workflowID}/runs", api.StartWorkflow) r.Get("/workflows/runs/{runID}", api.GetWorkflowStatus) r.Get("/workflows/runs/{runID}/steps", api.GetStepExecutions) r.Post("/workflows/runs/{runID}/cancel", api.CancelWorkflow) r.Get("/workflows/{workflowID}/runs", api.ListWorkflowRuns) return r } func (api *WorkflowAPI) StartWorkflow(w http.ResponseWriter, r *http.Request) { workflowID := chi.URLParam(r, "workflowID") wf, exists := api.workflows[workflowID] if !exists { http.Error(w, "Workflow not found", http.StatusNotFound) return } var input map[string]interface{} if err := json.NewDecoder(r.Body).Decode(&input); err != nil { http.Error(w, "Invalid request body", http.StatusBadRequest) return } runID, err := api.engine.StartWorkflow( r.Context(), wf, input, workflow.WithTags(map[string]string{ "user_id": r.Header.Get("X-User-ID"), "source": "http_api", }), workflow.WithTriggerType("http"), workflow.WithTriggerSource(r.RemoteAddr), ) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(map[string]string{ "run_id": runID, }) } func (api *WorkflowAPI) GetWorkflowStatus(w http.ResponseWriter, r *http.Request) { runID := chi.URLParam(r, "runID") run, err := api.engine.GetRun(r.Context(), runID) if err != nil { http.Error(w, err.Error(), http.StatusNotFound) return } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(run) } func (api *WorkflowAPI) GetStepExecutions(w http.ResponseWriter, r *http.Request) { runID := chi.URLParam(r, "runID") stepExecs, err := api.engine.GetStepExecutions(r.Context(), runID) if err != nil { http.Error(w, err.Error(), http.StatusNotFound) return } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(stepExecs) } func (api *WorkflowAPI) CancelWorkflow(w http.ResponseWriter, r *http.Request) { runID := chi.URLParam(r, "runID") if err := api.engine.Cancel(r.Context(), runID); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } w.WriteHeader(http.StatusNoContent) } func (api *WorkflowAPI) ListWorkflowRuns(w http.ResponseWriter, r *http.Request) { workflowID := chi.URLParam(r, "workflowID") status := r.URL.Query().Get("status") filter := workflow.RunFilter{ WorkflowID: workflowID, Limit: 20, } if status != "" { filter.Status = workflow.RunStatus(status) } runs, err := api.engine.ListRuns(r.Context(), filter) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(runs) } // Start HTTP server ``` -------------------------------- ### GET /workflows/runs/{runID} Source: https://context7.com/sicko7947/workflow-go/llms.txt Retrieves the current status and details of a specific workflow run. ```APIDOC ## GET /workflows/runs/{runID} ### Description Retrieves the current status and details of a specific workflow run. ### Method GET ### Endpoint /workflows/runs/{runID} #### Path Parameters - **runID** (string) - Required - The ID of the workflow run to retrieve. ### Response #### Success Response (200) - **run** (object) - An object containing the details of the workflow run, including its status, start time, end time, etc. #### Response Example ```json { "id": "a1b2c3d4-e5f6-7890-1234-567890abcdef", "workflowID": "my-workflow", "status": "running", "startTime": "2023-10-27T10:00:00Z", "endTime": null } ``` #### Error Response (404) - Workflow run not found. ``` -------------------------------- ### GET /workflows/{workflowID}/runs Source: https://context7.com/sicko7947/workflow-go/llms.txt Lists all runs for a given workflow, with optional filtering by status. ```APIDOC ## GET /workflows/{workflowID}/runs ### Description Lists all runs for a given workflow, with optional filtering by status. ### Method GET ### Endpoint /workflows/{workflowID}/runs #### Path Parameters - **workflowID** (string) - Required - The ID of the workflow. #### Query Parameters - **status** (string) - Optional - Filters the runs by their status (e.g., "running", "completed", "failed"). ### Response #### Success Response (200) - **runs** (array) - An array of workflow run objects, each containing details about a specific run. #### Response Example ```json [ { "id": "run-1", "workflowID": "my-workflow", "status": "completed", "startTime": "2023-10-27T09:00:00Z", "endTime": "2023-10-27T09:05:00Z" }, { "id": "run-2", "workflowID": "my-workflow", "status": "running", "startTime": "2023-10-27T10:00:00Z", "endTime": null } ] ``` #### Error Response (500) - An error occurred while retrieving the workflow runs. ``` -------------------------------- ### GET /workflows/runs/{runID}/steps Source: https://context7.com/sicko7947/workflow-go/llms.txt Retrieves a list of step executions for a specific workflow run. ```APIDOC ## GET /workflows/runs/{runID}/steps ### Description Retrieves a list of step executions for a specific workflow run. ### Method GET ### Endpoint /workflows/runs/{runID}/steps #### Path Parameters - **runID** (string) - Required - The ID of the workflow run. ### Response #### Success Response (200) - **stepExecutions** (array) - An array of objects, where each object represents a step execution and contains details like step ID, status, start time, end time, etc. #### Response Example ```json [ { "stepID": "step-1", "status": "completed", "startTime": "2023-10-27T10:00:05Z", "endTime": "2023-10-27T10:00:10Z" }, { "stepID": "step-2", "status": "running", "startTime": "2023-10-27T10:00:15Z", "endTime": null } ] ``` #### Error Response (404) - Workflow run not found. ``` -------------------------------- ### Build Workflow Sequence (Go) Source: https://github.com/sicko7947/workflow-go/blob/main/PROJECT_INDEX.md Illustrates the process of building a workflow by defining a sequence of steps. This involves creating a new workflow builder and chaining the steps to be executed in order. ```Go builder.NewWorkflow().Sequence(...).Build() ``` -------------------------------- ### Go AWS Lambda Integration for SQS Events Source: https://context7.com/sicko7947/workflow-go/llms.txt Provides a Go function to handle AWS SQS events for triggering workflow executions. It iterates through SQS records, unmarshals JSON messages into workflow inputs, and starts workflows using the provided engine. Dependencies include 'context', 'encoding/json', 'fmt', and specific AWS Lambda event types and workflow-go packages. It returns an error if message unmarshalling or workflow starting fails. ```go // AWS Lambda integration example func HandleSQSEvent(ctx context.Context, event events.SQSEvent, eng *engine.Engine, wf *workflow.Workflow) error { for _, record := range event.Records { var input map[string]interface{} if err := json.Unmarshal([]byte(record.Body), &input); err != nil { return fmt.Errorf("failed to unmarshal message: %w", err) } runID, err := eng.StartWorkflow( ctx, wf, input, workflow.WithTriggerType("sqs"), workflow.WithTriggerSource(record.MessageId), workflow.WithTags(map[string]string{ "message_id": record.MessageId, "queue": record.EventSourceARN, }), ) if err != nil { return fmt.Errorf("failed to start workflow: %w", err) } fmt.Printf("Started workflow %s for message %s\n", runID, record.MessageId) } return nil } ```