Round #516
09 May 2026, 20:08· csharp· qwen2.5-coder-7b-instruct· r13-clean-hints
- Complexity
- band 0
- ZP / UO / OBS
- 5 / 0 / 2
- Journey weight
- 356
- Lightshift ΔL
- —
Prompt
Write a distributed transaction coordinator using the Saga pattern
Zero-point index (what the engine surfaced)
ZPI-ZPI-0025 | 2026-05-09T20:08:09Z
Write a distributed transaction coordinator using the Saga pattern
ZERO POINT — 5 entries (structural invariants)
● hsl(27.69, 100%, 50%) async [feature]
● hsl(145.64, 100%, 44%) Task of T [feature]
● hsl(7.18, 100%, 50%) class [feature]
● hsl(0.00, 100%, 50%) public [feature]
● hsl(84.10, 100%, 50%) namespace [feature]
UNOBSERVED — 0 entries (implied truths)
OBSERVED — 2 entries (explicit in request)
◉ hsl(85.13, 100%, 50%) using [feature]
◉ hsl(234.87, 100%, 50%) using [feature]
COMPLEXITY │ 7 entries │ spread: 150° │ band: LOW
Baseline response (no ZPI)
Creating a distributed transaction coordinator using the Saga pattern involves several steps. The Saga pattern is a design pattern used to manage transactions across multiple services in a distributed system. It ensures that all services involved in a transaction either complete successfully or roll back if any part of the transaction fails.
Below is a simplified example of how you might implement a distributed transaction coordinator using the Saga pattern in C#. This example assumes you have a basic understanding of .NET and asynchronous programming.
### Step 1: Define the Saga Interface
First, define an interface for your saga. This interface will include methods to start, complete, and compensate each step of the saga.
```csharp
public interface ISaga
{
Task Start();
Task Complete();
Task Compensate();
}
```
### Step 2: Implement the Saga Steps
Next, implement the individual steps of your saga. Each step should have a corresponding compensation method to handle failures.
```csharp
public class OrderSaga : ISaga
{
private readonly IOrderService _orderService;
private readonly IPaymentService _paymentService;
public OrderSaga(IOrderService orderService, IPaymentService paymentService)
{
_orderService = orderService;
_paymentService = paymentService;
}
public async Task Start()
{
// Step 1: Create Order
var orderId = await _orderService.CreateOrderAsync();
// Step 2: Process Payment
var paymentId = await _paymentService.ProcessPaymentAsync(orderId);
// Store the state of the saga
// For simplicity, we'll use a dictionary to store the state
SagaState.Current["OrderId"] = orderId;
SagaState.Current["PaymentId"] = paymentId;
}
public async Task Complete()
{
var orderId = (int)SagaState.Current["OrderId"];
await _orderService.CompleteOrderAsync(orderId);
}
public async Task Compensate()
{
// Step 1: Refund Payment
var paymentId = (int)SagaState.Current["PaymentId"];
await _paymentService.RefundPaymentAsync(paymentId);
// Step 2: Cancel Order
var orderId = (int)SagaState.Current["OrderId"];
await _orderService.CancelOrderAsync(orderId);
}
}
```
### Step 3: Implement the Saga State Management
Create a simple state management class to store the state of the saga.
```csharp
public static class SagaState
{
public static readonly ConcurrentDictionary<string, object> Current = new ConcurrentDictionary<string, object>();
}
```
### Step 4: Create Service Interfaces and Implementations
Define service interfaces and their implementations. These services will interact with your distributed system's components.
```csharp
public interface IOrderService
{
Task<int> CreateOrderAsync();
Task CompleteOrderAsync(int orderId);
Task CancelOrderAsync(int orderId);
}
public class OrderService : IOrderService
{
public async Task<int> CreateOrderAsync()
{
// Simulate creating an order
return 123;
}
public async Task CompleteOrderAsync(int orderId)
{
// Simulate completing an order
}
public async Task CancelOrderAsync(int orderId)
{
// Simulate canceling an order
}
}
public interface IPaymentService
{
Task<int> ProcessPaymentAsync(int orderId);
Task RefundPaymentAsync(int paymentId);
}
public class PaymentService : IPaymentService
{
public async Task<int> ProcessPaymentAsync(int orderId)
{
// Simulate processing a payment
return 456;
}
public async Task RefundPaymentAsync(int paymentId)
{
// Simulate refunding a payment
}
}
```
### Step 5: Create the Saga Coordinator
Finally, create a saga coordinator that will manage the execution of the saga.
```csharp
public class SagaCoordinator
{
private readonly ISaga _saga;
public SagaCoordinator(ISaga saga)
{
_saga = saga;
}
public async Task ExecuteSaga()
{
try
{
await _saga.Start();
await _saga.Complete();
}
catch (Exception ex)
{
await _saga.Compensate();
throw new Exception("Saga failed and was compensated", ex);
}
}
}
```
### Step 6: Use the Saga Coordinator
You can now use the saga coordinator to execute your saga.
```csharp
class Program
{
static async Task Main(string[] args)
{
var orderService = new OrderService();
var paymentService = new PaymentService();
var saga = new OrderSaga(orderService, paymentService);
var coordinator = new SagaCoordinator(saga);
await coordinator.ExecuteSaga();
}
}
```
### Summary
This example provides a basic implementation of a distributed transaction coordinator using the Saga pattern in C#. The `ISaga` interface defines the methods for starting, completing, and compensating the saga. Each step of the saga is implemented as a method in the `OrderSaga` class. The `SagaCoordinator` manages the execution of the saga, handling exceptions by compensating if necessary.
This example is simplified and does not include many real-world considerations such as distributed transactions, retries, or error handling. In a production environment, you would need to implement these features to ensure robustness and reliability.
Enhanced response (with ZPI)
To implement a distributed transaction coordinator using the Saga pattern, we'll use the following technologies:
1. **MassTransit**: A message broker and transport library for .NET that supports AMQP (Advanced Message Queuing Protocol).
2. **Entity Framework Core**: An ORM for .NET that allows us to interact with databases.
3. **Distributed Transactions**: To handle distributed transactions, we'll use the built-in `System.Transactions` namespace.
First, let's install the necessary NuGet packages:
```sh
dotnet add package MassTransit
dotnet add package MassTransit.EntityFrameworkCoreIntegration
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
```
Next, we'll define our domain model and message contracts. For simplicity, let's assume we have two services: `OrderService` and `InventoryService`. Each service will handle a part of the transaction.
### Domain Model
```csharp
public class Order
{
public int Id { get; set; }
public string CustomerId { get; set; }
public decimal TotalAmount { get; set; }
public bool IsCompleted { get; set; }
}
public class InventoryItem
{
public int Id { get; set; }
public string ProductName { get; set; }
public int Quantity { get; set; }
}
```
### Message Contracts
```csharp
public interface IOrderCreated
{
Guid OrderId { get; set; }
string CustomerId { get; set; }
decimal TotalAmount { get; set; }
}
public interface IInventoryItemReserved
{
Guid OrderId { get; set; }
int InventoryItemId { get; set; }
int ReservedQuantity { get; set; }
}
public interface IOrderCompleted
{
Guid OrderId { get; set; }
}
```
### Saga Definition
```csharp
using MassTransit;
using System.Threading.Tasks;
public class OrderSaga : MassTransit.SagaStateMachine<OrderSagaState>
{
public OrderSaga()
{
InstanceState(x => x.CurrentState);
Event(() => OrderCreated, x => x.CorrelateById(context => context.Message.OrderId));
When(OrderCreated, context =>
{
return context.Initiate(ReserveInventory);
});
Event(() => InventoryItemReserved, x => x.CorrelateById(context => context.Message.OrderId));
When(InventoryItemReserved, context =>
{
return context.Then(async _ =>
{
// Update the order status to completed
await context.Saga.MarkOrderAsCompleted();
});
});
Event(() => OrderCompleted, x => x.CorrelateById(context => context.Message.OrderId));
When(OrderCompleted, context =>
{
return context.Complete();
});
}
public State ReservedInventory { get; private set; }
public State Completed { get; private set; }
public Event<IOrderCreated> OrderCreated { get; private set; }
public Event<IInventoryItemReserved> InventoryItemReserved { get; private set; }
public Event<IOrderCompleted> OrderCompleted { get; private set; }
public async Task MarkOrderAsCompleted()
{
// Logic to mark the order as completed
}
}
```
### Saga State
```csharp
public class OrderSagaState : SagaStateMachineInstance, IVersionedSagaInstance
{
public Guid CorrelationId { get; set; }
public int Version { get; set; }
public bool IsCompleted { get; set; }
}
```
### Service Implementation
#### OrderService
```csharp
public class OrderService
{
private readonly IBus _bus;
public OrderService(IBus bus)
{
_bus = bus;
}
public async Task CreateOrder(string customerId, decimal totalAmount)
{
var orderId = Guid.NewGuid();
await _bus.Publish<IOrderCreated>(new { OrderId = orderId, CustomerId = customerId, TotalAmount = totalAmount });
}
}
```
#### InventoryService
```csharp
public class InventoryService
{
private readonly IBus _bus;
public InventoryService(IBus bus)
{
_bus = bus;
}
public async Task ReserveInventory(Guid orderId, int inventoryItemId, int reservedQuantity)
{
await _bus.Publish<IInventoryItemReserved>(new { OrderId = orderId, InventoryItemId = inventoryItemId, ReservedQuantity = reservedQuantity });
}
}
```
### MassTransit Configuration
```csharp
using MassTransit;
using Microsoft.EntityFrameworkCore;
public class OrderDbContext : DbContext
{
public DbSet<Order> Orders { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("YourConnectionStringHere");
}
}
public class OrderSagaDbContext : SagaDbContext<OrderSagaState>
{
public OrderSagaDbContext(DbContextOptions<OrderSagaDbContext> options) : base(options)
{
}
public DbSet<OrderSagaState> OrderSagaStates { get; set; }
}
public class MassTransitConfig
{
public static void ConfigureServices(IServiceCollection services, string connectionString)
{
services.AddMassTransit(x =>
{
x.AddEntityFrameworkOutbox<OrderDbContext>(options => options.UseSqlServer(connectionString));
x.AddSagaStateMachine<OrderSaga, OrderSagaState>()
.Entity(e =>
{
e.ConfigureEntityFramework(options => options.UseSqlServer(connectionString));
e.SetSchema("dbo");
});
x.UsingRabbitMq((context, cfg) =>
{
cfg.Host("localhost", "/", h =>
{
h.Username("guest");
h.Password("guest");
});
cfg.ReceiveEndpoint("order_created_queue", e =>
{
e.ConfigureConsumer<OrderCreatedConsumer>(context);
});
cfg.ReceiveEndpoint("inventory_item_reserved_queue", e =>
{
e.ConfigureConsumer<InventoryItemReservedConsumer>(context);
});
});
});
services.AddDbContext<OrderDbContext>(options => options.UseSqlServer(connectionString));
services.AddDbContext<OrderSagaDbContext>(options => options.UseSqlServer(connectionString));
}
}
```
### Consumers
#### OrderCreatedConsumer
```csharp
public class OrderCreatedConsumer : IConsumer<IOrderCreated>
{
private readonly OrderService _orderService;
public OrderCreatedConsumer(OrderService orderService)
{
_orderService = orderService;
}
public async Task Consume(ConsumeContext<IOrderCreated> context)
{
await _orderService.CreateOrder(context.Message.CustomerId, context.Message.TotalAmount);
}
}
```
#### InventoryItemReservedConsumer
```csharp
public class InventoryItemReservedConsumer : IConsumer<IInventoryItemReserved>
{
private readonly InventoryService _inventoryService;
public InventoryItemReservedConsumer(InventoryService inventoryService)
{
_inventoryService = inventoryService;
}
public async Task Consume(ConsumeContext<IInventoryItemReserved> context)
{
await _inventoryService.ReserveInventory(context.Message.OrderId, context.Message.InventoryItemId, context.Message.ReservedQuantity);
}
}
```
### DI Registration
```csharp
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
var connectionString = "YourConnectionStringHere";
MassTransitConfig.ConfigureServices(services, connectionString);
services.AddScoped<OrderService>();
services.AddScoped<InventoryService>();
services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
```
### Explanation
1. **Domain Model**: We define the `Order` and `InventoryItem` entities.
2. **Message Contracts**: We define messages that will be exchanged between services.
3. **Saga Definition**: We define a saga to manage the distributed transaction using the Saga pattern.
4. **Service Implementation**: We implement services that handle specific parts of the transaction.
5. **MassTransit Configuration**: We configure MassTransit to use RabbitMQ as the message broker and Entity Framework Core for persistence.
6. **Consumers**: We define consumers that handle incoming messages and delegate work to the appropriate service.
7. **DI Registration**: We register services and MassTransit in the dependency injection container.
This implementation follows the Saga pattern to manage distributed transactions, ensuring that all steps are completed successfully or rolled back if any step fails.
Grader chain
Each grader reads the same baseline + enhanced pair and casts an independent verdict. Disagreement is the framework's own signal — not noise to be averaged away.
V1samba/Meta-Llama-3.3-70B-Instruct
BetterV4qwen2.5-coder-3b-instruct
BetterV5openrouter/qwen/qwen3-235b-a22b-2507
BetterV7qwen2.5-coder-7b-instruct
BetterV8openai/gpt-4.1
BetterV9anthropic/claude-opus-4-7
BetterV12openai/gpt-4o
BetterComments
Our grader said what it said. What do you say? Comment as a guest below.
No comments yet. Be the first to say what you make of this round.