WJb Docs - Intermediate

Learn workflows, persistence, scheduling, and production-ready patterns.

πŸš€ Start Here
🧩 Mental Model
🌊 Building Workflows
πŸ’₯ Failures & Control
πŸ‘€ Observation & Debugging
πŸ›  Practical Patterns
βœ… Working Examples
➑️ What’s Next

πŸ“₯ Import β†’ Process β†’ Notify

A practical sequential workflow that imports data, processes it, and sends a notification.

import
  ↓
process
  ↓
notify
  ↓
Complete

1. Input Models

public sealed class ImportInput
{
    public string Source { get; init; } = string.Empty;
}

public sealed class ProcessInput { public List<string> Records { get; init; } = new(); }

public sealed class NotifyInput { public int ProcessedCount { get; init; } public string AdminEmail { get; init; } = string.Empty; }


2. Actions

[ActionName("import")]
public sealed class ImportAction : JobAction<ImportInput>
{
    public override async Task<IActionResult> ExecuteAsync(
        ImportInput input, CancellationToken ct)
    {
        // Simulate importing records
        var records = new List<string>
        {
            "record-1",
            "record-2",
            "record-3"
        };

Console.WriteLine($"Imported {records.Count} records from {input.Source}");

return await NextAsync<ProcessAction>( new ProcessInput { Records = records }); } }

[ActionName("process")] public sealed class ProcessAction : JobAction<ProcessInput> { public override async Task<IActionResult> ExecuteAsync( ProcessInput input, CancellationToken ct) { // Simulate processing foreach (var record in input.Records) { Console.WriteLine($"Processing {record}"); }

return await NextAsync<NotifyAction>( new NotifyInput { ProcessedCount = input.Records.Count, AdminEmail = "admin@example.com" }); } }

[ActionName("notify")] public sealed class NotifyAction : JobAction<NotifyInput> { public override async Task<IActionResult> ExecuteAsync( NotifyInput input, CancellationToken ct) { Console.WriteLine( $"Notification sent to {input.AdminEmail}: " + $"{input.ProcessedCount} records processed");

return await CompleteAsync(); } }


3. Registration

var wjb = WJbBuilder.Create(store, cfg =>
{
    cfg.AddAction<ImportAction>();
    cfg.AddAction<ProcessAction>();
    cfg.AddAction<NotifyAction>();
});

4. Starting the Workflow

await wjb.EnqueueAsync("import",
    new ImportInput
    {
        Source = "customers.csv"
    });

5. Expected Output

Imported 3 records from customers.csv
Processing record-1
Processing record-2
Processing record-3
Notification sent to admin@example.com: 3 records processed

Key Point

This example shows a realistic multi-step pipeline:

  • Import loads the data
  • Process transforms it
  • Notify reports the outcome
Each step explicitly passes only the data needed by the next step.

An unhandled error has occurred. Reload πŸ—™

Rejoining the server...

Rejoin failed... trying again in seconds.

Failed to rejoin.
Please retry or reload the page.

The session has been paused by the server.

Failed to resume the session.
Please retry or reload the page.