Mediarq.Saga 1.5.1

dotnet add package Mediarq.Saga --version 1.5.1
                    
NuGet\Install-Package Mediarq.Saga -Version 1.5.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Mediarq.Saga" Version="1.5.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Mediarq.Saga" Version="1.5.1" />
                    
Directory.Packages.props
<PackageReference Include="Mediarq.Saga" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Mediarq.Saga --version 1.5.1
                    
#r "nuget: Mediarq.Saga, 1.5.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Mediarq.Saga@1.5.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Mediarq.Saga&version=1.5.1
                    
Install as a Cake Addin
#tool nuget:?package=Mediarq.Saga&version=1.5.1
                    
Install as a Cake Tool

Mediarq.Saga

Saga / process-manager primitives: persisted, correlated state across a sequence of notifications. Each step is a regular notification handler that loads its instance's state, mutates it, and saves it back — no orchestration DSL, no new dispatch pipeline.

dotnet add package Mediarq.Saga

Usage

builder.Services.AddMediarqSaga<OrderFulfillmentState>();
public sealed class OrderFulfillmentState : ISagaState
{
    public required Guid CorrelationId { get; init; }
    public bool IsComplete { get; set; }
    public bool PaymentReceived { get; set; }
}

public sealed class OnOrderPlaced(ISagaStore<OrderFulfillmentState> store)
    : SagaNotificationHandler<OrderPlacedEvent, OrderFulfillmentState>(store)
{
    protected override Guid GetCorrelationId(OrderPlacedEvent e) => e.OrderId;
    protected override OrderFulfillmentState CreateState(Guid correlationId) => new() { CorrelationId = correlationId };

    protected override Task HandleAsync(OrderPlacedEvent e, OrderFulfillmentState state, CancellationToken ct)
    {
        // e.g. outbox.Enqueue(new RequestPaymentCommand(e.OrderId)); — Mediarq.Outbox delivers it reliably.
        return Task.CompletedTask;
    }
}

public sealed class OnPaymentReceived(ISagaStore<OrderFulfillmentState> store)
    : SagaNotificationHandler<PaymentReceivedEvent, OrderFulfillmentState>(store)
{
    protected override Guid GetCorrelationId(PaymentReceivedEvent e) => e.OrderId;
    protected override OrderFulfillmentState CreateState(Guid correlationId) => new() { CorrelationId = correlationId };

    protected override Task HandleAsync(PaymentReceivedEvent e, OrderFulfillmentState state, CancellationToken ct)
    {
        state.PaymentReceived = true;
        state.IsComplete = true; // further notifications for this correlation id are ignored
        return Task.CompletedTask;
    }
}

OnOrderPlaced and OnPaymentReceived both resolve the same CorrelationId (the order id) from their respective events, so they read and write the same persisted OrderFulfillmentState instance across two separate notification dispatches — that shared, correlated state is what makes this a process manager rather than two unrelated handlers.

Pairing with the outbox

A step usually needs to trigger the next one. Enqueue that follow-up via Mediarq.Outbox's IOutbox.Enqueue from inside HandleAsync — it is staged on the same unit of work and only published once the transaction commits, so a crash between steps can't lose the trigger the way an in-process Publish call could.

Persistent stores

AddMediarqSaga<TState>() registers InMemorySagaStore<TState> — process-lifetime only, lost on restart. Register your own ISagaStore<TState> (e.g. backed by a database via Mediarq.EntityFrameworkCore) before calling AddMediarqSaga<TState>() to use it instead; the extension only fills in a default when nothing is already registered.

Learn more

Wiring extensions · Full README

MIT © Nicolas Rouffart

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.5.1 117 7/26/2026
1.5.0 113 7/26/2026
1.4.0 116 7/24/2026