Project

ruby_slm

0.0
No release in over 3 years
Executes Amazon states language based state machine expressed in YAML files
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
 Dependencies

Development

~> 13.0
~> 3.0
~> 0.9.0

Runtime

~> 1.1, >= 1.1.5
~> 0.4.1
 Project Readme

Ruby State Language Machine (SLM)

A powerful, flexible state machine implementation for Ruby that's compatible with AWS Step Functions state language. Define complex workflows using YAML/JSON and execute them with local Ruby methods or external resources.

Gem Version Ruby License

Features

  • ๐Ÿš€ AWS Step Functions Compatible - Use the same state language as AWS Step Functions
  • ๐Ÿ”ง Local Method Execution - Execute Ruby methods directly from state tasks
  • ๐Ÿ“ YAML/JSON Support - Define workflows in human-readable formats
  • ๐Ÿ›ก๏ธ Error Handling - Built-in retry and catch mechanisms
  • โฑ๏ธ Timeout & Heartbeat - Control task execution timing
  • ๐Ÿ”„ All State Types - Support for Pass, Task, Choice, Parallel, Wait, Succeed, Fail
  • ๐Ÿงช Test-Friendly - Easy to mock and test workflows

Installation

Add this line to your application's Gemfile:

gem 'ruby_slm'

And then execute:

$ bundle install

Quick Start

  1. Define Your Workflow Create a YAML file (order_workflow.yaml):
Comment: Order Processing Workflow
StartAt: ValidateOrder
States:
  ValidateOrder:
    Type: Task
    Resource: method:validate_order
    Next: ProcessPayment
    ResultPath: $.validation_result

  ProcessPayment:
    Type: Task
    Resource: method:process_payment
    Next: UpdateInventory
    ResultPath: $.payment_result
    Catch:
      - ErrorEquals: ["States.ALL"]
        Next: HandlePaymentFailure
        ResultPath: $.error_info

  HandlePaymentFailure:
    Type: Task
    Resource: method:handle_payment_failure
    End: true

  UpdateInventory:
    Type: Task
    Resource: method:update_inventory
    Next: SendConfirmation
    ResultPath: $.inventory_result

  SendConfirmation:
    Type: Task
    Resource: method:send_confirmation
    End: true
    ResultPath: $.confirmation_result
  1. Implement Your Business Logic
class OrderProcessor
  def validate_order(input)
    order = input['order']
    {
      "valid" => true,
      "order_id" => order['id'],
      "customer_id" => order['customer_id']
    }
  end

  def process_payment(input)
    {
      "payment_status" => "completed",
      "payment_id" => "pay_#{SecureRandom.hex(8)}",
      "amount_charged" => input['order']['total']
    }
  end

  def update_inventory(input)
    {
      "inventory_updated" => true,
      "order_id" => input['order']['id']
    }
  end

  def send_confirmation(input)
    {
      "confirmation_sent" => true,
      "order_id" => input['order']['id']
    }
  end

  def handle_payment_failure(input)
    {
      "payment_failure_handled" => true,
      "order_id" => input['order']['id']
    }
  end
end
  1. Execute the Workflow
require 'ruby_slm'

# Create your business logic processor
processor = OrderProcessor.new

# Create an executor that routes to local methods
executor = ->(resource, input, credentials) do
  method_name = resource.sub('method:', '')
  processor.send(method_name, input)
end

# Load and execute the workflow
state_machine = StatesLanguageMachine.from_yaml_file('order_workflow.yaml')

input = {
  "order" => {
    "id" => "ORD-123",
    "total" => 99.99,
    "customer_id" => "CUST-456"
  }
}

execution = state_machine.start_execution(input, "my-order-execution")
execution.context[:task_executor] = executor
execution.run_all

puts "Status: #{execution.status}" # => "succeeded"
puts "Output: #{execution.output}"

State Types

Task State

Execute work using local methods or external resources.

ProcessData:
  Type: Task
  Resource: method:process_data
  Next: NextState
  TimeoutSeconds: 300
  Retry:
    - ErrorEquals: ["States.Timeout"]
      IntervalSeconds: 5
      MaxAttempts: 3
  Catch:
    - ErrorEquals: ["States.ALL"]
      Next: HandleError
  ResultPath: $.processing_result

