Skip to content

Commit aa7f909

Browse files
authored
feat: add timeout manager pattern
Adds Timeout Manager fluent and source-generated paths with docs, examples, DI integration, benchmarks, and TinyBDD coverage. Closes #447.
1 parent e8114c0 commit aa7f909

27 files changed

Lines changed: 968 additions & 12 deletions

File tree

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -473,11 +473,11 @@ var cachedRemoteProxy = Proxy<int, string>.Create(id => remoteProxy.Execute(id))
473473
---
474474

475475
## Patterns Table
476-
PatternKit currently tracks 106 production-readiness patterns. Each catalog pattern is represented in tests, documentation, real-world examples, IoC integration, and the BenchmarkDotNet coverage matrix.
476+
PatternKit currently tracks 107 production-readiness patterns. Each catalog pattern is represented in tests, documentation, real-world examples, IoC integration, and the BenchmarkDotNet coverage matrix.
477477

478478
| Category | Count | Patterns |
479479
| --- | ---: | --- |
480-
| Application Architecture | 21 | 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, Materialized View, Repository, Service Layer, Specification, Table Data Gateway, Transaction Script, Unit of Work, Value Object |
480+
| Application Architecture | 22 | 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, Materialized View, Repository, Service Layer, Specification, Table Data Gateway, Timeout Manager, Transaction Script, Unit of Work, Value Object |
481481
| Behavioral | 11 | Chain of Responsibility, Command, Interpreter, Iterator, Mediator, Memento, Observer, State, Strategy, Template Method, Visitor |
482482
| 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 |
483483
| Creational | 5 | Abstract Factory, Builder, Factory Method, Prototype, Singleton |
@@ -497,6 +497,8 @@ BenchmarkDotNet guidance is documented in [docs/guides/benchmarks.md](docs/guide
497497
| Adapter | Execution | 59.084 ns | 416 B | 20.479 ns | 80 B | Generated adapter execution was faster and allocated less for shipment adaptation. |
498498
| Activity Tracker | Construction | 13.09 ns | 152 B | 12.98 ns | 152 B | Same allocation; generated was slightly faster in this microbenchmark. |
499499
| Activity Tracker | Execution | 446.88 ns | 1,656 B | 452.36 ns | 1,656 B | Same allocation; fluent was slightly faster for dashboard loading gates. |
500+
| Timeout Manager | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
501+
| Timeout Manager | Execution | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
500502
| Aggregate Root | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
501503
| Aggregate Root | Execution | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
502504
| Aggregator | Construction | 14.562 ns | 168 B | 15.235 ns | 168 B | Same allocation; fluent was slightly faster in this microbenchmark. |
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using BenchmarkDotNet.Attributes;
2+
using PatternKit.Application.Timeouts;
3+
using PatternKit.Examples.TimeoutManagerDemo;
4+
5+
namespace PatternKit.Benchmarks.Application;
6+
7+
[BenchmarkCategory("ApplicationArchitecture", "TimeoutManager")]
8+
public class TimeoutManagerBenchmarks
9+
{
10+
private static readonly OrderReservationRequest Request = new(
11+
Guid.Parse("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"),
12+
"REQ-100",
13+
TimeSpan.FromMinutes(15));
14+
15+
private static readonly DateTimeOffset ExpiresAt = DateTimeOffset.UtcNow.AddMinutes(20);
16+
17+
[Benchmark(Baseline = true, Description = "Fluent: create timeout manager")]
18+
[BenchmarkCategory("Fluent", "Construction")]
19+
public TimeoutManager<Guid> Fluent_CreateTimeoutManager()
20+
=> OrderReservationTimeoutManagers.CreateFluent();
21+
22+
[Benchmark(Description = "Generated: create timeout manager")]
23+
[BenchmarkCategory("Generated", "Construction")]
24+
public TimeoutManager<Guid> Generated_CreateTimeoutManager()
25+
=> GeneratedOrderReservationTimeoutManager.CreateGenerated();
26+
27+
[Benchmark(Description = "Fluent: expire order reservation timeout")]
28+
[BenchmarkCategory("Fluent", "Execution")]
29+
public OrderReservationTimeoutSummary Fluent_ExpireOrderReservation()
30+
=> OrderReservationTimeoutDemoRunner.RunFluent(Request, ExpiresAt);
31+
32+
[Benchmark(Description = "Generated: expire order reservation timeout")]
33+
[BenchmarkCategory("Generated", "Execution")]
34+
public OrderReservationTimeoutSummary Generated_ExpireOrderReservation()
35+
=> OrderReservationTimeoutDemoRunner.RunGeneratedStatic(Request, ExpiresAt);
36+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Order Reservation Timeout Manager
2+
3+
This example models an order reservation hold that expires if the customer does not complete checkout before the deadline.
4+
5+
The fluent path builds the manager directly:
6+
7+
```csharp
8+
var manager = OrderReservationTimeoutManagers.CreateFluent();
9+
```
10+
11+
The generated path uses a source-generated factory:
12+
13+
```csharp
14+
var manager = GeneratedOrderReservationTimeoutManager.CreateGenerated();
15+
```
16+
17+
The example is importable through standard dependency injection:
18+
19+
```csharp
20+
services.AddOrderReservationTimeoutDemo();
21+
```
22+
23+
`OrderReservationTimeoutDemoRunner` schedules a reservation timeout and expires due holds. Production applications can pair the expired order identifiers with a message channel, outbox, saga, or service layer operation to release inventory and notify customers.

docs/examples/toc.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
- name: Dashboard Activity Tracker
88
href: dashboard-activity-tracker.md
99

10+
- name: Order Reservation Timeout Manager
11+
href: order-reservation-timeout-manager.md
12+
1013
- name: Auth & Logging with `ActionChain<HttpRequest>`
1114
href: auth-logging-chain.md
1215

docs/generators/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ PatternKit includes a Roslyn incremental generator package (`PatternKit.Generato
6262
| [**Repository**](repository.md) | In-memory repository factories from key selectors | `[GenerateRepository]` |
6363
| [**Anti-Corruption Layer**](anti-corruption-layer.md) | External-to-domain translation boundaries with validation | `[GenerateAntiCorruptionLayer]` |
6464
| [**Activity Tracker**](activity-tracker.md) | Active-work tracker gates for loading and readiness workflows | `[GenerateActivityTracker]` |
65+
| [**Timeout Manager**](timeout-manager.md) | Deadline registry for expiring pending workflow work | `[GenerateTimeoutManager]` |
6566
| [**Audit Log**](audit-log.md) | Append-only audit log factories from key selectors | `[GenerateAuditLog]` |
6667
| [**Unit of Work**](unit-of-work.md) | Ordered commit and rollback units | `[GenerateUnitOfWork]` |
6768
| [**Data Mapper**](data-mapper.md) | Domain/data model mapper factories | `[GenerateDataMapper]` |

docs/generators/timeout-manager.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Timeout Manager Generator
2+
3+
The Timeout Manager generator creates a strongly typed factory for `TimeoutManager<TKey>` from a partial host type.
4+
5+
```csharp
6+
using PatternKit.Generators.Timeouts;
7+
8+
[GenerateTimeoutManager(typeof(Guid), FactoryMethodName = "CreateGenerated", ManagerName = "order-reservation-timeouts")]
9+
public static partial class GeneratedOrderReservationTimeoutManager;
10+
```
11+
12+
Generated output:
13+
14+
```csharp
15+
TimeoutManager<Guid> manager = GeneratedOrderReservationTimeoutManager.CreateGenerated();
16+
```
17+
18+
The generated path removes repeated factory boilerplate while keeping the runtime manager explicit and importable through normal `IServiceCollection` registration.
19+
20+
## Diagnostics
21+
22+
- `PKTM001`: the host type must be partial.
23+
- `PKTM002`: `FactoryMethodName` and `ManagerName` must be non-empty.

docs/generators/toc.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,9 @@
261261
- name: Table Data Gateway
262262
href: table-data-gateway.md
263263

264+
- name: Timeout Manager
265+
href: timeout-manager.md
266+
264267
- name: Strategy
265268
href: strategy.md
266269

docs/guides/benchmark-results.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ The latest measured timings below were captured on Windows 11, Intel Core i9-149
1717
| Adapter | Execution | 59.084 ns | 416 B | 20.479 ns | 80 B | Generated adapter execution was faster and allocated less for shipment adaptation. |
1818
| Activity Tracker | Construction | 13.09 ns | 152 B | 12.98 ns | 152 B | Same allocation; generated was slightly faster in this microbenchmark. |
1919
| Activity Tracker | Execution | 446.88 ns | 1,656 B | 452.36 ns | 1,656 B | Same allocation; fluent was slightly faster for dashboard loading gates. |
20+
| Timeout Manager | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
21+
| Timeout Manager | Execution | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
2022
| Aggregate Root | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
2123
| Aggregate Root | Execution | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
2224
| Aggregator | Construction | 14.562 ns | 168 B | 15.235 ns | 168 B | Same allocation; fluent was slightly faster in this microbenchmark. |
@@ -230,19 +232,19 @@ The latest measured timings below were captured on Windows 11, Intel Core i9-149
230232

231233
## Coverage Matrix Summary
232234

233-
The coverage matrix currently publishes 106 catalog patterns and 424 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.
235+
The coverage matrix currently publishes 107 catalog patterns and 428 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.
234236

235237
| Category | Patterns | Published route results |
236238
| --- | ---: | ---: |
237-
| Application Architecture | 21 | 84 |
239+
| Application Architecture | 22 | 88 |
238240
| Behavioral | 11 | 44 |
239241
| Cloud Architecture | 17 | 68 |
240242
| Creational | 5 | 20 |
241243
| Enterprise Integration | 41 | 164 |
242244
| Messaging Reliability | 3 | 12 |
243245
| Structural | 7 | 28 |
244246

245-
The generator matrix currently publishes 101 generator source route results.
247+
The generator matrix currently publishes 102 generator source route results.
246248

247249
## Hosting Integration Matrix Results
248250

@@ -263,6 +265,7 @@ The generator matrix currently publishes 101 generator source route results.
263265
| Category | Pattern | Fluent construction | Fluent execution | Generated construction | Generated execution |
264266
| --- | --- | --- | --- | --- | --- |
265267
| Application Architecture | Activity Tracker | Covered | Covered | Covered | Covered |
268+
| Application Architecture | Timeout Manager | Covered | Covered | Covered | Covered |
266269
| Application Architecture | Aggregate Root | Covered | Covered | Covered | Covered |
267270
| Application Architecture | Anti-Corruption Layer | Covered | Covered | Covered | Covered |
268271
| Application Architecture | Audit Log | Covered | Covered | Covered | Covered |
@@ -373,6 +376,7 @@ The generator matrix currently publishes 101 generator source route results.
373376
| Generator | Source | Matrix result |
374377
| --- | --- | --- |
375378
| ActivityTrackerGenerator | `src/PatternKit.Generators/ActivityTracking/ActivityTrackerGenerator.cs` | Covered |
379+
| TimeoutManagerGenerator | `src/PatternKit.Generators/Timeouts/TimeoutManagerGenerator.cs` | Covered |
376380
| AggregateCommandHandlerGenerator | `src/PatternKit.Generators/Aggregates/AggregateCommandHandlerGenerator.cs` | Covered |
377381
| AdapterGenerator | `src/PatternKit.Generators/Adapter/AdapterGenerator.cs` | Covered |
378382
| AmbassadorGenerator | `src/PatternKit.Generators/Ambassador/AmbassadorGenerator.cs` | Covered |

docs/guides/benchmarks.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ The following numbers were captured on Windows 11, Intel Core i9-14900K, .NET SD
3434
| Adapter | Execution | 59.084 ns | 416 B | 20.479 ns | 80 B | Generated adapter execution was faster and allocated less for shipment adaptation. |
3535
| Activity Tracker | Construction | 13.09 ns | 152 B | 12.98 ns | 152 B | Same allocation; generated was slightly faster in this microbenchmark. |
3636
| Activity Tracker | Execution | 446.88 ns | 1,656 B | 452.36 ns | 1,656 B | Same allocation; fluent was slightly faster for dashboard loading gates. |
37+
| Timeout Manager | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
38+
| Timeout Manager | Execution | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
3739
| Aggregate Root | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
3840
| Aggregate Root | Execution | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
3941
| Aggregator | Construction | 14.562 ns | 168 B | 15.235 ns | 168 B | Same allocation; fluent was slightly faster in this microbenchmark. |

docs/guides/pattern-coverage.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ The source of truth is `PatternKitPatternCatalog` in `src/PatternKit.Examples/Pr
125125
| Application Architecture | Materialized View | `IMaterializedView<TState,TEvent>` and `MaterializedView<TState,TEvent>` | Materialized View generator |
126126
| Application Architecture | Anti-Corruption Layer | `AntiCorruptionLayer<TExternal, TDomain>` | Anti-Corruption Layer generator |
127127
| Application Architecture | Activity Tracker | `ActivityTracker` | Activity Tracker generator |
128+
| Application Architecture | Timeout Manager | `TimeoutManager<TKey>` | Timeout Manager generator |
128129

129130
## Research Baselines
130131

0 commit comments

Comments
 (0)