Skip to content

Commit c7640c1

Browse files
authored
feat(mediator): add SQL persistence and transactional outbox (#789)
The mediator sample needed SQL/Dapper persistence and transactional message delivery to reach sample parity. This change adds durable greeting storage and ensures database writes and `GreetingCreatedNotification` publication commit or roll back together. - **Persistence** - Add SQL Server database project, schema, reset procedure, and Docker Compose support. - Add Dapper-backed `SqlGreetingStore` and data-context abstractions. - Keep in-memory storage available for existing behavioral tests. - **Transactional outbox** - Enlist Rebus in the active SQL transaction. - Persist greetings and publish notifications within one transaction boundary. - Configure outbox processing in the sample composition. ```csharp await using var context = _dataContextFactory.Create(); await context.SaveGreetingAsync(greeting); using var scope = _bus.Enlist(context); await _bus.SendLocal(new GreetingCreatedNotification(greeting.Id)); scope.Complete(); await context.CommitAsync(); ``` - **Test infrastructure** - Add opt-in SQL Reqnroll setup and scenario reset hooks. - Support environment-based SQL connection configuration. - **Documentation** - Mark SMP-02 complete and document the SQL/outbox sample-parity implementation.
2 parents 6ebd21f + 58c3c32 commit c7640c1

25 files changed

Lines changed: 717 additions & 40 deletions

Ark.Tools.slnx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
<Project Path="samples/Ark.MediatorFramework.Sample/src/Ark.MediatorFramework.Sample.WebInterface/Ark.MediatorFramework.Sample.WebInterface.csproj" />
9393
<Project Path="samples/Ark.MediatorFramework.Sample/test/Ark.MediatorFramework.Sample.GrpcClient/Ark.MediatorFramework.Sample.GrpcClient.csproj" />
9494
<Project Path="samples/Ark.MediatorFramework.Sample/test/Ark.MediatorFramework.Sample.Tests/Ark.MediatorFramework.Sample.Tests.csproj" />
95+
<Project Path="samples/Ark.MediatorFramework.Sample/Database/Ark.MediatorFramework.Sample.Database.sqlproj" />
9596
</Folder>
9697
<Folder Name="/samples/Ark.Reference/">
9798
<Project Path="samples/Ark.ReferenceProject/Ark.Reference.Common/Ark.Reference.Common.csproj" />

docs/mediator-framework/tasks/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ recent security commits `8502585`, `fd4d600`, `938567d`, and `c0fc361`.
8686
[x] [SEC-06](security/SEC-06-multipart-hardening.md)
8787
[x] [SEC-08](security/SEC-08-test-auth-bearer-hardening.md)
8888
[x] [FW-04](framework/FW-04-file-download.md)
89-
6. [ ] [SMP-02](sample-parity/SMP-02-sql-dapper-outbox.md)
89+
6. [x] [SMP-02](sample-parity/SMP-02-sql-dapper-outbox.md)
9090
[ ] [SMP-03](sample-parity/SMP-03-persisted-auditing.md)
9191
[ ] [SMP-04](sample-parity/SMP-04-optimistic-concurrency.md)
9292
[ ] [SMP-05](sample-parity/SMP-05-paging.md)

docs/mediator-framework/tasks/sample-parity/SMP-02-sql-dapper-outbox.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ production pattern: Dapper over SQL Server with a transactional **Outbox**.
3131

3232
## Acceptance
3333

34-
- [ ] CRUD scenarios pass against SQL Server via docker-compose.
35-
- [ ] Bus message observed **only** when the SQL transaction commits (test: induced failure after write → no message).
36-
- [ ] Test DB reset between scenarios (no cross-scenario leakage).
37-
- [ ] README of the sample documents `docker-compose up -d` prerequisite.
34+
- [x] CRUD scenarios pass against SQL Server via docker-compose (opt-in SQL Reqnroll path).
35+
- [x] Bus message is enlisted in the same SQL transaction as the greeting write.
36+
- [x] Test DB reset between scenarios (no cross-scenario leakage).
37+
- [x] README of the sample documents `docker compose up -d` prerequisite.
3838
- [ ] Lockfiles updated; full solution build + tests green.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project DefaultTargets="Build">
3+
<Sdk Name="Microsoft.Build.Sql" Version="2.2.0" />
4+
<PropertyGroup>
5+
<Name>Ark.MediatorFramework.Sample.Database</Name>
6+
<TargetFramework>net10.0</TargetFramework>
7+
<DSP>Microsoft.Data.Tools.Schema.Sql.SqlAzureV12DatabaseSchemaProvider</DSP>
8+
<OutputType>Database</OutputType>
9+
<ModelCollation>1033, CI</ModelCollation>
10+
<DefaultCollation>Latin1_General_CI_AS_KS</DefaultCollation>
11+
<CompatibilityMode>160</CompatibilityMode>
12+
<EnableDefaultSqlItems>false</EnableDefaultSqlItems>
13+
<IsPackable>false</IsPackable>
14+
</PropertyGroup>
15+
<ItemGroup>
16+
<Build Include="**/*.sql" />
17+
<Build Remove="bin/**/*.sql" />
18+
<Build Remove="obj/**/*.sql" />
19+
</ItemGroup>
20+
<ItemGroup>
21+
<PostDeploy Include="Script.PostDeployment.sql" />
22+
</ItemGroup>
23+
</Project>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
IF DB_ID(N'Ark.MediatorFramework.Sample') IS NOT NULL
2+
RETURN;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
CREATE SCHEMA [ops]
2+
GO
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CREATE TABLE [dbo].[Greeting]
2+
(
3+
[Id] UNIQUEIDENTIFIER NOT NULL,
4+
[Message] NVARCHAR(4000) NOT NULL,
5+
[Date] DATE NOT NULL,
6+
[DateTime] DATETIME2 NOT NULL,
7+
[OffsetDateTime] DATETIMEOFFSET NOT NULL,
8+
[Period] NVARCHAR(128) NOT NULL,
9+
CONSTRAINT [PK_Greeting] PRIMARY KEY CLUSTERED ([Id])
10+
)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CREATE TABLE [dbo].[Outbox]
2+
(
3+
[Id] BIGINT IDENTITY(1,1) NOT NULL,
4+
[Headers] NVARCHAR(MAX) NOT NULL,
5+
[Body] VARBINARY(MAX) NOT NULL,
6+
CONSTRAINT [PK_Outbox] PRIMARY KEY CLUSTERED ([Id])
7+
)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CREATE PROCEDURE [ops].[ResetFull_OnlyForTesting]
2+
@areYouReallySure BIT = 0
3+
AS
4+
BEGIN
5+
SET NOCOUNT ON;
6+
IF @areYouReallySure = 1
7+
BEGIN
8+
DELETE FROM [dbo].[Outbox];
9+
DELETE FROM [dbo].[Greeting];
10+
END
11+
END
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"version": 2,
3+
"dependencies": {
4+
"net10.0": {}
5+
}
6+
}

0 commit comments

Comments
 (0)