Skip to main content

Hierarchical Execution in WSL

This guide provides a comprehensive overview of hierarchical execution in the Workflow Specification Language (WSL), covering both regular WSL and SimplifiedWSL syntax.

Table of Contents​

  1. Overview
  2. Architecture
  3. Workflow Types
  4. Context Sharing
  5. Regular WSL Syntax
  6. SimplifiedWSL Syntax
  7. Examples
  8. Best Practices

Overview​

Hierarchical execution allows you to organize workflows into three levels:

  • Solutions - Top-level orchestration of features and workflows
  • Features - Mid-level orchestration of workflows
  • Workflows - Low-level execution of actions

All levels share the same WorkerSessionContext, enabling seamless data flow across the entire execution hierarchy.

Architecture​

Execution Hierarchy​

┌─────────────────────────────────────┐
│ Solution │
│ - Orchestrates features/workflows │
│ - Highest level of abstraction │
└───────────────┬─────────────────────┘
│ Shared Context
▼
┌─────────────────────────────────────┐
│ Feature │
│ - Orchestrates workflows │
│ - Groups related functionality │
└───────────────┬─────────────────────┘
│ Shared Context
▼
┌─────────────────────────────────────┐
│ Workflow │
│ - Executes actions │
│ - Contains states and transitions │
└─────────────────────────────────────┘

Runner Architecture​

The engine provides three modular runners:

  1. SolutionRunner - Executes solution-type workflows

    • Can call features and workflows
    • Loads .wsl or .swsl files from disk
  2. FeatureRunner - Executes feature-type workflows

    • Can call workflows
    • Loads .wsl or .swsl files from disk
  3. WorkflowRunner - Executes workflow-type workflows

    • Executes actions
    • Loads .wsl or .swsl files from disk

Workflow Types​

Solution​

Purpose: Orchestrate features and workflows at the highest level

Use Cases:

  • Complete business solutions
  • Multi-feature applications
  • System-wide orchestration

Can Call:

  • Features
  • Workflows
  • Actions

Feature​

Purpose: Group related workflows into cohesive features

Use Cases:

  • Feature modules (e.g., payment processing)
  • Subsystem orchestration
  • Reusable functionality groups

Can Call:

  • Workflows
  • Actions

Workflow​

Purpose: Execute sequences of actions

Use Cases:

  • Individual business processes
  • Data transformations
  • Service integrations

Can Call:

  • Actions only

Context Sharing​

All hierarchical components share the same WorkerSessionContext, which provides:

  • Persistent Data: Values set in one component are accessible in all others
  • Session State: Track execution state across the hierarchy
  • Result Passing: Pass results between components seamlessly

Example Context Usage​

// In a workflow - set a value
context["user_id"] = "12345"
context["payment_amount"] = 100.00

// In a subsequent workflow or feature - access the value
userId := context["user_id"] // "12345"
amount := context["payment_amount"] // 100.00

Regular WSL Syntax​

Solution Declaration​

module payment_solution

solution complete_payment {
start: Initialize

state Initialize {
action context/Set(key: "solution_id", value: "sol_001")
on success -> CallPaymentFeature
}

state CallPaymentFeature {
action workflow/Call(name: "payment_feature")
on success -> CallNotificationFeature
}

state CallNotificationFeature {
action workflow/Call(name: "notification_feature")
on success -> Complete
}

state Complete {
action services/common/Response(message: "Solution completed")
end ok
}
}

Feature Declaration​

module payment_processing

feature payment_feature {
start: ValidatePayment

state ValidatePayment {
action workflow/Call(name: "validate_payment_workflow")
on success -> ProcessPayment
}

state ProcessPayment {
action workflow/Call(name: "process_payment_workflow")
on success -> Complete
}

state Complete {
action services/common/Response(message: "Feature completed")
end ok
}
}

Workflow Declaration​

module payment_validation

workflow validate_payment_workflow {
start: CheckAmount

state CheckAmount {
action payment/ValidateAmount(amount: $context.payment_amount)
on success -> CheckAccount
}

state CheckAccount {
action payment/ValidateAccount(userId: $context.user_id)
end ok
}
}

SimplifiedWSL Syntax​

SimplifiedWSL provides a streamlined syntax for hierarchical execution:

Solution (SimplifiedWSL)​

module payment_solution

solution complete_payment

const {
solution_id: "sol_001",
timeout: 5000
}

def errors.HandleError(level: "critical") as errorHandler -> .

# Initialize context
context.Set(key: "solution_id", value: $constants.solution_id) ->

# Call payment feature
payment.ProcessFeature() <- errorHandler ->

# Call notification feature
notification.SendFeature() <- errorHandler ->

# Complete
services/common.Response(message: "Solution completed") -> .

Feature (SimplifiedWSL)​

module payment_processing

feature payment_feature

const {
max_retries: 3
}

def errors.LogError() as errorHandler -> .

# Validate payment
payment.Validate() <- errorHandler ->

# Process payment
payment.Process(retries: $constants.max_retries) <- errorHandler ->

