@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.
Files changed (77) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +38 -0
  3. package/package.json +37 -0
  4. package/skills/MANIFEST.json +373 -0
  5. package/skills/MANIFEST.md +121 -0
  6. package/skills/temporal-architect/SKILL.md +99 -0
  7. package/skills/temporal-architect/reference/decomposition.md +78 -0
  8. package/skills/temporal-architect-author-go/README.md +16 -0
  9. package/skills/temporal-architect-author-go/SKILL.md +191 -0
  10. package/skills/temporal-architect-author-go/SUBAGENT_ADOPTION.md +161 -0
  11. package/skills/temporal-architect-author-go/reference/activity-call.md +73 -0
  12. package/skills/temporal-architect-author-go/reference/activity-def.md +54 -0
  13. package/skills/temporal-architect-author-go/reference/assignment.md +36 -0
  14. package/skills/temporal-architect-author-go/reference/await-all.md +104 -0
  15. package/skills/temporal-architect-author-go/reference/await-one.md +193 -0
  16. package/skills/temporal-architect-author-go/reference/await-timer.md +35 -0
  17. package/skills/temporal-architect-author-go/reference/close.md +71 -0
  18. package/skills/temporal-architect-author-go/reference/composite-patterns.md +176 -0
  19. package/skills/temporal-architect-author-go/reference/condition.md +56 -0
  20. package/skills/temporal-architect-author-go/reference/control-flow.md +151 -0
  21. package/skills/temporal-architect-author-go/reference/dependency-resolution.md +29 -0
  22. package/skills/temporal-architect-author-go/reference/detach.md +52 -0
  23. package/skills/temporal-architect-author-go/reference/heartbeat.md +84 -0
  24. package/skills/temporal-architect-author-go/reference/nexus-service-def.md +73 -0
  25. package/skills/temporal-architect-author-go/reference/nexus.md +35 -0
  26. package/skills/temporal-architect-author-go/reference/options.md +138 -0
  27. package/skills/temporal-architect-author-go/reference/promise.md +73 -0
  28. package/skills/temporal-architect-author-go/reference/proto-driven.md +197 -0
  29. package/skills/temporal-architect-author-go/reference/query-handler.md +34 -0
  30. package/skills/temporal-architect-author-go/reference/signal-handler.md +73 -0
  31. package/skills/temporal-architect-author-go/reference/three-layer-testing.md +173 -0
  32. package/skills/temporal-architect-author-go/reference/types.md +72 -0
  33. package/skills/temporal-architect-author-go/reference/update-handler.md +64 -0
  34. package/skills/temporal-architect-author-go/reference/worker.md +215 -0
  35. package/skills/temporal-architect-author-go/reference/workflow-call.md +37 -0
  36. package/skills/temporal-architect-author-go/reference/workflow-def.md +45 -0
  37. package/skills/temporal-architect-author-infra/README.md +16 -0
  38. package/skills/temporal-architect-author-infra/SKILL.md +132 -0
  39. package/skills/temporal-architect-author-infra/reference/tcld.md +112 -0
  40. package/skills/temporal-architect-author-infra/reference/terraform.md +125 -0
  41. package/skills/temporal-architect-design/README.md +16 -0
  42. package/skills/temporal-architect-design/SKILL.md +224 -0
  43. package/skills/temporal-architect-design/reference/LANGUAGE.md +5 -0
  44. package/skills/temporal-architect-design/reference/anti-patterns.md +332 -0
  45. package/skills/temporal-architect-design/reference/common-errors.md +88 -0
  46. package/skills/temporal-architect-design/reference/core-principles.md +52 -0
  47. package/skills/temporal-architect-design/reference/design-checklist.md +59 -0
  48. package/skills/temporal-architect-design/reference/namespaces.md +84 -0
  49. package/skills/temporal-architect-design/reference/notation-examples.md +304 -0
  50. package/skills/temporal-architect-design/reference/notation-reference.md +70 -0
  51. package/skills/temporal-architect-design/reference/primitives-reference.md +65 -0
  52. package/skills/temporal-architect-design/reference/project-discovery-subagent.md +80 -0
  53. package/skills/temporal-architect-design/reference/reverse-engineering.md +53 -0
  54. package/skills/temporal-architect-design/reference/twf-conventions.md +43 -0
  55. package/skills/temporal-architect-design/reference/workflow-boundaries.md +43 -0
  56. package/skills/temporal-architect-design/topics/activities-advanced.md +358 -0
  57. package/skills/temporal-architect-design/topics/activities-advanced.twf +107 -0
  58. package/skills/temporal-architect-design/topics/child-workflows.md +347 -0
  59. package/skills/temporal-architect-design/topics/child-workflows.twf +171 -0
  60. package/skills/temporal-architect-design/topics/long-running.md +230 -0
  61. package/skills/temporal-architect-design/topics/long-running.twf +100 -0
  62. package/skills/temporal-architect-design/topics/nexus.md +248 -0
  63. package/skills/temporal-architect-design/topics/nexus.twf +148 -0
  64. package/skills/temporal-architect-design/topics/patterns.md +469 -0
  65. package/skills/temporal-architect-design/topics/patterns.twf +346 -0
  66. package/skills/temporal-architect-design/topics/promises-conditions.md +179 -0
  67. package/skills/temporal-architect-design/topics/promises-conditions.twf +213 -0
  68. package/skills/temporal-architect-design/topics/signals-queries-updates.md +319 -0
  69. package/skills/temporal-architect-design/topics/signals-queries-updates.twf +234 -0
  70. package/skills/temporal-architect-design/topics/task-queues.md +205 -0
  71. package/skills/temporal-architect-design/topics/task-queues.twf +184 -0
  72. package/skills/temporal-architect-design/topics/testing.md +437 -0
  73. package/skills/temporal-architect-design/topics/testing.twf +177 -0
  74. package/skills/temporal-architect-design/topics/timers-scheduling.md +131 -0
  75. package/skills/temporal-architect-design/topics/timers-scheduling.twf +129 -0
  76. package/skills/temporal-architect-design/topics/versioning.md +434 -0
  77. package/skills/temporal-architect-design/topics/versioning.twf +174 -0
