@eventmodelers/cli 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +175 -0
- package/cli.js +676 -0
- package/package.json +35 -0
- package/shared/build-kit/code-export.mjs +560 -0
- package/shared/build-kit/lib/ollama-agent.js +147 -0
- package/shared/build-kit/package.json +11 -0
- package/shared/build-kit/ralph-ollama.js +39 -0
- package/shared/build-kit/realtime-agent.js +18 -0
- package/stacks/axon/templates/.claude/skills/build-automation/SKILL.md +407 -0
- package/stacks/axon/templates/.claude/skills/build-automation/references/feature-flag-patterns.md +114 -0
- package/stacks/axon/templates/.claude/skills/build-automation-workflow/SKILL.md +496 -0
- package/stacks/axon/templates/.claude/skills/build-automation-workflow/references/axon-workflow-api.md +279 -0
- package/stacks/axon/templates/.claude/skills/build-automation-workflow/references/feature-flag-patterns.md +114 -0
- package/stacks/axon/templates/.claude/skills/build-state-change/SKILL.md +396 -0
- package/stacks/axon/templates/.claude/skills/build-state-change/references/axon-test-fixture-patterns.md +162 -0
- package/stacks/axon/templates/.claude/skills/build-state-change/references/feature-flag-patterns.md +56 -0
- package/stacks/axon/templates/.claude/skills/build-state-change/references/rest-api-patterns.md +115 -0
- package/stacks/axon/templates/.claude/skills/build-state-view/SKILL.md +282 -0
- package/stacks/axon/templates/.claude/skills/connect/SKILL.md +178 -0
- package/stacks/axon/templates/.claude/skills/learn-eventmodelers-api/SKILL.md +611 -0
- package/stacks/axon/templates/.claude/skills/load-slice/SKILL.md +141 -0
- package/stacks/axon/templates/.claude/skills/update-slice-status/SKILL.md +105 -0
- package/stacks/axon/templates/build-kit/lib/AGENT.md +47 -0
- package/stacks/axon/templates/build-kit/lib/agent.sh +20 -0
- package/stacks/axon/templates/build-kit/lib/backend-prompt.md +158 -0
- package/stacks/axon/templates/build-kit/lib/prompt.md +126 -0
- package/stacks/axon/templates/build-kit/lib/ralph.js +369 -0
- package/stacks/axon/templates/build-kit/ralph-claude.js +44 -0
- package/stacks/axon/templates/build-kit/ralph.sh +98 -0
- package/stacks/axon/templates/root/.env.example +5 -0
- package/stacks/axon/templates/root/CLAUDE.md +60 -0
- package/stacks/axon/templates/root/README.md +44 -0
- package/stacks/axon/templates/root/docker-compose.yml +64 -0
- package/stacks/axon/templates/root/mvnw +259 -0
- package/stacks/axon/templates/root/mvnw.cmd +149 -0
- package/stacks/axon/templates/root/pom.xml +125 -0
- package/stacks/axon/templates/root/src/main/java/io/axoniq/quickstart/QuickstartApplication.java +128 -0
- package/stacks/axon/templates/root/src/main/java/io/axoniq/quickstart/config/WebConfig.java +155 -0
- package/stacks/axon/templates/root/src/main/resources/application.properties +2 -0
- package/stacks/axon/templates/root/src/main/resources/static/bg-body.png +0 -0
- package/stacks/axon/templates/root/src/main/resources/static/bg-header.png +0 -0
- package/stacks/axon/templates/root/src/main/resources/static/index.html +596 -0
- package/stacks/cratis-csharp/templates/.claude/skills/_shared/cratis-conventions.md +251 -0
- package/stacks/cratis-csharp/templates/.claude/skills/build-automation/SKILL.md +99 -0
- package/stacks/cratis-csharp/templates/.claude/skills/build-automation/references/patterns.md +115 -0
- package/stacks/cratis-csharp/templates/.claude/skills/build-state-change/SKILL.md +163 -0
- package/stacks/cratis-csharp/templates/.claude/skills/build-state-change/references/patterns.md +234 -0
- package/stacks/cratis-csharp/templates/.claude/skills/build-state-view/SKILL.md +120 -0
- package/stacks/cratis-csharp/templates/.claude/skills/build-state-view/references/patterns.md +166 -0
- package/stacks/cratis-csharp/templates/.claude/skills/connect/SKILL.md +169 -0
- package/stacks/cratis-csharp/templates/.claude/skills/learn-eventmodelers-api/SKILL.md +609 -0
- package/stacks/cratis-csharp/templates/.claude/skills/load-slice/SKILL.md +141 -0
- package/stacks/cratis-csharp/templates/.claude/skills/update-slice-status/SKILL.md +105 -0
- package/stacks/cratis-csharp/templates/build-kit/lib/AGENT.md +58 -0
- package/stacks/cratis-csharp/templates/build-kit/lib/agent.sh +20 -0
- package/stacks/cratis-csharp/templates/build-kit/lib/backend-prompt.md +129 -0
- package/stacks/cratis-csharp/templates/build-kit/lib/prompt.md +124 -0
- package/stacks/cratis-csharp/templates/build-kit/lib/ralph.js +302 -0
- package/stacks/cratis-csharp/templates/build-kit/ralph-claude.js +37 -0
- package/stacks/cratis-csharp/templates/build-kit/ralph.sh +98 -0
- package/stacks/cratis-csharp/templates/root/.frontend/index.css +29 -0
- package/stacks/cratis-csharp/templates/root/.frontend/index.html +17 -0
- package/stacks/cratis-csharp/templates/root/.frontend/main.tsx +18 -0
- package/stacks/cratis-csharp/templates/root/.frontend/tsconfig.json +42 -0
- package/stacks/cratis-csharp/templates/root/.frontend/tsconfig.node.json +11 -0
- package/stacks/cratis-csharp/templates/root/.frontend/vite.config.ts +56 -0
- package/stacks/cratis-csharp/templates/root/App.tsx +23 -0
- package/stacks/cratis-csharp/templates/root/CLAUDE.md +62 -0
- package/stacks/cratis-csharp/templates/root/CratisApp.csproj +25 -0
- package/stacks/cratis-csharp/templates/root/CratisApp.sln +18 -0
- package/stacks/cratis-csharp/templates/root/GlobalUsings.cs +3 -0
- package/stacks/cratis-csharp/templates/root/Home.tsx +102 -0
- package/stacks/cratis-csharp/templates/root/Program.cs +26 -0
- package/stacks/cratis-csharp/templates/root/README.md +192 -0
- package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Listing/AllListings.ts +47 -0
- package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Listing/Listing.cs +11 -0
- package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Listing/Listing.ts +12 -0
- package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Listing/ListingDataTable.tsx +17 -0
- package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Listing/index.ts +1 -0
- package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Registration/Register.ts +51 -0
- package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Registration/RegisterDialog.tsx +18 -0
- package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Registration/Registration.cs +27 -0
- package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Registration/index.ts +1 -0
- package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/SomeFeature.tsx +22 -0
- package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/SomeName.cs +3 -0
- package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/index.ts +1 -0
- package/stacks/cratis-csharp/templates/root/appsettings.Development.json +9 -0
- package/stacks/cratis-csharp/templates/root/appsettings.json +26 -0
- package/stacks/cratis-csharp/templates/root/docker-compose.yml +23 -0
- package/stacks/cratis-csharp/templates/root/package.json +33 -0
- package/stacks/cratis-csharp/templates/root/tsconfig.json +3 -0
- package/stacks/modeling-kit/templates/.claude/settings.local.json +13 -0
- package/stacks/modeling-kit/templates/.claude/skills/analyze-existing-model/SKILL.md +215 -0
- package/stacks/modeling-kit/templates/.claude/skills/attributes/SKILL.md +176 -0
- package/stacks/modeling-kit/templates/.claude/skills/connect/SKILL.md +182 -0
- package/stacks/modeling-kit/templates/.claude/skills/discover-storyboard/SKILL.md +383 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-applying-conways-law/SKILL.md +465 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-brainstorming-events/SKILL.md +587 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-brainstorming-events/references/facilitating-event-modeling-workshops.md +626 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-checking-completeness/SKILL.md +542 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-designing-event-models/SKILL.md +497 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-elaborating-scenarios/SKILL.md +783 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-inputs/SKILL.md +604 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-outputs/SKILL.md +699 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-integrating-legacy-systems/SKILL.md +674 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/SKILL.md +231 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/references/domain-patterns.md +150 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/references/patterns.md +329 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/references/snapshotting.md +204 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-orchestrating-event-modeling/SKILL.md +352 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-orchestrating-event-modeling/references/project-planning-with-event-modeling.md +341 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-plotting-events/SKILL.md +153 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/SKILL.md +136 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/references/examples.md +78 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/references/patterns.md +85 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-storyboarding-events/SKILL.md +655 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-translating-external-events/SKILL.md +479 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models/SKILL.md +234 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models-checklist/SKILL.md +353 -0
- package/stacks/modeling-kit/templates/.claude/skills/examples/SKILL.md +200 -0
- package/stacks/modeling-kit/templates/.claude/skills/handle-comment/SKILL.md +94 -0
- package/stacks/modeling-kit/templates/.claude/skills/learn-eventmodelers-api/SKILL.md +441 -0
- package/stacks/modeling-kit/templates/.claude/skills/place-element/SKILL.md +290 -0
- package/stacks/modeling-kit/templates/.claude/skills/storyboard/SKILL.md +212 -0
- package/stacks/modeling-kit/templates/.claude/skills/storyboard-screen/SKILL.md +123 -0
- package/stacks/modeling-kit/templates/.claude/skills/timeline/SKILL.md +353 -0
- package/stacks/modeling-kit/templates/.claude/skills/update-slice-status/SKILL.md +110 -0
- package/stacks/modeling-kit/templates/.claude/skills/wdyt/SKILL.md +134 -0
- package/stacks/modeling-kit/templates/kit/lib/agent.sh +20 -0
- package/stacks/modeling-kit/templates/kit/lib/ollama-agent.js +147 -0
- package/stacks/modeling-kit/templates/kit/lib/ralph.js +286 -0
- package/stacks/modeling-kit/templates/kit/package.json +12 -0
- package/stacks/modeling-kit/templates/kit/ralph-claude.js +50 -0
- package/stacks/modeling-kit/templates/kit/ralph-ollama.js +38 -0
- package/stacks/modeling-kit/templates/kit/ralph.sh +61 -0
- package/stacks/modeling-kit/templates/kit/realtime-agent.js +18 -0
- package/stacks/modeling-kit/templates/root/CLAUDE.md +56 -0
- package/stacks/node/templates/.claude/skills/build-automation/SKILL.md +266 -0
- package/stacks/node/templates/.claude/skills/build-state-change/SKILL.md +344 -0
- package/stacks/node/templates/.claude/skills/build-state-view/SKILL.md +412 -0
- package/stacks/node/templates/.claude/skills/connect/SKILL.md +178 -0
- package/stacks/node/templates/.claude/skills/learn-eventmodelers-api/SKILL.md +628 -0
- package/stacks/node/templates/.claude/skills/load-slice/SKILL.md +143 -0
- package/stacks/node/templates/.claude/skills/update-slice-status/SKILL.md +110 -0
- package/stacks/node/templates/build-kit/README.md +86 -0
- package/stacks/node/templates/build-kit/lib/AGENT.md +47 -0
- package/stacks/node/templates/build-kit/lib/agent.sh +20 -0
- package/stacks/node/templates/build-kit/lib/backend-prompt.md +152 -0
- package/stacks/node/templates/build-kit/lib/prompt.md +122 -0
- package/stacks/node/templates/build-kit/lib/ralph.js +369 -0
- package/stacks/node/templates/build-kit/ralph-claude.js +44 -0
- package/stacks/node/templates/build-kit/ralph.sh +98 -0
- package/stacks/node/templates/root/.env.example +15 -0
- package/stacks/node/templates/root/CLAUDE.md +60 -0
- package/stacks/node/templates/root/docker-compose.yml +15 -0
- package/stacks/node/templates/root/flyway.conf +17 -0
- package/stacks/node/templates/root/migrations/V1__schema.sql.example +12 -0
- package/stacks/node/templates/root/package.json +50 -0
- package/stacks/node/templates/root/server.ts +130 -0
- package/stacks/node/templates/root/setup-env.sh +53 -0
- package/stacks/node/templates/root/src/common/assertions.ts +6 -0
- package/stacks/node/templates/root/src/common/db.ts +32 -0
- package/stacks/node/templates/root/src/common/loadPostgresEventstore.ts +23 -0
- package/stacks/node/templates/root/src/common/parseEndpoint.ts +51 -0
- package/stacks/node/templates/root/src/common/processorDlq.ts +28 -0
- package/stacks/node/templates/root/src/common/realtimeBroadcast.ts +12 -0
- package/stacks/node/templates/root/src/common/replay.ts +16 -0
- package/stacks/node/templates/root/src/common/routes.ts +19 -0
- package/stacks/node/templates/root/src/common/testHelpers.ts +44 -0
- package/stacks/node/templates/root/src/swagger.ts +34 -0
- package/stacks/node/templates/root/src/util/assertions.ts +6 -0
- package/stacks/node/templates/root/src/util/hash.ts +9 -0
- package/stacks/node/templates/root/src/util/sanitize.ts +23 -0
- package/stacks/node/templates/root/tsconfig.json +32 -0
- package/stacks/node/templates/root/vercel.json +8 -0
- package/stacks/supabase/templates/.claude/skills/build-automation/SKILL.md +266 -0
- package/stacks/supabase/templates/.claude/skills/build-state-change/SKILL.md +344 -0
- package/stacks/supabase/templates/.claude/skills/build-state-view/SKILL.md +390 -0
- package/stacks/supabase/templates/.claude/skills/build-webhook/SKILL.md +303 -0
- package/stacks/supabase/templates/.claude/skills/connect/SKILL.md +178 -0
- package/stacks/supabase/templates/.claude/skills/learn-eventmodelers-api/SKILL.md +628 -0
- package/stacks/supabase/templates/.claude/skills/load-slice/SKILL.md +143 -0
- package/stacks/supabase/templates/.claude/skills/update-slice-status/SKILL.md +110 -0
- package/stacks/supabase/templates/build-kit/README.md +86 -0
- package/stacks/supabase/templates/build-kit/lib/AGENT.md +47 -0
- package/stacks/supabase/templates/build-kit/lib/agent.sh +20 -0
- package/stacks/supabase/templates/build-kit/lib/backend-prompt.md +152 -0
- package/stacks/supabase/templates/build-kit/lib/prompt.md +123 -0
- package/stacks/supabase/templates/build-kit/lib/ralph.js +369 -0
- package/stacks/supabase/templates/build-kit/ralph-claude.js +44 -0
- package/stacks/supabase/templates/build-kit/ralph.sh +98 -0
- package/stacks/supabase/templates/root/.env.example +22 -0
- package/stacks/supabase/templates/root/CLAUDE.md +61 -0
- package/stacks/supabase/templates/root/flyway.conf +17 -0
- package/stacks/supabase/templates/root/package.json +52 -0
- package/stacks/supabase/templates/root/server.ts +177 -0
- package/stacks/supabase/templates/root/setup-env.sh +53 -0
- package/stacks/supabase/templates/root/src/common/assertions.ts +6 -0
- package/stacks/supabase/templates/root/src/common/db.ts +32 -0
- package/stacks/supabase/templates/root/src/common/loadPostgresEventstore.ts +23 -0
- package/stacks/supabase/templates/root/src/common/parseEndpoint.ts +51 -0
- package/stacks/supabase/templates/root/src/common/processorDlq.ts +28 -0
- package/stacks/supabase/templates/root/src/common/realtimeBroadcast.ts +19 -0
- package/stacks/supabase/templates/root/src/common/replay.ts +16 -0
- package/stacks/supabase/templates/root/src/common/routes.ts +23 -0
- package/stacks/supabase/templates/root/src/common/testHelpers.ts +54 -0
- package/stacks/supabase/templates/root/src/supabase/README.md +141 -0
- package/stacks/supabase/templates/root/src/supabase/api.ts +56 -0
- package/stacks/supabase/templates/root/src/supabase/requireOrgaAdmin.ts +32 -0
- package/stacks/supabase/templates/root/src/supabase/requireSysUser.ts +40 -0
- package/stacks/supabase/templates/root/src/supabase/requireUser.ts +72 -0
- package/stacks/supabase/templates/root/src/swagger.ts +34 -0
- package/stacks/supabase/templates/root/src/util/assertions.ts +6 -0
- package/stacks/supabase/templates/root/src/util/hash.ts +9 -0
- package/stacks/supabase/templates/root/src/util/sanitize.ts +23 -0
- package/stacks/supabase/templates/root/supabase/config.toml +295 -0
- package/stacks/supabase/templates/root/supabase/migrations/V1__schema.sql.example +12 -0
- package/stacks/supabase/templates/root/supabase/seed.sql +1 -0
- package/stacks/supabase/templates/root/tsconfig.json +32 -0
- package/stacks/supabase/templates/root/vercel.json +8 -0
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
# Axon Framework 5 — Workflow API Reference
|
|
2
|
+
|
|
3
|
+
> Preview feature — APIs may change. Source: https://docs.axoniq.io/axon-framework-reference/development/workflows/
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## `@Workflow` annotation
|
|
8
|
+
|
|
9
|
+
```java
|
|
10
|
+
@Workflow(
|
|
11
|
+
idProperty = "orderId", // field on trigger event used as workflow instance ID
|
|
12
|
+
startOnEventClass = OrderPlacedEvent.class, // event that starts a new instance
|
|
13
|
+
workflowNamespace = "io.myapp.orders" // namespace for internal event names
|
|
14
|
+
)
|
|
15
|
+
public void execute(SimpleWorkflowContext ctx) { ... }
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Alternative: start by event name string (useful for sub-workflows started via `EventSink`):
|
|
19
|
+
|
|
20
|
+
```java
|
|
21
|
+
@Workflow(
|
|
22
|
+
idProperty = "childWorkflowId",
|
|
23
|
+
startOnEventName = "io.myapp.StartPaymentProcess",
|
|
24
|
+
workflowNamespace = "io.myapp.payments"
|
|
25
|
+
)
|
|
26
|
+
public void execute(SimpleWorkflowContext ctx) { ... }
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## `SimpleWorkflowContext` — core API
|
|
32
|
+
|
|
33
|
+
### Data access
|
|
34
|
+
|
|
35
|
+
```java
|
|
36
|
+
ctx.workflowId() // String — the workflow instance ID
|
|
37
|
+
ctx.workflowPayload() // Map<String,Object> — durable payload (snapshot of trigger event + updates)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Execution steps
|
|
41
|
+
|
|
42
|
+
```java
|
|
43
|
+
// Blocking: dispatches action and waits for completion. Throws StepFailedException on failure.
|
|
44
|
+
ctx.awaitExecute(
|
|
45
|
+
stepName, // String — unique name within this workflow instance
|
|
46
|
+
payload, // Map<String,Object> — data passed to the handler
|
|
47
|
+
handler // BiFunction<ProcessingContext, Map<String,Object>, Map<String,Object>>
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
// Non-blocking: dispatches action, returns handle immediately
|
|
51
|
+
WorkflowStepResult result = ctx.execute(
|
|
52
|
+
stepName,
|
|
53
|
+
payload,
|
|
54
|
+
handler,
|
|
55
|
+
Duration.ofSeconds(30), // step timeout
|
|
56
|
+
defaults() // WorkflowStepOptions
|
|
57
|
+
);
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Event suspension
|
|
61
|
+
|
|
62
|
+
```java
|
|
63
|
+
// Wait until event arrives or timeout fires. Returns WorkflowStepResult.
|
|
64
|
+
WorkflowStepResult r = ctx.waitForEvent(
|
|
65
|
+
stepName,
|
|
66
|
+
SomeEvent.class,
|
|
67
|
+
Duration.ofDays(3)
|
|
68
|
+
);
|
|
69
|
+
r.timeout() // true if timeout fired before event arrived
|
|
70
|
+
r.await() // blocks until completed (call after !timeout() check)
|
|
71
|
+
r.result() // Optional<T> — the event payload
|
|
72
|
+
|
|
73
|
+
// With association predicate (match specific event by payload field)
|
|
74
|
+
ctx.awaitEvent(
|
|
75
|
+
stepName,
|
|
76
|
+
SomeEvent.class,
|
|
77
|
+
associate(payloadProperty("orderId"), equalsTo(ctx.workflowId())),
|
|
78
|
+
Duration.ofMinutes(30)
|
|
79
|
+
);
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Timer
|
|
83
|
+
|
|
84
|
+
```java
|
|
85
|
+
// Durable sleep — survives restarts, recalculates remaining delay on resume
|
|
86
|
+
ctx.sleep(stepName, Duration.ofHours(24));
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Orchestration combinators
|
|
90
|
+
|
|
91
|
+
```java
|
|
92
|
+
// Fan-in: wait until ALL matching. Returns a guard with matched/unmatched.
|
|
93
|
+
var guard = ctx.allMatch(WorkflowStepResult::isCompleted, step1, step2, step3);
|
|
94
|
+
guard.success() // true if all matched
|
|
95
|
+
guard.matched() // list of steps that matched
|
|
96
|
+
guard.unmatched() // list of steps that did not match
|
|
97
|
+
|
|
98
|
+
// Scatter-gather: wait until ANY matching. Returns the first matching result.
|
|
99
|
+
var fastest = ctx.anyMatch(WorkflowStepResult::isCompleted, step1, step2, step3);
|
|
100
|
+
fastest.await()
|
|
101
|
+
fastest.matched().getFirst() // the winning step
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### State mutation
|
|
105
|
+
|
|
106
|
+
```java
|
|
107
|
+
// Persist new data to the durable payload (survives restarts)
|
|
108
|
+
ctx.setPayload(stepName, payload("count", newCount).getValues());
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Termination
|
|
112
|
+
|
|
113
|
+
```java
|
|
114
|
+
ctx.fail(new RuntimeException("reason")) // FAILED terminal state
|
|
115
|
+
ctx.cancel() // CANCELLED terminal state
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Workflow states
|
|
121
|
+
|
|
122
|
+
| State | Trigger |
|
|
123
|
+
|---|---|
|
|
124
|
+
| `STARTED` | Workflow instance created |
|
|
125
|
+
| `COMPLETED` | `execute()` method returned normally |
|
|
126
|
+
| `FAILED` | `ctx.fail()` called, or unhandled exception |
|
|
127
|
+
| `CANCELLED` | `ctx.cancel()` called, or external cancellation |
|
|
128
|
+
| `TIMED_OUT` | Overall workflow timeout exceeded |
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Lifecycle listeners
|
|
133
|
+
|
|
134
|
+
```java
|
|
135
|
+
@OnSuccess public void onSuccess(SimpleWorkflowContext ctx) { ... }
|
|
136
|
+
@OnFailure public void onFailure(SimpleWorkflowContext ctx) { ... }
|
|
137
|
+
@OnCancellation public void onCancelled(SimpleWorkflowContext ctx) { ... }
|
|
138
|
+
@OnTimeout public void onTimeout(SimpleWorkflowContext ctx) { ... }
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Or programmatically via `.registerWorkflowStatusChangeListener(WorkflowStatus.COMPLETED, (status, ctx) -> {...})`.
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## `WorkflowModule` configuration
|
|
146
|
+
|
|
147
|
+
```java
|
|
148
|
+
WorkflowModule
|
|
149
|
+
.usingContext(SimpleWorkflowContext.class)
|
|
150
|
+
.workflowContextFactory(c -> new SimpleWorkflowContextFactory())
|
|
151
|
+
.workflowExecutionFactory(c -> new DSLAdoptingExecutionFactory<>(SimpleWorkflowContext.class))
|
|
152
|
+
.definitions(d -> d
|
|
153
|
+
// Annotation-based (reads @Workflow from the instance)
|
|
154
|
+
.autodetected(c -> new MyWorkflow(), SimpleWorkflowContext.class)
|
|
155
|
+
|
|
156
|
+
// Declarative (explicit name + trigger)
|
|
157
|
+
.declarative(c -> workflow::execute)
|
|
158
|
+
.workflowName("OrderFulfillment")
|
|
159
|
+
.on(EventConditions.fromType(OrderPlacedEvent.class))
|
|
160
|
+
.customized((c, w) -> w
|
|
161
|
+
.eventNameCustomizer(namespace("io.myapp.orders"))
|
|
162
|
+
.workflowIdProvider(fromPayloadAttribute(c, "orderId"))
|
|
163
|
+
.registerWorkflowStatusChangeListener(WorkflowStatus.COMPLETED,
|
|
164
|
+
(status, ctx) -> logger.info("Done: {}", ctx.workflowId()))
|
|
165
|
+
)
|
|
166
|
+
);
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Start condition with predicate
|
|
170
|
+
|
|
171
|
+
```java
|
|
172
|
+
.on(EventConditions.fromType(
|
|
173
|
+
OrderPlacedEvent.class,
|
|
174
|
+
associate(payloadProperty("type"), equalsTo("priority")) // only start for priority orders
|
|
175
|
+
))
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Workflow ID providers
|
|
179
|
+
|
|
180
|
+
```java
|
|
181
|
+
fromPayloadAttribute(c, "orderId") // extract "orderId" field as-is
|
|
182
|
+
fromPayloadAttribute(c, "orderId", id -> "o-" + id) // with transformation
|
|
183
|
+
// default: MessageWorkflowIdProvider — uses the event message's native ID
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Custom context (domain-specific DSL)
|
|
187
|
+
|
|
188
|
+
```java
|
|
189
|
+
public class ApprovalWorkflowContext extends SimpleWorkflowContext {
|
|
190
|
+
public ApprovalWorkflowContext(String workflowId, Map<String, Object> payload,
|
|
191
|
+
ProcessingContext pc, WorkflowConfiguration<?> cfg) {
|
|
192
|
+
super(workflowId, payload, pc, cfg);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
public boolean requestApproval(String approver, Duration deadline) {
|
|
196
|
+
awaitExecute("requestApproval",
|
|
197
|
+
payload("approver", approver, "requestId", workflowId()).getValues(),
|
|
198
|
+
ApprovalService::sendRequest);
|
|
199
|
+
var decision = awaitEvent("awaitDecision", ApprovalDecisionEvent.class, deadline);
|
|
200
|
+
return "approved".equals(decision.result().map(ApprovalDecisionEvent::outcome).orElse(""));
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Factory
|
|
205
|
+
public class ApprovalContextFactory implements WorkflowContextFactory<ApprovalWorkflowContext> {
|
|
206
|
+
@Override
|
|
207
|
+
public ApprovalWorkflowContext createContext(Map<String, Object> payload, String workflowId,
|
|
208
|
+
ProcessingContext pc, WorkflowConfiguration<?> cfg) {
|
|
209
|
+
return new ApprovalWorkflowContext(workflowId, payload, pc, cfg);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Metadata keys propagated by the engine
|
|
217
|
+
|
|
218
|
+
| Key | Value |
|
|
219
|
+
|---|---|
|
|
220
|
+
| `workflowId` | Workflow instance ID |
|
|
221
|
+
| `stepName` | Name of the currently executing step |
|
|
222
|
+
| `stepType` | Type of step (execute, event, sleep, etc.) |
|
|
223
|
+
| `workflowStatus` | Current workflow status |
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Sub-workflow pattern
|
|
228
|
+
|
|
229
|
+
```java
|
|
230
|
+
// Parent: publish trigger event for child via EventSink (no workflow metadata)
|
|
231
|
+
ctx.awaitExecute("startChild",
|
|
232
|
+
payload("childId", "child-" + ctx.workflowId(), "orderId", ctx.workflowId()).getValues(),
|
|
233
|
+
(pc, p) -> {
|
|
234
|
+
var trigger = new StartChildWorkflow((String) p.get("childId"), (String) p.get("orderId"));
|
|
235
|
+
eventSink.publish(null, new GenericEventMessage<>(
|
|
236
|
+
messageTypeResolver.resolveOrThrow(trigger), trigger));
|
|
237
|
+
return Map.of();
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
// Parent: wait for child completion event, matched by orderId
|
|
241
|
+
ctx.awaitEvent("awaitChild",
|
|
242
|
+
ChildWorkflowCompleted.class,
|
|
243
|
+
associate(payloadProperty("orderId"), equalsTo(ctx.workflowId())),
|
|
244
|
+
Duration.ofMinutes(30));
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Child workflow:
|
|
248
|
+
```java
|
|
249
|
+
@Workflow(idProperty = "childId",
|
|
250
|
+
startOnEventName = "io.myapp.StartChildWorkflow",
|
|
251
|
+
workflowNamespace = "io.myapp.child")
|
|
252
|
+
public void execute(SimpleWorkflowContext ctx) {
|
|
253
|
+
// ... do work ...
|
|
254
|
+
// Signal parent via EventSink
|
|
255
|
+
ctx.awaitExecute("notifyParent", ctx.workflowPayload(),
|
|
256
|
+
(pc, p) -> {
|
|
257
|
+
var done = new ChildWorkflowCompleted(
|
|
258
|
+
(String) p.get("orderId"), (String) p.get("childId"));
|
|
259
|
+
eventSink.publish(null, new GenericEventMessage<>(
|
|
260
|
+
messageTypeResolver.resolveOrThrow(done), done));
|
|
261
|
+
return Map.of();
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## `payload(...)` helper
|
|
269
|
+
|
|
270
|
+
```java
|
|
271
|
+
payload("key1", value1, "key2", value2).getValues() // returns Map<String, Object>
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
## Testing
|
|
277
|
+
|
|
278
|
+
Use `AbstractDeclarativeTestBase` from the AF5 workflow test module for integration tests.
|
|
279
|
+
For unit tests, mock `SimpleWorkflowContext` with Mockito and verify step call order.
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Feature Flag Patterns
|
|
2
|
+
|
|
3
|
+
How to conditionally enable/disable individual slice components. Examples use a generic `Ordering` bounded context.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Option 1: Spring Boot `@ConditionalOnProperty` (default)
|
|
8
|
+
|
|
9
|
+
Add `@ConditionalOnProperty` to every conditionally-loaded component in the slice. Update config files
|
|
10
|
+
and Spring metadata so the IDE auto-completes property keys.
|
|
11
|
+
|
|
12
|
+
### Annotation on slice components
|
|
13
|
+
|
|
14
|
+
```java
|
|
15
|
+
// Entity
|
|
16
|
+
@ConditionalOnProperty(prefix = "slices.ordering", name = "write.placeorder.enabled")
|
|
17
|
+
@EventSourced(tagKey = EventTags.ORDER_ID)
|
|
18
|
+
class PlaceOrderEntity { ... }
|
|
19
|
+
|
|
20
|
+
// Handler
|
|
21
|
+
@ConditionalOnProperty(prefix = "slices.ordering", name = "write.placeorder.enabled")
|
|
22
|
+
@Component
|
|
23
|
+
public class PlaceOrderHandler { ... }
|
|
24
|
+
|
|
25
|
+
// REST controller (if applicable)
|
|
26
|
+
@ConditionalOnProperty(prefix = "slices.ordering", name = "write.placeorder.enabled")
|
|
27
|
+
@RestController
|
|
28
|
+
public class PlaceOrderRestController { ... }
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
For the **Explicit Registration pattern**, put `@ConditionalOnProperty` on the `@Configuration` class only:
|
|
32
|
+
|
|
33
|
+
```java
|
|
34
|
+
@ConditionalOnProperty(prefix = "slices.ordering", name = "write.placeorder.enabled")
|
|
35
|
+
@Configuration
|
|
36
|
+
class PlaceOrderWriteSliceConfig { ... }
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### `application.properties` (main — enable by default)
|
|
40
|
+
|
|
41
|
+
```properties
|
|
42
|
+
slices.ordering.write.placeorder.enabled=true
|
|
43
|
+
slices.ordering.read.getorders.enabled=true
|
|
44
|
+
slices.ordering.automation.notifycustomeronorder.enabled=true
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### `application.properties` (test — disable by default, opt-in per test)
|
|
48
|
+
|
|
49
|
+
```properties
|
|
50
|
+
slices.ordering.write.placeorder.enabled=false
|
|
51
|
+
slices.ordering.read.getorders.enabled=false
|
|
52
|
+
slices.ordering.automation.notifycustomeronorder.enabled=false
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Opt-in in a specific test class
|
|
56
|
+
|
|
57
|
+
```java
|
|
58
|
+
@TestPropertySource(properties = {"slices.ordering.write.placeorder.enabled=true"})
|
|
59
|
+
@SpringBootTest
|
|
60
|
+
class PlaceOrderTest { ... }
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### `META-INF/additional-spring-configuration-metadata.json`
|
|
64
|
+
|
|
65
|
+
Register each property so IDEs auto-complete and validate it:
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"properties": [
|
|
70
|
+
{
|
|
71
|
+
"name": "slices.ordering.write.placeorder.enabled",
|
|
72
|
+
"type": "java.lang.Boolean",
|
|
73
|
+
"description": "Enable/disable the PlaceOrder write slice in the Ordering bounded context."
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"name": "slices.ordering.read.getorders.enabled",
|
|
77
|
+
"type": "java.lang.Boolean",
|
|
78
|
+
"description": "Enable/disable the GetOrders read slice in the Ordering bounded context."
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Option 2: Spring Profile (`@Profile`)
|
|
87
|
+
|
|
88
|
+
Enable/disable components by activating a named Spring profile. Simpler for "all or nothing" rollouts,
|
|
89
|
+
less granular than `@ConditionalOnProperty`.
|
|
90
|
+
|
|
91
|
+
```java
|
|
92
|
+
@Profile("ordering-write")
|
|
93
|
+
@Component
|
|
94
|
+
public class PlaceOrderHandler { ... }
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Activate in tests via `@ActiveProfiles("ordering-write")` or `spring.profiles.active=ordering-write`.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Option 3: No feature flags
|
|
102
|
+
|
|
103
|
+
If the project ships all slices unconditionally, omit `@ConditionalOnProperty` entirely. Applicable when:
|
|
104
|
+
- The project is small and startup time is not a concern
|
|
105
|
+
- There is no partial-rollout requirement
|
|
106
|
+
- Feature branches are the rollout mechanism
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Convention recommendation
|
|
111
|
+
|
|
112
|
+
- Use `@ConditionalOnProperty` for new projects: zero extra dependencies, IDE-friendly, test-friendly.
|
|
113
|
+
- Disable all slices by default in the test properties; opt-in per test class via `@TestPropertySource`.
|
|
114
|
+
- Always enable BOTH the slice under test AND its dependencies (e.g., the automation AND the target write slice).
|