Skip to content

feat: add Leader Election pattern#326

Merged
JerrettDavis merged 2 commits into
mainfrom
feature/leader-election-321
May 22, 2026
Merged

feat: add Leader Election pattern#326
JerrettDavis merged 2 commits into
mainfrom
feature/leader-election-321

Conversation

@JerrettDavis
Copy link
Copy Markdown
Owner

Summary

  • add Leader Election runtime with lease acquisition, renewal, expiry, contention, and release semantics
  • add source generator and public attributes for generated election/candidate factories
  • add warehouse leader election example with IServiceCollection and Generic Host hosted service integration
  • document the pattern/generator/example and wire production catalogs
  • add TinyBDD runtime, generator, attribute, catalog, and example coverage with extra failure-path coverage for Codecov recovery

Closes #321.

Validation

  • dotnet build src\PatternKit.Core\PatternKit.Core.csproj -f net8.0 /p:UseSharedCompilation=false
  • dotnet build src\PatternKit.Core\PatternKit.Core.csproj -f net9.0 /p:UseSharedCompilation=false
  • dotnet build src\PatternKit.Core\PatternKit.Core.csproj -f net10.0 /p:UseSharedCompilation=false
  • dotnet build src\PatternKit.Core\PatternKit.Core.csproj -f netstandard2.0 /p:UseSharedCompilation=false
  • dotnet build src\PatternKit.Generators.Abstractions\PatternKit.Generators.Abstractions.csproj /p:UseSharedCompilation=false
  • dotnet build src\PatternKit.Generators\PatternKit.Generators.csproj /p:UseSharedCompilation=false
  • dotnet test test\PatternKit.Tests\PatternKit.Tests.csproj -f net8.0 --no-restore --filter "FullyQualifiedName~LeaderElectionTests" /p:BuildProjectReferences=false /p:UseSharedCompilation=false
  • dotnet test test\PatternKit.Tests\PatternKit.Tests.csproj -f net9.0 --no-restore --filter "FullyQualifiedName~LeaderElectionTests" /p:BuildProjectReferences=false /p:UseSharedCompilation=false
  • dotnet test test\PatternKit.Tests\PatternKit.Tests.csproj -f net10.0 --no-restore --filter "FullyQualifiedName~LeaderElectionTests" /p:BuildProjectReferences=false /p:UseSharedCompilation=false
  • dotnet test test\PatternKit.Generators.Tests\PatternKit.Generators.Tests.csproj -f net8.0 --no-restore --filter "FullyQualifiedNameLeaderElectionGeneratorTests|FullyQualifiedNameAbstractionsAttributeCoverageTests" /p:BuildProjectReferences=false /p:UseSharedCompilation=false
  • dotnet test test\PatternKit.Generators.Tests\PatternKit.Generators.Tests.csproj -f net9.0 --no-restore --filter "FullyQualifiedNameLeaderElectionGeneratorTests|FullyQualifiedNameAbstractionsAttributeCoverageTests" /p:BuildProjectReferences=false /p:UseSharedCompilation=false
  • dotnet test test\PatternKit.Generators.Tests\PatternKit.Generators.Tests.csproj -f net10.0 --no-restore --filter "FullyQualifiedNameLeaderElectionGeneratorTests|FullyQualifiedNameAbstractionsAttributeCoverageTests" /p:BuildProjectReferences=false /p:UseSharedCompilation=false
  • git diff --check

Note: the local full examples build still hits the existing analyzer/compiler mismatch (CS9057 with generated demo types); hosted CI validates the full examples/docs surface.

Copilot AI review requested due to automatic review settings May 22, 2026 21:25
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 22, 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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 22, 2026

Test Results

    1 files      1 suites   2m 49s ⏱️
  997 tests   997 ✅ 0 💤 0 ❌
1 002 runs  1 002 ✅ 0 💤 0 ❌

Results for commit 874f457.

♻️ This comment has been updated with latest results.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 22, 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.

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 a new Leader Election pattern to PatternKit, including a fluent in-memory runtime, a Roslyn incremental source generator (plus public attributes), and a production-shaped warehouse demo wired into the example/pattern catalogs and documentation.

Changes:

  • Introduces LeaderElection<TContext> runtime with lease acquire/renew/expire/release semantics and result types.
  • Adds [GenerateLeaderElection] + callback attributes and a LeaderElectionGenerator that emits election/candidate factories with diagnostics.
  • Adds a “Warehouse Leader Election” example (DI + Generic Host hosted service) plus test and documentation/catalog wiring.

Reviewed changes

Copilot reviewed 22 out of 22 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
test/PatternKit.Tests/Cloud/LeaderElection/LeaderElectionTests.cs New TinyBDD coverage for acquire/renew/release, contention/expiry, and guard clauses.
test/PatternKit.Generators.Tests/LeaderElectionGeneratorTests.cs Verifies generator output shape and diagnostic IDs for invalid declarations.
test/PatternKit.Generators.Tests/AbstractionsAttributeCoverageTests.cs Adds coverage/assertions for new leader election attributes.
test/PatternKit.Examples.Tests/ProductionReadiness/PatternKitPatternCatalogTests.cs Updates expected catalog contents/counts to include Leader Election.
test/PatternKit.Examples.Tests/LeaderElectionDemo/WarehouseLeaderElectionDemoTests.cs Validates fluent + generated demo, DI import, hosted service lifecycle, and catalog inclusion.
src/PatternKit.Generators/LeaderElection/LeaderElectionGenerator.cs New incremental generator for typed leader election + candidate factory emission with diagnostics.
src/PatternKit.Generators/AnalyzerReleases.Unshipped.md Registers new analyzer diagnostic IDs PKLE001–PKLE004.
src/PatternKit.Generators.Abstractions/Cloud/LeaderElectionAttributes.cs Adds public attributes consumed by the generator.
src/PatternKit.Examples/ProductionReadiness/PatternKitPatternCatalog.cs Adds Leader Election to the pattern coverage catalog (runtime/generator/example paths).
src/PatternKit.Examples/ProductionReadiness/PatternKitExampleCatalog.cs Adds “Warehouse Leader Election” to the example catalog.
src/PatternKit.Examples/LeaderElectionDemo/WarehouseLeaderElectionDemo.cs Implements warehouse leader election demo, generated host, and DI extension.
src/PatternKit.Examples/DependencyInjection/PatternKitExampleServiceCollectionExtensions.cs Wires the new example into aggregate AddPatternKitExamples() registration.
src/PatternKit.Core/Cloud/LeaderElection/LeaderElection.cs New leader election runtime types (LeaderLease, results, candidate builder, election).
docs/patterns/toc.yml Adds Leader Election to the patterns TOC.
docs/patterns/cloud/leader-election.md New pattern documentation page with runtime usage snippet and guidance.
docs/guides/pattern-coverage.md Updates coverage matrix to include Leader Election runtime + generator.
docs/generators/toc.yml Adds Leader Election to generators TOC.
docs/generators/leader-election.md New generator documentation page including diagnostics list.
docs/generators/index.md Adds Leader Election to generator index table.
docs/examples/warehouse-leader-election.md New example documentation page for the warehouse demo.
docs/examples/toc.yml Adds Warehouse Leader Election to examples TOC.
docs/examples/index.md Adds Warehouse Leader Election to the examples index list.

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

"docs/examples/warehouse-leader-election.md",
"src/PatternKit.Examples/LeaderElectionDemo/WarehouseLeaderElectionDemo.cs",
"test/PatternKit.Examples.Tests/LeaderElectionDemo/WarehouseLeaderElectionDemoTests.cs",
["fluent lease election", "generated candidate factory", "DI-importable Generic Host worker example"]),
Comment on lines +71 to +75
private readonly Func<DateTimeOffset> _clock;
private readonly TimeSpan _leaseDuration;
private LeaderLease? _currentLease;

private LeaderElection(string name, TimeSpan leaseDuration, Func<DateTimeOffset>? clock)
@github-actions
Copy link
Copy Markdown
Contributor

Code Coverage

Summary
  Generated on: 05/22/2026 - 21:41:25
  Coverage date: 05/22/2026 - 21:39:33 - 05/22/2026 - 21:41:14
  Parser: MultiReport (9x Cobertura)
  Assemblies: 4
  Classes: 1415
  Files: 577
  Line coverage: 94.6%
  Covered lines: 38316
  Uncovered lines: 2161
  Coverable lines: 40477
  Total lines: 88744
  Branch coverage: 75.4% (11202 of 14856)
  Covered branches: 11202
  Total branches: 14856
  Method coverage: 96.2% (7558 of 7850)
  Full method coverage: 88.3% (6933 of 7850)
  Covered methods: 7558
  Fully covered methods: 6933
  Total methods: 7850

PatternKit.Core                                                                                                     95.8%
  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.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.EventSourcing.EventStoreAppendResult                                                        100%
  PatternKit.Application.EventSourcing.InMemoryEventStore<T1, T2>                                                   97.9%
  PatternKit.Application.EventSourcing.StoredEvent<T1, T2>                                                            80%
  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.MaterializedViews.MaterializedView<T1, T2>                                                 98.4%
  PatternKit.Application.Repository.InMemoryRepository<T1, T2>                                                      92.8%
  PatternKit.Application.Repository.RepositoryResult<T>                                                             93.3%
  PatternKit.Application.ServiceLayer.ServiceLayerOperation<T1, T2>                                                 96.7%
  PatternKit.Application.ServiceLayer.ServiceLayerResult<T>                                                         94.7%
  PatternKit.Application.ServiceLayer.ServiceLayerRule<T>                                                            100%
  PatternKit.Application.Specification.Specification<T>                                                              100%
  PatternKit.Application.Specification.SpecificationRegistry<T>                                                     93.3%
  PatternKit.Application.TableDataGateway.InMemoryTableDataGateway<T1, T2>                                            86%
  PatternKit.Application.TableDataGateway.TableGatewayResult<T>                                                     82.3%
  PatternKit.Application.TransactionScript.TransactionScript<T1, T2>                                                  97%
  PatternKit.Application.TransactionScript.TransactionScriptError                                                     90%
  PatternKit.Application.TransactionScript.TransactionScriptResult<T>                                                100%
  PatternKit.Application.UnitOfWork.UnitOfWork                                                                      90.9%
  PatternKit.Application.UnitOfWork.UnitOfWorkResult                                                                94.7%
  PatternKit.Application.UnitOfWork.UnitOfWorkRollbackResult                                                         100%
  PatternKit.Application.UnitOfWork.UnitOfWorkStep                                                                   100%
  PatternKit.Behavioral.Chain.ActionChain<T>                                                                         100%
  PatternKit.Behavioral.Chain.AsyncActionChain<T>                                                                    100%
  PatternKit.Behavioral.Chain.AsyncResultChain<T1, T2>                                                              97.7%
  PatternKit.Behavioral.Chain.ResultChain<T1, T2>                                                                    100%

@codecov
Copy link
Copy Markdown

codecov Bot commented May 22, 2026

Codecov Report

❌ Patch coverage is 95.12987% with 15 lines in your changes missing coverage. Please review.
✅ Project coverage is 95.73%. Comparing base (3eb565a) to head (874f457).

Files with missing lines Patch % Lines
...nerators/LeaderElection/LeaderElectionGenerator.cs 90.57% 13 Missing ⚠️
...ernKit.Core/Cloud/LeaderElection/LeaderElection.cs 98.98% 1 Missing ⚠️
.../LeaderElectionDemo/WarehouseLeaderElectionDemo.cs 97.22% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #326      +/-   ##
==========================================
+ Coverage   89.75%   95.73%   +5.97%     
==========================================
  Files         468      472       +4     
  Lines       38681    38987     +306     
  Branches     5524     5577      +53     
==========================================
+ Hits        34718    37323    +2605     
+ Misses       1777     1664     -113     
+ Partials     2186        0    -2186     
Flag Coverage Δ
unittests 95.73% <95.12%> (+5.97%) ⬆️

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.

@JerrettDavis JerrettDavis merged commit ec2e4f1 into main May 22, 2026
12 checks passed
@JerrettDavis JerrettDavis deleted the feature/leader-election-321 branch May 22, 2026 21:47
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 Leader Election pattern

2 participants