@@ -0,0 +1,234 @@
1
+ # Source: signals-queries-updates.md
2
+ # Patterns: signal/query/update declarations, watch blocks, approval flows
3
+
4
+ # --- Signal-driven order workflow ---
5
+
6
+ workflow OrderTrackingWorkflow(orderId: string) -> (OrderResult):
7
+ signal PaymentReceived(transactionId: string, amount: decimal):
8
+ status = "payment_received"
9
+ lastTransactionId = transactionId
10
+
11
+ query GetStatus() -> (string):
12
+ return status
13
+
14
+ query GetProgress() -> (Progress):
15
+ return Progress{status: status, orderId: orderId}
16
+
17
+ activity LoadOrderRecord(orderId) -> order
18
+
19
+ status = "validating"
20
+ activity ValidateOrderRecord(order)
21
+
22
+ status = "awaiting_payment"
23
+
24
+ # Wait for payment signal with timeout
25
+ await one:
26
+ signal PaymentReceived:
27
+ status = "completed"
28
+ close complete(OrderResult{status: "completed"})
29
+ timer(24h):
30
+ status = "payment_timeout"
31
+ close fail(OrderResult{status: "payment_timeout"})
32
+
33
+ # --- Approval flow with multi-target await ---
34
+
35
+ workflow ApprovalWorkflow(request: Request) -> (Decision):
36
+ signal Approved(approver: string):
37
+ approved = true
38
+ approver_name = approver
39
+
40
+ signal Rejected(approver: string, reason: string):
41
+ rejected = true
42
+ reject_reason = reason
43
+
44
+ approved = false
45
+ rejected = false
46
+ approver_name = ""
47
+ reject_reason = ""
48
+
49
+ activity NotifyApprovers(request)
50
+
51
+ # Wait for either Approved or Rejected signal, or timeout
52
+ await one:
53
+ signal Approved:
54
+ close complete(Decision{status: "approved", approver: approver_name})
55
+ signal Rejected:
56
+ close fail(Decision{status: "rejected", reason: reject_reason})
57
+ timer(7d):
58
+ activity NotifyExpired(request)
59
+ close fail(Decision{status: "expired"})
60
+
61
+ # --- Batch collector with signal accumulation ---
62
+
63
+ workflow BatchCollector(batchId: string) -> (BatchResult):
64
+ signal AddItem(item: Item):
65
+ itemCount = itemCount + 1
66
+
67
+ signal CompleteBatch():
68
+ completed = true
69
+
70
+ itemCount = 0
71
+ completed = false
72
+
73
+ for:
74
+ await one:
75
+ signal CompleteBatch:
76
+ break
77
+ timer(1h):
78
+ break
79
+
80
+ activity RunBatchProcessing(batchId, itemCount) -> result
81
+ close complete(BatchResult{itemCount: itemCount, result: result})
82
+
83
+ # --- Update-driven subscription workflow ---
84
+ # Updates are read-write: caller sends data and blocks for a result.
85
+
86
+ workflow SubscriptionWorkflow(userId: string):
87
+ signal Cancel():
88
+ cancelled = true
89
+
90
+ # Simple update: immediate state mutation + return
91
+ update AddCredits(amount: int) -> (CreditResult):
92
+ credits = credits + amount
93
+ return CreditResult{total: credits}
94
+
95
+ # Update with activity: validates before mutating, caller blocks for the full round-trip
96
+ update ChangePlan(newPlan: string) -> (ChangeResult):
97
+ activity ValidatePlan(newPlan) -> validation
98
+ if (validation.valid):
99
+ plan = newPlan
100
+ return ChangeResult{success: true, plan: plan}
101
+ else:
102
+ return ChangeResult{success: false, error: validation.reason}
103
+
104
+ query GetPlan() -> (string):
105
+ return plan
106
+
107
+ plan = "free"
108
+ credits = 0
109
+ cancelled = false
110
+
111
+ for:
112
+ await one:
113
+ signal Cancel:
114
+ break
115
+ timer(30d):
116
+ activity BillUser(userId, plan)
117
+
118
+ close complete
119
+
120
+ # --- Shipping workflow: update racing in await one ---
121
+ # Shows update as an await one case competing with a timer.
122
+
123
+ workflow ShippingWorkflow(orderId: string) -> (ShipResult):
124
+ update ChangeAddress(newAddress: Address) -> (AddressResult):
125
+ address = newAddress
126
+ return AddressResult{updated: true}
127
+
128
+ query GetAddress() -> (Address):
129
+ return address
130
+
131
+ activity LoadOrderRecord(orderId) -> order
132
+ address = order.shippingAddress
133
+
134
+ # Race: accept address changes until the cutoff window closes
135
+ await one:
136
+ update ChangeAddress:
137
+ activity NotifyShippingUpdate(orderId, address)
138
+ timer(1h):
139
+ activity FinalizeShipping(orderId, address)
140
+
141
+ activity Ship(orderId, address) -> shipment
142
+ close complete(ShipResult{shipment: shipment})
143
+
144
+ # --- Update handler waiting on condition ---
145
+ # Shows the condition + update handler pattern where the caller blocks
146
+ # until the condition is set by the main workflow body.
147
+
148
+ workflow JobCoordinator(config: JobConfig):
149
+ state:
150
+ condition jobReady
151
+
152
+ signal Shutdown():
153
+ shutdownRequested = true
154
+
155
+ update WaitUntilReady() -> (JobState):
156
+ await jobReady
157
+ return JobState{ready: true}
158
+
159
+ query GetStatus() -> (string):
160
+ return status
161
+
162
+ status = "provisioning"
163
+ activity ProvisionJobRunner(config)
164
+ activity StartJobRunner(config)
165
+ set jobReady
166
+ status = "running"
167
+
168
+ await signal Shutdown
169
+ close complete
170
+
171
+ # --- Supporting activities ---
172
+
173
+ activity LoadOrderRecord(orderId: string) -> (Order):
174
+ return db.get(orderId)
175
+
176
+ activity ValidateOrderRecord(order: Order):
177
+ validate(order)
178
+
179
+ activity NotifyApprovers(request: Request):
180
+ notify_approvers(request)
181
+
182
+ activity NotifyExpired(request: Request):
183
+ notify_expired(request)
184
+
185
+ activity RunBatchProcessing(batchId: string, count: int) -> (BatchResult):
186
+ return process(batchId, count)
187
+
188
+ activity BillUser(userId: string, plan: string):
189
+ bill(userId, plan)
190
+
191
+ activity ValidatePlan(plan: string) -> (Validation):
192
+ return validate_plan(plan)
193
+
194
+ activity NotifyShippingUpdate(orderId: string, address: Address):
195
+ notify_shipping(orderId, address)
196
+
197
+ activity FinalizeShipping(orderId: string, address: Address):
198
+ finalize(orderId, address)
199
+
200
+ activity Ship(orderId: string, address: Address) -> (Shipment):
201
+ return ship(orderId, address)
202
+
203
+ activity ProvisionJobRunner(config: JobConfig):
204
+ provision(config)
205
+
206
+ activity StartJobRunner(config: JobConfig):
207
+ start(config)
208
+
209
+ # --- Worker and namespace ---
210
+
211
+ worker handlerWorker:
212
+ workflow OrderTrackingWorkflow
213
+ workflow ApprovalWorkflow
214
+ workflow BatchCollector
215
+ workflow SubscriptionWorkflow
216
+ workflow ShippingWorkflow
217
+ workflow JobCoordinator
218
+ activity LoadOrderRecord
219
+ activity ValidateOrderRecord
220
+ activity NotifyApprovers
221
+ activity NotifyExpired
222
+ activity RunBatchProcessing
223
+ activity BillUser
224
+ activity ValidatePlan
225
+ activity NotifyShippingUpdate
226
+ activity FinalizeShipping
227
+ activity Ship
228
+ activity ProvisionJobRunner
229
+ activity StartJobRunner
230
+
231
+ namespace handlers:
232
+ worker handlerWorker
233
+ options:
234
+ task_queue: "handlers"
@@ -0,0 +1,205 @@
1
+ # Workers, Task Queues, and Deployment Topology
2
+
3
+ > **Example:** [`task-queues.twf`](./task-queues.twf)
4
+
5
+ Workers group type registrations. Task queues route work to workers. Namespaces instantiate workers with deployment options. Together they answer: **what runs together, how work reaches it, and where it's deployed.**
6
+
7
+ ---
8
+
9
+ ## Worker Type Sets
10
+
11
+ Workers are reusable type sets that list which workflows, activities, and nexus services belong together:
12
+
13
+ ```twf
14
+ worker orderTypes:
15
+ workflow ProcessOrder
16
+ workflow CancelOrder
17
+ activity ChargePayment
18
+ activity SendNotification
19
+
20
+ worker paymentTypes:
21
+ activity ChargePayment
22
+ activity GetPaymentStatus
23
+ nexus service PaymentService
24
+ ```
25
+
26
+ Workers contain only type references — no deployment config. Naming: `lowerCamelCase`.
27
+
28
+ ---
29
+
30
+ ## Namespace Instantiation
31
+
32
+ Namespaces instantiate workers with deployment options (task queue, versioning strategy, and more — see [Worker Options](#worker-options) below) and expose nexus endpoints for external callers:
33
+
34
+ ```twf
35
+ namespace ecommerce:
36
+ worker orderTypes
37
+ options:
38
+ task_queue: "orderProcessing"
39
+ max_concurrent_activity_executions: 50
40
+ worker paymentTypes
41
+ options:
42
+ task_queue: "payments"
43
+ # Nexus endpoint lives in the target namespace alongside the worker that serves it.
44
+ # External callers in other namespaces reach PaymentService via this endpoint.
45
+ nexus endpoint PaymentEndpoint
46
+ options:
47
+ task_queue: "payments"
48
+ ```
49
+
50
+ The same worker type set can be reused across namespaces:
51
+
52
+ ```twf
53
+ namespace staging:
54
+ worker orderTypes
55
+ options:
56
+ task_queue: "staging-orders"
57
+ ```
58
+
59
+ ### Worker Options
60
+
61
+ The worker `options:` block is the **union of SDK worker options**, accepted *permissively* — the parser does no per-language validation, so an option a given SDK lacks is still allowed. Use it to express **strategy and intent at design altitude**, not exhaustive numeric ops tuning (exact poller counts and cache TTLs belong in implementation):
62
+
63
+ - **`task_queue`** (required) — routing; pins the worker pool.
64
+ - **`versioning: none | build_id | deployment`** — the worker-versioning *strategy* a pool follows (see [versioning.md](./versioning.md#declaring-the-strategy-in-twf)). A reliability/availability decision the design should make; concrete Build IDs / deployment names are deploy-time inputs, not `.twf` content.
65
+ - **`enable_sessions`** — a genuine design call: sessions pin a sequence of activities to one worker (host-affinity for stateful or resource-bound work), distinct from numeric tuning.
66
+ - **Concurrency caps and rate limiters** (`max_concurrent_*`, `*_rate_limit`, sticky cache) are part of the union but are ops tuning — include them only when a workload demands it; the design agent generally should not hand-set them.
67
+
68
+ The full key list lives in the spec — run `twf spec` or see [`tools/spec/sections/03-workers-and-namespaces.md`](../../../tools/spec/sections/03-workers-and-namespaces.md) — rather than being duplicated here (avoids drift, keeps the design at altitude).
69
+
70
+ ### Nexus Endpoints in Namespaces
71
+
72
+ A `nexus endpoint` in a namespace declaration exposes a nexus service to callers in other namespaces. The endpoint's `task_queue` must match the queue where a worker with that nexus service is running. See [nexus.md](./nexus.md) for the full cross-namespace pattern.
73
+
74
+ ### What the Resolver Validates
75
+
76
+ - **Undefined references** — Catch typos (e.g., referencing a workflow or worker that doesn't exist)
77
+ - **Coverage gaps** — Warn when a defined workflow/activity isn't registered on any instantiated worker
78
+ - **Task queue coherence** — Error when different workers on the same queue register different type sets
79
+ - **Missing configuration** — Error when a worker instantiation is missing the required `task_queue` option
80
+
81
+ ### Rules
82
+
83
+ - Workers contain only `workflow`, `activity`, and `nexus service` entries (type set only, no deployment config)
84
+ - Each worker instantiation in a namespace requires a `task_queue` option
85
+ - Worker names use lowerCamelCase; workflow/activity names keep UpperCamelCase
86
+ - Multiple workers can be instantiated on the same task queue (but must register the same type sets)
87
+ - Workers not instantiated in any namespace produce warnings
88
+
89
+ ---
90
+
91
+ ## Task Queue Design Decisions
92
+
93
+ ### Single vs Multiple Task Queues
94
+
95
+ | Single Queue | Multiple Queues |
96
+ |--------------|-----------------|
97
+ | Simple deployment | More operational complexity |
98
+ | All workers handle all work | Workers specialize |
99
+ | Scaling affects everything | Scale queues independently |
100
+ | One failure domain | Isolated failure domains |
101
+
102
+ ### When to Use Separate Task Queues
103
+
104
+ > **Different runtimes do not require different namespaces — use task queues.** GPU workers, licensed-software workers, region-specific workers, and bursty-vs-steady workloads are all *task queue* concerns within a single namespace. Reaching for a namespace per runtime is the misconception that produces namespace-per-worker. See [namespaces.md](../reference/namespaces.md) — the default namespace count is one.
105
+
106
+ | Use Case | Rationale |
107
+ |----------|-----------|
108
+ | **Different resource requirements** | CPU-heavy vs I/O-heavy work |
109
+ | **Different scaling characteristics** | Bursty vs steady workloads |
110
+ | **Isolation requirements** | Tenant isolation, security boundaries |
111
+ | **Priority handling** | High-priority vs batch processing |
112
+ | **Geographic distribution** | Region-specific workers |
113
+ | **Specialized capabilities** | GPU workers, licensed software |
114
+
115
+ ---
116
+
117
+ ## Task Queue Patterns
118
+
119
+ ### Priority Queues
120
+
121
+ Separate queues for different priorities:
122
+
123
+ ```twf
124
+ workflow OrderWorkflow(order: Order) -> (Result):
125
+ if (order.priority == "express"):
126
+ activity ProcessOrder(order)
127
+ options:
128
+ task_queue: "high-priority"
129
+ else:
130
+ activity ProcessOrder(order)
131
+ options:
132
+ task_queue: "standard"
133
+ ```
134
+
135
+ ### Tenant Isolation
136
+
137
+ Separate queues per tenant:
138
+
139
+ ```twf
140
+ workflow TenantWorkflow(tenantId: string, data: Data) -> (Result):
141
+ # Route to tenant-specific queue
142
+ activity ProcessData(data)
143
+ options:
144
+ task_queue: "tenant-{tenantId}"
145
+ ```
146
+
147
+ ### Capability-Based Routing
148
+
149
+ Route based on required capabilities:
150
+
151
+ ```twf
152
+ workflow MediaWorkflow(media: Media) -> (Result):
153
+ if (media.type == "video"):
154
+ # Needs GPU workers
155
+ activity TranscodeVideo(media)
156
+ options:
157
+ task_queue: "gpu-workers"
158
+ else:
159
+ activity ProcessImage(media)
160
+ options:
161
+ task_queue: "standard-workers"
162
+ ```
163
+
164
+ ### Geographic Routing
165
+
166
+ Route to region-specific workers:
167
+
168
+ ```twf
169
+ workflow GlobalWorkflow(request: Request) -> (Result):
170
+ # Route to nearest region
171
+ activity ProcessLocally(request)
172
+ options:
173
+ task_queue: "workers-{request.region}"
174
+ ```
175
+
176
+ ---
177
+
178
+ ## Anti-Patterns
179
+
180
+ ### One Queue Per Workflow Type
181
+
182
+ ```twf
183
+ # BAD: Unnecessary complexity — one queue per type
184
+ # Results in many queues, complex deployment
185
+
186
+ # GOOD: Shared queue unless isolation needed
187
+ # Put related workflows on the same worker and task queue
188
+ ```
189
+
190
+ ### Dynamic Queue Names Without Cleanup
191
+
192
+ ```twf
193
+ # BAD: Creates queue per request (never cleaned up)
194
+ workflow Process(requestId: string):
195
+ activity DoWork()
196
+ options:
197
+ task_queue: "request-{requestId}" # Unbounded queues!
198
+
199
+ # GOOD: Bounded set of queues
200
+ workflow Process(request: Request):
201
+ queue = selectQueue(request.priority) # "high", "medium", "low"
202
+ activity DoWork()
203
+ options:
204
+ task_queue: queue
205
+ ```
@@ -0,0 +1,184 @@
1
+ # Workers, task queues, and deployment topology
2
+ # Demonstrates: worker type sets, namespace instantiation, explicit routing, capability-based queues
3
+
4
+ # --- Explicit routing + implicit inheritance ---
5
+
6
+ workflow OrderWorkflow(order: Order) -> (Result):
7
+ # Implicit: inherits OrderWorkflow's queue ("orders")
8
+ activity ValidateOrder(order) -> validated
9
+
10
+ # Explicit: route to dedicated payment workers
11
+ activity ChargePayment(order) -> payment
12
+ options:
13
+ task_queue: "payments"
14
+
15
+ # Explicit: conditional routing by shipping priority
16
+ if (order.priority == "express"):
17
+ activity ShipOrder(order, payment) -> shipment
18
+ options:
19
+ task_queue: "shipping-express"
20
+ else:
21
+ activity ShipOrder(order, payment) -> shipment
22
+ options:
23
+ task_queue: "shipping-standard"
24
+
25
+ close complete(Result{shipment})
26
+
27
+ # --- Capability-based routing ---
28
+
29
+ workflow MediaPipeline(media: Media) -> (Result):
30
+ # Explicit: route to GPU-capable workers
31
+ activity TranscodeVideo(media) -> transcoded
32
+ options:
33
+ task_queue: "gpu-transcode"
34
+ start_to_close_timeout: 10m
35
+
36
+ # Implicit: inherits MediaPipeline's queue ("media")
37
+ activity GenerateThumbnail(transcoded) -> thumb
38
+
39
+ close complete(Result{thumb})
40
+
41
+ # --- Activities ---
42
+
43
+ activity ValidateOrder(order: Order) -> (ValidationResult):
44
+ return validate(order)
45
+
46
+ activity ChargePayment(order: Order) -> (Payment):
47
+ return charge(order)
48
+
49
+ activity ShipOrder(order: Order, payment: Payment) -> (Shipment):
50
+ return ship(order)
51
+
52
+ activity TranscodeVideo(media: Media) -> (TranscodeResult):
53
+ heartbeat(media.progress)
54
+ return transcode(media)
55
+
56
+ activity GenerateThumbnail(video: Video) -> (Thumbnail):
57
+ return thumbnail(video)
58
+
59
+ # --- Nexus services (exposed for external callers in other namespaces) ---
60
+
61
+ # PaymentService: registered on paymentWorker, exposed via PaymentEndpoint in ecommerce namespace.
62
+ # External callers (e.g., partner namespace below) reach it cross-namespace via the endpoint.
63
+ nexus service PaymentService:
64
+ sync CheckPaymentStatus(paymentId: string) -> (PaymentStatus):
65
+ activity GetPaymentStatus(paymentId) -> status
66
+ close complete(status)
67
+
68
+ # AnalyticsService: independent scaling on its own worker, same cross-namespace exposure pattern.
69
+ nexus service AnalyticsService:
70
+ async TrackEvent workflow TrackEventWorkflow
71
+
72
+ activity GetPaymentStatus(paymentId: string) -> (PaymentStatus):
73
+ return lookup(paymentId)
74
+
75
+ workflow TrackEventWorkflow(event: Event):
76
+ activity RecordEvent(event)
77
+ close complete
78
+
79
+ activity RecordEvent(event: Event):
80
+ record(event)
81
+
82
+ # --- Workers ---
83
+
84
+ worker orderWorker:
85
+ workflow OrderWorkflow
86
+ activity ValidateOrder
87
+
88
+ worker paymentWorker:
89
+ activity ChargePayment
90
+ activity GetPaymentStatus
91
+ nexus service PaymentService
92
+
93
+ worker analyticsWorker:
94
+ workflow TrackEventWorkflow
95
+ activity RecordEvent
96
+ nexus service AnalyticsService
97
+
98
+ worker expressShipWorker:
99
+ activity ShipOrder
100
+
101
+ worker standardShipWorker:
102
+ activity ShipOrder
103
+
104
+ # Tiered registration: a workflow or nexus service hosted on multiple
105
+ # workers, each on its OWN task queue (same pattern as expressShipWorker
106
+ # / standardShipWorker above). The registered type set is shared across
107
+ # the tier so the caller picks behaviour by routing to the right queue —
108
+ # realtime vs batch analytics here, primary vs DR-region payments below.
109
+ worker realtimeAnalyticsWorker:
110
+ workflow TrackEventWorkflow
111
+ activity RecordEvent
112
+
113
+ worker paymentWorkerSecondary:
114
+ activity ChargePayment
115
+ activity GetPaymentStatus
116
+ nexus service PaymentService
117
+
118
+ worker mediaWorker:
119
+ workflow MediaPipeline
120
+ activity GenerateThumbnail
121
+
122
+ worker gpuWorker:
123
+ activity TranscodeVideo
124
+
125
+ # --- Namespaces ---
126
+
127
+ namespace ecommerce:
128
+ worker orderWorker
129
+ options:
130
+ task_queue: "orders"
131
+ worker paymentWorker
132
+ options:
133
+ task_queue: "payments"
134
+ # Same registered type set as paymentWorker, on its own queue —
135
+ # callers route by region by picking the destination task queue.
136
+ worker paymentWorkerSecondary
137
+ options:
138
+ task_queue: "payments-secondary"
139
+ worker expressShipWorker
140
+ options:
141
+ task_queue: "shipping-express"
142
+ worker standardShipWorker
143
+ options:
144
+ task_queue: "shipping-standard"
145
+ # Endpoints live in the target namespace (ecommerce) alongside the workers that serve them.
146
+ # External callers in other namespaces (e.g., partner) reach these services cross-namespace.
147
+ nexus endpoint PaymentEndpoint
148
+ options:
149
+ task_queue: "payments"
150
+ worker analyticsWorker
151
+ options:
152
+ task_queue: "analytics"
153
+ # Same registered type set as analyticsWorker, on its own queue —
154
+ # callers pick the realtime tier by dispatching to this queue.
155
+ worker realtimeAnalyticsWorker
156
+ options:
157
+ task_queue: "analytics-realtime"
158
+ nexus endpoint AnalyticsEndpoint
159
+ options:
160
+ task_queue: "analytics"
161
+
162
+ namespace media:
163
+ worker mediaWorker
164
+ options:
165
+ task_queue: "media"
166
+ worker gpuWorker
167
+ options:
168
+ task_queue: "gpu-transcode"
169
+
170
+ # --- Cross-namespace caller ---
171
+ # A partner service in a separate namespace reaches into ecommerce via Nexus endpoints.
172
+
173
+ workflow PartnerCheckout(request: PartnerRequest) -> (PartnerResult):
174
+ nexus PaymentEndpoint PaymentService.CheckPaymentStatus(request.paymentId) -> status
175
+ detach nexus AnalyticsEndpoint AnalyticsService.TrackEvent(request.event)
176
+ close complete(PartnerResult{status: status})
177
+
178
+ worker partnerWorker:
179
+ workflow PartnerCheckout
180
+
181
+ namespace partner:
182
+ worker partnerWorker
183
+ options:
184
+ task_queue: "partner"