Skip to content

Commit 08d101b

Browse files
committed
Add BbQ.Events.Samples and update checkpoint schema
Added BbQ.Events.Samples project with usage examples for event bus, event store, and projections using SQL Server. Updated SQL Server checkpoint table: PartitionKey is now nullable, primary key removed, and a unique clustered index added for better support of non-partitioned projections. Bumped BbQ.Events.SqlServer version to 0.2.1. Also fixed minor formatting in Outcome.slnx.
1 parent 542a35c commit 08d101b

File tree

5 files changed

+141
-5
lines changed

5 files changed

+141
-5
lines changed

Outcome.slnx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<Folder Name="/CQRS/">
33
<Project Path="src/BbQ.Cqrs/BbQ.Cqrs.csproj" />
44
<Project Path="src/BbQ.Cqrs.SourceGenerators/BbQ.Cqrs.SourceGenerators.csproj" />
5-
<Project Path="src/BbQ.Cqrs.Samples/BbQ.Cqrs.Samples.csproj" />
5+
<Project Path="src/BbQ.Cqrs.Samples/BbQ.Cqrs.Samples.csproj" />
66
<Project Path="tests/BbQ.Cqrs.Tests/BbQ.Cqrs.Tests.csproj" />
77
</Folder>
88
<Folder Name="/Events/">
@@ -13,6 +13,9 @@
1313
<Project Path="tests/BbQ.Events.SqlServer.Tests/BbQ.Events.SqlServer.Tests.csproj" />
1414
<Project Path="tests/BbQ.Events.PostgreSql.Tests/BbQ.Events.PostgreSql.Tests.csproj" />
1515
</Folder>
16+
<Folder Name="/Samples/">
17+
<Project Path="samples/BbQ.Events.Samples/BbQ.Events.Samples.csproj" Id="f2343415-bdae-4ab0-be93-2159e9840f4b" />
18+
</Folder>
1619
<Project Path="src/Outcome.SourceGenerators/Outcome.SourceGenerators.csproj" />
1720
<Project Path="tests/Outcome.Tests/Outcome.Tests.csproj" />
1821
<Project Path="src/Outcome/Outcome.csproj" />
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net8.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
</PropertyGroup>
9+
<ItemGroup>
10+
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.2" />
11+
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="10.0.2" />
12+
</ItemGroup>
13+
<ItemGroup>
14+
<ProjectReference Include="..\..\src\BbQ.Events.SourceGenerators\BbQ.Events.SourceGenerators.csproj" />
15+
<ProjectReference Include="..\..\src\BbQ.Events.SqlServer\BbQ.Events.SqlServer.csproj" />
16+
<ProjectReference Include="..\..\src\BbQ.Events\BbQ.Events.csproj" />
17+
</ItemGroup>
18+
</Project>
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
using BbQ.Events.Configuration;
2+
using BbQ.Events.Engine;
3+
using BbQ.Events.Events;
4+
using BbQ.Events.Schema;
5+
using BbQ.Events.SqlServer.Configuration;
6+
using Microsoft.Extensions.DependencyInjection;
7+
using Microsoft.Extensions.Hosting;
8+
using Microsoft.Extensions.Logging;
9+
using System;
10+
using System.Runtime.CompilerServices;
11+
12+
var builder = Host.CreateDefaultBuilder(args)
13+
.ConfigureAppConfiguration((context, config) =>
14+
{
15+
// Additional configuration can be set up here if needed
16+
})
17+
.ConfigureServices((context, services) =>
18+
{
19+
services.AddLogging();
20+
21+
services.AddInMemoryEventBus()
22+
.AddProjectionEngine()
23+
.AddProjection<UserProjection>(options =>
24+
{
25+
options.StartupMode = ProjectionStartupMode.Replay;
26+
});
27+
services.UseSqlServerEventStore(options =>
28+
{
29+
options.ConnectionString = "server=.;database=event_sourcing;Integrated Security=true;TrustServerCertificate=true";
30+
options.AutoCreateSchema = true;
31+
options.IncludeMetadata = true;
32+
});
33+
34+
services.UseSqlServerCheckpoints("server=.;database=event_sourcing;Integrated Security=true;TrustServerCertificate=true");
35+
36+
services.AddScoped<IEventHandler<UserCreatedEvent>, UserCreatedEventHandler>();
37+
services.AddScoped<UserCreatedSubscriber>();
38+
});
39+
40+
var app = builder.Build();
41+
var eventBus = app.Services.GetRequiredService<IEventBus>();
42+
var eventStore = app.Services.GetRequiredService<IEventStore>();
43+
var initializer = app.Services.GetRequiredService<ISchemaInitializer>();
44+
var engine = app.Services.GetRequiredService<IProjectionEngine>();
45+
var rebuilder = app.Services.GetRequiredService<IProjectionRebuilder>();
46+
var replayService = app.Services.GetRequiredService<IReplayService>();
47+
48+
49+
50+
var userCreatedEvent = new UserCreatedEvent("1", $"JohnDoe @ {DateTime.UtcNow}");
51+
using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(10));
52+
53+
_ = engine.RunAsync(cts.Token);
54+
55+
await initializer.EnsureSchemaAsync(cts.Token);
56+
57+
//await rebuilder.ResetAllProjectionsAsync(cts.Token);
58+
59+
//await eventStore.AppendAsync(nameof(UserProjection), userCreatedEvent);
60+
61+
62+
//await eventBus.Publish(userCreatedEvent, cts.Token);
63+
//var sub = serviceProvider.GetRequiredService<UserCreatedSubscriber>();
64+
//var projection = serviceProvider.GetRequiredService<UserProjection>();
65+
66+
//await foreach (var item in sub.Subscribe(cts.Token))
67+
//{
68+
// await projection.ProjectAsync(item, cts.Token);
69+
//}
70+
71+
await replayService.ReplayAsync(nameof(UserProjection), new ReplayOptions
72+
{
73+
BatchSize = 10,
74+
FromCheckpoint = false,
75+
FromPosition = 0
76+
}, cts.Token);
77+
78+
Console.ReadKey();
79+
80+
record UserCreatedEvent(string UserId, string UserName);
81+
82+
class UserCreatedEventHandler : IEventHandler<UserCreatedEvent>
83+
{
84+
public Task Handle(UserCreatedEvent @event, CancellationToken ct = default)
85+
{
86+
Console.WriteLine($"User created: {@event.UserId}, {@event.UserName}");
87+
88+
return Task.CompletedTask;
89+
}
90+
}
91+
92+
class UserCreatedSubscriber(IEventStore store) : IEventSubscriber<UserCreatedEvent>
93+
{
94+
public async IAsyncEnumerable<UserCreatedEvent> Subscribe([EnumeratorCancellation] CancellationToken ct = default)
95+
{
96+
await foreach (var item in store.ReadAsync<UserCreatedEvent>("users", 0, ct))
97+
{
98+
yield return item.Event;
99+
}
100+
}
101+
}
102+
103+
class UserProjection : BbQ.Events.Projections.IProjectionHandler<UserCreatedEvent>
104+
{
105+
public ValueTask ProjectAsync(UserCreatedEvent @event, CancellationToken ct = default)
106+
{
107+
Console.WriteLine($"Projecting user created event: {@event.UserId}, {@event.UserName}");
108+
return ValueTask.CompletedTask;
109+
}
110+
}