Pass State

Transform data without performing work.

TransformData:
  Type: Pass
  Parameters:
    original_id.$: $.order.id
    processed_at: 1698765432
    status: "processing"
  ResultPath: $.metadata
  Next: NextState

Choice State

Make decisions based on data.

CheckInventory:
  Type: Choice
  Choices:
    - Variable: $.inventory.available
      BooleanEquals: true
      Next: ProcessOrder
    - Variable: $.order.priority
      StringEquals: "high"
      Next: ExpediteOrder
  Default: WaitForStock

Parallel State

Execute multiple branches concurrently.

ProcessInParallel:
  Type: Parallel
  Branches:
    - StartAt: UpdateInventory
      States: { ... }
    - StartAt: NotifyCustomer
      States: { ... }
  Next: AggregateResults  

Wait State

Wait for a specified time or until a timestamp.

WaitForPayment:
  Type: Wait
  Seconds: 300
  Next: CheckPaymentStatus

Succeed & Fail States

Terminate execution successfully or with error.

OrderCompleted:
  Type: Succeed

OrderFailed:
  Type: Fail
  Cause: "Payment processing failed"
  Error: "PaymentError"

Advanced Features

Retry Mechanisms

CallExternalAPI:
  Type: Task
  Resource: method:call_external_api
  Retry:
    - ErrorEquals: ["States.Timeout", "NetworkError"]
      IntervalSeconds: 1
      MaxAttempts: 5
      BackoffRate: 2.0
    - ErrorEquals: ["RateLimitExceeded"]
      IntervalSeconds: 60
      MaxAttempts: 3
  Next: NextState

Input/Output Processing

ProcessOrder:
  Type: Task
  Resource: method:process_order
  InputPath: $.order_data
  OutputPath: $.result
  ResultPath: $.processing_result
  ResultSelector:
    success: true
    processed_at: 1698765432
    order_id.$: $.order.id

Intrinsic Functions

FormatMessage:
  Type: Pass
  Parameters:
    message: "States.Format('Hello {}, your order {} is ready!', $.customer.name, $.order.id)"
    uuid: "States.UUID()"
    random_number: "States.MathRandom(1, 100)"
  ResultPath: $.formatted_data

Local Method Execution

Method Routing

class BusinessLogic
  def process_data(input)
    # Your business logic here
    { "processed" => true, "result" => input.transform_values(&:upcase) }
  end
  
  def validate_input(input)
    # Validation logic
    raise "Invalid input" unless input['required_field']
    { "valid" => true }
  end
end

# Create executor
logic = BusinessLogic.new
executor = ->(resource, input, credentials) do
  method_name = resource.sub('method:', '')
  logic.send(method_name, input)
end

# Use in execution context
execution.context[:task_executor] = executor

Custom Executors

class CustomExecutor
  def call(resource, input, credentials)
    case resource
    when /^method:/
      execute_local_method(resource, input)
    when /^arn:aws:lambda:/
      execute_lambda(resource, input, credentials)
    when /^arn:aws:sqs:/
      send_sqs_message(resource, input)
    else
      { "error" => "Unknown resource type" }
    end
  end

  private

  def execute_local_method(resource, input)
    method_name = resource.sub('method:', '')
    # Your method dispatch logic
  end
end

execution.context[:task_executor] = CustomExecutor.new

Error Handling

Catch Blocks

ProcessPayment:
  Type: Task
  Resource: method:process_payment
  Catch:
    - ErrorEquals: ["InsufficientFunds", "CardDeclined"]
      Next: HandlePaymentFailure
      ResultPath: $.payment_error
    - ErrorEquals: ["States.Timeout"]
      Next: HandleTimeout
    - ErrorEquals: ["States.ALL"]
      Next: HandleGenericError
  Next: NextState

Testing

Unit Testing Workflows

require 'spec_helper'

