Skip to content

feat: add change data capture pattern#496

Merged
JerrettDavis merged 1 commit into
mainfrom
feature/change-data-capture-pattern-485
Jun 1, 2026
Merged

feat: add change data capture pattern#496
JerrettDavis merged 1 commit into
mainfrom
feature/change-data-capture-pattern-485

Conversation

@JerrettDavis
Copy link
Copy Markdown
Owner

Closes #485.

Summary

  • Adds Change Data Capture runtime primitives with ordered capture entries, store abstraction, in-memory store, publisher dispatch, and pending retry tracking.
  • Adds source-generator attributes, generator diagnostics, TinyBDD runtime/generator/example coverage, and BenchmarkDotNet fluent vs generated routes.
  • Adds a product catalog CDC example with IServiceCollection import, docs, README/docs tables, and production-readiness catalog wiring.

Validation

  • dotnet build PatternKit.slnx --no-restore -p:UseSharedCompilation=false
  • dotnet test test\PatternKit.Tests\PatternKit.Tests.csproj --framework net8.0 --no-build -p:UseSharedCompilation=false
  • dotnet test test\PatternKit.Generators.Tests\PatternKit.Generators.Tests.csproj --framework net8.0 --no-build -p:UseSharedCompilation=false
  • dotnet test test\PatternKit.Examples.Tests\PatternKit.Examples.Tests.csproj --framework net8.0 --no-build -p:UseSharedCompilation=false
  • dotnet format PatternKit.slnx --verify-no-changes --verbosity minimal
  • git diff --check

Copilot AI review requested due to automatic review settings June 1, 2026 09:45
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 1, 2026

⚠️ Deprecation Warning: The deny-licenses option is deprecated for possible removal in the next major release. For more information, see issue 997.

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds the Change Data Capture (CDC) pattern across PatternKit’s runtime, source-generator route, examples, benchmarks, docs, and production-readiness catalogs, aligning with the repo’s “pattern must be covered by tests + docs + examples + benchmarks” approach.

Changes:

  • Introduces ChangeDataCapturePipeline<TMutation,TEvent> with an IChangeDataCaptureStore abstraction and an in-memory store implementation.
  • Adds [GenerateChangeDataCapture] + ChangeDataCaptureGenerator with diagnostics and generator tests.
  • Adds a DI-importable Product Catalog CDC demo, catalog/coverage wiring, docs, and benchmark coverage entries.

Reviewed changes

Copilot reviewed 25 out of 25 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
test/PatternKit.Tests/Messaging/ChangeDataCapture/ChangeDataCapturePipelineTests.cs Adds runtime TinyBDD coverage for ordered capture/publish and failure retry tracking.
test/PatternKit.Generators.Tests/ChangeDataCaptureGeneratorTests.cs Adds generator output + diagnostics + attribute contract tests.
test/PatternKit.Examples.Tests/ProductionReadiness/PatternKitPatternCatalogTests.cs Updates catalog assertions to include CDC and adjusts expected family counts.
test/PatternKit.Examples.Tests/ProductionReadiness/PatternKitBenchmarkCoverageTests.cs Updates expected benchmark-route totals for the new pattern.
test/PatternKit.Examples.Tests/ChangeDataCaptureDemo/ProductCatalogChangeDataCaptureDemoTests.cs Validates fluent vs generated demo behavior and DI importability.
src/PatternKit.Generators/ChangeDataCapture/ChangeDataCaptureGenerator.cs Implements incremental generator emitting a CDC pipeline factory + diagnostics.
src/PatternKit.Generators/AnalyzerReleases.Unshipped.md Registers new PKCDC diagnostics in analyzer release notes.
src/PatternKit.Generators.Abstractions/ChangeDataCapture/ChangeDataCaptureAttributes.cs Adds the [GenerateChangeDataCapture] attribute definition.
src/PatternKit.Examples/ProductionReadiness/PatternKitPatternCatalog.cs Registers CDC pattern metadata for production-readiness catalog.
src/PatternKit.Examples/ProductionReadiness/PatternKitExampleCatalog.cs Registers the Product Catalog CDC example in the example catalog.
src/PatternKit.Examples/DependencyInjection/PatternKitExampleServiceCollectionExtensions.cs Adds DI wiring for the new example in the examples extension surface.
src/PatternKit.Examples/ChangeDataCaptureDemo/ProductCatalogChangeDataCaptureDemo.cs Adds demo domain types, fluent + generated policies, and IServiceCollection extension.
src/PatternKit.Core/Messaging/ChangeDataCapture/ChangeDataCapturePipeline.cs Adds CDC runtime primitives, store abstraction, in-memory store, and pipeline behavior.
README.md Updates pattern counts and benchmark matrix placeholders for CDC.
docs/patterns/toc.yml Adds CDC to the patterns TOC.
docs/patterns/messaging/change-data-capture.md Adds the CDC pattern documentation page.
docs/index.md Updates pattern counts and pattern table to include CDC.
docs/guides/benchmark-results.md Updates benchmark matrix placeholders + coverage matrix counts and generator matrix entries.
docs/generators/toc.yml Adds CDC generator docs to generator TOC.
docs/generators/index.md Adds CDC generator to the generators index table and sample attribute list.
docs/generators/change-data-capture.md Adds detailed CDC generator documentation + diagnostics list.
docs/examples/toc.yml Adds Product Catalog CDC demo to examples TOC.
docs/examples/product-catalog-change-data-capture.md Adds documentation page for the new CDC demo.
docs/examples/index.md Adds CDC demo to examples landing page.
benchmarks/PatternKit.Benchmarks/Messaging/ChangeDataCaptureBenchmarks.cs Adds BenchmarkDotNet coverage for fluent vs generated CDC routes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 1, 2026

