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
8 changes: 8 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ jobs:
run: |
dotnet test test/PatternKit.Tests/PatternKit.Tests.csproj \
--configuration Release \
--framework net8.0 \
--no-build \
-p:TestTfmsInParallel=false \
--collect:"XPlat Code Coverage" \
Expand All @@ -65,6 +66,7 @@ jobs:
-- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=cobertura
dotnet test test/PatternKit.Generators.Tests/PatternKit.Generators.Tests.csproj \
--configuration Release \
--framework net8.0 \
--no-build \
-p:TestTfmsInParallel=false \
--collect:"XPlat Code Coverage" \
Expand All @@ -73,6 +75,7 @@ jobs:
-- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=cobertura
dotnet test test/PatternKit.Hosting.Extensions.Tests/PatternKit.Hosting.Extensions.Tests.csproj \
--configuration Release \
--framework net8.0 \
--no-build \
-p:TestTfmsInParallel=false \
--collect:"XPlat Code Coverage" \
Expand All @@ -81,6 +84,7 @@ jobs:
-- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=cobertura
dotnet test test/PatternKit.Examples.Tests/PatternKit.Examples.Tests.csproj \
--configuration Release \
--framework net8.0 \
--no-build \
-p:TestTfmsInParallel=false \
--collect:"XPlat Code Coverage" \
Expand Down Expand Up @@ -198,6 +202,7 @@ jobs:
run: |
dotnet test test/PatternKit.Tests/PatternKit.Tests.csproj \
--configuration Release \
--framework net8.0 \
--no-build \
-p:TestTfmsInParallel=false \
--collect:"XPlat Code Coverage" \
Expand All @@ -206,6 +211,7 @@ jobs:
-- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=cobertura
dotnet test test/PatternKit.Generators.Tests/PatternKit.Generators.Tests.csproj \
--configuration Release \
--framework net8.0 \
--no-build \
-p:TestTfmsInParallel=false \
--collect:"XPlat Code Coverage" \
Expand All @@ -214,6 +220,7 @@ jobs:
-- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=cobertura
dotnet test test/PatternKit.Hosting.Extensions.Tests/PatternKit.Hosting.Extensions.Tests.csproj \
--configuration Release \
--framework net8.0 \
--no-build \
-p:TestTfmsInParallel=false \
--collect:"XPlat Code Coverage" \
Expand All @@ -222,6 +229,7 @@ jobs:
-- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=cobertura
dotnet test test/PatternKit.Examples.Tests/PatternKit.Examples.Tests.csproj \
--configuration Release \
--framework net8.0 \
--no-build \
-p:TestTfmsInParallel=false \
--collect:"XPlat Code Coverage" \
Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ var cachedRemoteProxy = Proxy<int, string>.Create(id => remoteProxy.Execute(id))
---

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

| Category | Count | Patterns |
| --- | ---: | --- |
Expand All @@ -482,7 +482,7 @@ PatternKit currently tracks 115 production-readiness patterns. Each catalog patt
| Cloud Architecture | 20 | 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, Read-Through Cache, Retry, Scheduler Agent Supervisor, Sidecar, Strangler Fig, Write-Through Cache |
| Creational | 6 | Abstract Factory, Builder, Factory Method, Object Pool, 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 |
| Messaging Reliability | 4 | Backpressure, Idempotent Receiver, Inbox, Outbox |
| Structural | 7 | Adapter, Bridge, Composite, Decorator, Facade, Flyweight, Proxy |

## Benchmark Snapshot
Expand Down Expand Up @@ -527,6 +527,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. |
| Backpressure | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
| Backpressure | Execution | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
| 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. |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using BenchmarkDotNet.Attributes;
using PatternKit.Examples.BackpressureDemo;
using PatternKit.Messaging.Reliability.Backpressure;

namespace PatternKit.Benchmarks.Messaging;

[BenchmarkCategory("MessagingReliability", "Backpressure")]
public class BackpressureBenchmarks
{
private static readonly CheckoutWork Work = new("ORDER-100", 42m);

[Benchmark(Baseline = true, Description = "Fluent: create backpressure policy")]
[BenchmarkCategory("Fluent", "Construction")]
public BackpressurePolicy<CheckoutAdmission> Fluent_CreatePolicy()
=> CheckoutBackpressurePolicies.CreateFluentPolicy();

[Benchmark(Description = "Generated: create backpressure policy")]
[BenchmarkCategory("Generated", "Construction")]
public BackpressurePolicy<CheckoutAdmission> Generated_CreatePolicy()
=> GeneratedCheckoutBackpressurePolicy.CreateGeneratedPolicy();

[Benchmark(Description = "Fluent: submit checkout work")]
[BenchmarkCategory("Fluent", "Execution")]
public ValueTask<CheckoutAdmission> Fluent_Submit()
{
var service = new CheckoutBackpressureService(
new ScriptedCheckoutProcessor(new CheckoutAdmission("", true, "accepted")),
CheckoutBackpressurePolicies.CreateFluentPolicy());

return service.SubmitAsync(Work);
}

[Benchmark(Description = "Generated: submit checkout work")]
[BenchmarkCategory("Generated", "Execution")]
public ValueTask<CheckoutAdmission> Generated_Submit()
{
var service = new CheckoutBackpressureService(
new ScriptedCheckoutProcessor(new CheckoutAdmission("", true, "accepted")),
GeneratedCheckoutBackpressurePolicy.CreateGeneratedPolicy());

return service.SubmitAsync(Work);
}
}
20 changes: 20 additions & 0 deletions docs/examples/checkout-backpressure.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Checkout Backpressure