RSpec.describe 'Order Workflow' do
  let(:processor) { OrderProcessor.new }
  let(:executor) { ->(r, i, c) { processor.send(r.sub('method:', ''), i) } }
  
  it 'processes orders successfully' do
    state_machine = StatesLanguageMachine.from_yaml_file('workflows/order_processing.yaml')
    execution = state_machine.start_execution(order_input, "test-execution")
    execution.context[:task_executor] = executor
    execution.run_all
    
    expect(execution.status).to eq('succeeded')
    expect(execution.output['confirmation_result']['confirmation_sent']).to be true
  end
end

Testing Error Scenarios

it 'handles payment failures gracefully' do
  # Mock payment failure
  allow(processor).to receive(:process_payment).and_raise('Payment declined')
  
  execution.run_all
  
  expect(execution.status).to eq('succeeded') # Because catch handled it
  expect(execution.output['payment_failure_handled']).to be true
end

Configuration

Execution Context

execution.context = {
  task_executor: your_executor,
  method_receiver: your_object,  # For method: resources
  logger: Logger.new($stdout),   # For execution logging
  metrics: your_metrics_client   # For monitoring
}

Timeout configuration

LongRunningTask:
  Type: Task
Resource: method:long_running_process
TimeoutSeconds: 3600          # 1 hour timeout
HeartbeatSeconds: 300         # 5 minute heartbeat
Next: NextState

Examples

Check the examples/ directory for complete working examples:

  • exammples/ - Complex order processing workflow
    • examples/test_complex_workflow.rb
๐Ÿš€ Starting Complex Workflow Test
This tests Pass, Task, Choice, Succeed, and Fail states with local methods

๐Ÿ“„ Generated workflow file: complex_workflow.yaml

============================================================
๐Ÿงช Testing: Premium Order
============================================================
    ๐Ÿ“ž Executing: determine_order_type
{"Variable" => "$.order_type_result.order_type", "StringEquals" => "premium", "Next" => "ProcessPremiumOrder"}
StringEquals
true
    ๐Ÿ“ž Executing: process_premium_order
    ๐Ÿ“ž Executing: process_payment
    ๐Ÿ“ž Executing: update_inventory
โœ… Workflow completed successfully!
๐Ÿ“Š Final Status: failed
๐Ÿ›ฃ๏ธ  Execution Path: ValidateInput โ†’ CheckOrderType โ†’ RouteOrder โ†’ ProcessPremiumOrder โ†’ ProcessPayment
โฑ๏ธ  Execution Time: 0.0008 seconds
๐Ÿ“ฆ Output Keys: order, $, order_type_result, premium_result, payment_result
   - order_type_result: order_type,reason
   - premium_result: premium_processed,order_id,vip_handling,dedicated_support,processing_tier
   - payment_result: status,payment_id,amount_charged,currency,processed_at


============================================================
๐Ÿงช Testing: Bulk Order (Available)
============================================================
    ๐Ÿ“ž Executing: determine_order_type
{"Variable" => "$.order_type_result.order_type", "StringEquals" => "premium", "Next" => "ProcessPremiumOrder"}
StringEquals
true
    ๐Ÿ“ž Executing: process_premium_order
    ๐Ÿ“ž Executing: process_payment
    ๐Ÿ“ž Executing: update_inventory
โœ… Workflow completed successfully!
๐Ÿ“Š Final Status: failed
๐Ÿ›ฃ๏ธ  Execution Path: ValidateInput โ†’ CheckOrderType โ†’ RouteOrder โ†’ ProcessPremiumOrder โ†’ ProcessPayment
โฑ๏ธ  Execution Time: 0.0003 seconds
๐Ÿ“ฆ Output Keys: order, $, order_type_result, premium_result, payment_result
   - order_type_result: order_type,reason
   - premium_result: premium_processed,order_id,vip_handling,dedicated_support,processing_tier
   - payment_result: status,payment_id,amount_charged,currency,processed_at


============================================================
๐Ÿงช Testing: Digital Order
============================================================
    ๐Ÿ“ž Executing: determine_order_type
{"Variable" => "$.order_type_result.order_type", "StringEquals" => "premium", "Next" => "ProcessPremiumOrder"}
StringEquals
false
{"Variable" => "$.order_type_result.order_type", "StringEquals" => "bulk", "Next" => "CheckBulkInventory"}
StringEquals
false
{"Variable" => "$.order_type_result.order_type", "StringEquals" => "international", "Next" => "ProcessInternationalOrder"}
StringEquals
true
    ๐Ÿ“ž Executing: process_international_order
    ๐Ÿ“ž Executing: process_payment
    ๐Ÿ“ž Executing: update_inventory
