![]() |
VOOZH | about |
dotnet add package Pervaxis.Genesis.Workflow.AWS --version 3.4.4
NuGet\Install-Package Pervaxis.Genesis.Workflow.AWS -Version 3.4.4
<PackageReference Include="Pervaxis.Genesis.Workflow.AWS" Version="3.4.4" />
<PackageVersion Include="Pervaxis.Genesis.Workflow.AWS" Version="3.4.4" />Directory.Packages.props
<PackageReference Include="Pervaxis.Genesis.Workflow.AWS" />Project file
paket add Pervaxis.Genesis.Workflow.AWS --version 3.4.4
#r "nuget: Pervaxis.Genesis.Workflow.AWS, 3.4.4"
#:package Pervaxis.Genesis.Workflow.AWS@3.4.4
#addin nuget:?package=Pervaxis.Genesis.Workflow.AWS&version=3.4.4Install as a Cake Addin
#tool nuget:?package=Pervaxis.Genesis.Workflow.AWS&version=3.4.4Install as a Cake Tool
AWS Step Functions implementation for the Pervaxis Genesis platform. Orchestrate complex workflows and distributed processes.
dotnet add package Pervaxis.Genesis.Workflow.AWS
{
"Workflow": {
"Region": "us-east-1",
"StateMachineArns": {
"OrderProcessing": "arn:aws:states:us-east-1:123456789012:stateMachine:OrderWorkflow",
"PaymentProcessing": "arn:aws:states:us-east-1:123456789012:stateMachine:PaymentWorkflow",
"InventorySync": "arn:aws:states:us-east-1:123456789012:stateMachine:InventoryWorkflow"
},
"ExecutionNamePrefix": "pervaxis",
"MaxRetries": 3,
"RequestTimeoutSeconds": 30,
"UseLocalEmulator": false,
"LocalEmulatorUrl": "http://localhost:4566"
}
}
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
Region |
string | Yes | - | AWS region (e.g., "us-east-1") |
StateMachineArns |
Dictionary | Yes | - | Map of workflow names to state machine ARNs |
ExecutionNamePrefix |
string | No | workflow name | Prefix for execution names |
MaxRetries |
int | No | 3 | Maximum retry attempts |
RequestTimeoutSeconds |
int | No | 30 | Request timeout in seconds |
UseLocalEmulator |
bool | No | false | Use LocalStack for local testing |
LocalEmulatorUrl |
string | No | - | LocalStack endpoint URL |
using Pervaxis.Genesis.Workflow.AWS.Extensions;
var builder = WebApplication.CreateBuilder(args);
// Add workflow services from appsettings.json
builder.Services.AddGenesisWorkflow(
builder.Configuration.GetSection("Workflow"));
var app = builder.Build();
builder.Services.AddGenesisWorkflow(options =>
{
options.Region = "us-east-1";
options.StateMachineArns = new Dictionary<string, string>
{
["OrderProcessing"] = "arn:aws:states:us-east-1:123456789012:stateMachine:OrderWorkflow"
};
options.UseLocalEmulator = true;
options.LocalEmulatorUrl = new Uri("http://localhost:4566");
});
using Pervaxis.Core.Abstractions.Genesis.Modules;
public class OrderService
{
private readonly IWorkflow _workflow;
public OrderService(IWorkflow workflow)
{
_workflow = workflow;
}
public async Task ProcessOrderAsync(Order order, CancellationToken ct)
{
var input = new
{
orderId = order.Id,
customerId = order.CustomerId,
items = order.Items,
totalAmount = order.TotalAmount
};
try
{
var executionArn = await _workflow.StartExecutionAsync(
"OrderProcessing",
input,
ct);
_logger.LogInformation("Started order workflow: {ExecutionArn}", executionArn);
// Store executionArn for later status checks
order.WorkflowExecutionArn = executionArn;
await _db.SaveChangesAsync(ct);
}
catch (GenesisException ex)
{
_logger.LogError(ex, "Failed to start order workflow");
throw;
}
}
}
public async Task<string> GetOrderStatusAsync(string executionArn, CancellationToken ct)
{
var status = await _workflow.GetExecutionStatusAsync(executionArn, ct);
return status switch
{
"RUNNING" => "Processing",
"SUCCEEDED" => "Completed",
"FAILED" => "Failed",
"TIMED_OUT" => "Timed Out",
"ABORTED" => "Cancelled",
_ => "Unknown"
};
}
public record OrderResult(string OrderId, string Status, decimal FinalAmount);
public async Task<OrderResult?> GetOrderResultAsync(string executionArn, CancellationToken ct)
{
// Returns null if execution hasn't completed yet
var result = await _workflow.GetExecutionOutputAsync<OrderResult>(executionArn, ct);
if (result is null)
{
_logger.LogInformation("Order workflow still running");
return null;
}
_logger.LogInformation("Order {OrderId} completed with status {Status}",
result.OrderId, result.Status);
return result;
}
public async Task CancelOrderAsync(string executionArn, CancellationToken ct)
{
var stopped = await _workflow.StopExecutionAsync(executionArn, ct);
if (stopped)
{
_logger.LogInformation("Order workflow cancelled: {ExecutionArn}", executionArn);
}
else
{
_logger.LogWarning("Failed to cancel order workflow: {ExecutionArn}", executionArn);
}
}
{
"Comment": "Order processing workflow",
"StartAt": "ValidateOrder",
"States": {
"ValidateOrder": {
"Type": "Task",
"Resource": "arn:aws:lambda:us-east-1:123456789012:function:ValidateOrder",
"Next": "ProcessPayment",
"Catch": [{
"ErrorEquals": ["ValidationError"],
"Next": "OrderFailed"
}]
},
"ProcessPayment": {
"Type": "Task",
"Resource": "arn:aws:lambda:us-east-1:123456789012:function:ProcessPayment",
"Next": "UpdateInventory",
"Catch": [{
"ErrorEquals": ["PaymentError"],
"Next": "PaymentFailed"
}]
},
"UpdateInventory": {
"Type": "Task",
"Resource": "arn:aws:lambda:us-east-1:123456789012:function:UpdateInventory",
"Next": "OrderCompleted"
},
"OrderCompleted": {
"Type": "Succeed"
},
"OrderFailed": {
"Type": "Fail",
"Error": "OrderValidationFailed",
"Cause": "Order validation failed"
},
"PaymentFailed": {
"Type": "Fail",
"Error": "PaymentProcessingFailed",
"Cause": "Payment processing failed"
}
}
}
# Create state machine
aws stepfunctions create-state-machine \
--name OrderWorkflow \
--definition file://order-workflow.json \
--role-arn arn:aws:iam::123456789012:role/StepFunctionsExecutionRole
# Get ARN (use this in appsettings.json)
aws stepfunctions list-state-machines --query "stateMachines[?name=='OrderWorkflow'].stateMachineArn" --output text
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"states:StartExecution",
"states:DescribeExecution",
"states:StopExecution"
],
"Resource": "arn:aws:states:us-east-1:123456789012:stateMachine:*"
},
{
"Effect": "Allow",
"Action": [
"states:DescribeExecution"
],
"Resource": "arn:aws:states:us-east-1:123456789012:execution:*"
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"lambda:InvokeFunction"
],
"Resource": "arn:aws:lambda:us-east-1:123456789012:function:*"
},
{
"Effect": "Allow",
"Action": [
"dynamodb:GetItem",
"dynamodb:PutItem",
"dynamodb:UpdateItem"
],
"Resource": "arn:aws:dynamodb:us-east-1:123456789012:table/*"
}
]
}
For local development without AWS:
services:
localstack:
image: localstack/localstack:latest
ports:
- "4566:4566"
environment:
- SERVICES=stepfunctions,lambda
- DEBUG=1
- DATA_DIR=/tmp/localstack/data
- LAMBDA_EXECUTOR=docker
- DOCKER_HOST=unix:///var/run/docker.sock
volumes:
- "./localstack-data:/tmp/localstack"
- "/var/run/docker.sock:/var/run/docker.sock"
{
"Workflow": {
"Region": "us-east-1",
"StateMachineArns": {
"TestWorkflow": "arn:aws:states:us-east-1:000000000000:stateMachine:TestWorkflow"
},
"UseLocalEmulator": true,
"LocalEmulatorUrl": "http://localhost:4566"
}
}
# Set AWS endpoint for LocalStack
export AWS_ENDPOINT_URL=http://localhost:4566
# Create state machine
awslocal stepfunctions create-state-machine \
--name TestWorkflow \
--definition file://test-workflow.json \
--role-arn arn:aws:iam::000000000000:role/DummyRole
# List state machines
awslocal stepfunctions list-state-machines
Step Functions returns the following status values:
| Status | Description |
|---|---|
RUNNING |
Execution is in progress |
SUCCEEDED |
Execution completed successfully |
FAILED |
Execution failed due to an error |
TIMED_OUT |
Execution exceeded timeout limit |
ABORTED |
Execution was manually stopped |
For long-running workflows, implement a polling pattern:
public async Task<OrderResult> WaitForCompletionAsync(
string executionArn,
TimeSpan timeout,
CancellationToken ct)
{
var pollInterval = TimeSpan.FromSeconds(5);
var stopwatch = Stopwatch.StartNew();
while (stopwatch.Elapsed < timeout)
{
var status = await _workflow.GetExecutionStatusAsync(executionArn, ct);
if (status == "SUCCEEDED")
{
var result = await _workflow.GetExecutionOutputAsync<OrderResult>(executionArn, ct);
return result ?? throw new InvalidOperationException("No output from succeeded execution");
}
if (status == "FAILED" || status == "TIMED_OUT" || status == "ABORTED")
{
throw new InvalidOperationException($"Workflow failed with status: {status}");
}
await Task.Delay(pollInterval, ct);
}
throw new TimeoutException($"Workflow did not complete within {timeout}");
}
Instead of polling, use EventBridge to receive execution completion events:
// Subscribe to Step Functions execution events in EventBridge
// Rule pattern:
{
"source": ["aws.states"],
"detail-type": ["Step Functions Execution Status Change"],
"detail": {
"status": ["SUCCEEDED", "FAILED", "ABORTED", "TIMED_OUT"]
}
}
Then handle events in your application via SQS/SNS subscription.
Problem: GenesisException: Execution not found
Solution:
arn:aws:states:)Problem: GenesisException: State machine ARN not found for workflow: XYZ
Solution:
StateMachineArns dictionary (case-sensitive)Problem: Validation fails with StartsWith("arn:aws:states:")
Solution:
arn:aws:states: (not arn:aws:stepfunctions:)arn:aws:states:region:account:stateMachine:nameaws stepfunctions list-state-machinesProblem: JsonException when getting execution output
Solution:
T matches the structure of Step Functions outputProblem: Execution status is FAILED immediately after start
Solution:
State Machine Design
Execution Names
ExecutionNamePrefixInput/Output
Error Handling
GenesisException specificallyMonitoring
Cost Optimization
IWorkflow)Copyright © 2026 Clarivex Technologies Private Limited. All rights reserved.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 net10.0 is compatible. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
This package is not used by any NuGet packages.
This package is not used by any popular GitHub repositories.