Skip to content

Commit a5bfa66

Browse files
authored
feat: add workflow orchestration pattern
1 parent 23428a4 commit a5bfa66

28 files changed

Lines changed: 1537 additions & 10 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 111 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 112 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 | 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 |
480+
| Application Architecture | 24 | 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, Workflow Orchestration |
481481
| Behavioral | 11 | Chain of Responsibility, Command, Interpreter, Iterator, Mediator, Memento, Observer, State, Strategy, Template Method, Visitor |
482482
| 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 |
483483
| Creational | 5 | Abstract Factory, Builder, Factory Method, Prototype, Singleton |
@@ -499,6 +499,8 @@ BenchmarkDotNet guidance is documented in [docs/guides/benchmarks.md](docs/guide
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. |
500500
| Manual Task Gate | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
501501
| Manual Task Gate | Execution | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
502+
| Workflow Orchestration | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
503+
| Workflow Orchestration | Execution | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
502504
| Timeout Manager | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
503505
| Timeout Manager | Execution | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
504506
| Aggregate Root | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using BenchmarkDotNet.Attributes;
2+
using PatternKit.Application.WorkflowOrchestration;
3+
using PatternKit.Examples.WorkflowOrchestrationDemo;
4+
5+
namespace PatternKit.Benchmarks.Application;
6+
7+
[BenchmarkCategory("ApplicationArchitecture", "WorkflowOrchestration")]
8+
public class WorkflowOrchestrationBenchmarks
9+
{
10+
private static readonly FulfillmentRequest Request = new("ORDER-100", RequiresFraudReview: true, PaymentShouldFail: false);
11+
12+
[Benchmark(Baseline = true, Description = "Fluent: create workflow orchestration")]
13+
[BenchmarkCategory("Fluent", "Construction")]
14+
public WorkflowOrchestrator<FulfillmentWorkflowContext> Fluent_CreateWorkflowOrchestration()
15+
=> FulfillmentWorkflowOrchestrations.CreateFluent();
16+
17+
[Benchmark(Description = "Generated: create workflow orchestration")]
18+
[BenchmarkCategory("Generated", "Construction")]
19+
public WorkflowOrchestrator<FulfillmentWorkflowContext> Generated_CreateWorkflowOrchestration()
20+
=> GeneratedFulfillmentWorkflowOrchestration.CreateGenerated();
21+
22+
[Benchmark(Description = "Fluent: execute fulfillment workflow orchestration")]
23+
[BenchmarkCategory("Fluent", "Execution")]
24+
public FulfillmentSummary Fluent_ExecuteFulfillmentWorkflow()
25+
=> FulfillmentWorkflowOrchestrationDemoRunner.RunFluentAsync(Request).AsTask().GetAwaiter().GetResult();
26+
27+
[Benchmark(Description = "Generated: execute fulfillment workflow orchestration")]
28+
[BenchmarkCategory("Generated", "Execution")]
29+
public FulfillmentSummary Generated_ExecuteFulfillmentWorkflow()
30+
=> FulfillmentWorkflowOrchestrationDemoRunner.RunGeneratedStaticAsync(Request).AsTask().GetAwaiter().GetResult();
31+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Fulfillment Workflow Orchestration
2+
3+
This example models a production fulfillment workflow with inventory reservation, optional fraud review, payment capture, warehouse release, retry behavior, and compensation.
4+
5+
The fluent path builds the workflow directly:
6+
7+
```csharp
8+
var workflow = FulfillmentWorkflowOrchestrations.CreateFluent();
9+
```
10+
11+
The generated path uses annotated workflow methods:
12+
13+
```csharp
14+
var workflow = GeneratedFulfillmentWorkflowOrchestration.CreateGenerated();
15+
```
16+
17+
The example is importable through standard dependency injection:
18+
19+
```csharp
20+
services.AddFulfillmentWorkflowOrchestrationDemo();
21+
```
22+
23+
`FulfillmentWorkflowOrchestrationDemoRunner` returns a summary containing the final status, domain events, and workflow history. Production applications can attach the history to audit logs, traces, or outbox messages while keeping the orchestration itself explicit and testable.

docs/examples/index.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Welcome! This section collects small, focused demos that show **how to compose b
1818
* **Enterprise messaging workflows** for envelopes, routers, recipient lists, splitters, aggregators, routing slips, sagas, mailboxes, idempotent receivers, inboxes, and outboxes.
1919
* **Messaging backplane facade** for host-style setup, typed request/reply, and publish/subscribe over an application-owned transport boundary.
2020
* **Production-readiness catalog** for DI, generic host, and ASP.NET Core diagnostics that maps every documented example to its source, TinyBDD tests, docs page, integration surfaces, and production checks.
21+
* **Workflow orchestration** for explicit ordered fulfillment steps with retries, conditional gates, compensation, and execution history.
2122

2223
## Demos in this section
2324

@@ -39,6 +40,9 @@ Welcome! This section collects small, focused demos that show **how to compose b
3940
* **Enterprise Feature Slices with .NET DI**
4041
A checkout feature slice registered with `Microsoft.Extensions.DependencyInjection`, exposing a typed `IEnterpriseCheckout` facade while the container owns Flyweight, Factory, Prototype, Chain, Strategy, Decorator, Abstract Factory, Proxy, TypeDispatcher, State Machine, Memento, Observer, and Flow artifacts. See [Enterprise Feature Slices with .NET DI](enterprise-feature-slices.md).
4142

43+
* **Fulfillment Workflow Orchestration**
44+
A Generic Host importable fulfillment workflow with fluent and source-generated routes for inventory reservation, fraud review, payment capture, retries, warehouse release, and compensation. See [Fulfillment Workflow Orchestration](fulfillment-workflow-orchestration.md).
45+
4246
* **Minimal Web Request Router**
4347
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.
4448

docs/examples/toc.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
- name: Order Reservation Timeout Manager
1414
href: order-reservation-timeout-manager.md
1515

16+
- name: Fulfillment Workflow Orchestration
17+
href: fulfillment-workflow-orchestration.md
18+
1619
- name: Auth & Logging with `ActionChain<HttpRequest>`
1720
href: auth-logging-chain.md
1821

docs/generators/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ PatternKit includes a Roslyn incremental generator package (`PatternKit.Generato
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]` |
6565
| [**Manual Task Gate**](manual-task-gate.md) | Human approval gates for workflow pauses and manual decisions | `[GenerateManualTaskGate]` |
66+
| [**Workflow Orchestration**](workflow-orchestration.md) | Ordered workflow factories from annotated step methods | `[WorkflowOrchestration]` |
6667
| [**Timeout Manager**](timeout-manager.md) | Deadline registry for expiring pending workflow work | `[GenerateTimeoutManager]` |
6768
| [**Audit Log**](audit-log.md) | Append-only audit log factories from key selectors | `[GenerateAuditLog]` |
6869
| [**Unit of Work**](unit-of-work.md) | Ordered commit and rollback units | `[GenerateUnitOfWork]` |

docs/generators/toc.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@
106106
- name: Manual Task Gate
107107
href: manual-task-gate.md
108108

109+
- name: Workflow Orchestration
110+
href: workflow-orchestration.md
111+
109112
- name: Iterator
110113
href: iterator.md
111114

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Workflow Orchestration Generator
2+
3+
The Workflow Orchestration generator creates a strongly typed factory from a partial host type and annotated workflow methods.
4+
5+
```csharp
6+
using PatternKit.Generators.WorkflowOrchestration;
7+
8+
[WorkflowOrchestration(FactoryMethodName = "CreateGenerated", WorkflowName = "fulfillment-orchestration")]
9+
public static partial class GeneratedFulfillmentWorkflow
10+
{
11+
[WorkflowStep("reserve-inventory", 1, Compensation = nameof(ReleaseInventory))]
12+
private static ValueTask ReserveInventory(FulfillmentContext context, CancellationToken cancellationToken)
13+
=> ValueTask.CompletedTask;
14+
15+
[WorkflowStep("capture-payment", 2, MaxAttempts = 2)]
16+
private static ValueTask CapturePayment(FulfillmentContext context, CancellationToken cancellationToken)
17+
=> ValueTask.CompletedTask;
18+
19+
private static ValueTask ReleaseInventory(FulfillmentContext context, CancellationToken cancellationToken)
20+
=> ValueTask.CompletedTask;
21+
}
22+
```
23+
24+
Generated output:
25+
26+
```csharp
27+
WorkflowOrchestrator<FulfillmentContext> workflow = GeneratedFulfillmentWorkflow.CreateGenerated();
28+
```
29+
30+
Step methods must accept `(TContext, CancellationToken)` and return `ValueTask`. Optional condition methods accept `TContext` and return `bool`. Optional compensation methods use the same signature as a step.
31+
32+
## Diagnostics
33+
34+
- `PKWO001`: the workflow host type must be partial.
35+
- `PKWO002`: the workflow must declare at least one `[WorkflowStep]` method.
36+
- `PKWO003`: step, condition, or compensation method signatures are invalid.
37+
- `PKWO004`: workflow step names or orders are duplicated.
38+
- `PKWO005`: `FactoryMethodName` and `WorkflowName` must be non-empty.

docs/guides/benchmark-results.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ The latest measured timings below were captured on Windows 11, Intel Core i9-149
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. |
2020
| Manual Task Gate | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
2121
| Manual Task Gate | Execution | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
22+
| Workflow Orchestration | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
23+
| Workflow Orchestration | Execution | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
2224
| Timeout Manager | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
2325
| Timeout Manager | Execution | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
2426
| Aggregate Root | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
@@ -242,19 +244,19 @@ The latest measured timings below were captured on Windows 11, Intel Core i9-149
242244

243245
## Coverage Matrix Summary
244246

245-
The coverage matrix currently publishes 111 catalog patterns and 444 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.
247+
The coverage matrix currently publishes 112 catalog patterns and 448 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.
246248

247249
| Category | Patterns | Published route results |
248250
| --- | ---: | ---: |
249-
| Application Architecture | 23 | 92 |
251+
| Application Architecture | 24 | 96 |
250252
| Behavioral | 11 | 44 |
251253
| Cloud Architecture | 20 | 80 |
252254
| Creational | 5 | 20 |
253255
| Enterprise Integration | 41 | 164 |
254256
| Messaging Reliability | 3 | 12 |
255257
| Structural | 7 | 28 |
256258

257-
The generator matrix currently publishes 105 generator source route results.
259+
The generator matrix currently publishes 106 generator source route results.
258260

259261
## Hosting Integration Matrix Results
260262

@@ -276,6 +278,7 @@ The generator matrix currently publishes 105 generator source route results.
276278
| --- | --- | --- | --- | --- | --- |
277279
| Application Architecture | Activity Tracker | Covered | Covered | Covered | Covered |
278280
| Application Architecture | Manual Task Gate | Covered | Covered | Covered | Covered |
281+
| Application Architecture | Workflow Orchestration | Covered | Covered | Covered | Covered |
279282
| Application Architecture | Timeout Manager | Covered | Covered | Covered | Covered |
280283
| Application Architecture | Aggregate Root | Covered | Covered | Covered | Covered |
281284
| Application Architecture | Anti-Corruption Layer | Covered | Covered | Covered | Covered |
@@ -392,6 +395,7 @@ The generator matrix currently publishes 105 generator source route results.
392395
| ActivityTrackerGenerator | `src/PatternKit.Generators/ActivityTracking/ActivityTrackerGenerator.cs` | Covered |
393396
| TimeoutManagerGenerator | `src/PatternKit.Generators/Timeouts/TimeoutManagerGenerator.cs` | Covered |
394397
| ManualTaskGateGenerator | `src/PatternKit.Generators/ManualTaskGates/ManualTaskGateGenerator.cs` | Covered |
398+
| WorkflowOrchestrationGenerator | `src/PatternKit.Generators/WorkflowOrchestration/WorkflowOrchestrationGenerator.cs` | Covered |
395399
| AggregateCommandHandlerGenerator | `src/PatternKit.Generators/Aggregates/AggregateCommandHandlerGenerator.cs` | Covered |
396400
| AdapterGenerator | `src/PatternKit.Generators/Adapter/AdapterGenerator.cs` | Covered |
397401
| 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
@@ -36,6 +36,8 @@ The following numbers were captured on Windows 11, Intel Core i9-14900K, .NET SD
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. |
3737
| Manual Task Gate | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
3838
| Manual Task Gate | Execution | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
39+
| Workflow Orchestration | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
40+
| Workflow Orchestration | Execution | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
3941
| Timeout Manager | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
4042
| Timeout Manager | Execution | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |
4143
| Aggregate Root | Construction | Pending | Pending | Pending | Pending | Covered by the BenchmarkDotNet matrix; publish measured values after the next benchmark refresh. |

0 commit comments

Comments
 (0)