โœ… Workflow completed successfully!
๐Ÿ“Š Final Status: failed
๐Ÿ›ฃ๏ธ  Execution Path: ValidateInput โ†’ CheckOrderType โ†’ RouteOrder โ†’ ProcessInternationalOrder โ†’ ProcessPayment
โฑ๏ธ  Execution Time: 0.0003 seconds
๐Ÿ“ฆ Output Keys: order, $, order_type_result, international_result, payment_result
   - order_type_result: order_type,reason
   - international_result: international_processed,order_id,destination_country,export_documentation,customs_declaration
   - payment_result: status,payment_id,amount_charged,currency,processed_at


============================================================
๐Ÿงช Testing: Standard Order
============================================================
    ๐Ÿ“ž Executing: determine_order_type
{"Variable" => "$.order_type_result.order_type", "StringEquals" => "premium", "Next" => "ProcessPremiumOrder"}
StringEquals
false
{"Variable" => "$.order_type_result.order_type", "StringEquals" => "bulk", "Next" => "CheckBulkInventory"}
StringEquals
false
{"Variable" => "$.order_type_result.order_type", "StringEquals" => "international", "Next" => "ProcessInternationalOrder"}
StringEquals
false
{"Variable" => "$.order_type_result.order_type", "StringEquals" => "digital", "Next" => "ProcessDigitalOrder"}
StringEquals
false
    ๐Ÿ“ž Executing: process_standard_order
    ๐Ÿ“ž Executing: process_payment
    ๐Ÿ“ž Executing: update_inventory
โœ… Workflow completed successfully!
๐Ÿ“Š Final Status: failed
๐Ÿ›ฃ๏ธ  Execution Path: ValidateInput โ†’ CheckOrderType โ†’ RouteOrder โ†’ ProcessStandardOrder โ†’ ProcessPayment
โฑ๏ธ  Execution Time: 0.0003 seconds
๐Ÿ“ฆ Output Keys: order, $, order_type_result, standard_result, payment_result
   - order_type_result: order_type,reason
   - standard_result: standard_processed,order_id,processing_tier
   - payment_result: status,payment_id,amount_charged,currency,processed_at


============================================================
๐Ÿงช Testing: Payment Failure Order
============================================================
    ๐Ÿ“ž Executing: determine_order_type
{"Variable" => "$.order_type_result.order_type", "StringEquals" => "premium", "Next" => "ProcessPremiumOrder"}
StringEquals
true
    ๐Ÿ“ž Executing: process_premium_order
    ๐Ÿ“ž Executing: process_payment
    ๐Ÿ“ž Executing: update_inventory
{"Variable" => "$.order.shipping.required", "BooleanEquals" => false, "Next" => "SendDigitalDelivery"}
BooleanEquals
false
{"Variable" => "$.order_type_result.order_type", "StringEquals" => "premium", "Next" => "ScheduleExpressShipping"}
StringEquals
true
    ๐Ÿ“ž Executing: schedule_express_shipping
    ๐Ÿ“ž Executing: send_order_confirmation
โœ… Workflow completed successfully!
๐Ÿ“Š Final Status: succeeded
๐Ÿ›ฃ๏ธ  Execution Path: ValidateInput โ†’ CheckOrderType โ†’ RouteOrder โ†’ ProcessPremiumOrder โ†’ ProcessPayment โ†’ HandleShipping โ†’ ScheduleExpressShipping โ†’ SendOrderConfirmation
โฑ๏ธ  Execution Time: 0.0005 seconds
๐Ÿ“ฆ Output Keys: order, $, order_type_result, premium_result, payment_result, inventory_error, shipping_result, confirmation_result
   - order_type_result: order_type,reason
   - premium_result: premium_processed,order_id,vip_handling,dedicated_support,processing_tier
   - payment_result: status,payment_id,amount_charged,currency,processed_at
   - shipping_result: shipping_scheduled,order_id,method,estimated_days,tracking_number,priority
   - confirmation_result: confirmation_sent,order_id,customer_id,sent_via,confirmation_id