Test Results

    12 files      12 suites   12m 42s ⏱️
 4 150 tests  4 150 ✅ 0 💤 0 ❌
12 881 runs  12 881 ✅ 0 💤 0 ❌

Results for commit b07a2c4.

♻️ This comment has been updated with latest results.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 1, 2026

🔍 PR Validation Results

Version: ``

✅ Validation Steps

  • Build solution
  • Run tests
  • Build documentation
  • Dry-run NuGet packaging

📊 Artifacts

Dry-run artifacts have been uploaded and will be available for 7 days.


This comment was automatically generated by the PR validation workflow.

@JerrettDavis JerrettDavis force-pushed the feature/change-data-capture-pattern-485 branch from 994e47e to 9601592 Compare June 1, 2026 10:41
@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 1, 2026

Codecov Report

❌ Patch coverage is 98.08743% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 97.40%. Comparing base (f9db564) to head (b07a2c4).

Files with missing lines Patch % Lines
...rs/ChangeDataCapture/ChangeDataCaptureGenerator.cs 95.42% 7 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #496      +/-   ##
==========================================
- Coverage   97.40%   97.40%   -0.01%     
==========================================
  Files         595      599       +4     
  Lines       48648    49014     +366     
  Branches     3138       34    -3104     
==========================================
+ Hits        47385    47741     +356     
- Misses       1263     1273      +10     
Flag Coverage Δ
unittests 97.40% <98.08%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI review requested due to automatic review settings June 1, 2026 11:00
@JerrettDavis JerrettDavis force-pushed the feature/change-data-capture-pattern-485 branch from 9601592 to b07a2c4 Compare June 1, 2026 11:00
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 25 out of 25 changed files in this pull request and generated 3 comments.

Comment on lines +249 to +262
public static Builder Create(string name = "change-data-capture") => new(name);

public async ValueTask<ChangeDataCaptureEntry<TMutation, TEvent>> CaptureAsync(
TMutation mutation,
CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
if (mutation is null)
throw new ArgumentNullException(nameof(mutation));

var nextSequence = await _store.GetNextSequenceAsync(Name, cancellationToken).ConfigureAwait(false);
var @event = _eventFactory(mutation, nextSequence);
return await _store.AppendAsync(Name, nextSequence, mutation, @event, _utcNow(), cancellationToken).ConfigureAwait(false);
}
Comment on lines +21 to +26
| ID | Severity | Message |
| --- | --- | --- |
| `PKCDC001` | Error | The host type must be partial. |
| `PKCDC002` | Error | Factory and mapper method names must be valid C# identifiers. |
| `PKCDC003` | Error | Mutation and event types are required. |

Comment on lines +8 to +16
var pipeline = ChangeDataCapturePipeline<ProductMutation, ProductChanged>
.Create("product-catalog-cdc")
.UseStore(store)
.MapWith((mutation, sequence) => new ProductChanged(sequence, mutation.Sku, mutation.Name))
.PublishWith((changed, ct) => publisher.PublishAsync(changed, ct))
.Build();

await pipeline.CaptureAsync(new ProductMutation("sku-1", "Desk"));
await pipeline.PublishPendingAsync();
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 1, 2026

Code Coverage

Summary
  Generated on: 06/01/2026 - 11:08:16
  Coverage date: 06/01/2026 - 11:06:23 - 06/01/2026 - 11:08:05
  Parser: MultiReport (8x Cobertura)
  Assemblies: 5
  Classes: 1774
  Files: 599
  Line coverage: 97.3%
  Covered lines: 47739
  Uncovered lines: 1275
  Coverable lines: 49014
  Total lines: 104065
  Branch coverage: 84.3% (15267 of 18093)
  Covered branches: 15267
  Total branches: 18093
  Method coverage: 97.2% (9295 of 9553)
  Full method coverage: 91.5% (8748 of 9553)
  Covered methods: 9295
  Fully covered methods: 8748
  Total methods: 9553

PatternKit.Core                                                                                                     96.1%
  PatternKit.Application.ActivityTracking.ActivityGateState                                                          100%
  PatternKit.Application.ActivityTracking.ActivityLease                                                              100%
  PatternKit.Application.ActivityTracking.ActivityRecord                                                             100%
  PatternKit.Application.ActivityTracking.ActivityTracker                                                            100%
  PatternKit.Application.Aggregates.AggregateCommandHandler<T1, T2, T3>                                              100%
  PatternKit.Application.Aggregates.AggregateCommandResult<T>                                                        100%
  PatternKit.Application.Aggregates.AggregateRoot<T1, T2>                                                            100%
  PatternKit.Application.AntiCorruption.AntiCorruptionLayer<T1, T2>                                                 90.4%
  PatternKit.Application.AntiCorruption.AntiCorruptionResult<T>                                                      100%
  PatternKit.Application.AuditLog.AuditLogAppendResult<T>                                                           85.7%
  PatternKit.Application.AuditLog.InMemoryAuditLog<T1, T2>                                                          95.4%
  PatternKit.Application.BoundedContexts.BoundedContextAdapter                                                       100%
  PatternKit.Application.BoundedContexts.BoundedContextCapability                                                   83.3%
  PatternKit.Application.BoundedContexts.BoundedContextDescriptor                                                   95.4%
  PatternKit.Application.ContextMaps.ContextMapDescriptor                                                           96.8%
  PatternKit.Application.ContextMaps.ContextMapRelationship                                                          100%
  PatternKit.Application.DataMapping.DataMapper<T1, T2>                                                             94.6%
  PatternKit.Application.DataMapping.DataMapperError                                                                  90%
  PatternKit.Application.DataMapping.DataMapperResult<T>                                                            84.6%
  PatternKit.Application.DomainEvents.DomainEventDispatcher<T>                                                      95.4%
  PatternKit.Application.DomainEvents.DomainEventDispatchResult                                                      100%
  PatternKit.Application.DomainServices.DomainServiceOperation<T1, T2>                                               100%
  PatternKit.Application.DomainServices.DomainServiceRegistry<T1, T2>                                                100%
  PatternKit.Application.EventSourcing.EventStoreAppendResult                                                        100%
  PatternKit.Application.EventSourcing.InMemoryEventStore<T1, T2>                                                   97.9%
  PatternKit.Application.EventSourcing.StoredEvent<T1, T2>                                                            80%
  PatternKit.Application.EventualConsistency.EventualConsistencyEvaluation<T>                                       92.3%
  PatternKit.Application.EventualConsistency.EventualConsistencyMonitor<T>                                          97.2%
  PatternKit.Application.EventualConsistency.EventualConsistencyMonitorState<T>                                      100%
  PatternKit.Application.EventualConsistency.EventualConsistencyWatermarks<T>                                       96.7%
  PatternKit.Application.FeatureToggles.FeatureToggleDecision                                                       87.5%
  PatternKit.Application.FeatureToggles.FeatureToggleRule<T>                                                         100%
  PatternKit.Application.FeatureToggles.FeatureToggleSet<T>                                                         96.9%
  PatternKit.Application.IdentityMap.IdentityMap<T1, T2>                                                             100%
  PatternKit.Application.IdentityMap.IdentityMapResult<T>                                                           92.8%
  PatternKit.Application.LazyLoading.LazyLoad<T>                                                                    98.1%
  PatternKit.Application.LazyLoading.LazyLoadResult<T>                                                               100%
  PatternKit.Application.ManualTaskGates.ManualTaskGate<T>                                                          98.5%

@JerrettDavis JerrettDavis merged commit fc97436 into main Jun 1, 2026
13 checks passed
@JerrettDavis JerrettDavis deleted the feature/change-data-capture-pattern-485 branch June 1, 2026 11:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Change Data Capture pattern

2 participants