| Pattern | Consistency | Scale | Complexity | Suitable For |
|---|---|---|---|---|
| Pessimistic Locking | Strong | Low | Low | Monoliths, legacy systems |
| Saga Pattern | Eventual | High | High | Microservices |
| CQRS | Eventual | High | High | Read-heavy systems, DDD |
| Mediator | Depends | Med | Medium | Coordinated command handling |
| Event Sourcing | Eventual | High | High | Auditable systems |
| Two-Phase Commit | Strong | Low | High | Cross-DB transactional ops |
| Outbox Pattern | Eventual | High | Medium | DB + messaging consistency |
Two powerful transaction patterns for modern applications: AtomicService for ACID transactions and SagaPatternService for distributed transactions with eventual consistency.
π― Overview
This library offers two complementary approaches to handle transactions in both monolithic and distributed architectures:
| Pattern | Use Case | Consistency | Scope | Recovery |
|---|---|---|---|---|
| AtomicService | Single service/database | Immediate (ACID) | Local operations | Transaction rollback |
| SagaPatternService | Multiple services | Eventual | Distributed operations | Compensating actions |
β¨ Features
π‘οΈ AtomicService (ACID Transactions)
- Hierarchical Transactions - Parent-child transaction support
- Enhanced Retry Logic - Configurable retry with exponential backoff
- Performance Monitoring - Built-in metrics and correlation tracking
- Multiple Isolation Levels - ReadCommitted, RepeatableRead, Serializable
- Deadlock Detection - Smart handling of transient database errors
- Flexible Configuration - Per-operation timeouts and retry policies
π SagaPatternService (Distributed Transactions)
- Compensating Actions - Automatic rollback through compensation
- State Persistence - Durable saga state with resume capability
- Step Orchestration - Sequential, conditional, and parallel execution
- Error Recovery - Comprehensive error handling and retry strategies
- Monitoring & Observability - Full saga lifecycle tracking
- Integration Ready - Works seamlessly with AtomicService
π Quick Start
Basic Setup
// Program.cs
using Persistence.Database;
var builder = WebApplication.CreateBuilder(args);
// Configure AtomicService
builder.Services.Configure<AtomicServiceOptions>(options =>
{
options.MaxRetryAttempts = 3;
options.TransactionTimeout = TimeSpan.FromMinutes(5);
options.DefaultIsolationLevel = IsolationLevel.ReadCommitted;
});
// Configure SagaPatternService
builder.Services.Configure<SagaPatternOptions>(options =>
{
options.StepTimeout = TimeSpan.FromMinutes(5);
options.MaxRetryAttempts = 3;
options.EnableStateLogging = true;
});
// Register services
builder.Services.AddScoped<IAtomicService, AtomicService>();
builder.Services.AddScoped<ISagaStateStore, InMemorySagaStateStore>();
builder.Services.AddScoped<ISagaPatternService, SagaPatternService>();
var app = builder.Build();
π Usage Examples
AtomicService - Local ACID Transactions
public class OrderService
{
private readonly IAtomicService _atomicService;
// Simple atomic operation
public async Task CreateOrderAsync(Order order)
{
await _atomicService.ExecuteAtomicallyAsync(async () =>
{
await _orderRepository.CreateAsync(order);
await _auditRepository.LogAsync(order.Id, "OrderCreated");
await _notificationService.SendConfirmationAsync(order.CustomerId);
});
}
// Parent-child hierarchical transaction
public async Task ProcessComplexOrderAsync(Order order)
{
await _atomicService.ExecuteAsParentAsync(async () =>
{
await CreateOrderAsync(order); // Child transaction
await _paymentService.ProcessPaymentAsync(order.Payment); // Child transaction
await _inventoryService.ReserveItemsAsync(order.Items); // Child transaction
});
}
// With custom options
public async Task ProcessCriticalOrderAsync(Order order)
{
var options = new AtomicOperationOptions
{
OperationName = "CriticalOrderProcessing",
IsolationLevel = IsolationLevel.Serializable,
Timeout = TimeSpan.FromMinutes(10),
MaxRetryAttempts = 5
};
await _atomicService.ExecuteAtomicallyAsync(async () =>
{
// Critical business logic here
}, options);
}
}
SagaPatternService - Distributed Transactions
public class DistributedOrderService
{
private readonly ISagaPatternService _sagaService;
public async Task<SagaExecutionResult> ProcessDistributedOrderAsync(OrderRequest request)
{
var context = new OrderSagaContext(request);
var steps = new List<ISagaStep<OrderSagaContext>>
{
// Step 1: Process Payment
SagaStepBuilder.Create<OrderSagaContext>(
"ProcessPayment", 1,
executeAction: async (ctx, ct) =>
{
var payment = await _paymentService.ChargeAsync(ctx.OrderRequest.Payment);
ctx.PaymentId = payment.Id;
return StepResult.Success;
},
compensateAction: async (ctx, ct) =>
{
if (!string.IsNullOrEmpty(ctx.PaymentId))
{
await _paymentService.RefundAsync(ctx.PaymentId);
}
return StepResult.Success;
}
),
// Step 2: Reserve Inventory
SagaStepBuilder.Create<OrderSagaContext>(
"ReserveInventory", 2,
executeAction: async (ctx, ct) =>
{
var reservation = await _inventoryService.ReserveAsync(ctx.OrderRequest.Items);
ctx.ReservationId = reservation.Id;
return StepResult.Success;
},
compensateAction: async (ctx, ct) =>
{
if (!string.IsNullOrEmpty(ctx.ReservationId))
{
await _inventoryService.ReleaseAsync(ctx.ReservationId);
}
return StepResult.Success;
}
),
// Step 3: Schedule Shipping
SagaStepBuilder.Create<OrderSagaContext>(
"ScheduleShipping", 3,
executeAction: async (ctx, ct) =>
{
var shipping = await _shippingService.ScheduleAsync(ctx.OrderRequest);
ctx.Data["ShippingId"] = shipping.Id;
return StepResult.Success;
},
compensateAction: async (ctx, ct) =>
{
if (ctx.Data.TryGetValue("ShippingId", out var shippingId))
{
await _shippingService.CancelAsync(shippingId.ToString()!);
}
return StepResult.Success;
}
)
};
return await _sagaService.ExecuteSagaAsync(context, steps);
}
}
Hybrid Approach - Best of Both Worlds
public class HybridOrderService
{
public async Task<StepResult> ProcessOrderDataAsync(OrderContext context, CancellationToken ct)
{
// Use AtomicService for local consistency within saga steps
await _atomicService.ExecuteAtomicallyAsync(async () =>
{
// Local ACID operations within the distributed saga step
await _orderRepository.CreateAsync(context.Order);
await _auditRepository.LogAsync(context.Order.Id, "OrderCreated");
await _customerRepository.UpdateOrderCountAsync(context.Order.CustomerId);
}, new AtomicOperationOptions
{
OperationName = "SagaStep.LocalOrderData",
CorrelationData = new Dictionary<string, object>
{
["SagaId"] = context.SagaId,
["OrderId"] = context.Order.Id
}
});
return StepResult.Success;
}
}
π― When to Use Which Pattern
Use AtomicService When:
- β Single service operations - All operations within one service/database
- β Need immediate consistency - ACID properties required
- β Traditional database transactions - Relational database operations
- β Parent-child service relationships - Hierarchical transaction coordination
- β Short-lived operations - Transactions that complete quickly
Use Saga Pattern When:
- β Multiple microservices involved - Cross-service coordination needed
- β External API integrations - Third-party services in the flow
- β Long-running business processes - Operations that take significant time
- β Need eventual consistency - Can tolerate temporary inconsistency
- β Distributed architecture - Services across different databases/systems
Use Both Together When:
- π Each saga step needs local ACID guarantees - Best of both worlds
- π Distributed coordination with local consistency - Hybrid approach
- π Complex business processes - Spanning multiple services with local data integrity
ποΈ Architecture Overview
graph TB
A[Client Request] --> B{Transaction Type?}
B -->|Local Operations| C[AtomicService]
B -->|Distributed Operations| D[SagaPatternService]
B -->|Hybrid| E[Both Services]
C --> C1[Transaction Scope]
C --> C2[Retry Logic]
C --> C3[Performance Monitoring]
D --> D1[Saga Steps]
D --> D2[Compensation Actions]
D --> D3[State Persistence]
E --> E1[Saga Orchestration]
E1 --> E2[Step 1: AtomicService]
E1 --> E3[Step 2: AtomicService]
E1 --> E4[Step N: AtomicService]
C1 --> F[Database]
D3 --> G[Saga State Store]
E2 --> F
E3 --> F
E4 --> F
π Performance Characteristics
| Pattern | Latency | Throughput | Consistency | Complexity | Scalability |
|---|---|---|---|---|---|
| AtomicService | Low | High | Strong | Low | Vertical |
| SagaPattern | Medium | Medium | Eventual | Medium | Horizontal |
| Hybrid | Medium | High | Mixed | High | Both |
π Documentation
Core Documentation
- AtomicService Usage Guide - Comprehensive guide for ACID transactions
- Saga Pattern Usage Guide - Complete saga implementation guide
- API Reference - Full API documentation
- Configuration Guide - Setup and configuration options
Examples & Tutorials
- E-commerce Order Processing - Real-world e-commerce example
- Banking Transfers - Financial transaction examples
- Microservices Integration - Cross-service coordination
- Performance Optimization - High-throughput scenarios
Advanced Topics
- Error Handling Strategies - Comprehensive error management
- Monitoring & Observability - Metrics and logging
- Testing Strategies - Unit and integration testing
- Production Deployment - Production considerations
π οΈ Configuration Options
AtomicService Configuration
public class AtomicServiceOptions
{
public int MaxRetryAttempts { get; set; } = 3;
public TimeSpan BaseRetryDelay { get; set; } = TimeSpan.FromMilliseconds(100);
public TimeSpan TransactionTimeout { get; set; } = TimeSpan.FromMinutes(5);
public IsolationLevel DefaultIsolationLevel { get; set; } = IsolationLevel.ReadCommitted;
public bool EnablePerformanceLogging { get; set; } = true;
public bool EnableDistributedTransactions { get; set; } = false;
}
SagaPatternService Configuration
public class SagaPatternOptions
{
public TimeSpan StepTimeout { get; set; } = TimeSpan.FromMinutes(5);
public TimeSpan CompensationTimeout { get; set; } = TimeSpan.FromMinutes(10);
public int MaxRetryAttempts { get; set; } = 3;
public TimeSpan RetryDelay { get; set; } = TimeSpan.FromSeconds(1);
public bool EnableStateLogging { get; set; } = true;
public bool EnableCompensationLogging { get; set; } = true;
}
π Monitoring & Observability
Both services provide comprehensive monitoring capabilities:
Built-in Metrics
- Transaction success/failure rates
- Operation duration and performance
- Retry attempt tracking
- Compensation execution monitoring
- Resource usage statistics
Logging Integration
- Structured logging with correlation IDs
- Performance logging for optimization
- Error tracking with context
- Saga state change events
Health Checks
// Built-in health checks
services.AddHealthChecks()
.AddCheck<AtomicServiceHealthCheck>("atomic-service")
.AddCheck<SagaPatternHealthCheck>("saga-pattern");
π§ͺ Testing
Unit Testing
[Test]
public async Task AtomicService_Should_Rollback_On_Exception()
{
// Arrange
var mockRepository = new Mock<IRepository>();
mockRepository.Setup(x => x.SaveAsync(It.IsAny<Entity>()))
.ThrowsAsync(new InvalidOperationException());
// Act & Assert
await Assert.ThrowsAsync<InvalidOperationException>(() =>
_atomicService.ExecuteAtomicallyAsync(async () =>
{
await mockRepository.Object.SaveAsync(new Entity());
}));
// Verify rollback occurred
mockRepository.Verify(x => x.SaveAsync(It.IsAny<Entity>()), Times.Once);
}
Integration Testing
[Test]
public async Task SagaPattern_Should_Compensate_On_Step_Failure()
{
// Arrange
var context = new TestSagaContext();
var steps = CreateTestStepsWithFailure();
// Act
var result = await _sagaService.ExecuteSagaAsync(context, steps);
// Assert
Assert.That(result.FinalStatus, Is.EqualTo(SagaStatus.Compensated));
Assert.That(context.CompensatedSteps.Count, Is.GreaterThan(0));
}
Reference
akkaraponph
/
iamatomic
Atomic Hanlding C# | Consistency within a single transaction scope
π Summary Table Of Data Consistency Handling
Pattern
Consistency
Scale
Complexity
Suitable For
Pessimistic Locking
Strong
Low
Low
Monoliths, legacy systems
Saga Pattern
Eventual
High
High
Microservices
CQRS
Eventual
High
High
Read-heavy systems, DDD
Mediator
Depends
Med
Medium
Coordinated command handling
Event Sourcing
Eventual
High
High
Auditable systems
Two-Phase Commit
Strong
Low
High
Cross-DB transactional ops
Outbox Pattern
Eventual
High
Medium
DB + messaging consistency
π I Am Atomic Transaction Patterns
Two powerful transaction patterns for modern applications: AtomicService for ACID transactions and SagaPatternService for distributed transactions with eventual consistency.
π― Overview
This library offers two complementary approaches to handle transactions in both monolithic and distributed architectures:
Pattern
Use Case
Consistency
Scope
Recovery
AtomicService
Single service/database
Immediate (ACID)
Local operations
Transaction rollback
SagaPatternService
Multiple services
Eventual
Distributed operations
Compensating actions
β¨ Features
π‘οΈ AtomicService (ACID Transactions)
- Hierarchical Transactions - Parent-child transaction support
- Enhanced Retry Logic - Configurable retry with exponentialβ¦
Top comments (0)