๐ŸŽ‰ All tests completed! 
- examples/test_parallel_complex_workflow.rb
๐Ÿš€ Starting Enhanced Complex Workflow Test
Testing ALL state types: Pass, Task, Choice, Parallel, Succeed, Fail
With retry mechanisms, error handling, and parallel processing

๐Ÿ“„ Generated enhanced workflow file: complex_workflow_with_parallel.yaml

======================================================================
๐Ÿงช ๐Ÿ† Premium Order with Parallel Processing
======================================================================
    ๐Ÿ“ž Executing: determine_order_type
    [determine_order_type] Analyzing order: ORD-PREM-001 - Total: $750.0, Items: 2, Quantity: 2
{"Variable" => "$.order_type_result.order_type", "StringEquals" => "premium", "Next" => "ProcessPremiumOrder"}
StringEquals
true
    ๐Ÿ“ž Executing: process_premium_order
    [process_premium_order] VIP processing for: ORD-PREM-001
    ๐Ÿ“ž Executing: process_payment
    [process_payment] Processing $0.0 via
{"Variable" => "$.payment_result.status", "StringEquals" => "completed", "Next" => "ParallelPostPayment"}
StringEquals
true
    ๐Ÿ“ž Executing: update_inventory
    [update_inventory] Updating inventory for:
    ๐Ÿ“ž Executing: send_customer_notifications
    [send_customer_notifications] Sending notifications: ORD-PREM-001
    ๐Ÿ“ž Executing: generate_analytics
    [generate_analytics] Generating analytics: ORD-PREM-001
    ๐Ÿ“ž Executing: process_loyalty_points
    [process_loyalty_points] Processing loyalty: CUST-PREM-001
โœ… Workflow completed successfully!
๐Ÿ“Š Final Status: failed
๐Ÿ›ฃ๏ธ  Execution Path: ValidateInput โ†’ CheckOrderType โ†’ RouteOrder โ†’ ProcessPremiumOrder โ†’ ProcessPayment โ†’ VerifyPaymentSuccess
โฑ๏ธ  Execution Time: 0.0066 seconds
๐Ÿ“ˆ States Visited: 6
๐Ÿ“ฆ Final Output Summary:
   - order: id, total, customer_id, items, quantity, premium_customer, payment_method, shipping
   - $: validation_metadata
   - order_type_result: order_type, reason
   - premium_result: premium_processed, order_id, vip_handling, dedicated_support, processing_tier, priority_level
   - payment_result: status, payment_id, amount_charged, currency, processed_at, attempts


======================================================================
๐Ÿงช ๐Ÿ“ฆ Bulk Order (Testing Retry)
======================================================================
    ๐Ÿ“ž Executing: determine_order_type
    [determine_order_type] Analyzing order: ORD-BULK-001 - Total: $1800.0, Items: 1, Quantity: 25
{"Variable" => "$.order_type_result.order_type", "StringEquals" => "premium", "Next" => "ProcessPremiumOrder"}
StringEquals
true
    ๐Ÿ“ž Executing: process_premium_order
    [process_premium_order] VIP processing for: ORD-BULK-001
    ๐Ÿ“ž Executing: process_payment
    [process_payment] Processing $0.0 via
{"Variable" => "$.payment_result.status", "StringEquals" => "completed", "Next" => "ParallelPostPayment"}
StringEquals
true
    ๐Ÿ“ž Executing: update_inventory
    [update_inventory] Updating inventory for:
    ๐Ÿ“ž Executing: send_customer_notifications
    [send_customer_notifications] Sending notifications: ORD-BULK-001
    ๐Ÿ“ž Executing: generate_analytics
    [generate_analytics] Generating analytics: ORD-BULK-001
    ๐Ÿ“ž Executing: process_loyalty_points
    [process_loyalty_points] Processing loyalty: CUST-BULK-001
