Franz.Common.Messaging.Sagas 2.0.2

dotnet add package Franz.Common.Messaging.Sagas --version 2.0.2
                    
NuGet\Install-Package Franz.Common.Messaging.Sagas -Version 2.0.2
                    
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="Franz.Common.Messaging.Sagas" Version="2.0.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Franz.Common.Messaging.Sagas" Version="2.0.2" />
                    
Directory.Packages.props
<PackageReference Include="Franz.Common.Messaging.Sagas" />
                    
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 Franz.Common.Messaging.Sagas --version 2.0.2
                    
#r "nuget: Franz.Common.Messaging.Sagas, 2.0.2"
                    
#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 Franz.Common.Messaging.Sagas@2.0.2
                    
#: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=Franz.Common.Messaging.Sagas&version=2.0.2
                    
Install as a Cake Addin
#tool nuget:?package=Franz.Common.Messaging.Sagas&version=2.0.2
                    
Install as a Cake Tool

πŸ“¦ Franz.Common.Messaging.Sagas

Version 1.7.5 β€” Distributed Orchestration Engine for the Franz Framework

Franz.Common.Messaging.Sagas provides long-running workflow orchestration, distributed coordination, and deterministic state machines fully integrated into the Franz architecture.

Sagas in Franz unify:

  • Microservice coordination
  • Async transactional consistency
  • Compensating workflows
  • Message-driven state transitions
  • Outbox-based reliability

They operate transport-agnostically and integrate seamlessly with:

  • Franz.Common.Messaging
  • Franz.Common.Mediator
  • Kafka
  • RabbitMQ
  • Azure CosmosDB
  • MongoDB
  • EntityFramework
  • In-memory transient orchestration

πŸ”– Current Version: 2.0.2


πŸš€ What’s New in v1.7.5

βœ” CosmosDB & Mongo-backed Saga Stores

New persistence providers added:

  • MongoSagaRepository
  • CosmosSagaRepository

Both support:

  • Deterministic serialization (JsonSagaStateSerializer)
  • Concurrency tokens
  • Timestamped audit markers
  • Partition-aware storage (CosmosDB)

βœ” Deterministic Saga ID & State Rules

Saga identity now follows one deterministic rule:

SagaId = derived from IMessageCorrelation<T> interface

This eliminates ambiguity across transports and persistence layers.


βœ” Execution Pipeline Improvements

  • Fully async-safe execution
  • Deterministic handler invocation
  • Better error propagation
  • Handler return types aligned with Task<ISagaTransition>

βœ” Improved DI Boot Sequence

All saga infrastructure is now guaranteed to resolve before message listeners start:

  • SagaRouter registered early
  • SagaOrchestrator registered before Messaging listeners
  • Automatic discovery and finalization via BuildFranzSagas()

βœ” Null-Safety + .NET 10 Compliance

The entire Saga engine is now:

  • <Nullable>enable
  • <TreatWarningsAsErrors>true>
  • Aligned with .NET 10 runtime

βœ” Stabilized Mapping & Reflection

  • Stronger validation in SagaRegistration
  • Improved scanning for Start, Step, Compensation handlers
  • Unified contract resolution

βœ” Bug Fixes

  • Fixed handler discovery with ICompensateWith<>
  • Fixed rare DI timing issues
  • Fixed correlation-based saga continuation rules

🧩 Core Components

The Saga engine is composed of:

ISaga<TState>
    ↓
SagaRegistration
    ↓
SagaRouter
    ↓
SagaOrchestrator
    ↓
SagaExecutionPipeline
    ↓
ISagaRepository (EF / Mongo / Cosmos / Memory)
    ↓
ISagaAuditSink

🧩 Defining a Saga

A complete saga is defined by:

public sealed class OrderSaga :
    SagaBase<OrderState>,
    IStartWith<OrderCreated>,
    IHandle<PaymentAccepted>,
    ICompensateWith<PaymentFailed>,
    IMessageCorrelation<OrderCreated>,
    IMessageCorrelation<PaymentFailed>
{
    public override Task OnCreatedAsync(ISagaContext ctx, CancellationToken ct)
    {
        State.Id = GetCorrelationId((OrderCreated)ctx.Message);
        State.CreatedAt = DateTime.UtcNow;
        return Task.CompletedTask;
    }

    public Task<ISagaTransition> HandleAsync(OrderCreated msg, ISagaContext ctx, CancellationToken ct)
        => SagaTransition.Continue(null);

    public Task<ISagaTransition> HandleAsync(PaymentAccepted msg, ISagaContext ctx, CancellationToken ct)
        => SagaTransition.Continue(null);

    public Task<ISagaTransition> HandleAsync(PaymentFailed msg, ISagaContext ctx, CancellationToken ct)
        => SagaTransition.Continue(null);

    public string GetCorrelationId(OrderCreated message) => message.OrderId;
    public string GetCorrelationId(PaymentFailed message) => message.OrderId;
}

Handler discovery uses:

  • IStartWith<TEvent>
  • IHandle<TEvent>
  • ICompensateWith<TEvent>

πŸ—‚οΈ Registering Sagas

var builder = services.AddFranzSagas(opts =>
{
    opts.ValidateMappings = true;
});

builder.AddSaga<OrderSaga>();
builder.AddSaga<PaymentSaga>();

services.AddFranzMediator(…);
services.AddRabbitMQMessaging(…);

var app = host.Build();
app.Services.BuildFranzSagas();

βš™οΈ Persistence Providers (1.7.5)

Provider Package / Class Status
InMemory InMemorySagaRepository βœ“ Stable
EntityFramework EfSagaRepository βœ“ Production
MongoDB MongoSagaRepository βœ“ New in 1.7.5
Cosmos DB CosmosSagaRepository βœ“ New in 1.7.5
Redis RedisSagaRepository βœ“ Stable
Kafka Compaction (future provider) βœ“ Stable

πŸ“ Saga State Model

All saga states must implement:

public interface ISagaState
{
    string? ConcurrencyToken { get; set; }
    DateTime UpdatedAt { get; set; }
}

And optionally:

public interface ISagaStateWithId
{
    string Id { get; set; }
}

🎯 Execution Pipeline

Wraps each handler:

await _pipeline.ExecuteAsync(async () =>
{
    var result = handler.Invoke(...);
    if (result is Task t) await t;
});

Allows user-defined middlewares:

  • telemetry
  • retries
  • tracing
  • error behavior

🧾 Auditing & Logging

SagaLogEvents provides structured logs for all key lifecycle events:

  • Saga Start
  • Step Execution
  • Compensation
  • Outgoing message
  • Errors

Default auditing sink:

ISagaAuditSink = DefaultSagaAuditSink

Override with:

builder.AddAuditSink<MyElasticSink>();

πŸ§ͺ Testing

For unit tests:

services
    .AddFranzSagas(o => o.ValidateMappings = true)
    .AddSaga<TestSaga>();

services.AddSingleton<ISagaRepository, InMemorySagaRepository>();

The in-memory store is:

  • deterministic
  • instant
  • ideal for workflow validation

🧱 Design Philosophy

The Saga engine adheres to Franz’s core principles:

Principle Meaning
Deterministic Saga identity, mapping, and execution order are guaranteed.
Modular Stores, handlers, and audit sinks are fully pluggable.
Transport-agnostic Kafka, RabbitMQ, HTTP, or custom transports.
Zero runtime reflection Only startup scanning.
Safe by default Built-in validation + null-safety.

v2.0.1 – Internal Modernization

  • Messaging and infrastructure refactored for async, thread-safety, and modern .NET 10 patterns.
  • All APIs remain fully backward compatible.
  • Tests, listeners, and pipeline components modernized.
Product Compatible and additional computed target framework versions.
.NET 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
2.0.2 82 3/30/2026
2.0.1 81 3/29/2026
1.7.8 90 3/2/2026
1.7.7 116 1/31/2026
1.7.6 100 1/22/2026
1.7.5 107 1/10/2026
1.7.4 102 12/27/2025
1.7.3 194 12/22/2025
1.7.2 182 12/21/2025
1.7.1 128 12/20/2025
1.7.0 291 12/16/2025
1.6.21 213 11/27/2025