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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -473,11 +473,11 @@ var cachedRemoteProxy = Proxy<int, string>.Create(id => remoteProxy.Execute(id))
---

## Patterns Table
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.
PatternKit currently tracks 117 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 | 26 | Activity Tracker, Aggregate Root, Anti-Corruption Layer, Audit Log, Bounded Context, Context Map, CQRS, Data Mapper, Domain Event, Domain Service, Event Sourcing, Eventual Consistency Monitor, Feature Toggle, Identity Map, Manual Task Gate, Materialized View, Repository, Service Layer, Snapshot / Checkpoint Management, Specification, Table Data Gateway, Timeout Manager, Transaction Script, Unit of Work, Value Object, Workflow Orchestration |
| Application Architecture | 27 | Activity Tracker, Aggregate Root, Anti-Corruption Layer, Audit Log, Bounded Context, Context Map, CQRS, Data Mapper, Domain Event, Domain Service, Event Sourcing, Eventual Consistency Monitor, Feature Toggle, Identity Map, Lazy Load, Manual Task Gate, Materialized View, Repository, Service Layer, Snapshot / Checkpoint Management, Specification, Table Data Gateway, Timeout Manager, Transaction Script, Unit of Work, Value Object, Workflow Orchestration |
| Behavioral | 12 | Chain of Responsibility, Command, Interpreter, Iterator, Mediator, Memento, Null Object, Observer, State, Strategy, Template Method, Visitor |
| 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 |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using BenchmarkDotNet.Attributes;
using PatternKit.Application.LazyLoading;
using PatternKit.Examples.LazyLoadDemo;

namespace PatternKit.Benchmarks.Application;

[BenchmarkCategory("ApplicationArchitecture", "LazyLoad")]
public class LazyLoadBenchmarks
{
private static readonly ICustomerProfileStore Store = new InMemoryCustomerProfileStore(new CustomerProfile(Guid.Empty, "Ada Lovelace", "Gold"));

[Benchmark(Baseline = true, Description = "Fluent: create lazy load")]
[BenchmarkCategory("Fluent", "Construction")]
public LazyLoad<CustomerProfile> Fluent_Create()
=> CustomerProfileLazyLoadPolicies.CreateFluent(Store);

[Benchmark(Description = "Generated: create lazy load")]
[BenchmarkCategory("Generated", "Construction")]
public LazyLoad<CustomerProfile> Generated_Create()
{
GeneratedCustomerProfileLazyLoad.UseStore(Store);
return GeneratedCustomerProfileLazyLoad.CreateGenerated();
}

[Benchmark(Description = "Fluent: resolve lazy value")]
[BenchmarkCategory("Fluent", "Execution")]
public async ValueTask<string> Fluent_Resolve()
{
var service = new CustomerProfileLazyLoadService(CustomerProfileLazyLoadPolicies.CreateFluent(Store));
return await service.GetTierAsync().ConfigureAwait(false);
}

[Benchmark(Description = "Generated: resolve lazy value")]
[BenchmarkCategory("Generated", "Execution")]
public async ValueTask<string> Generated_Resolve()
{
GeneratedCustomerProfileLazyLoad.UseStore(Store);
var service = new CustomerProfileLazyLoadService(GeneratedCustomerProfileLazyLoad.CreateGenerated());
return await service.GetTierAsync().ConfigureAwait(false);
}
}
24 changes: 24 additions & 0 deletions docs/examples/customer-profile-lazy-load.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Customer Profile Lazy Load

The customer profile lazy-load example shows a production-shaped deferred profile lookup. It includes a fluent lazy loader, a source-generated lazy loader factory, and an `IServiceCollection` extension that registers the loader and application service.

Import it into a host:

```csharp
services.AddCustomerProfileLazyLoadDemo();
```

For reusable app-level registration without importing examples:

```csharp
services.AddPatternKitLazyLoad<CustomerProfile>(
(provider, ct) =>
{
var store = provider.GetRequiredService<ICustomerProfileStore>();
return store.LoadAsync(customerId, ct);
},
"customer-profile",
builder => builder.WithTimeToLive(TimeSpan.FromMinutes(5)));
```

