@temporal-architect/claude-plugin 0.9.0
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/LICENSE +21 -0
- package/README.md +38 -0
- package/package.json +37 -0
- package/skills/MANIFEST.json +373 -0
- package/skills/MANIFEST.md +121 -0
- package/skills/temporal-architect/SKILL.md +99 -0
- package/skills/temporal-architect/reference/decomposition.md +78 -0
- package/skills/temporal-architect-author-go/README.md +16 -0
- package/skills/temporal-architect-author-go/SKILL.md +191 -0
- package/skills/temporal-architect-author-go/SUBAGENT_ADOPTION.md +161 -0
- package/skills/temporal-architect-author-go/reference/activity-call.md +73 -0
- package/skills/temporal-architect-author-go/reference/activity-def.md +54 -0
- package/skills/temporal-architect-author-go/reference/assignment.md +36 -0
- package/skills/temporal-architect-author-go/reference/await-all.md +104 -0
- package/skills/temporal-architect-author-go/reference/await-one.md +193 -0
- package/skills/temporal-architect-author-go/reference/await-timer.md +35 -0
- package/skills/temporal-architect-author-go/reference/close.md +71 -0
- package/skills/temporal-architect-author-go/reference/composite-patterns.md +176 -0
- package/skills/temporal-architect-author-go/reference/condition.md +56 -0
- package/skills/temporal-architect-author-go/reference/control-flow.md +151 -0
- package/skills/temporal-architect-author-go/reference/dependency-resolution.md +29 -0
- package/skills/temporal-architect-author-go/reference/detach.md +52 -0
- package/skills/temporal-architect-author-go/reference/heartbeat.md +84 -0
- package/skills/temporal-architect-author-go/reference/nexus-service-def.md +73 -0
- package/skills/temporal-architect-author-go/reference/nexus.md +35 -0
- package/skills/temporal-architect-author-go/reference/options.md +138 -0
- package/skills/temporal-architect-author-go/reference/promise.md +73 -0
- package/skills/temporal-architect-author-go/reference/proto-driven.md +197 -0
- package/skills/temporal-architect-author-go/reference/query-handler.md +34 -0
- package/skills/temporal-architect-author-go/reference/signal-handler.md +73 -0
- package/skills/temporal-architect-author-go/reference/three-layer-testing.md +173 -0
- package/skills/temporal-architect-author-go/reference/types.md +72 -0
- package/skills/temporal-architect-author-go/reference/update-handler.md +64 -0
- package/skills/temporal-architect-author-go/reference/worker.md +215 -0
- package/skills/temporal-architect-author-go/reference/workflow-call.md +37 -0
- package/skills/temporal-architect-author-go/reference/workflow-def.md +45 -0
- package/skills/temporal-architect-author-infra/README.md +16 -0
- package/skills/temporal-architect-author-infra/SKILL.md +132 -0
- package/skills/temporal-architect-author-infra/reference/tcld.md +112 -0
- package/skills/temporal-architect-author-infra/reference/terraform.md +125 -0
- package/skills/temporal-architect-design/README.md +16 -0
- package/skills/temporal-architect-design/SKILL.md +224 -0
- package/skills/temporal-architect-design/reference/LANGUAGE.md +5 -0
- package/skills/temporal-architect-design/reference/anti-patterns.md +332 -0
- package/skills/temporal-architect-design/reference/common-errors.md +88 -0
- package/skills/temporal-architect-design/reference/core-principles.md +52 -0
- package/skills/temporal-architect-design/reference/design-checklist.md +59 -0
- package/skills/temporal-architect-design/reference/namespaces.md +84 -0
- package/skills/temporal-architect-design/reference/notation-examples.md +304 -0
- package/skills/temporal-architect-design/reference/notation-reference.md +70 -0
- package/skills/temporal-architect-design/reference/primitives-reference.md +65 -0
- package/skills/temporal-architect-design/reference/project-discovery-subagent.md +80 -0
- package/skills/temporal-architect-design/reference/reverse-engineering.md +53 -0
- package/skills/temporal-architect-design/reference/twf-conventions.md +43 -0
- package/skills/temporal-architect-design/reference/workflow-boundaries.md +43 -0
- package/skills/temporal-architect-design/topics/activities-advanced.md +358 -0
- package/skills/temporal-architect-design/topics/activities-advanced.twf +107 -0
- package/skills/temporal-architect-design/topics/child-workflows.md +347 -0
- package/skills/temporal-architect-design/topics/child-workflows.twf +171 -0
- package/skills/temporal-architect-design/topics/long-running.md +230 -0
- package/skills/temporal-architect-design/topics/long-running.twf +100 -0
- package/skills/temporal-architect-design/topics/nexus.md +248 -0
- package/skills/temporal-architect-design/topics/nexus.twf +148 -0
- package/skills/temporal-architect-design/topics/patterns.md +469 -0
- package/skills/temporal-architect-design/topics/patterns.twf +346 -0
- package/skills/temporal-architect-design/topics/promises-conditions.md +179 -0
- package/skills/temporal-architect-design/topics/promises-conditions.twf +213 -0
- package/skills/temporal-architect-design/topics/signals-queries-updates.md +319 -0
- package/skills/temporal-architect-design/topics/signals-queries-updates.twf +234 -0
- package/skills/temporal-architect-design/topics/task-queues.md +205 -0
- package/skills/temporal-architect-design/topics/task-queues.twf +184 -0
- package/skills/temporal-architect-design/topics/testing.md +437 -0
- package/skills/temporal-architect-design/topics/testing.twf +177 -0
- package/skills/temporal-architect-design/topics/timers-scheduling.md +131 -0
- package/skills/temporal-architect-design/topics/timers-scheduling.twf +129 -0
- package/skills/temporal-architect-design/topics/versioning.md +434 -0
- package/skills/temporal-architect-design/topics/versioning.twf +174 -0
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
# Advanced Activity Patterns
|
|
2
|
+
|
|
3
|
+
> **Example:** [`activities-advanced.twf`](./activities-advanced.twf)
|
|
4
|
+
|
|
5
|
+
Heartbeats, async completion, local activities, and timeout configuration for sophisticated activity designs.
|
|
6
|
+
|
|
7
|
+
## Activity Heartbeats
|
|
8
|
+
|
|
9
|
+
Long-running activities should periodically heartbeat to report progress and allow early failure detection.
|
|
10
|
+
|
|
11
|
+
### Why Heartbeat
|
|
12
|
+
|
|
13
|
+
| Without Heartbeat | With Heartbeat |
|
|
14
|
+
|-------------------|----------------|
|
|
15
|
+
| Worker crash detected only at activity timeout | Worker crash detected within heartbeat timeout |
|
|
16
|
+
| No visibility into progress | Progress visible during execution |
|
|
17
|
+
| Full retry on any failure | Can resume from last heartbeat |
|
|
18
|
+
|
|
19
|
+
### Basic Heartbeat Pattern
|
|
20
|
+
|
|
21
|
+
> Note: Activity body implementations are SDK-level code, not TWF notation.
|
|
22
|
+
|
|
23
|
+
```pseudo
|
|
24
|
+
activity ProcessLargeFile(fileId: string) -> ProcessResult:
|
|
25
|
+
file = download(fileId)
|
|
26
|
+
total = len(file.chunks)
|
|
27
|
+
|
|
28
|
+
for i, chunk in enumerate(file.chunks):
|
|
29
|
+
process(chunk)
|
|
30
|
+
|
|
31
|
+
# Report progress every chunk
|
|
32
|
+
heartbeat(progress: {
|
|
33
|
+
current: i + 1,
|
|
34
|
+
total: total,
|
|
35
|
+
percentage: (i + 1) / total * 100
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
return ProcessResult{success: true}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Heartbeat with Cancellation Check
|
|
42
|
+
|
|
43
|
+
```pseudo
|
|
44
|
+
activity LongRunningTask(taskId: string) -> TaskResult:
|
|
45
|
+
for step in steps:
|
|
46
|
+
# Check if workflow requested cancellation
|
|
47
|
+
if heartbeat_and_check_cancelled():
|
|
48
|
+
cleanup(taskId)
|
|
49
|
+
raise CancelledException("Task cancelled")
|
|
50
|
+
|
|
51
|
+
execute(step)
|
|
52
|
+
|
|
53
|
+
return TaskResult{complete: true}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Heartbeat Timeout Configuration
|
|
57
|
+
|
|
58
|
+
```twf
|
|
59
|
+
workflow Parent(data: Data) -> (Result):
|
|
60
|
+
activity LongProcess(data) -> result
|
|
61
|
+
options:
|
|
62
|
+
start_to_close_timeout: 1h
|
|
63
|
+
heartbeat_timeout: 30s
|
|
64
|
+
|
|
65
|
+
close complete(result)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Resume from Heartbeat Details
|
|
69
|
+
|
|
70
|
+
```pseudo
|
|
71
|
+
activity ResumableProcess(batchId: string) -> BatchResult:
|
|
72
|
+
# Get last heartbeat details (if resuming after failure)
|
|
73
|
+
lastProgress = get_heartbeat_details()
|
|
74
|
+
startIndex = lastProgress?.index ?? 0
|
|
75
|
+
|
|
76
|
+
items = getItems(batchId)
|
|
77
|
+
|
|
78
|
+
for i in range(startIndex, len(items)):
|
|
79
|
+
process(items[i])
|
|
80
|
+
heartbeat(index: i + 1) # Save progress
|
|
81
|
+
|
|
82
|
+
return BatchResult{processed: len(items)}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Async Activity Completion
|
|
88
|
+
|
|
89
|
+
Complete an activity from outside the activity execution context. Useful for human tasks, external callbacks, and webhook-driven flows.
|
|
90
|
+
|
|
91
|
+
### When to Use
|
|
92
|
+
|
|
93
|
+
| Use Case | Description |
|
|
94
|
+
|----------|-------------|
|
|
95
|
+
| Human tasks | Activity waits for human action in external system |
|
|
96
|
+
| External callbacks | Third-party API will callback when done |
|
|
97
|
+
| Long polling avoidance | External system notifies completion |
|
|
98
|
+
| Multi-system coordination | Completion triggered by external event |
|
|
99
|
+
|
|
100
|
+
### Async Completion Pattern
|
|
101
|
+
|
|
102
|
+
```pseudo
|
|
103
|
+
activity RequestHumanApproval(request: ApprovalRequest) -> ApprovalResult:
|
|
104
|
+
# Get task token for external completion
|
|
105
|
+
taskToken = get_activity_task_token()
|
|
106
|
+
|
|
107
|
+
# Send task to external system (e.g., ticketing system)
|
|
108
|
+
createTicket(
|
|
109
|
+
title: request.title,
|
|
110
|
+
callback_token: taskToken, # External system uses this to complete
|
|
111
|
+
callback_url: "https://temporal/complete-activity"
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
# Activity does NOT complete here
|
|
115
|
+
# It will be completed externally via API call
|
|
116
|
+
do_not_complete()
|
|
117
|
+
|
|
118
|
+
# External system calls Temporal API:
|
|
119
|
+
# POST /complete-activity
|
|
120
|
+
# {
|
|
121
|
+
# "task_token": "...",
|
|
122
|
+
# "result": {"approved": true, "approver": "alice"}
|
|
123
|
+
# }
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Workflow Using Async Activity
|
|
127
|
+
|
|
128
|
+
```twf
|
|
129
|
+
workflow PublishApprovalWorkflow(request: Request) -> (Decision):
|
|
130
|
+
activity NotifyRequestCreated(request)
|
|
131
|
+
|
|
132
|
+
# This activity blocks until external completion
|
|
133
|
+
activity RequestHumanApproval(request) -> result
|
|
134
|
+
options:
|
|
135
|
+
start_to_close_timeout: 7d
|
|
136
|
+
|
|
137
|
+
if (result.approved):
|
|
138
|
+
activity ExecuteApprovedAction(request)
|
|
139
|
+
|
|
140
|
+
close complete(Decision{approved: result.approved})
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### External Completion API
|
|
144
|
+
|
|
145
|
+
> Note: Temporal API calls are SDK-level, not TWF notation.
|
|
146
|
+
|
|
147
|
+
```pseudo
|
|
148
|
+
# Complete activity successfully
|
|
149
|
+
temporal.complete_activity(
|
|
150
|
+
task_token: "...",
|
|
151
|
+
result: {approved: true}
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
# Fail activity
|
|
155
|
+
temporal.fail_activity(
|
|
156
|
+
task_token: "...",
|
|
157
|
+
error: {message: "Rejected by compliance"}
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
# Report activity cancelled
|
|
161
|
+
temporal.cancel_activity(
|
|
162
|
+
task_token: "..."
|
|
163
|
+
)
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Local Activities
|
|
169
|
+
|
|
170
|
+
Lightweight activities that execute in the workflow worker process without task queue round-trip.
|
|
171
|
+
|
|
172
|
+
### When to Use Local Activities
|
|
173
|
+
|
|
174
|
+
| Use Local Activity | Use Regular Activity |
|
|
175
|
+
|--------------------|---------------------|
|
|
176
|
+
| Very short operations (< 10s) | Longer operations |
|
|
177
|
+
| Low latency required | Normal latency acceptable |
|
|
178
|
+
| Simple operations | Complex operations |
|
|
179
|
+
| Tight retry needed | Standard retry policies |
|
|
180
|
+
| Same worker has required resources | May need different worker |
|
|
181
|
+
|
|
182
|
+
### Local Activity Pattern
|
|
183
|
+
|
|
184
|
+
> Note: Local activities are an SDK-level concept. In TWF notation, use `activity` with an `options:` block specifying local execution. The syntax below is conceptual.
|
|
185
|
+
|
|
186
|
+
```pseudo
|
|
187
|
+
workflow ProcessOrder(order: Order) -> (Result):
|
|
188
|
+
# Local activity: fast, in-process (SDK: use local activity API)
|
|
189
|
+
activity ValidateInput(order) -> validated
|
|
190
|
+
options:
|
|
191
|
+
local: true
|
|
192
|
+
start_to_close_timeout: 5s
|
|
193
|
+
|
|
194
|
+
# Regular activity: goes through task queue
|
|
195
|
+
activity ProcessPayment(order) -> result
|
|
196
|
+
|
|
197
|
+
close complete(result)
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Local Activity Limitations
|
|
201
|
+
|
|
202
|
+
| Limitation | Implication |
|
|
203
|
+
|------------|-------------|
|
|
204
|
+
| No task queue routing | Must execute on workflow worker |
|
|
205
|
+
| Limited retries | Short retry window |
|
|
206
|
+
| Worker restart = retry | Not persisted across restarts |
|
|
207
|
+
| No heartbeat | Not for long operations |
|
|
208
|
+
|
|
209
|
+
### Local Activity Configuration
|
|
210
|
+
|
|
211
|
+
> Note: Local activity configuration is SDK-specific.
|
|
212
|
+
|
|
213
|
+
```pseudo
|
|
214
|
+
workflow Parent(data: Data) -> (Result):
|
|
215
|
+
activity QuickValidation(data) -> result
|
|
216
|
+
options:
|
|
217
|
+
local: true
|
|
218
|
+
start_to_close_timeout: 10s
|
|
219
|
+
local_retry_threshold: 5s
|
|
220
|
+
retry_policy:
|
|
221
|
+
maximum_attempts: 3
|
|
222
|
+
initial_interval: 100ms
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Activity Timeout Configuration
|
|
228
|
+
|
|
229
|
+
### Timeout Types
|
|
230
|
+
|
|
231
|
+
| Timeout | Description | Default |
|
|
232
|
+
|---------|-------------|---------|
|
|
233
|
+
| `schedule_to_start` | Time from scheduled to worker pickup | None |
|
|
234
|
+
| `start_to_close` | Time from worker pickup to completion | Required |
|
|
235
|
+
| `schedule_to_close` | Total time from scheduled to completion | None |
|
|
236
|
+
| `heartbeat` | Max time between heartbeats | None |
|
|
237
|
+
|
|
238
|
+
### Timeout Relationships
|
|
239
|
+
|
|
240
|
+
```text
|
|
241
|
+
|-------- schedule_to_close --------|
|
|
242
|
+
|-- schedule_to_start --|-- start_to_close --|
|
|
243
|
+
|
|
244
|
+
schedule_to_close >= schedule_to_start + start_to_close
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Configuration Examples
|
|
248
|
+
|
|
249
|
+
```twf
|
|
250
|
+
workflow Parent(data: Data) -> (Result):
|
|
251
|
+
# Short operation, tight timeout
|
|
252
|
+
activity QuickLookup(data.id) -> result
|
|
253
|
+
options:
|
|
254
|
+
start_to_close_timeout: 30s
|
|
255
|
+
|
|
256
|
+
# Long operation with heartbeat
|
|
257
|
+
activity ProcessBatch(data) -> result
|
|
258
|
+
options:
|
|
259
|
+
start_to_close_timeout: 2h
|
|
260
|
+
heartbeat_timeout: 60s
|
|
261
|
+
|
|
262
|
+
# Operation with queue wait tolerance
|
|
263
|
+
activity LowPriorityTask(data) -> result
|
|
264
|
+
options:
|
|
265
|
+
schedule_to_start_timeout: 5m
|
|
266
|
+
start_to_close_timeout: 10m
|
|
267
|
+
|
|
268
|
+
close complete(result)
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### Timeout Selection Guidelines
|
|
272
|
+
|
|
273
|
+
| Operation Type | schedule_to_start | start_to_close | heartbeat |
|
|
274
|
+
|----------------|-------------------|----------------|-----------|
|
|
275
|
+
| Quick lookup | None | 10-30s | None |
|
|
276
|
+
| API call | None | 30s-2m | None |
|
|
277
|
+
| Batch processing | None | Minutes-hours | 30-60s |
|
|
278
|
+
| Human task | Minutes-hours | Days | None |
|
|
279
|
+
| External callback | None | Hours-days | None |
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## Retry Policies
|
|
284
|
+
|
|
285
|
+
### Retry Configuration
|
|
286
|
+
|
|
287
|
+
```twf
|
|
288
|
+
workflow Parent(data: Data) -> (Result):
|
|
289
|
+
activity UnreliableService(data) -> result
|
|
290
|
+
options:
|
|
291
|
+
retry_policy:
|
|
292
|
+
initial_interval: 1s
|
|
293
|
+
backoff_coefficient: 2.0
|
|
294
|
+
maximum_interval: 60s
|
|
295
|
+
maximum_attempts: 5
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### Error Classification
|
|
299
|
+
|
|
300
|
+
```pseudo
|
|
301
|
+
activity CallExternalAPI(request: Request) -> Response:
|
|
302
|
+
try:
|
|
303
|
+
return api.call(request)
|
|
304
|
+
catch RateLimitError:
|
|
305
|
+
# Retryable - throw and let Temporal retry
|
|
306
|
+
raise
|
|
307
|
+
catch InvalidInputError:
|
|
308
|
+
# Non-retryable - application error
|
|
309
|
+
raise NonRetryableError("Invalid input: " + error.message)
|
|
310
|
+
catch NotFoundError:
|
|
311
|
+
# Business logic - handle gracefully
|
|
312
|
+
return Response{found: false}
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
## Anti-Patterns
|
|
318
|
+
|
|
319
|
+
### Missing Heartbeat on Long Operations
|
|
320
|
+
|
|
321
|
+
```pseudo
|
|
322
|
+
# BAD: 2-hour activity with no heartbeat
|
|
323
|
+
activity ProcessHugeFile(fileId: string):
|
|
324
|
+
for chunk in file.chunks: # Takes 2 hours
|
|
325
|
+
process(chunk)
|
|
326
|
+
# Worker crash at 1h59m = full retry from start
|
|
327
|
+
|
|
328
|
+
# GOOD: Heartbeat with resumable progress
|
|
329
|
+
activity ProcessHugeFile(fileId: string):
|
|
330
|
+
lastIndex = get_heartbeat_details()?.index ?? 0
|
|
331
|
+
for i in range(lastIndex, len(chunks)):
|
|
332
|
+
process(chunks[i])
|
|
333
|
+
heartbeat(index: i + 1)
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### Wrong Timeout for Operation Type
|
|
337
|
+
|
|
338
|
+
```pseudo
|
|
339
|
+
# BAD: 1-minute timeout for human task
|
|
340
|
+
activity GetHumanApproval():
|
|
341
|
+
start_to_close_timeout: 1m # Humans are slower than this!
|
|
342
|
+
|
|
343
|
+
# GOOD: Appropriate timeout for human task
|
|
344
|
+
activity GetHumanApproval():
|
|
345
|
+
start_to_close_timeout: 7d
|
|
346
|
+
# Or use async completion
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### Local Activity for External Calls
|
|
350
|
+
|
|
351
|
+
```pseudo
|
|
352
|
+
# BAD: Network call in local activity (SDK-level concept)
|
|
353
|
+
# Local activities should not make network calls
|
|
354
|
+
|
|
355
|
+
# GOOD: Regular activity for external calls
|
|
356
|
+
activity CallExternalAPI(data):
|
|
357
|
+
return http.post(external_url, data)
|
|
358
|
+
```
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Source: activities-advanced.md
|
|
2
|
+
# Patterns: heartbeat, progress, timeout configs, retry via options
|
|
3
|
+
|
|
4
|
+
# --- Long-running activity with heartbeat ---
|
|
5
|
+
|
|
6
|
+
activity ProcessLargeFile(fileId: string) -> (ProcessResult):
|
|
7
|
+
file = download(fileId)
|
|
8
|
+
total = len(file.chunks)
|
|
9
|
+
for (i in file.chunks):
|
|
10
|
+
process(i)
|
|
11
|
+
heartbeat(progress: {current: i, total: total})
|
|
12
|
+
return ProcessResult{success: true}
|
|
13
|
+
|
|
14
|
+
# --- Resumable activity using heartbeat details ---
|
|
15
|
+
|
|
16
|
+
activity ResumableProcess(batchId: string) -> (BatchResult):
|
|
17
|
+
lastProgress = get_heartbeat_details()
|
|
18
|
+
startIndex = lastProgress.index
|
|
19
|
+
items = getItems(batchId)
|
|
20
|
+
for (i in items):
|
|
21
|
+
process(i)
|
|
22
|
+
heartbeat(index: i)
|
|
23
|
+
return BatchResult{processed: len(items)}
|
|
24
|
+
|
|
25
|
+
# --- Async completion activity (human approval) ---
|
|
26
|
+
|
|
27
|
+
activity RequestHumanApproval(request: ApprovalRequest) -> (ApprovalResult):
|
|
28
|
+
taskToken = get_activity_task_token()
|
|
29
|
+
createTicket(title: request.title, callback_token: taskToken)
|
|
30
|
+
do_not_complete()
|
|
31
|
+
|
|
32
|
+
# --- Notification activity ---
|
|
33
|
+
|
|
34
|
+
activity NotifyRequestCreated(request: Request):
|
|
35
|
+
send_notification(request)
|
|
36
|
+
|
|
37
|
+
# --- Execute approved action ---
|
|
38
|
+
|
|
39
|
+
activity ExecuteApprovedAction(request: Request):
|
|
40
|
+
execute(request)
|
|
41
|
+
|
|
42
|
+
# --- Workflow using async activity with timeout ---
|
|
43
|
+
|
|
44
|
+
workflow PublishApprovalWorkflow(request: Request) -> (Decision):
|
|
45
|
+
activity NotifyRequestCreated(request)
|
|
46
|
+
|
|
47
|
+
# This blocks until external completion
|
|
48
|
+
activity RequestHumanApproval(request) -> result
|
|
49
|
+
options:
|
|
50
|
+
start_to_close_timeout: 7d
|
|
51
|
+
|
|
52
|
+
if (result.approved):
|
|
53
|
+
activity ExecuteApprovedAction(request)
|
|
54
|
+
|
|
55
|
+
close complete(Decision{approved: result.approved})
|
|
56
|
+
|
|
57
|
+
# --- Workflow with various timeout configurations ---
|
|
58
|
+
|
|
59
|
+
workflow LargeFileIngestion(data: Data) -> (Result):
|
|
60
|
+
# Short operation, tight timeout
|
|
61
|
+
activity QuickLookup(data.id) -> result1
|
|
62
|
+
options:
|
|
63
|
+
start_to_close_timeout: 30s
|
|
64
|
+
|
|
65
|
+
# Long operation with heartbeat
|
|
66
|
+
activity ProcessLargeFile(data.fileId) -> result2
|
|
67
|
+
options:
|
|
68
|
+
start_to_close_timeout: 2h
|
|
69
|
+
heartbeat_timeout: 30s
|
|
70
|
+
|
|
71
|
+
# Operation with retry policy
|
|
72
|
+
activity UnreliableService(data) -> result3
|
|
73
|
+
options:
|
|
74
|
+
start_to_close_timeout: 2m
|
|
75
|
+
retry_policy:
|
|
76
|
+
maximum_attempts: 5
|
|
77
|
+
initial_interval: 1s
|
|
78
|
+
backoff_coefficient: 2.0
|
|
79
|
+
maximum_interval: 60s
|
|
80
|
+
|
|
81
|
+
close complete(Result{result1, result2, result3})
|
|
82
|
+
|
|
83
|
+
# --- Supporting activities ---
|
|
84
|
+
|
|
85
|
+
activity QuickLookup(id: string) -> (LookupResult):
|
|
86
|
+
return db.lookup(id)
|
|
87
|
+
|
|
88
|
+
activity UnreliableService(data: Data) -> (ServiceResult):
|
|
89
|
+
return external_api.call(data)
|
|
90
|
+
|
|
91
|
+
# --- Worker and namespace ---
|
|
92
|
+
|
|
93
|
+
worker activitiesAdvancedWorker:
|
|
94
|
+
workflow PublishApprovalWorkflow
|
|
95
|
+
workflow LargeFileIngestion
|
|
96
|
+
activity ProcessLargeFile
|
|
97
|
+
activity ResumableProcess
|
|
98
|
+
activity RequestHumanApproval
|
|
99
|
+
activity NotifyRequestCreated
|
|
100
|
+
activity ExecuteApprovedAction
|
|
101
|
+
activity QuickLookup
|
|
102
|
+
activity UnreliableService
|
|
103
|
+
|
|
104
|
+
namespace activitiesAdvanced:
|
|
105
|
+
worker activitiesAdvancedWorker
|
|
106
|
+
options:
|
|
107
|
+
task_queue: "activities-advanced"
|