eva4j 1.0.11 → 1.0.13
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/AGENTS.md +441 -14
- package/DOMAIN_YAML_GUIDE.md +425 -21
- package/FUTURE_FEATURES.md +315 -115
- package/QUICK_REFERENCE.md +101 -153
- package/README.md +77 -70
- package/bin/eva4j.js +57 -1
- package/config/defaults.json +3 -0
- package/docs/commands/GENERATE_ENTITIES.md +662 -1968
- package/docs/commands/GENERATE_HTTP_EXCHANGE.md +274 -450
- package/docs/commands/GENERATE_KAFKA_EVENT.md +219 -498
- package/docs/commands/GENERATE_KAFKA_LISTENER.md +18 -18
- package/docs/commands/GENERATE_RECORD.md +335 -311
- package/docs/commands/GENERATE_TEMPORAL_ACTIVITY.md +174 -0
- package/docs/commands/GENERATE_TEMPORAL_FLOW.md +237 -0
- package/docs/commands/GENERATE_USECASE.md +216 -282
- package/docs/commands/INDEX.md +36 -7
- package/examples/doctor-evaluation.yaml +3 -3
- package/examples/domain-audit-complete.yaml +2 -2
- package/examples/domain-collections.yaml +2 -2
- package/examples/domain-ecommerce.yaml +2 -2
- package/examples/domain-events.yaml +201 -0
- package/examples/domain-field-visibility.yaml +11 -5
- package/examples/domain-multi-aggregate.yaml +12 -6
- package/examples/domain-one-to-many.yaml +1 -1
- package/examples/domain-one-to-one.yaml +1 -1
- package/examples/domain-secondary-onetomany.yaml +1 -1
- package/examples/domain-secondary-onetoone.yaml +1 -1
- package/examples/domain-simple.yaml +1 -1
- package/examples/domain-soft-delete.yaml +3 -3
- package/examples/domain-transitions.yaml +1 -1
- package/examples/domain-value-objects.yaml +1 -1
- package/package.json +2 -2
- package/src/commands/add-kafka-client.js +3 -1
- package/src/commands/add-temporal-client.js +286 -0
- package/src/commands/generate-entities.js +75 -4
- package/src/commands/generate-kafka-event.js +273 -89
- package/src/commands/generate-temporal-activity.js +228 -0
- package/src/commands/generate-temporal-flow.js +216 -0
- package/src/generators/module-generator.js +1 -0
- package/src/generators/shared-generator.js +26 -0
- package/src/utils/yaml-to-entity.js +93 -4
- package/templates/aggregate/AggregateRepository.java.ejs +3 -2
- package/templates/aggregate/AggregateRepositoryImpl.java.ejs +15 -7
- package/templates/aggregate/AggregateRoot.java.ejs +38 -2
- package/templates/aggregate/DomainEntity.java.ejs +6 -2
- package/templates/aggregate/DomainEventHandler.java.ejs +62 -0
- package/templates/aggregate/DomainEventRecord.java.ejs +50 -0
- package/templates/aggregate/JpaAggregateRoot.java.ejs +3 -1
- package/templates/aggregate/JpaEntity.java.ejs +3 -1
- package/templates/base/docker/kafka-services.yaml.ejs +2 -2
- package/templates/base/docker/temporal-services.yaml.ejs +29 -0
- package/templates/base/resources/parameters/develop/temporal.yaml.ejs +9 -0
- package/templates/base/resources/parameters/local/temporal.yaml.ejs +9 -0
- package/templates/base/resources/parameters/production/temporal.yaml.ejs +9 -0
- package/templates/base/resources/parameters/test/temporal.yaml.ejs +9 -0
- package/templates/base/root/AGENTS.md.ejs +916 -51
- package/templates/crud/Controller.java.ejs +36 -6
- package/templates/crud/ListQuery.java.ejs +6 -2
- package/templates/crud/ListQueryHandler.java.ejs +24 -10
- package/templates/crud/UpdateCommand.java.ejs +52 -0
- package/templates/crud/UpdateCommandHandler.java.ejs +105 -0
- package/templates/kafka-event/DomainEventHandlerMethod.ejs +1 -0
- package/templates/kafka-event/Event.java.ejs +23 -0
- package/templates/shared/application/dtos/PagedResponse.java.ejs +30 -0
- package/templates/shared/configurations/temporalConfig/TemporalConfig.java.ejs +104 -0
- package/templates/shared/domain/DomainEvent.java.ejs +40 -0
- package/templates/shared/interfaces/HeavyActivity.java.ejs +4 -0
- package/templates/shared/interfaces/LightActivity.java.ejs +4 -0
- package/templates/temporal-activity/ActivityImpl.java.ejs +14 -0
- package/templates/temporal-activity/ActivityInterface.java.ejs +11 -0
- package/templates/temporal-flow/WorkFlowImpl.java.ejs +64 -0
- package/templates/temporal-flow/WorkFlowInterface.java.ejs +19 -0
- package/templates/temporal-flow/WorkFlowService.java.ejs +49 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# Command `generate temporal-activity` (alias: `g temporal-activity`)
|
|
2
|
+
|
|
3
|
+
## 📋 Description
|
|
4
|
+
|
|
5
|
+
Generates a Temporal activity with its interface (port) and Spring implementation, then registers the activity stub inside a chosen `*WorkFlowImpl.java`.
|
|
6
|
+
|
|
7
|
+
## 🎯 Purpose
|
|
8
|
+
|
|
9
|
+
Create a single, focused unit of work that can be executed and retried independently by the Temporal server. Activities are the building blocks invoked by workflows — each activity handles one side-effect (database write, HTTP call, email, etc.) and can be categorised as **Light** (fast, < 30 s) or **Heavy** (long-running, up to 2 min) to route it to the appropriate worker queue.
|
|
10
|
+
|
|
11
|
+
## 📝 Syntax
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
eva generate temporal-activity <module>
|
|
15
|
+
eva g temporal-activity <module> # Short alias
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Parameters
|
|
19
|
+
|
|
20
|
+
| Parameter | Required | Description |
|
|
21
|
+
|-----------|----------|-------------|
|
|
22
|
+
| `module` | Yes | Target module where the activity **interface** lives |
|
|
23
|
+
|
|
24
|
+
> **Interactive prompts (4 steps):**
|
|
25
|
+
> 1. **Activity name** — e.g., `send-confirmation-email` or `SendConfirmationEmail`
|
|
26
|
+
> 2. **Category** — `LightActivity` (< 30 s, `LIGHT_TASK_QUEUE`) or `HeavyActivity` (up to 2 min, `HEAVY_TASK_QUEUE`)
|
|
27
|
+
> 3. **Workflow to register in** — lists all `*WorkFlowImpl.java` found across all modules; select the one that will invoke this activity
|
|
28
|
+
|
|
29
|
+
## 💡 Examples
|
|
30
|
+
|
|
31
|
+
### Example 1: Light activity for e-mail notifications
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
eva g temporal-activity notification
|
|
35
|
+
# Prompted:
|
|
36
|
+
# Activity name: send-confirmation-email
|
|
37
|
+
# Category: LightActivity
|
|
38
|
+
# Workflow: order/ProcessOrderWorkFlowImpl.java
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Generates:**
|
|
42
|
+
- `notification/application/ports/SendConfirmationEmailActivity.java` — `@ActivityInterface`
|
|
43
|
+
- `notification/infrastructure/adapters/activities/SendConfirmationEmailActivityImpl.java` — `@Component` implementing `LightActivity`
|
|
44
|
+
- Patches `order/application/usecases/ProcessOrderWorkFlowImpl.java` with a stub field
|
|
45
|
+
|
|
46
|
+
### Example 2: Heavy activity for file processing
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
eva g temporal-activity documents
|
|
50
|
+
# Prompted:
|
|
51
|
+
# Activity name: generate-pdf-report
|
|
52
|
+
# Category: HeavyActivity
|
|
53
|
+
# Workflow: documents/ProcessDocumentWorkFlowImpl.java
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Generates:**
|
|
57
|
+
- `documents/application/ports/GeneratePdfReportActivity.java`
|
|
58
|
+
- `documents/infrastructure/adapters/activities/GeneratePdfReportActivityImpl.java` — implements `HeavyActivity`
|
|
59
|
+
- Patches `ProcessDocumentWorkFlowImpl.java` with a `heavyActivityOptions` stub
|
|
60
|
+
|
|
61
|
+
### Example 3: Multiple activities on the same workflow
|
|
62
|
+
|
|
63
|
+
Run the command multiple times with different names to build up a workflow's activity set:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
eva g temporal-activity order # ValidateStockActivity → LightActivity
|
|
67
|
+
eva g temporal-activity order # ChargePaymentActivity → HeavyActivity
|
|
68
|
+
eva g temporal-activity order # SendReceiptActivity → LightActivity
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Each run adds a new stub field in the selected `WorkFlowImpl` without touching existing ones.
|
|
72
|
+
|
|
73
|
+
## 📦 Generated Code Structure
|
|
74
|
+
|
|
75
|
+
### Activity Interface — `SendConfirmationEmailActivity.java`
|
|
76
|
+
|
|
77
|
+
```java
|
|
78
|
+
package com.example.project.notification.application.ports;
|
|
79
|
+
|
|
80
|
+
import io.temporal.activity.ActivityInterface;
|
|
81
|
+
import io.temporal.activity.ActivityMethod;
|
|
82
|
+
|
|
83
|
+
@ActivityInterface
|
|
84
|
+
public interface SendConfirmationEmailActivity {
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* @ActivityMethod(name = "SendConfirmationEmail") ensures a globally unique
|
|
88
|
+
* method name, preventing TypeAlreadyRegisteredException when multiple
|
|
89
|
+
* activity types are registered on the same worker.
|
|
90
|
+
*/
|
|
91
|
+
@ActivityMethod(name = "SendConfirmationEmail")
|
|
92
|
+
void execute(String flowId);
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
> **Why `name = "..."`?**
|
|
97
|
+
> Without an explicit name, Temporal defaults every activity method to `"Execute"`. If the same worker hosts two activity interfaces both with `execute()`, Temporal throws `TypeAlreadyRegisteredException`. The generated unique name prevents this.
|
|
98
|
+
|
|
99
|
+
### Activity Implementation — `SendConfirmationEmailActivityImpl.java`
|
|
100
|
+
|
|
101
|
+
```java
|
|
102
|
+
package com.example.project.notification.infrastructure.adapters.activities;
|
|
103
|
+
|
|
104
|
+
import com.example.project.notification.application.ports.SendConfirmationEmailActivity;
|
|
105
|
+
import com.example.project.shared.domain.interfaces.LightActivity;
|
|
106
|
+
import org.springframework.stereotype.Component;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Implements LightActivity — Spring DI injects this into TemporalConfig
|
|
110
|
+
* via List<LightActivity>, automatically registering it on LIGHT_TASK_QUEUE.
|
|
111
|
+
* No manual TemporalConfig.java patching is required.
|
|
112
|
+
*/
|
|
113
|
+
@Component
|
|
114
|
+
public class SendConfirmationEmailActivityImpl
|
|
115
|
+
implements SendConfirmationEmailActivity, LightActivity {
|
|
116
|
+
|
|
117
|
+
@Override
|
|
118
|
+
public void execute(String flowId) {
|
|
119
|
+
// TODO: implement activity logic
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### WorkFlowImpl — Auto-patched Stub Field
|
|
125
|
+
|
|
126
|
+
```java
|
|
127
|
+
// Added inside ProcessOrderWorkFlowImpl by the command:
|
|
128
|
+
private final SendConfirmationEmailActivity sendConfirmationEmailActivity =
|
|
129
|
+
Workflow.newActivityStub(SendConfirmationEmailActivity.class, lightActivityOptions);
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
For a `HeavyActivity`, `heavyActivityOptions` is used instead.
|
|
133
|
+
|
|
134
|
+
## 🏗️ Queue & Registration Architecture
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
Spring Boot startup
|
|
138
|
+
│
|
|
139
|
+
▼
|
|
140
|
+
TemporalConfig.workerFactory()
|
|
141
|
+
│
|
|
142
|
+
├─ workflowWorker (FLOW_QUEUE)
|
|
143
|
+
│ └─ registerWorkflowImplementationTypes(ProcessOrderWorkFlowImpl.class)
|
|
144
|
+
│
|
|
145
|
+
├─ lightWorker (LIGHT_TASK_QUEUE)
|
|
146
|
+
│ └─ registerActivitiesImplementations(List<LightActivity> beans...)
|
|
147
|
+
│ ↑
|
|
148
|
+
│ SendConfirmationEmailActivityImpl @Component
|
|
149
|
+
│
|
|
150
|
+
└─ heavyWorker (HEAVY_TASK_QUEUE)
|
|
151
|
+
└─ registerActivitiesImplementations(List<HeavyActivity> beans...)
|
|
152
|
+
↑
|
|
153
|
+
GeneratePdfReportActivityImpl @Component
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Key points:**
|
|
157
|
+
- Activities are registered automatically via **Spring DI list injection** — adding `@Component` + marker interface is sufficient.
|
|
158
|
+
- The workflow stub field routes execution to the correct queue through `lightActivityOptions` / `heavyActivityOptions`.
|
|
159
|
+
- `TemporalConfig.java` is **not** patched for activities (only for workflows).
|
|
160
|
+
|
|
161
|
+
## 📊 Light vs Heavy — Decision Guide
|
|
162
|
+
|
|
163
|
+
| Criterion | LightActivity | HeavyActivity |
|
|
164
|
+
|-----------|--------------|---------------|
|
|
165
|
+
| Max execution time | 30 seconds | 2 minutes |
|
|
166
|
+
| Typical use cases | Cache lookups, email dispatch, simple DB writes | PDF generation, external API calls, image processing |
|
|
167
|
+
| Retry timeout | 30 s per attempt | 120 s per attempt |
|
|
168
|
+
| Worker queue | `LIGHT_TASK_QUEUE` | `HEAVY_TASK_QUEUE` |
|
|
169
|
+
| Options variable in WorkFlowImpl | `lightActivityOptions` | `heavyActivityOptions` |
|
|
170
|
+
|
|
171
|
+
## ✅ Prerequisites
|
|
172
|
+
|
|
173
|
+
- `eva add temporal-client` must have been run
|
|
174
|
+
- At least one workflow must exist in the project (created via `eva g temporal-flow`) — the command lists them in the interactive prompt
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# Command `generate temporal-flow` (alias: `g temporal-flow`)
|
|
2
|
+
|
|
3
|
+
## 📋 Description
|
|
4
|
+
|
|
5
|
+
Generates a complete Temporal workflow with interface, implementation and service facade, then automatically registers the workflow in the existing `TemporalConfig.java`.
|
|
6
|
+
|
|
7
|
+
## 🎯 Purpose
|
|
8
|
+
|
|
9
|
+
Create the scaffolding for a new Temporal workflow (orchestration unit) within a module. Follows the Saga pattern with compensation support and provides both async and sync invocation modes via the generated service facade.
|
|
10
|
+
|
|
11
|
+
## 📝 Syntax
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
eva generate temporal-flow <module>
|
|
15
|
+
eva g temporal-flow <module> # Short alias
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Parameters
|
|
19
|
+
|
|
20
|
+
| Parameter | Required | Description |
|
|
21
|
+
|-----------|----------|-------------|
|
|
22
|
+
| `module` | Yes | Target module name (e.g., `order`, `payment`) |
|
|
23
|
+
|
|
24
|
+
> **Interactive prompt:** When the module is provided, the CLI asks for the **workflow name**. You can write it in `kebab-case` (`process-order`) or `PascalCase` (`ProcessOrder`) — both are accepted and normalised to PascalCase internally.
|
|
25
|
+
|
|
26
|
+
## 💡 Examples
|
|
27
|
+
|
|
28
|
+
### Example 1: Order processing workflow
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
eva g temporal-flow order
|
|
32
|
+
# Prompted for workflow name: process-order (or ProcessOrder)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Generates:**
|
|
36
|
+
- `application/usecases/ProcessOrderWorkFlow.java` — `@WorkflowInterface`
|
|
37
|
+
- `application/usecases/ProcessOrderWorkFlowImpl.java` — implementation with Saga
|
|
38
|
+
- `application/usecases/ProcessOrderWorkFlowService.java` — Spring service facade
|
|
39
|
+
- Patches `shared/infrastructure/configurations/TemporalConfig.java` to register `ProcessOrderWorkFlowImpl`
|
|
40
|
+
|
|
41
|
+
### Example 2: Payment workflow
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
eva g temporal-flow payment
|
|
45
|
+
# Prompted for workflow name: process-payment
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**Generates:**
|
|
49
|
+
- `application/usecases/ProcessPaymentWorkFlow.java`
|
|
50
|
+
- `application/usecases/ProcessPaymentWorkFlowImpl.java`
|
|
51
|
+
- `application/usecases/ProcessPaymentWorkFlowService.java`
|
|
52
|
+
- Patches `TemporalConfig.java`
|
|
53
|
+
|
|
54
|
+
### Example 3: Multiple workflows in the same module
|
|
55
|
+
|
|
56
|
+
You can run the command again with a different name to add more workflows:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
eva g temporal-flow order
|
|
60
|
+
# process-order → generates ProcessOrder files
|
|
61
|
+
|
|
62
|
+
eva g temporal-flow order
|
|
63
|
+
# refund-order → generates RefundOrder files
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Each run appends a new `registerWorkflowImplementationTypes(...)` entry to `TemporalConfig.java` without duplicating existing registrations.
|
|
67
|
+
|
|
68
|
+
## 📦 Generated Code Structure
|
|
69
|
+
|
|
70
|
+
### WorkFlow Interface — `ProcessOrderWorkFlow.java`
|
|
71
|
+
|
|
72
|
+
```java
|
|
73
|
+
package com.example.project.order.application.usecases;
|
|
74
|
+
|
|
75
|
+
import io.temporal.workflow.QueryMethod;
|
|
76
|
+
import io.temporal.workflow.SignalMethod;
|
|
77
|
+
import io.temporal.workflow.WorkflowInterface;
|
|
78
|
+
import io.temporal.workflow.WorkflowMethod;
|
|
79
|
+
|
|
80
|
+
@WorkflowInterface
|
|
81
|
+
public interface ProcessOrderWorkFlow {
|
|
82
|
+
|
|
83
|
+
@WorkflowMethod
|
|
84
|
+
void start(String input);
|
|
85
|
+
|
|
86
|
+
@SignalMethod
|
|
87
|
+
void confirm();
|
|
88
|
+
|
|
89
|
+
@QueryMethod
|
|
90
|
+
String getStatus();
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### WorkFlow Implementation — `ProcessOrderWorkFlowImpl.java`
|
|
95
|
+
|
|
96
|
+
```java
|
|
97
|
+
package com.example.project.order.application.usecases;
|
|
98
|
+
|
|
99
|
+
import io.temporal.activity.ActivityOptions;
|
|
100
|
+
import io.temporal.common.RetryOptions;
|
|
101
|
+
import io.temporal.workflow.Saga;
|
|
102
|
+
import io.temporal.workflow.SignalMethod;
|
|
103
|
+
import io.temporal.workflow.QueryMethod;
|
|
104
|
+
import io.temporal.workflow.Workflow;
|
|
105
|
+
|
|
106
|
+
import java.time.Duration;
|
|
107
|
+
|
|
108
|
+
public class ProcessOrderWorkFlowImpl implements ProcessOrderWorkFlow {
|
|
109
|
+
|
|
110
|
+
private Saga.Options sagaOptions = new Saga.Options.Builder()
|
|
111
|
+
.setParallelCompensation(false)
|
|
112
|
+
.build();
|
|
113
|
+
|
|
114
|
+
private Saga saga = new Saga(sagaOptions);
|
|
115
|
+
|
|
116
|
+
// Light activities (<30 s) — routed to LIGHT_TASK_QUEUE
|
|
117
|
+
private final ActivityOptions lightActivityOptions = ActivityOptions.newBuilder()
|
|
118
|
+
.setStartToCloseTimeout(Duration.ofSeconds(30))
|
|
119
|
+
.setTaskQueue("LIGHT_TASK_QUEUE")
|
|
120
|
+
.setRetryOptions(
|
|
121
|
+
RetryOptions.newBuilder()
|
|
122
|
+
.setMaximumAttempts(2)
|
|
123
|
+
.setInitialInterval(Duration.ofSeconds(1))
|
|
124
|
+
.setMaximumInterval(Duration.ofSeconds(10))
|
|
125
|
+
.setBackoffCoefficient(2.0)
|
|
126
|
+
.build()
|
|
127
|
+
).build();
|
|
128
|
+
|
|
129
|
+
// Heavy activities (up to 2 min) — routed to HEAVY_TASK_QUEUE
|
|
130
|
+
private final ActivityOptions heavyActivityOptions = ActivityOptions.newBuilder()
|
|
131
|
+
.setStartToCloseTimeout(Duration.ofSeconds(120))
|
|
132
|
+
.setTaskQueue("HEAVY_TASK_QUEUE")
|
|
133
|
+
.setRetryOptions(
|
|
134
|
+
RetryOptions.newBuilder()
|
|
135
|
+
.setMaximumAttempts(2)
|
|
136
|
+
.setInitialInterval(Duration.ofSeconds(1))
|
|
137
|
+
.setMaximumInterval(Duration.ofSeconds(10))
|
|
138
|
+
.setBackoffCoefficient(2.0)
|
|
139
|
+
.build()
|
|
140
|
+
).build();
|
|
141
|
+
|
|
142
|
+
private String status = "PENDING";
|
|
143
|
+
|
|
144
|
+
@Override
|
|
145
|
+
public void start(String workFlowId) {
|
|
146
|
+
try {
|
|
147
|
+
//todo: workflow logic
|
|
148
|
+
} catch (Exception e) {
|
|
149
|
+
saga.compensate();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
@Override
|
|
154
|
+
public void confirm() {
|
|
155
|
+
// Handle confirmation signal
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
@Override
|
|
159
|
+
public String getStatus() {
|
|
160
|
+
return status;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### WorkFlow Service Facade — `ProcessOrderWorkFlowService.java`
|
|
166
|
+
|
|
167
|
+
```java
|
|
168
|
+
package com.example.project.order.application.usecases;
|
|
169
|
+
|
|
170
|
+
import com.example.project.shared.domain.annotations.ApplicationComponent;
|
|
171
|
+
import io.temporal.client.WorkflowClient;
|
|
172
|
+
import io.temporal.client.WorkflowOptions;
|
|
173
|
+
import org.springframework.beans.factory.annotation.Value;
|
|
174
|
+
|
|
175
|
+
import java.util.UUID;
|
|
176
|
+
|
|
177
|
+
@ApplicationComponent
|
|
178
|
+
public class ProcessOrderWorkFlowService {
|
|
179
|
+
|
|
180
|
+
private final WorkflowClient workflowClient;
|
|
181
|
+
|
|
182
|
+
@Value("${temporal.flow-queue}")
|
|
183
|
+
private String flowQueue;
|
|
184
|
+
|
|
185
|
+
// ... constructor injection
|
|
186
|
+
|
|
187
|
+
/** Fire and forget — returns the workflow ID immediately */
|
|
188
|
+
public String startAsync(String input) {
|
|
189
|
+
String workflowId = "ProcessOrderWorkFlow-" + UUID.randomUUID();
|
|
190
|
+
ProcessOrderWorkFlow workflow = workflowClient.newWorkflowStub(
|
|
191
|
+
ProcessOrderWorkFlow.class,
|
|
192
|
+
WorkflowOptions.newBuilder()
|
|
193
|
+
.setWorkflowId(workflowId)
|
|
194
|
+
.setTaskQueue(flowQueue)
|
|
195
|
+
.build());
|
|
196
|
+
WorkflowClient.start(workflow::start, input);
|
|
197
|
+
return workflowId;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/** Blocking — waits until the workflow finishes */
|
|
201
|
+
public void startSync(String input) {
|
|
202
|
+
String workflowId = "ProcessOrderWorkFlow-" + UUID.randomUUID();
|
|
203
|
+
ProcessOrderWorkFlow workflow = workflowClient.newWorkflowStub(
|
|
204
|
+
ProcessOrderWorkFlow.class,
|
|
205
|
+
WorkflowOptions.newBuilder()
|
|
206
|
+
.setWorkflowId(workflowId)
|
|
207
|
+
.setTaskQueue(flowQueue)
|
|
208
|
+
.build());
|
|
209
|
+
workflow.start(input);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
public void confirm(String workflowId) { /* signal */ }
|
|
213
|
+
public String getStatus(String workflowId) { /* query */ return null; }
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### TemporalConfig.java — Auto-patched Entry
|
|
218
|
+
|
|
219
|
+
```java
|
|
220
|
+
// registered automatically by eva g temporal-flow
|
|
221
|
+
workflowWorker.registerWorkflowImplementationTypes(ProcessOrderWorkFlowImpl.class);
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## 🏗️ Queue Architecture
|
|
225
|
+
|
|
226
|
+
| Queue | Purpose |
|
|
227
|
+
|-------|---------|
|
|
228
|
+
| `FLOW_QUEUE` | Workflow orchestration (WorkFlowImpl runs here) |
|
|
229
|
+
| `LIGHT_TASK_QUEUE` | Fast activities (< 30 s), injected via `lightActivityOptions` |
|
|
230
|
+
| `HEAVY_TASK_QUEUE` | Long-running activities (up to 2 min), injected via `heavyActivityOptions` |
|
|
231
|
+
|
|
232
|
+
Activity stubs created inside the workflow must pass the matching options object — see [GENERATE_TEMPORAL_ACTIVITY.md](./GENERATE_TEMPORAL_ACTIVITY.md).
|
|
233
|
+
|
|
234
|
+
## ✅ Prerequisites
|
|
235
|
+
|
|
236
|
+
- `eva add temporal-client` must have been run before this command
|
|
237
|
+
- The target `<module>` must already exist (`eva add module <module>`)
|