The example validates that the expensive load is deferred, cached, refreshable through invalidation, and importable through standard Microsoft dependency injection.
3 changes: 3 additions & 0 deletions docs/examples/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ Welcome! This section collects small, focused demos that show **how to compose b
* **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).

* **Customer Profile Lazy Load**
A Generic Host importable deferred profile lookup with fluent and source-generated routes, `IServiceCollection` registration, TTL caching, and invalidation. See [Customer Profile Lazy Load](customer-profile-lazy-load.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 @@ -208,6 +208,9 @@
- name: Order Identity Map Pattern
href: order-identity-map-pattern.md

- name: Customer Profile Lazy Load
href: customer-profile-lazy-load.md

- name: Order Transaction Script Pattern
href: order-transaction-script-pattern.md

Expand Down
5 changes: 5 additions & 0 deletions docs/generators/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ PatternKit includes a Roslyn incremental generator package (`PatternKit.Generato
| [**Unit of Work**](unit-of-work.md) | Ordered commit and rollback units | `[GenerateUnitOfWork]` |
| [**Data Mapper**](data-mapper.md) | Domain/data model mapper factories | `[GenerateDataMapper]` |
| [**Identity Map**](identity-map.md) | Scoped object identity caches from key selectors | `[GenerateIdentityMap]` |
| [**Lazy Load**](lazy-load.md) | Deferred value factories with caching, TTL, and invalidation | `[GenerateLazyLoad]` |
| [**Materialized View**](materialized-view.md) | Event projection read-model factories from handlers | `[GenerateMaterializedView]` |
| [**Transaction Script**](transaction-script.md) | Typed application workflow factories | `[GenerateTransactionScript]` |
| [**Service Layer**](service-layer.md) | Application operation boundary factories | `[GenerateServiceLayerOperation]` |
Expand Down Expand Up @@ -234,6 +235,10 @@ public static partial class InventoryStateTransfer { }
[GenerateEventNotification(typeof(OrderAccepted), typeof(string))]
public static partial class OrderAcceptedNotification { }

// Lazy load - deferred value factory
[GenerateLazyLoad(typeof(CustomerProfile), LoaderMethodName = "LoadProfileAsync", TimeToLiveMilliseconds = 300000)]
public static partial class CustomerProfileLazyLoad { }

// Claim check - external payload storage reference
[GenerateClaimCheck(typeof(LargeOrderDocument), StoreName = "document-archive")]
public static partial class LargeDocumentClaims { }
Expand Down
31 changes: 31 additions & 0 deletions docs/generators/lazy-load.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Lazy Load Generator

`LazyLoadGenerator` emits a typed `LazyLoad<TValue>` factory from a loader method.

```csharp
[GenerateLazyLoad(
typeof(CustomerProfile),
FactoryMethodName = "CreateProfile",
LoaderMethodName = "LoadProfileAsync",
LazyLoadName = "customer-profile",
TimeToLiveMilliseconds = 300000)]
public static partial class CustomerProfileLazyLoad
{
public static ValueTask<CustomerProfile> LoadProfileAsync(CancellationToken cancellationToken)
=> store.LoadAsync(customerId, cancellationToken);
}
```

## Diagnostics

| ID | Severity | Message |
| --- | --- | --- |
| `PKLL001` | Error | The host type must be partial. |
| `PKLL002` | Error | Time-to-live values must be non-negative. |
| `PKLL003` | Error | Factory and loader method names must be valid C# identifiers. |

Register generated lazy loaders with normal .NET hosts by calling the generated factory from the service registration:

```csharp
services.AddSingleton(_ => CustomerProfileLazyLoad.CreateProfile());
```
3 changes: 3 additions & 0 deletions docs/generators/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@
- name: Identity Map
href: identity-map.md

- name: Lazy Load
href: lazy-load.md

- name: Materialized View
href: materialized-view.md

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

## Coverage Matrix Summary

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.
The coverage matrix currently publishes 117 catalog patterns and 468 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 12 reusable hosting integration route results for package-level `IServiceCollection` registrations.

| Category | Patterns | Published route results |
| --- | ---: | ---: |
| Application Architecture | 26 | 104 |
| Application Architecture | 27 | 108 |
| Behavioral | 12 | 48 |
| Cloud Architecture | 20 | 80 |
| Creational | 6 | 24 |
| Enterprise Integration | 41 | 164 |
| Messaging Reliability | 4 | 16 |
| Structural | 7 | 28 |

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

## Hosting Integration Matrix Results

Expand All @@ -276,6 +278,7 @@ The generator matrix currently publishes 111 generator source route results.
| 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` |
| Lazy Load | `IServiceCollection` | `AddPatternKitLazyLoad<TValue>` | `src/PatternKit.Hosting.Extensions/DependencyInjection/PatternKitServiceCollectionExtensions.cs` | `test/PatternKit.Hosting.Extensions.Tests/DependencyInjection/PatternKitServiceCollectionExtensionsTests.cs` | `docs/guides/hosting-extensions.md` |
| Message Channel | `IServiceCollection` | `AddPatternKitMessageChannel<TPayload>` | `src/PatternKit.Hosting.Extensions/DependencyInjection/PatternKitServiceCollectionExtensions.cs` | `test/PatternKit.Hosting.Extensions.Tests/DependencyInjection/PatternKitServiceCollectionExtensionsTests.cs` | `docs/guides/hosting-extensions.md` |
| Message Store | `IServiceCollection` | `AddPatternKitMessageStore<TPayload>` | `src/PatternKit.Hosting.Extensions/DependencyInjection/PatternKitServiceCollectionExtensions.cs` | `test/PatternKit.Hosting.Extensions.Tests/DependencyInjection/PatternKitServiceCollectionExtensionsTests.cs` | `docs/guides/hosting-extensions.md` |
| Null Object | `IServiceCollection` | `AddPatternKitNullObject<TContract>` | `src/PatternKit.Hosting.Extensions/DependencyInjection/PatternKitServiceCollectionExtensions.cs` | `test/PatternKit.Hosting.Extensions.Tests/DependencyInjection/PatternKitServiceCollectionExtensionsTests.cs` | `docs/guides/hosting-extensions.md` |
Expand Down Expand Up @@ -304,9 +307,10 @@ The generator matrix currently publishes 111 generator source route results.
| Application Architecture | Domain Event | Covered | Covered | Covered | Covered |
| Application Architecture | Domain Service | Covered | Covered | Covered | Covered |
| Application Architecture | Event Sourcing | Covered | Covered | Covered | Covered |
| Application Architecture | Feature Toggle | Covered | Covered | Covered | Covered |
| Application Architecture | Identity Map | Covered | Covered | Covered | Covered |
| Application Architecture | Materialized View | Covered | Covered | Covered | Covered |
| Application Architecture | Feature Toggle | Covered | Covered | Covered | Covered |
| Application Architecture | Identity Map | Covered | Covered | Covered | Covered |
| Application Architecture | Lazy Load | Covered | Covered | Covered | Covered |
| Application Architecture | Materialized View | Covered | Covered | Covered | Covered |
| Application Architecture | Repository | Covered | Covered | Covered | Covered |
| Application Architecture | Service Layer | Covered | Covered | Covered | Covered |
| Application Architecture | Specification | Covered | Covered | Covered | Covered |
Expand Down Expand Up @@ -452,8 +456,9 @@ The generator matrix currently publishes 111 generator source route results.
| GatewayAggregationGenerator | `src/PatternKit.Generators/GatewayAggregation/GatewayAggregationGenerator.cs` | Covered |
| GatewayRoutingGenerator | `src/PatternKit.Generators/GatewayRouting/GatewayRoutingGenerator.cs` | Covered |
| HealthEndpointMonitoringGenerator | `src/PatternKit.Generators/HealthEndpointMonitoring/HealthEndpointMonitoringGenerator.cs` | Covered |
| IdentityMapGenerator | `src/PatternKit.Generators/IdentityMap/IdentityMapGenerator.cs` | Covered |
| InterpreterGenerator | `src/PatternKit.Generators/Interpreter/InterpreterGenerator.cs` | Covered |
| IdentityMapGenerator | `src/PatternKit.Generators/IdentityMap/IdentityMapGenerator.cs` | Covered |
| LazyLoadGenerator | `src/PatternKit.Generators/LazyLoading/LazyLoadGenerator.cs` | Covered |
| InterpreterGenerator | `src/PatternKit.Generators/Interpreter/InterpreterGenerator.cs` | Covered |
| IteratorGenerator | `src/PatternKit.Generators/Iterator/IteratorGenerator.cs` | Covered |
| LeaderElectionGenerator | `src/PatternKit.Generators/LeaderElection/LeaderElectionGenerator.cs` | Covered |
| MaterializedViewGenerator | `src/PatternKit.Generators/MaterializedViews/MaterializedViewGenerator.cs` | Covered |
Expand Down
5 changes: 5 additions & 0 deletions docs/guides/hosting-extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ services
.WithCapacity(8)
.WithMode(BackpressureMode.Wait)
.WithWaitTimeout(TimeSpan.FromMilliseconds(50)))
.AddPatternKitLazyLoad<ServiceReply>(
(_, _) => new ValueTask<ServiceReply>(new ServiceReply(true)),
"inventory-lazy",
lazy => lazy.WithTimeToLive(TimeSpan.FromMinutes(5)))
.AddPatternKitRateLimitPolicy<ServiceReply>(
"inventory-rate-limit",
rateLimit => rateLimit
Expand Down Expand Up @@ -122,6 +126,7 @@ Every catalog pattern is importable through the production example catalog. The
| Circuit Breaker | `AddPatternKitCircuitBreakerPolicy<TResult>` | Register named circuit breakers with shared state. |
| Bulkhead | `AddPatternKitBulkheadPolicy<TResult>` | Register concurrency and queue isolation policies. |
| Backpressure | `AddPatternKitBackpressurePolicy<TResult>` | Register admission gates for saturated work boundaries. |
| Lazy Load | `AddPatternKitLazyLoad<TValue>` | Register deferred value loaders with cache, TTL, and invalidation support. |
| Rate Limiting | `AddPatternKitRateLimitPolicy<TResult>` | Register per-key rate windows. |
| Queue-Based Load Leveling | `AddPatternKitQueueLoadLevelingPolicy<TResult>` | Register queue-backed worker policies. |
| Priority Queue | `AddPatternKitPriorityQueue<TItem, TPriority>` | Register priority-ordered work queues. |
Expand Down
4 changes: 2 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,11 @@ if (parser.Execute("123", out var value))

## 📚 Available Patterns

PatternKit covers 116 production-readiness patterns with fluent APIs, source-generated routes where applicable, IoC integration examples, TinyBDD coverage, and BenchmarkDotNet coverage-matrix validation:
PatternKit covers 117 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 | 26 | Activity Tracker, Aggregate Root, Anti-Corruption Layer, Audit Log, Bounded Context, Context Map, CQRS, Data Mapper, Domain Event, Domain Service, Event Sourcing, Eventual Consistency Monitor, Feature Toggle, Identity Map, Manual Task Gate, Materialized View, Repository, Service Layer, Snapshot / Checkpoint Management, Specification, Table Data Gateway, Timeout Manager, Transaction Script, Unit of Work, Value Object, Workflow Orchestration |
| Application Architecture | 27 | Activity Tracker, Aggregate Root, Anti-Corruption Layer, Audit Log, Bounded Context, Context Map, CQRS, Data Mapper, Domain Event, Domain Service, Event Sourcing, Eventual Consistency Monitor, Feature Toggle, Identity Map, Lazy Load, Manual Task Gate, Materialized View, Repository, Service Layer, Snapshot / Checkpoint Management, Specification, Table Data Gateway, Timeout Manager, Transaction Script, Unit of Work, Value Object, Workflow Orchestration |
| Behavioral | 12 | Chain of Responsibility, Command, Interpreter, Iterator, Mediator, Memento, Null Object, Observer, State, Strategy, Template Method, Visitor |
| 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 |
Expand Down
Loading
Loading