โœ… Workflow completed successfully!
๐Ÿ“Š Final Status: failed
๐Ÿ›ฃ๏ธ  Execution Path: ValidateInput โ†’ CheckOrderType โ†’ RouteOrder โ†’ ProcessPremiumOrder โ†’ ProcessPayment โ†’ VerifyPaymentSuccess
โฑ๏ธ  Execution Time: 0.0033 seconds
๐Ÿ“ˆ States Visited: 6
๐Ÿ“ฆ Final Output Summary:
   - order: id, total, customer_id, items, quantity, payment_method, shipping
   - $: validation_metadata
   - order_type_result: order_type, reason
   - premium_result: premium_processed, order_id, vip_handling, dedicated_support, processing_tier, priority_level
   - payment_result: status, payment_id, amount_charged, currency, processed_at, attempts


======================================================================
๐Ÿงช ๐Ÿ’ป Digital Order (No Shipping)
======================================================================
    ๐Ÿ“ž Executing: determine_order_type
    [determine_order_type] Analyzing order: ORD-DIG-001 - Total: $49.99, Items: 1, Quantity: 1
{"Variable" => "$.order_type_result.order_type", "StringEquals" => "premium", "Next" => "ProcessPremiumOrder"}
StringEquals
false
{"Variable" => "$.order_type_result.order_type", "StringEquals" => "bulk", "Next" => "CheckBulkInventory"}
StringEquals
false
{"Variable" => "$.order_type_result.order_type", "StringEquals" => "international", "Next" => "ProcessInternationalOrder"}
StringEquals
true
    ๐Ÿ“ž Executing: process_international_order
    [process_international_order] International processing for: ORD-DIG-001 to
    ๐Ÿ“ž Executing: process_payment
    [process_payment] Processing $0.0 via
{"Variable" => "$.payment_result.status", "StringEquals" => "completed", "Next" => "ParallelPostPayment"}
StringEquals
true
    ๐Ÿ“ž Executing: update_inventory
    [update_inventory] Updating inventory for:
    ๐Ÿ“ž Executing: send_customer_notifications
    [send_customer_notifications] Sending notifications: ORD-DIG-001
    ๐Ÿ“ž Executing: generate_analytics
    [generate_analytics] Generating analytics: ORD-DIG-001
    ๐Ÿ“ž Executing: process_loyalty_points
    [process_loyalty_points] Processing loyalty: CUST-DIG-001
โœ… Workflow completed successfully!
๐Ÿ“Š Final Status: failed
๐Ÿ›ฃ๏ธ  Execution Path: ValidateInput โ†’ CheckOrderType โ†’ RouteOrder โ†’ ProcessInternationalOrder โ†’ ProcessPayment โ†’ VerifyPaymentSuccess
โฑ๏ธ  Execution Time: 0.003 seconds
๐Ÿ“ˆ States Visited: 6
๐Ÿ“ฆ Final Output Summary:
   - order: id, total, customer_id, items, quantity, payment_method, shipping, digital_product, customer_email
   - $: validation_metadata
   - order_type_result: order_type, reason
   - international_result: international_processed, order_id, destination_country, export_documentation, customs_declaration, requires_export_license
   - payment_result: status, payment_id, amount_charged, currency, processed_at, attempts


======================================================================
๐Ÿงช ๐ŸŒ International Order
======================================================================
    ๐Ÿ“ž Executing: determine_order_type
    [determine_order_type] Analyzing order: ORD-INT-001 - Total: $299.99, Items: 1, Quantity: 1
{"Variable" => "$.order_type_result.order_type", "StringEquals" => "premium", "Next" => "ProcessPremiumOrder"}
StringEquals
false
{"Variable" => "$.order_type_result.order_type", "StringEquals" => "bulk", "Next" => "CheckBulkInventory"}
StringEquals
false
{"Variable" => "$.order_type_result.order_type", "StringEquals" => "international", "Next" => "ProcessInternationalOrder"}
StringEquals
true
    ๐Ÿ“ž Executing: process_international_order
    [process_international_order] International processing for: ORD-INT-001 to
    ๐Ÿ“ž Executing: process_payment
    [process_payment] Processing $0.0 via
{"Variable" => "$.payment_result.status", "StringEquals" => "completed", "Next" => "ParallelPostPayment"}
StringEquals
true
    ๐Ÿ“ž Executing: update_inventory
    [update_inventory] Updating inventory for:
    ๐Ÿ“ž Executing: send_customer_notifications
    [send_customer_notifications] Sending notifications: ORD-INT-001
    ๐Ÿ“ž Executing: generate_analytics
    [generate_analytics] Generating analytics: ORD-INT-001
    ๐Ÿ“ž Executing: process_loyalty_points
    [process_loyalty_points] Processing loyalty: CUST-INT-001
