A high-performance .NET library for event sourcing with hash-based integrity verification and snapshot-based replay
- Event Sourcing Made Simple: Clean, intuitive API for implementing event sourcing patterns
- Hash-Based Integrity: Built-in integrity verification using cryptographic hashes for events, handlers, and snapshots
- Snapshot-Based Replay: Efficient event replay from snapshots with intelligent invalidation
- Code Change Detection: Automatic detection of event handler changes with smart replay strategies
- High Performance: Optimized for throughput with minimal memory allocation
- Type Safety: Strongly typed event handlers and snapshots with full generic support
- Framework Integration: Seamless integration with ASP.NET Core, dependency injection, and logging
Install StreamDingo via NuGet Package Manager:
dotnet add package StreamDingoOr via Package Manager Console:
Install-Package StreamDingousing StreamDingo;
// Define your events
public record UserCreated(string Name, string Email);
public record UserEmailUpdated(string NewEmail);
// Define your aggregate state
public record UserState(string Name, string Email, bool IsActive = true);
// Create event handlers
public class UserEventHandlers
{
public static UserState Apply(UserState? state, UserCreated @event)
{
return new UserState(@event.Name, @event.Email);
}
public static UserState Apply(UserState state, UserEmailUpdated @event)
{
return state with { Email = @event.NewEmail };
}
}
// Use the event store
var eventStore = new StreamDingoEventStore();
// Create a new stream
var streamId = Guid.NewGuid();
await eventStore.AppendAsync(streamId, new UserCreated("John Doe", "john@example.com"));
await eventStore.AppendAsync(streamId, new UserEmailUpdated("john.doe@example.com"));
// Replay events to get current state
var currentState = await eventStore.ReplayAsync<UserState>(streamId);
Console.WriteLine($"User: {currentState.Name}, Email: {currentState.Email}");Event handlers are pure functions that take a previous state snapshot and an event, returning a new state:
public static TState Apply(TState previousState, TEvent @event)
{
// Apply event logic
return newState;
}Each event handler is automatically hashed using the HashStamp library to detect code changes.
Snapshots represent the state of an aggregate at a specific point in time:
- Each snapshot is cryptographically hashed for integrity verification
- Snapshots serve as checkpoints for efficient event replay
- The last snapshot represents the current entity state
StreamDingo ensures data integrity through multiple hash layers:
- Event Handler Hashes: Detect when business logic changes
- Snapshot Hashes: Verify snapshot integrity and detect corruption
- Event Hashes: Ensure event data hasn't been tampered with
When changes are detected, StreamDingo intelligently replays events:
- Event Order Changes: Replay from the last stable snapshot
- Handler Code Changes: Replay affected event types until snapshot hashes stabilize
- Corruption Detection: Validate integrity at each step during replay
The main entry point for event sourcing operations.
// Append events to a stream
Task AppendAsync<T>(Guid streamId, T @event, CancellationToken cancellationToken = default);
// Replay events to rebuild state
Task<TState> ReplayAsync<TState>(Guid streamId, CancellationToken cancellationToken = default);
// Get stream information
Task<StreamInfo> GetStreamInfoAsync(Guid streamId, CancellationToken cancellationToken = default);
// Create snapshots manually
Task CreateSnapshotAsync<TState>(Guid streamId, TState state, CancellationToken cancellationToken = default);Configure StreamDingo in your application:
// Program.cs
builder.Services.AddStreamDingo(options =>
{
options.UseInMemoryStorage(); // or UseSqlServer, UsePostgreSQL, etc.
options.EnableAutomaticSnapshots(every: 100); // Create snapshots every 100 events
options.EnableIntegrityChecking(true);
options.ConfigureHashing(hash => hash.IncludeMethodBodies = true);
});- .NET 9.0 SDK or later
- Optional: Git for source control
Clone the repository and build:
git clone https://github.com/alexwiese/StreamDingo.git
cd StreamDingo
dotnet builddotnet testWe use EditorConfig for consistent code formatting:
dotnet formatWe welcome contributions! Please see our Contributing Guide for details.
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Make your changes and add tests
- Ensure all tests pass:
dotnet test - Format your code:
dotnet format - Commit your changes:
git commit -m 'Add amazing feature' - Push to your fork:
git push origin feature/amazing-feature - Open a Pull Request
- Additional storage providers (Redis, MongoDB, Event Store DB)
- GraphQL integration
- Event versioning and migration tools
- Performance benchmarking suite
- Event sourcing best practices documentation
- Integration with popular CQRS frameworks
This project is licensed under the MIT License - see the LICENSE file for details.
- Built with HashStamp for code hashing capabilities
- Inspired by event sourcing patterns from the DDD community
- Thanks to all contributors
- π Documentation
- π Bug Reports
- π¬ Discussions
- π§ Contact the maintainer