# Complete
services/common.Response(message: "Feature completed") -> .

Workflow (SimplifiedWSL)​

module payment_validation

workflow validate_payment

def errors.OnError() as errorHandler -> .

# Check amount
payment.ValidateAmount(amount: $context.payment_amount) <- errorHandler ->

# Check account
payment.ValidateAccount(userId: $context.user_id) <- errorHandler -> .

Examples​

Complete Hierarchical Example​

1. Solution File (solution_example.swsl)​

module ecommerce_solution

solution complete_checkout

const {
solution_name: "E-commerce Checkout",
version: "1.0.0"
}

def errors.HandleCritical(level: "critical") as criticalError -> .

# Set solution context
context.Set(key: "solution_name", value: $constants.solution_name) ->

# Call payment feature
payment.ProcessCheckout() <- criticalError ->

# Call notification feature
notification.NotifyUser() <- criticalError ->

# Finalize
services/common.Response(message: "Checkout completed", status: "success") -> .

2. Payment Feature File (feature_payment.swsl)​

module payment_processing

feature payment_checkout

const {
timeout: 5000,
retries: 3
}

def errors.LogError(level: "error") as errorHandler -> .

# Validate payment
payment.ValidatePayment(timeout: $constants.timeout) <- errorHandler ->

# Process payment
payment.ProcessPayment(retries: $constants.retries) <- errorHandler ->

# Send receipt
payment.SendReceipt() <- errorHandler -> .

3. Notification Feature File (feature_notification.swsl)​

module notification_processing

feature notification_service

def errors.LogError(level: "error") as errorHandler -> .

# Prepare notification
notification.Prepare(userId: $context.user_id) <- errorHandler ->

# Send notification
notification.Send(message: "Payment processed successfully") <- errorHandler -> .

4. Workflow Files​

Validate Payment Workflow (workflow_validate.swsl):

module payment_validation

workflow validate_payment

def errors.OnError() as errorHandler -> .

payment.CheckAmount(amount: $context.payment_amount) <- errorHandler ->
payment.CheckBalance(userId: $context.user_id) <- errorHandler -> .

Process Payment Workflow (workflow_process.swsl):

module payment_processing

workflow process_payment

def errors.OnError() as errorHandler -> .

payment.Charge(amount: $context.payment_amount) <- errorHandler ->
payment.UpdateBalance(userId: $context.user_id) <- errorHandler -> .

Execution Flow​

When you execute the solution:

  1. Solution sets context and calls features
  2. Payment Feature validates and processes payment
  3. Notification Feature sends notifications
  4. All components share the same context
  5. Errors propagate up through error handlers

Best Practices​

1. Clear Separation of Concerns​

  • Solutions: High-level business processes
  • Features: Cohesive functional modules
  • Workflows: Specific tasks

2. Context Management​

# Set values early in the hierarchy
context.Set(key: "user_id", value: "12345") ->
context.Set(key: "timestamp", value: $datetime.now()) ->

# Use values in lower levels
payment.Process(userId: $context.user_id, timestamp: $context.timestamp) ->

3. Error Handling​

# Define error handlers at each level
def errors.SolutionError(severity: "critical") as solutionError -> .
def errors.FeatureError(severity: "high") as featureError -> .
def errors.WorkflowError(severity: "medium") as workflowError -> .

# Use appropriate handler for each component
payment.ProcessFeature() <- solutionError ->
payment.ValidateWorkflow() <- featureError ->
payment.CheckAction() <- workflowError -> .

4. File Organization​

workflows/
├── solutions/
│ └── ecommerce_solution.swsl
├── features/
│ ├── payment_feature.swsl
│ └── notification_feature.swsl
└── workflows/
├── validate_workflow.swsl
└── process_workflow.swsl

5. Testing Strategy​

  • Test workflows independently first
  • Test features with mock workflows
  • Test solutions with integration tests
  • Verify context sharing between levels

6. Naming Conventions​

  • Solutions: *_solution (e.g., ecommerce_solution)
  • Features: *_feature (e.g., payment_feature)
  • Workflows: *_workflow or descriptive names (e.g., validate_payment)

Common Patterns​

Sequential Execution​

# Solution coordinates sequential features
feature:feature_one() ->
feature:feature_two() ->
feature:feature_three() -> .

Conditional Execution​

Use regular WSL for complex conditions:

state ProcessPayment {
action workflow/Call(name: "process_payment")
on success when $context.amount > 100 -> SendReceipt
on success when $context.amount <= 100 -> Complete
}

Parallel Execution​

Future enhancement - currently sequential only.

Troubleshooting​

Context Not Shared​

Issue: Values set in one component not accessible in another

Solution: Ensure all components use the same WorkerSessionContext instance

Workflow Not Found​

Issue: Called workflow/feature file not found

Solution: Verify file naming matches call and files are in the correct directory

Type Mismatch​

Issue: Calling feature from workflow level

Solution: Verify hierarchy: Solutions call features/workflows, Features call workflows, Workflows call actions

See Also​