The checkout backpressure example shows a production-style admission gate in front of checkout work. It includes a fluent policy, a source-generated policy factory, and an `IServiceCollection` extension that registers the policy and workflow service.

Import it into a host:

```csharp
services.AddCheckoutBackpressureDemo();
```

For reusable app-level registration without importing examples:

```csharp
services.AddPatternKitBackpressurePolicy<CheckoutAdmission>(
"checkout-backpressure",
builder => builder
.WithCapacity(8)
.WithMode(BackpressureMode.Wait)
.WithWaitTimeout(TimeSpan.FromMilliseconds(50)));
```
3 changes: 3 additions & 0 deletions docs/examples/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ Welcome! This section collects small, focused demos that show **how to compose b
* **Customer Notification Null Object**
A Generic Host importable notification fallback with fluent and source-generated routes, `IServiceCollection` registration, and deterministic no-op behavior for optional collaborators. See [Customer Notification Null Object](null-object-notification.md).

* **Checkout Backpressure**
A Generic Host importable checkout admission gate with fluent and source-generated routes, `IServiceCollection` registration, and explicit saturation behavior. See [Checkout Backpressure](checkout-backpressure.md).

* **Minimal Web Request Router**
A tiny "API gateway" that separates **first-match middleware** (side effects/logging/auth) from **first-match routes** and **content negotiation**. A crisp example of Strategy patterns in an HTTP-ish setting.

Expand Down
3 changes: 3 additions & 0 deletions docs/examples/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,9 @@
- name: Shipping Bulkhead
href: shipping-bulkhead.md

- name: Checkout Backpressure
href: checkout-backpressure.md

- name: Fulfillment Queue Load Leveling
href: fulfillment-queue-load-leveling.md

Expand Down
21 changes: 21 additions & 0 deletions docs/generators/backpressure.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Backpressure Generator

`[GenerateBackpressurePolicy]` emits a static factory for `BackpressurePolicy<TResult>` with compile-time configuration for name, capacity, saturation mode, and wait timeout.

```csharp
[GenerateBackpressurePolicy(
typeof(CheckoutAdmission),
FactoryMethodName = "CreateGeneratedPolicy",
PolicyName = "checkout-backpressure",
Capacity = 8,
Mode = "Wait",
WaitTimeoutMilliseconds = 50)]
public static partial class GeneratedCheckoutBackpressurePolicy;
```

Diagnostics:

- `PKBP001`: the host type must be partial.
- `PKBP002`: capacity and wait timeout must be valid.
- `PKBP003`: the factory method name must be a valid identifier.
- `PKBP004`: mode must be one of `Reject`, `Wait`, `DropNewest`, `DropOldest`, `Shed`, or `Observe`.
5 changes: 5 additions & 0 deletions docs/generators/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ PatternKit includes a Roslyn incremental generator package (`PatternKit.Generato
| [**Routing Slip**](messaging.md#generated-routing-slip) | Ordered message itinerary factories | `[GenerateRoutingSlip]` |
| [**Saga**](messaging.md#generated-saga) | Typed process-manager transition factories | `[GenerateSaga]` |
| [**Mailbox**](messaging.md#generated-mailbox) | Serialized in-process inbox factories | `[GenerateMailbox]` |
| [**Backpressure**](backpressure.md) | Admission-control policy factories for saturated work boundaries | `[GenerateBackpressurePolicy]` |
| [**Reliability Pipeline**](messaging.md#generated-reliability-pipeline) | Idempotent receiver, inbox, and outbox factories | `[GenerateReliabilityPipeline]` |
| [**Backplane Topology**](messaging.md#generated-backplane-topology) | Request/reply routes and publish/subscribe endpoint topology | `[GenerateBackplaneTopology]` |

Expand Down Expand Up @@ -280,6 +281,10 @@ public static partial class OrderLineAggregator { }
[GenerateMailbox(typeof(OrderWork), Capacity = 32, BackpressurePolicy = "Wait")]
public static partial class OrderMailbox { }

// Backpressure - generated admission-control policy
[GenerateBackpressurePolicy(typeof(CheckoutAdmission), Capacity = 8, Mode = "Wait", WaitTimeoutMilliseconds = 50)]
public static partial class CheckoutBackpressurePolicy { }

// Reliability pipeline - generated idempotent receiver, inbox, and outbox factories
[GenerateReliabilityPipeline(typeof(AcceptOrder), typeof(string), typeof(OrderAccepted))]
public static partial class OrderReliability { }
Expand Down
3 changes: 3 additions & 0 deletions docs/generators/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
- name: Bulkhead
href: bulkhead.md

- name: Backpressure
href: backpressure.md

- name: Cache-Aside
href: cache-aside.md

Expand Down
17 changes: 11 additions & 6 deletions docs/guides/benchmark-results.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,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. |
| Backpressure | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
| Backpressure | Execution | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
| 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. |
Expand Down Expand Up @@ -252,7 +254,7 @@ The latest measured timings below were captured on Windows 11, Intel Core i9-149

## Coverage Matrix Summary

The coverage matrix currently publishes 115 catalog patterns and 460 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 10 reusable hosting integration route results for package-level `IServiceCollection` registrations.
The coverage matrix currently publishes 116 catalog patterns and 464 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 11 reusable hosting integration route results for package-level `IServiceCollection` registrations.

| Category | Patterns | Published route results |
| --- | ---: | ---: |
Expand All @@ -261,15 +263,16 @@ The coverage matrix currently publishes 115 catalog patterns and 460 pattern rou
| Cloud Architecture | 20 | 80 |
| Creational | 6 | 24 |
| Enterprise Integration | 41 | 164 |
| Messaging Reliability | 3 | 12 |
| Messaging Reliability | 4 | 16 |
| Structural | 7 | 28 |

The generator matrix currently publishes 110 generator source route results.
The generator matrix currently publishes 111 generator source route results.

## Hosting Integration Matrix Results

| Pattern | Route | Registration | Source | Tests | Docs |
| --- | --- | --- | --- | --- | --- |
| Backpressure | `IServiceCollection` | `AddPatternKitBackpressurePolicy<TResult>` | `src/PatternKit.Hosting.Extensions/DependencyInjection/PatternKitServiceCollectionExtensions.cs` | `test/PatternKit.Hosting.Extensions.Tests/DependencyInjection/PatternKitServiceCollectionExtensionsTests.cs` | `docs/guides/hosting-extensions.md` |
| Bulkhead | `IServiceCollection` | `AddPatternKitBulkheadPolicy<TResult>` | `src/PatternKit.Hosting.Extensions/DependencyInjection/PatternKitServiceCollectionExtensions.cs` | `test/PatternKit.Hosting.Extensions.Tests/DependencyInjection/PatternKitServiceCollectionExtensionsTests.cs` | `docs/guides/hosting-extensions.md` |
| Circuit Breaker | `IServiceCollection` | `AddPatternKitCircuitBreakerPolicy<TResult>` | `src/PatternKit.Hosting.Extensions/DependencyInjection/PatternKitServiceCollectionExtensions.cs` | `test/PatternKit.Hosting.Extensions.Tests/DependencyInjection/PatternKitServiceCollectionExtensionsTests.cs` | `docs/guides/hosting-extensions.md` |
| Guaranteed Delivery | `IServiceCollection` | `AddPatternKitGuaranteedDelivery<TPayload>` | `src/PatternKit.Hosting.Extensions/DependencyInjection/PatternKitServiceCollectionExtensions.cs` | `test/PatternKit.Hosting.Extensions.Tests/DependencyInjection/PatternKitServiceCollectionExtensionsTests.cs` | `docs/guides/hosting-extensions.md` |
Expand Down Expand Up @@ -390,7 +393,8 @@ The generator matrix currently publishes 110 generator source route results.
| Enterprise Integration | Service Activator | Covered | Covered | Covered | Covered |
| Enterprise Integration | Splitter | Covered | Covered | Covered | Covered |
| Enterprise Integration | Wire Tap | Covered | Covered | Covered | Covered |
| Messaging Reliability | Idempotent Receiver | Covered | Covered | Covered | Covered |
| Messaging Reliability | Backpressure | Covered | Covered | Covered | Covered |
| Messaging Reliability | Idempotent Receiver | Covered | Covered | Covered | Covered |
| Messaging Reliability | Inbox | Covered | Covered | Covered | Covered |
| Messaging Reliability | Outbox | Covered | Covered | Covered | Covered |
| Structural | Adapter | Covered | Covered | Covered | Covered |
Expand All @@ -416,8 +420,9 @@ The generator matrix currently publishes 110 generator source route results.
| AmbassadorGenerator | `src/PatternKit.Generators/Ambassador/AmbassadorGenerator.cs` | Covered |
| AntiCorruptionLayerGenerator | `src/PatternKit.Generators/AntiCorruption/AntiCorruptionLayerGenerator.cs` | Covered |
| AuditLogGenerator | `src/PatternKit.Generators/AuditLog/AuditLogGenerator.cs` | Covered |
| BackendsForFrontendsGenerator | `src/PatternKit.Generators/BackendsForFrontends/BackendsForFrontendsGenerator.cs` | Covered |
| BridgeGenerator | `src/PatternKit.Generators/Bridge/BridgeGenerator.cs` | Covered |
| BackendsForFrontendsGenerator | `src/PatternKit.Generators/BackendsForFrontends/BackendsForFrontendsGenerator.cs` | Covered |
| BackpressurePolicyGenerator | `src/PatternKit.Generators/Backpressure/BackpressurePolicyGenerator.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 |
Expand Down
Loading
Loading