Skip to content

Instantly share code, notes, and snippets.

@PiotrFerenc
Created March 13, 2025 10:34
Show Gist options
  • Save PiotrFerenc/c5a27d4a32f45af02702aab752257228 to your computer and use it in GitHub Desktop.
Save PiotrFerenc/c5a27d4a32f45af02702aab752257228 to your computer and use it in GitHub Desktop.
public interface IWorkflowStep
{
string Name { get; }
Task<WorkflowResult> ExecuteAsync(WorkflowContext context);
}
public class WorkflowResult
{
public bool Success { get; set; }
public string? Message { get; set; }
public static WorkflowResult SuccessResult() => new WorkflowResult { Success = true };
public static WorkflowResult Failure(string message) => new WorkflowResult { Success = false, Message = message };
}
public class WorkflowContext
{
public IDictionary<string, object> Data { get; } = new Dictionary<string, object>();
}
public class ConditionalStep : IWorkflowStep
{
public string Name { get; }
private readonly Func<WorkflowContext, bool> _condition;
private readonly IWorkflowStep _step;
public ConditionalStep(string name, Func<WorkflowContext, bool> condition, IWorkflowStep step)
{
Name = name;
_condition = condition;
_step = step;
}
public async Task<WorkflowResult> ExecuteAsync(WorkflowContext context)
{
if (_condition(context))
{
Console.WriteLine($"Executing conditional step: {Name}");
return await _step.ExecuteAsync(context);
}
Console.WriteLine($"Skipping step: {Name}");
return WorkflowResult.SuccessResult();
}
}
public class RetryStep : IWorkflowStep
{
public string Name { get; }
private readonly IWorkflowStep _step;
private readonly int _maxRetries;
public RetryStep(string name, IWorkflowStep step, int maxRetries = 3)
{
Name = name;
_step = step;
_maxRetries = maxRetries;
}
public async Task<WorkflowResult> ExecuteAsync(WorkflowContext context)
{
for (int attempt = 1; attempt <= _maxRetries; attempt++)
{
try
{
Console.WriteLine($"Attempt {attempt} for step: {Name}");
var result = await _step.ExecuteAsync(context);
if (result.Success) return result;
}
catch (Exception ex)
{
Console.WriteLine($"Error in step {Name}: {ex.Message}");
}
}
return WorkflowResult.Failure($"Step {Name} failed after {_maxRetries} attempts.");
}
}
public class ParallelStep : IWorkflowStep
{
public string Name { get; }
private readonly IList<IWorkflowStep> _steps;
public ParallelStep(string name, IEnumerable<IWorkflowStep> steps)
{
Name = name;
_steps = steps.ToList();
}
public async Task<WorkflowResult> ExecuteAsync(WorkflowContext context)
{
Console.WriteLine($"Executing parallel steps: {Name}");
var tasks = _steps.Select(step => step.ExecuteAsync(context)).ToArray();
var results = await Task.WhenAll(tasks);
if (results.All(r => r.Success))
return WorkflowResult.SuccessResult();
return WorkflowResult.Failure($"Parallel step {Name} failed.");
}
}
public class WorkflowEngine
{
private readonly IList<IWorkflowStep> _steps = new List<IWorkflowStep>();
public WorkflowEngine AddStep(IWorkflowStep step)
{
_steps.Add(step);
return this;
}
public async Task ExecuteAsync()
{
var context = new WorkflowContext();
foreach (var step in _steps)
{
var result = await step.ExecuteAsync(context);
if (!result.Success)
{
Console.WriteLine($"Workflow terminated at step {step.Name}: {result.Message}");
return;
}
}
Console.WriteLine("Workflow completed successfully.");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment