Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -473,13 +473,13 @@ var cachedRemoteProxy = Proxy<int, string>.Create(id => remoteProxy.Execute(id))
---

## Patterns Table
PatternKit currently tracks 108 production-readiness patterns. Each catalog pattern is represented in tests, documentation, real-world examples, IoC integration, and the BenchmarkDotNet coverage matrix.
PatternKit currently tracks 109 production-readiness patterns. Each catalog pattern is represented in tests, documentation, real-world examples, IoC integration, and the BenchmarkDotNet coverage matrix.

| Category | Count | Patterns |
| --- | ---: | --- |
| Application Architecture | 23 | Activity Tracker, Aggregate Root, Anti-Corruption Layer, Audit Log, Bounded Context, Context Map, CQRS, Data Mapper, Domain Event, Domain Service, Event Sourcing, Feature Toggle, Identity Map, Manual Task Gate, Materialized View, Repository, Service Layer, Specification, Table Data Gateway, Timeout Manager, Transaction Script, Unit of Work, Value Object |
| Behavioral | 11 | Chain of Responsibility, Command, Interpreter, Iterator, Mediator, Memento, Observer, State, Strategy, Template Method, Visitor |
| Cloud Architecture | 17 | Ambassador, Backends for Frontends, Bulkhead, Cache-Aside, Circuit Breaker, External Configuration Store, Gateway Aggregation, Gateway Routing, Health Endpoint Monitoring, Leader Election, Priority Queue, Queue-Based Load Leveling, Rate Limiting, Retry, Scheduler Agent Supervisor, Sidecar, Strangler Fig |
| Cloud Architecture | 18 | Ambassador, Backends for Frontends, Bulkhead, Cache-Aside, Cache Stampede Protection, Circuit Breaker, External Configuration Store, Gateway Aggregation, Gateway Routing, Health Endpoint Monitoring, Leader Election, Priority Queue, Queue-Based Load Leveling, Rate Limiting, Retry, Scheduler Agent Supervisor, Sidecar, Strangler Fig |
| Creational | 5 | Abstract Factory, Builder, Factory Method, Prototype, Singleton |
| Enterprise Integration | 41 | Aggregator, Canonical Data Model, Channel Adapter, Channel Purger, Claim Check, Competing Consumers, Content Enricher, Content-Based Router, Control Bus, Correlation Identifier, Dead Letter Channel, Durable Subscriber, Dynamic Router, Event Notification, Event-Carried State Transfer, Event-Driven Consumer, Guaranteed Delivery, Invalid Message Channel, Mailbox, Message Bus, Message Channel, Message Envelope, Message Expiration, Message Filter, Message History, Message Store, Message Translator, Messaging Bridge, Messaging Gateway, Pipes and Filters, Polling Consumer, Publish-Subscribe, Recipient List, Request-Reply, Resequencer, Routing Slip, Saga / Process Manager, Scatter-Gather, Service Activator, Splitter, Wire Tap |
| Messaging Reliability | 3 | Idempotent Receiver, Inbox, Outbox |
Expand Down Expand Up @@ -519,6 +519,8 @@ BenchmarkDotNet guidance is documented in [docs/guides/benchmarks.md](docs/guide
| Bridge | Execution | 91.848 ns | 664 B | 30.004 ns | 160 B | Generated bridge forwarding was faster and allocated less for notice rendering. |
| Bulkhead | Construction | 20.56 ns | 216 B | 20.48 ns | 216 B | Effectively equivalent for this microbenchmark. |
| Bulkhead | Execution | 102.70 ns | 592 B | 106.11 ns | 592 B | Same allocation; fluent was slightly faster for the shipping allocation workflow. |
| Cache Stampede Protection | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
| Cache Stampede Protection | Execution | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
| Cache-Aside | Construction | 19.91 ns | 200 B | 19.85 ns | 200 B | Effectively equivalent for this microbenchmark. |
| Cache-Aside | Execution | 216.50 ns | 1,048 B | 208.60 ns | 1,048 B | Same allocation; generated was slightly faster for the miss-then-hit workflow. |
| Canonical Data Model | Construction | 75.482 ns | 632 B | 59.947 ns | 496 B | Generated reduced construction time and allocation in this microbenchmark. |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using BenchmarkDotNet.Attributes;
using PatternKit.Cloud.CacheStampedeProtection;
using PatternKit.Examples.CacheStampedeProtectionDemo;

namespace PatternKit.Benchmarks.Cloud;

[BenchmarkCategory("Cloud", "CacheStampedeProtection")]
public class CacheStampedeProtectionBenchmarks
{
private static readonly ProductAvailabilityRequest Request = new("SKU-100", "us");

[Benchmark(Baseline = true, Description = "Fluent: create cache stampede protection policy")]
[BenchmarkCategory("Fluent", "Construction")]
public CacheStampedeProtectionPolicy<ProductAvailabilitySnapshot> Fluent_CreatePolicy()
=> ProductCatalogStampedeProtectionPolicies.CreateFluent();

[Benchmark(Description = "Generated: create cache stampede protection policy")]
[BenchmarkCategory("Generated", "Construction")]
public CacheStampedeProtectionPolicy<ProductAvailabilitySnapshot> Generated_CreatePolicy()
=> GeneratedProductCatalogStampedeProtectionPolicy.CreateGenerated();

[Benchmark(Description = "Fluent: share product catalog load")]
[BenchmarkCategory("Fluent", "Execution")]
public IReadOnlyList<ProductAvailabilitySummary> Fluent_ShareProductCatalogLoad()
=> ProductCatalogStampedeProtectionDemoRunner.RunFluentAsync(Request).AsTask().GetAwaiter().GetResult();

[Benchmark(Description = "Generated: share product catalog load")]
[BenchmarkCategory("Generated", "Execution")]
public IReadOnlyList<ProductAvailabilitySummary> Generated_ShareProductCatalogLoad()
=> ProductCatalogStampedeProtectionDemoRunner.RunGeneratedStaticAsync(Request).AsTask().GetAwaiter().GetResult();
}
23 changes: 23 additions & 0 deletions docs/examples/product-catalog-cache-stampede-protection.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Product Catalog Cache Stampede Protection

This example protects product availability reads from duplicate origin loads when two requests miss the same catalog key at the same time.

```csharp
var request = new ProductAvailabilityRequest("SKU-100", "us");
var results = await ProductCatalogStampedeProtectionDemoRunner.RunFluentAsync(request);
```

The generated route uses the same workflow through a generated policy factory:

```csharp
var policy = GeneratedProductCatalogStampedeProtectionPolicy.CreateGenerated();
var service = new ProductCatalogStampedeProtectionService(policy, origin);
```

Import the demo into a host with:

```csharp
services.AddProductCatalogStampedeProtectionDemo();
```

The registration provides `CacheStampedeProtectionPolicy<ProductAvailabilitySnapshot>`, `ProductCatalogOrigin`, `ProductCatalogStampedeProtectionService`, and `ProductCatalogStampedeProtectionDemoRunner`.
3 changes: 3 additions & 0 deletions docs/examples/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,9 @@
- name: Product Catalog Cache-Aside
href: product-catalog-cache-aside.md

- name: Product Catalog Cache Stampede Protection
href: product-catalog-cache-stampede-protection.md

- name: Product Search Rate Limiting
href: product-search-rate-limiting.md

Expand Down
18 changes: 18 additions & 0 deletions docs/generators/cache-stampede-protection.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Cache Stampede Protection Generator

The Cache Stampede Protection generator creates a strongly typed factory for `CacheStampedeProtectionPolicy<TResult>` from a partial host type.

```csharp
using PatternKit.Generators.CacheStampedeProtection;

[GenerateCacheStampedeProtection(typeof(ProductAvailabilitySnapshot), FactoryMethodName = "CreateGenerated", PolicyName = "product-catalog-single-flight")]
public static partial class GeneratedProductCatalogStampedeProtectionPolicy;
```

Generated usage:

```csharp
var policy = GeneratedProductCatalogStampedeProtectionPolicy.CreateGenerated();
```

The host type must be partial. `FactoryMethodName` and `PolicyName` must be non-empty when provided.
1 change: 1 addition & 0 deletions docs/generators/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ PatternKit includes a Roslyn incremental generator package (`PatternKit.Generato
| [**Health Endpoint Monitoring**](health-endpoint-monitoring.md) | Typed service health endpoint factories | `[GenerateHealthEndpoint]` |
| [**Priority Queue**](priority-queue.md) | Business-priority queue factories | `[GeneratePriorityQueue]` |
| [**Cache-Aside**](cache-aside.md) | Read-through cache policy factories with TTL and cache predicates | `[GenerateCacheAsidePolicy]` |
| [**Cache Stampede Protection**](cache-stampede-protection.md) | Keyed single-flight policy factories for suppressing duplicate cache-miss loads | `[GenerateCacheStampedeProtection]` |
| [**Rate Limiting**](rate-limiting.md) | Key-partitioned fixed-window rate limit policy factories | `[GenerateRateLimitPolicy]` |
| [**External Configuration Store**](external-configuration-store.md) | Typed centralized configuration loaders | `[GenerateExternalConfigurationStore]` |
| [**Gateway Aggregation**](gateway-aggregation.md) | API gateway response composition factories | `[GenerateGatewayAggregation]` |
Expand Down
3 changes: 3 additions & 0 deletions docs/generators/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
- name: Cache-Aside
href: cache-aside.md

- name: Cache Stampede Protection
href: cache-stampede-protection.md

- name: Canonical Data Model
href: canonical-data-model.md

Expand Down
20 changes: 12 additions & 8 deletions docs/guides/benchmark-results.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ The latest measured timings below were captured on Windows 11, Intel Core i9-149
| Bridge | Execution | 91.848 ns | 664 B | 30.004 ns | 160 B | Generated bridge forwarding was faster and allocated less for notice rendering. |
| Bulkhead | Construction | 20.56 ns | 216 B | 20.48 ns | 216 B | Effectively equivalent for this microbenchmark. |
| Bulkhead | Execution | 102.70 ns | 592 B | 106.11 ns | 592 B | Same allocation; fluent was slightly faster for the shipping allocation workflow. |
| Cache Stampede Protection | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
| Cache Stampede Protection | Execution | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
| Cache-Aside | Construction | 19.91 ns | 200 B | 19.85 ns | 200 B | Effectively equivalent for this microbenchmark. |
| Cache-Aside | Execution | 216.50 ns | 1,048 B | 208.60 ns | 1,048 B | Same allocation; generated was slightly faster for the miss-then-hit workflow. |
| Canonical Data Model | Construction | 75.482 ns | 632 B | 59.947 ns | 496 B | Generated reduced construction time and allocation in this microbenchmark. |
Expand Down Expand Up @@ -234,19 +236,19 @@ The latest measured timings below were captured on Windows 11, Intel Core i9-149

## Coverage Matrix Summary

The coverage matrix currently publishes 108 catalog patterns and 432 pattern route results. Each pattern has four BenchmarkDotNet routes: fluent construction, fluent execution, source-generated construction, and source-generated execution. The reusable hosting integration matrix publishes 9 reusable hosting integration route results for package-level `IServiceCollection` registrations.
The coverage matrix currently publishes 109 catalog patterns and 436 pattern route results. Each pattern has four BenchmarkDotNet routes: fluent construction, fluent execution, source-generated construction, and source-generated execution. The reusable hosting integration matrix publishes 9 reusable hosting integration route results for package-level `IServiceCollection` registrations.

| Category | Patterns | Published route results |
| --- | ---: | ---: |
| Application Architecture | 23 | 92 |
| Behavioral | 11 | 44 |
| Cloud Architecture | 17 | 68 |
| Cloud Architecture | 18 | 72 |
| Creational | 5 | 20 |
| Enterprise Integration | 41 | 164 |
| Messaging Reliability | 3 | 12 |
| Structural | 7 | 28 |

The generator matrix currently publishes 103 generator source route results.
The generator matrix currently publishes 104 generator source route results.

## Hosting Integration Matrix Results

Expand Down Expand Up @@ -301,9 +303,10 @@ The generator matrix currently publishes 103 generator source route results.
| Behavioral | Template Method | Covered | Covered | Covered | Covered |
| Behavioral | Visitor | Covered | Covered | Covered | Covered |
| Cloud Architecture | Ambassador | Covered | Covered | Covered | Covered |
| Cloud Architecture | Backends for Frontends | Covered | Covered | Covered | Covered |
| Cloud Architecture | Bulkhead | Covered | Covered | Covered | Covered |
| Cloud Architecture | Cache-Aside | Covered | Covered | Covered | Covered |
| Cloud Architecture | Backends for Frontends | Covered | Covered | Covered | Covered |
| Cloud Architecture | Bulkhead | Covered | Covered | Covered | Covered |
| Cloud Architecture | Cache Stampede Protection | Covered | Covered | Covered | Covered |
| Cloud Architecture | Cache-Aside | Covered | Covered | Covered | Covered |
| Cloud Architecture | Circuit Breaker | Covered | Covered | Covered | Covered |
| Cloud Architecture | External Configuration Store | Covered | Covered | Covered | Covered |
| Cloud Architecture | Gateway Aggregation | Covered | Covered | Covered | Covered |
Expand Down Expand Up @@ -389,8 +392,9 @@ The generator matrix currently publishes 103 generator source route results.
| BackendsForFrontendsGenerator | `src/PatternKit.Generators/BackendsForFrontends/BackendsForFrontendsGenerator.cs` | Covered |
| BridgeGenerator | `src/PatternKit.Generators/Bridge/BridgeGenerator.cs` | Covered |
| BuilderGenerator | `src/PatternKit.Generators/Builders/BuilderGenerator.cs` | Covered |
| BulkheadPolicyGenerator | `src/PatternKit.Generators/Bulkhead/BulkheadPolicyGenerator.cs` | Covered |
| CacheAsidePolicyGenerator | `src/PatternKit.Generators/CacheAside/CacheAsidePolicyGenerator.cs` | Covered |
| BulkheadPolicyGenerator | `src/PatternKit.Generators/Bulkhead/BulkheadPolicyGenerator.cs` | Covered |
| CacheAsidePolicyGenerator | `src/PatternKit.Generators/CacheAside/CacheAsidePolicyGenerator.cs` | Covered |
| CacheStampedeProtectionGenerator | `src/PatternKit.Generators/CacheStampedeProtection/CacheStampedeProtectionGenerator.cs` | Covered |
| CanonicalDataModelGenerator | `src/PatternKit.Generators/CanonicalDataModel/CanonicalDataModelGenerator.cs` | Covered |
| ChainGenerator | `src/PatternKit.Generators/Chain/ChainGenerator.cs` | Covered |
| CircuitBreakerPolicyGenerator | `src/PatternKit.Generators/CircuitBreaker/CircuitBreakerPolicyGenerator.cs` | Covered |
Expand Down
2 changes: 2 additions & 0 deletions docs/guides/benchmarks.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ The following numbers were captured on Windows 11, Intel Core i9-14900K, .NET SD
| Bridge | Execution | 91.848 ns | 664 B | 30.004 ns | 160 B | Generated bridge forwarding was faster and allocated less for notice rendering. |
| Bulkhead | Construction | 20.56 ns | 216 B | 20.48 ns | 216 B | Effectively equivalent for this microbenchmark. |
| Bulkhead | Execution | 102.70 ns | 592 B | 106.11 ns | 592 B | Same allocation; fluent was slightly faster for the shipping allocation workflow. |
| Cache Stampede Protection | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
| Cache Stampede Protection | Execution | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
| Cache-Aside | Construction | 19.91 ns | 200 B | 19.85 ns | 200 B | Effectively equivalent for this microbenchmark. |
| Cache-Aside | Execution | 216.50 ns | 1,048 B | 208.60 ns | 1,048 B | Same allocation; generated was slightly faster for the miss-then-hit workflow. |
| Canonical Data Model | Construction | 75.482 ns | 632 B | 59.947 ns | 496 B | Generated reduced construction time and allocation in this microbenchmark. |
Expand Down
1 change: 1 addition & 0 deletions docs/guides/pattern-coverage.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ The source of truth is `PatternKitPatternCatalog` in `src/PatternKit.Examples/Pr
| Cloud Architecture | Retry | `RetryPolicy<T>` | Retry generator |
| Cloud Architecture | Circuit Breaker | `CircuitBreakerPolicy<T>` | Circuit Breaker generator |
| Cloud Architecture | Bulkhead | `BulkheadPolicy<T>` | Bulkhead generator |
| Cloud Architecture | Cache Stampede Protection | `CacheStampedeProtectionPolicy<TResult>` | Cache Stampede Protection generator |
| Cloud Architecture | Queue-Based Load Leveling | `QueueLoadLevelingPolicy<T>` | Queue Load Leveling generator |
| Cloud Architecture | Health Endpoint Monitoring | `HealthEndpoint<TContext>` | Health Endpoint Monitoring generator |
| Cloud Architecture | Priority Queue | `PriorityQueuePolicy<TItem, TPriority>` | Priority Queue generator |
Expand Down
4 changes: 2 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,13 @@ if (parser.Execute("123", out var value))

## 📚 Available Patterns

PatternKit covers 108 production-readiness patterns with fluent APIs, source-generated routes where applicable, IoC integration examples, TinyBDD coverage, and BenchmarkDotNet coverage-matrix validation:
PatternKit covers 109 production-readiness patterns with fluent APIs, source-generated routes where applicable, IoC integration examples, TinyBDD coverage, and BenchmarkDotNet coverage-matrix validation:

| Category | Count | Patterns |
| --- | ---: | --- |
| Application Architecture | 23 | Activity Tracker, Aggregate Root, Anti-Corruption Layer, Audit Log, Bounded Context, Context Map, CQRS, Data Mapper, Domain Event, Domain Service, Event Sourcing, Feature Toggle, Identity Map, Manual Task Gate, Materialized View, Repository, Service Layer, Specification, Table Data Gateway, Timeout Manager, Transaction Script, Unit of Work, Value Object |
| Behavioral | 11 | Chain of Responsibility, Command, Interpreter, Iterator, Mediator, Memento, Observer, State, Strategy, Template Method, Visitor |
| Cloud Architecture | 17 | Ambassador, Backends for Frontends, Bulkhead, Cache-Aside, Circuit Breaker, External Configuration Store, Gateway Aggregation, Gateway Routing, Health Endpoint Monitoring, Leader Election, Priority Queue, Queue-Based Load Leveling, Rate Limiting, Retry, Scheduler Agent Supervisor, Sidecar, Strangler Fig |
| Cloud Architecture | 18 | Ambassador, Backends for Frontends, Bulkhead, Cache-Aside, Cache Stampede Protection, Circuit Breaker, External Configuration Store, Gateway Aggregation, Gateway Routing, Health Endpoint Monitoring, Leader Election, Priority Queue, Queue-Based Load Leveling, Rate Limiting, Retry, Scheduler Agent Supervisor, Sidecar, Strangler Fig |
| Creational | 5 | Abstract Factory, Builder, Factory Method, Prototype, Singleton |
| Enterprise Integration | 41 | Aggregator, Canonical Data Model, Channel Adapter, Channel Purger, Claim Check, Competing Consumers, Content Enricher, Content-Based Router, Control Bus, Correlation Identifier, Dead Letter Channel, Durable Subscriber, Dynamic Router, Event Notification, Event-Carried State Transfer, Event-Driven Consumer, Guaranteed Delivery, Invalid Message Channel, Mailbox, Message Bus, Message Channel, Message Envelope, Message Expiration, Message Filter, Message History, Message Store, Message Translator, Messaging Bridge, Messaging Gateway, Pipes and Filters, Polling Consumer, Publish-Subscribe, Recipient List, Request-Reply, Resequencer, Routing Slip, Saga / Process Manager, Scatter-Gather, Service Activator, Splitter, Wire Tap |
| Messaging Reliability | 3 | Idempotent Receiver, Inbox, Outbox |
Expand Down
25 changes: 25 additions & 0 deletions docs/patterns/cloud/cache-stampede-protection.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Cache Stampede Protection

Cache Stampede Protection coordinates concurrent cache misses so only one origin load runs for a key while followers await the same result. Use it around expensive catalog, configuration, entitlement, pricing, or profile loads that can receive bursts of identical requests after expiration.

`CacheStampedeProtectionPolicy<TResult>` provides the fluent path:

```csharp
var policy = CacheStampedeProtectionPolicy<ProductAvailabilitySnapshot>
.Create("product-catalog-single-flight")
.Build();

var result = await policy.GetOrLoadAsync(
"us:SKU-100",
ct => origin.LoadAsync(request, ct),
cancellationToken);
```

The first caller owns the load. Concurrent callers for the same key receive `SharedFlight = true` and the same loaded value once the origin call completes.

Use the source-generated path for reusable policy factories:

```csharp
[GenerateCacheStampedeProtection(typeof(ProductAvailabilitySnapshot), FactoryMethodName = "CreateGenerated", PolicyName = "product-catalog-single-flight")]
public static partial class GeneratedProductCatalogStampedeProtectionPolicy;
```
Loading
Loading