src/BbQ.Events.SqlServer/BbQ.Events.SqlServer.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<TargetFramework>net8.0</TargetFramework>
55

66
<PackageId>BbQ.Events.SqlServer</PackageId>
7-
<Version>0.2.0</Version>
7+
<Version>0.2.1</Version>
88
<Authors>Jean</Authors>
99
<Company>JM Mbouma</Company>
1010
<Description>SQL Server implementation for BbQ.Events, providing both IEventStore for event sourcing and IProjectionCheckpointStore for projection checkpoints. Features durable event persistence with sequential positions, atomic operations, JSON serialization, and thread-safe parallel processing support.</Description>

src/BbQ.Events.SqlServer/Schema/CreateCheckpointTable.sql

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@
44

55
CREATE TABLE BbQ_ProjectionCheckpoints (
66
ProjectionName NVARCHAR(200) NOT NULL,
7-
PartitionKey NVARCHAR(200) NOT NULL,
7+
PartitionKey NVARCHAR(200) NULL,
88
Position BIGINT NOT NULL,
9-
LastUpdatedUtc DATETIME2 NOT NULL DEFAULT SYSUTCDATETIME(),
10-
PRIMARY KEY (ProjectionName, PartitionKey)
9+
LastUpdatedUtc DATETIME2 NOT NULL DEFAULT SYSUTCDATETIME()
1110
);
1211

1312
-- Index for time-based queries (projection health monitoring)
@@ -17,3 +16,9 @@ ON BbQ_ProjectionCheckpoints(LastUpdatedUtc);
1716
-- Index for querying all checkpoints of a projection
1817
CREATE INDEX IX_BbQ_ProjectionCheckpoints_ProjectionName
1918
ON BbQ_ProjectionCheckpoints(ProjectionName);
19+
20+
CREATE UNIQUE CLUSTERED INDEX [UQ_BbQ_ProjectionCheckpoints_ProjectionPartition] ON BbQ_ProjectionCheckpoints
21+
(
22+
[ProjectionName] ASC,
23+
[PartitionKey] ASC
24+
)

0 commit comments

Comments
 (0)