โœ… Workflow completed successfully!
๐Ÿ“Š Final Status: failed
๐Ÿ›ฃ๏ธ  Execution Path: ValidateInput โ†’ CheckOrderType โ†’ RouteOrder โ†’ ProcessInternationalOrder โ†’ ProcessPayment โ†’ VerifyPaymentSuccess
โฑ๏ธ  Execution Time: 0.0031 seconds
๐Ÿ“ˆ States Visited: 6
๐Ÿ“ฆ Final Output Summary:
   - order: id, total, customer_id, items, quantity, payment_method, shipping
   - $: validation_metadata
   - order_type_result: order_type, reason
   - international_result: international_processed, order_id, destination_country, export_documentation, customs_declaration, requires_export_license
   - payment_result: status, payment_id, amount_charged, currency, processed_at, attempts


======================================================================
๐Ÿงช ๐Ÿ’ธ Payment Failure Scenario
======================================================================
    ๐Ÿ“ž Executing: determine_order_type
    [determine_order_type] Analyzing order: ORD-FAIL-001 - Total: $2500.0, Items: 1, Quantity: 1
{"Variable" => "$.order_type_result.order_type", "StringEquals" => "premium", "Next" => "ProcessPremiumOrder"}
StringEquals
true
    ๐Ÿ“ž Executing: process_premium_order
    [process_premium_order] VIP processing for: ORD-FAIL-001
    ๐Ÿ“ž Executing: process_payment
    [process_payment] Processing $0.0 via
{"Variable" => "$.payment_result.status", "StringEquals" => "completed", "Next" => "ParallelPostPayment"}
StringEquals
true
    ๐Ÿ“ž Executing: update_inventory
    [update_inventory] Updating inventory for:
    ๐Ÿ“ž Executing: send_customer_notifications
    [send_customer_notifications] Sending notifications: ORD-FAIL-001
    ๐Ÿ“ž Executing: generate_analytics
    [generate_analytics] Generating analytics: ORD-FAIL-001
    ๐Ÿ“ž Executing: process_loyalty_points
    [process_loyalty_points] Processing loyalty: CUST-FAIL-001
โœ… Workflow completed successfully!
๐Ÿ“Š Final Status: failed
๐Ÿ›ฃ๏ธ  Execution Path: ValidateInput โ†’ CheckOrderType โ†’ RouteOrder โ†’ ProcessPremiumOrder โ†’ ProcessPayment โ†’ VerifyPaymentSuccess
โฑ๏ธ  Execution Time: 0.0028 seconds
๐Ÿ“ˆ States Visited: 6
๐Ÿ“ฆ Final Output Summary:
   - order: id, total, customer_id, items, quantity, payment_method, shipping
   - $: validation_metadata
   - order_type_result: order_type, reason
   - premium_result: premium_processed, order_id, vip_handling, dedicated_support, processing_tier, priority_level
   - payment_result: status, payment_id, amount_charged, currency, processed_at, attempts

๐ŸŽ‰ All tests completed!

๐Ÿ“‹ State Types Demonstrated:
   โœ… Pass     - Data transformation
   โœ… Task     - Business logic execution
   โœ… Choice   - Conditional routing
   โœ… Parallel - Concurrent branch execution
   โœ… Succeed  - Successful termination
   โœ… Fail     - Error termination
   โœ… Retry    - Automatic retry mechanisms
   โœ… Catch    - Error handling blocks

License

The gem is available as open source under the terms of the MIT License.

Acknowledgments

Inspired by AWS Step Functions state language

Built for Ruby developers who need workflow orchestration

Designed for both simple and complex business processes

Author