nestjs-temporal-core 2.0.3 → 2.0.5
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 +407 -231
- package/dist/client/index.js.map +1 -1
- package/dist/client/temporal-client.module.js +12 -5
- package/dist/client/temporal-client.module.js.map +1 -1
- package/dist/client/temporal-client.service.d.ts +8 -1
- package/dist/client/temporal-client.service.js +90 -4
- package/dist/client/temporal-client.service.js.map +1 -1
- package/dist/constants.d.ts +57 -8
- package/dist/constants.js +51 -9
- package/dist/constants.js.map +1 -1
- package/dist/decorators/activity-method.decorator.d.ts +1 -7
- package/dist/decorators/activity-method.decorator.js +2 -2
- package/dist/decorators/activity-method.decorator.js.map +1 -1
- package/dist/decorators/activity.decorator.d.ts +1 -4
- package/dist/decorators/activity.decorator.js.map +1 -1
- package/dist/decorators/index.d.ts +5 -0
- package/dist/decorators/index.js +5 -0
- package/dist/decorators/index.js.map +1 -1
- package/dist/decorators/query.decorator.d.ts +2 -0
- package/dist/decorators/query.decorator.js +26 -0
- package/dist/decorators/query.decorator.js.map +1 -0
- package/dist/decorators/scheduled-workflow.decorator.d.ts +13 -0
- package/dist/decorators/scheduled-workflow.decorator.js +31 -0
- package/dist/decorators/scheduled-workflow.decorator.js.map +1 -0
- package/dist/decorators/signal.decorator.d.ts +2 -0
- package/dist/decorators/signal.decorator.js +26 -0
- package/dist/decorators/signal.decorator.js.map +1 -0
- package/dist/decorators/update.decorator.d.ts +2 -0
- package/dist/decorators/update.decorator.js +34 -0
- package/dist/decorators/update.decorator.js.map +1 -0
- package/dist/decorators/workflow-method.decorator.d.ts +2 -0
- package/dist/decorators/workflow-method.decorator.js +29 -0
- package/dist/decorators/workflow-method.decorator.js.map +1 -0
- package/dist/decorators/workflow.decorator.d.ts +2 -16
- package/dist/decorators/workflow.decorator.js +1 -0
- package/dist/decorators/workflow.decorator.js.map +1 -1
- package/dist/index.d.ts +10 -4
- package/dist/index.js +43 -4
- package/dist/index.js.map +1 -1
- package/dist/interfaces/activity.interface.d.ts +21 -0
- package/dist/interfaces/activity.interface.js +3 -0
- package/dist/interfaces/activity.interface.js.map +1 -0
- package/dist/interfaces/base.interface.d.ts +10 -1
- package/dist/interfaces/client.interface.d.ts +19 -3
- package/dist/interfaces/client.interface.js +11 -0
- package/dist/interfaces/client.interface.js.map +1 -1
- package/dist/interfaces/index.d.ts +8 -0
- package/dist/interfaces/index.js +17 -0
- package/dist/interfaces/index.js.map +1 -1
- package/dist/interfaces/schedule.interface.d.ts +40 -0
- package/dist/interfaces/schedule.interface.js +3 -0
- package/dist/interfaces/schedule.interface.js.map +1 -0
- package/dist/interfaces/worker.interface.d.ts +21 -5
- package/dist/interfaces/workflow.interface.d.ts +26 -0
- package/dist/interfaces/workflow.interface.js +3 -0
- package/dist/interfaces/workflow.interface.js.map +1 -0
- package/dist/schedule/index.d.ts +2 -0
- package/dist/schedule/index.js +19 -0
- package/dist/schedule/index.js.map +1 -0
- package/dist/schedule/temporal-schedule.module.d.ts +7 -0
- package/dist/schedule/temporal-schedule.module.js +94 -0
- package/dist/schedule/temporal-schedule.module.js.map +1 -0
- package/dist/schedule/temporal-schedule.service.d.ts +26 -0
- package/dist/schedule/temporal-schedule.service.js +210 -0
- package/dist/schedule/temporal-schedule.service.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/worker/temporal-metadata.accessor.d.ts +2 -0
- package/dist/worker/temporal-metadata.accessor.js +12 -0
- package/dist/worker/temporal-metadata.accessor.js.map +1 -1
- package/dist/worker/worker-manager.service.d.ts +3 -2
- package/dist/worker/worker-manager.service.js +50 -12
- package/dist/worker/worker-manager.service.js.map +1 -1
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -2,22 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
A robust NestJS integration for [Temporal.io](https://temporal.io/) that provides seamless worker and client support for building reliable distributed applications.
|
|
4
4
|
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
NestJS Temporal Core simplifies building fault-tolerant, long-running processes in your NestJS applications by integrating with Temporal.io - a durable execution system for reliable microservices and workflow orchestration.
|
|
8
|
+
|
|
5
9
|
## Features
|
|
6
10
|
|
|
7
|
-
- 🚀 Easy
|
|
8
|
-
- 🔄 Automatic worker initialization and shutdown
|
|
9
|
-
- 🎯 Declarative
|
|
10
|
-
- 🔌 Built-in connection
|
|
11
|
-
-
|
|
12
|
-
- 📡
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
- 📣 Signal handling
|
|
20
|
-
- 🚦 Workflow retry policies
|
|
11
|
+
- 🚀 **Easy NestJS Integration** - Register modules with sync/async configuration
|
|
12
|
+
- 🔄 **Complete Lifecycle Management** - Automatic worker initialization and graceful shutdown
|
|
13
|
+
- 🎯 **Declarative Decorators** - Type-safe `@Activity()`, `@Workflow()`, `@Signal()`, `@Query()`, and `@Update()` decorators
|
|
14
|
+
- 🔌 **Connection Management** - Built-in connection handling with TLS support
|
|
15
|
+
- 🔒 **Type Safety** - Strongly typed interfaces for all Temporal concepts
|
|
16
|
+
- 📡 **Client Operation Utilities** - Methods for starting, signaling, querying, updating and managing workflows
|
|
17
|
+
- 📊 **Monitoring Support** - Worker status tracking and metrics
|
|
18
|
+
- 📅 **Scheduling** - Native support for cron and interval-based workflow scheduling
|
|
19
|
+
- 🔍 **Queries and Signals** - First-class support for Temporal's query and signal patterns
|
|
20
|
+
- 🆕 **Updates** - Support for Temporal's workflow update functionality
|
|
21
|
+
- 🔢 **Versioning** - Support for Temporal worker versioning
|
|
22
|
+
- 🚦 **Advanced Policies** - Built-in retry, timeout, and workflow management policies
|
|
21
23
|
|
|
22
24
|
## Installation
|
|
23
25
|
|
|
@@ -33,54 +35,41 @@ First, make sure to enable shutdown hooks in your `main.ts` file:
|
|
|
33
35
|
|
|
34
36
|
```typescript
|
|
35
37
|
async function bootstrap() {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
const app = await NestFactory.create(AppModule);
|
|
39
|
+
app.enableShutdownHooks();
|
|
40
|
+
await app.listen(3000);
|
|
39
41
|
}
|
|
40
42
|
bootstrap();
|
|
41
43
|
```
|
|
42
44
|
|
|
43
|
-
### 2. Register the
|
|
45
|
+
### 2. Register the Modules
|
|
44
46
|
|
|
45
47
|
```typescript
|
|
46
48
|
import { Module } from '@nestjs/common';
|
|
47
49
|
import { TemporalWorkerModule, TemporalClientModule } from 'nestjs-temporal-core';
|
|
48
50
|
|
|
49
51
|
@Module({
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
},
|
|
72
|
-
// Optional monitoring configuration
|
|
73
|
-
monitoring: {
|
|
74
|
-
statsIntervalMs: 60000, // Log stats every minute
|
|
75
|
-
},
|
|
76
|
-
}),
|
|
77
|
-
TemporalClientModule.register({
|
|
78
|
-
connection: {
|
|
79
|
-
address: 'localhost:7233',
|
|
80
|
-
},
|
|
81
|
-
namespace: 'default',
|
|
82
|
-
}),
|
|
83
|
-
],
|
|
52
|
+
imports: [
|
|
53
|
+
TemporalWorkerModule.register({
|
|
54
|
+
connection: {
|
|
55
|
+
address: 'localhost:7233',
|
|
56
|
+
},
|
|
57
|
+
namespace: 'default',
|
|
58
|
+
taskQueue: 'my-task-queue',
|
|
59
|
+
workflowsPath: require.resolve('./workflows'),
|
|
60
|
+
activityClasses: [MyActivity],
|
|
61
|
+
autoStart: {
|
|
62
|
+
enabled: true,
|
|
63
|
+
delayMs: 1000, // Start worker after 1 second
|
|
64
|
+
},
|
|
65
|
+
}),
|
|
66
|
+
TemporalClientModule.register({
|
|
67
|
+
connection: {
|
|
68
|
+
address: 'localhost:7233',
|
|
69
|
+
},
|
|
70
|
+
namespace: 'default',
|
|
71
|
+
}),
|
|
72
|
+
],
|
|
84
73
|
})
|
|
85
74
|
export class AppModule {}
|
|
86
75
|
```
|
|
@@ -91,26 +80,26 @@ export class AppModule {}
|
|
|
91
80
|
import { Activity, ActivityMethod } from 'nestjs-temporal-core';
|
|
92
81
|
|
|
93
82
|
@Activity({
|
|
94
|
-
|
|
95
|
-
|
|
83
|
+
name: 'PaymentActivities', // Optional custom name
|
|
84
|
+
description: 'Activities for payment processing',
|
|
96
85
|
})
|
|
97
86
|
export class PaymentActivity {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
87
|
+
@ActivityMethod({
|
|
88
|
+
name: 'processPayment', // Optional custom name
|
|
89
|
+
timeout: {
|
|
90
|
+
startToClose: '30s',
|
|
91
|
+
},
|
|
92
|
+
})
|
|
93
|
+
async processPayment(amount: number): Promise<string> {
|
|
94
|
+
// Implementation
|
|
95
|
+
return 'payment-id';
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
@ActivityMethod()
|
|
99
|
+
async refundPayment(paymentId: string): Promise<boolean> {
|
|
100
|
+
// Implementation
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
114
103
|
}
|
|
115
104
|
```
|
|
116
105
|
|
|
@@ -120,16 +109,17 @@ export class PaymentActivity {
|
|
|
120
109
|
import { proxyActivities } from '@temporalio/workflow';
|
|
121
110
|
import type { PaymentActivity } from './payment.activity';
|
|
122
111
|
|
|
112
|
+
// Reference activities in your workflow
|
|
123
113
|
const { processPayment, refundPayment } = proxyActivities<PaymentActivity>({
|
|
124
|
-
|
|
114
|
+
startToCloseTimeout: '30 seconds',
|
|
125
115
|
});
|
|
126
116
|
|
|
127
117
|
export async function paymentWorkflow(amount: number): Promise<string> {
|
|
128
|
-
|
|
118
|
+
return await processPayment(amount);
|
|
129
119
|
}
|
|
130
120
|
|
|
131
121
|
export async function refundWorkflow(paymentId: string): Promise<boolean> {
|
|
132
|
-
|
|
122
|
+
return await refundPayment(paymentId);
|
|
133
123
|
}
|
|
134
124
|
```
|
|
135
125
|
|
|
@@ -141,37 +131,192 @@ import { TemporalClientService } from 'nestjs-temporal-core';
|
|
|
141
131
|
|
|
142
132
|
@Injectable()
|
|
143
133
|
export class PaymentService {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
134
|
+
constructor(private readonly temporalClient: TemporalClientService) {}
|
|
135
|
+
|
|
136
|
+
async initiatePayment(amount: number) {
|
|
137
|
+
const { result, workflowId } = await this.temporalClient.startWorkflow<string, [number]>(
|
|
138
|
+
'paymentWorkflow',
|
|
139
|
+
[amount],
|
|
140
|
+
{
|
|
141
|
+
taskQueue: 'my-task-queue',
|
|
142
|
+
workflowExecutionTimeout: '1h',
|
|
143
|
+
workflowTaskTimeout: '10s',
|
|
144
|
+
retry: {
|
|
145
|
+
maximumAttempts: 3,
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
// Wait for the workflow to complete
|
|
151
|
+
const paymentId = await result;
|
|
152
|
+
|
|
153
|
+
return { paymentId, workflowId };
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async checkPaymentStatus(workflowId: string) {
|
|
157
|
+
// Query a running workflow
|
|
158
|
+
return await this.temporalClient.queryWorkflow<string>(workflowId, 'getPaymentStatus');
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async cancelPayment(workflowId: string, reason: string) {
|
|
162
|
+
// Signal a running workflow
|
|
163
|
+
await this.temporalClient.signalWorkflow(workflowId, 'cancelPayment', [reason]);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Advanced Features
|
|
169
|
+
|
|
170
|
+
### Class-Based Workflows with Queries, Signals, and Updates
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
import { Workflow, WorkflowMethod, Query, Signal, Update } from 'nestjs-temporal-core';
|
|
174
|
+
|
|
175
|
+
@Workflow({
|
|
176
|
+
taskQueue: 'order-queue',
|
|
177
|
+
workflowExecutionTimeout: '24h',
|
|
178
|
+
})
|
|
179
|
+
export class OrderWorkflow {
|
|
180
|
+
private orderStatus: string = 'PENDING';
|
|
181
|
+
private orderItems: string[] = [];
|
|
182
|
+
private cancelReason: string | null = null;
|
|
183
|
+
|
|
184
|
+
@WorkflowMethod()
|
|
185
|
+
async execute(orderId: string): Promise<string> {
|
|
186
|
+
// Workflow implementation
|
|
187
|
+
return this.orderStatus;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
@Query()
|
|
191
|
+
getStatus(): string {
|
|
192
|
+
return this.orderStatus;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
@Signal()
|
|
196
|
+
cancel(reason: string): void {
|
|
197
|
+
this.orderStatus = 'CANCELLED';
|
|
198
|
+
this.cancelReason = reason;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
@Update({
|
|
202
|
+
validator: (items: string[]) => {
|
|
203
|
+
if (items.length === 0) {
|
|
204
|
+
throw new Error('Order must contain at least one item');
|
|
205
|
+
}
|
|
156
206
|
},
|
|
157
|
-
|
|
158
|
-
)
|
|
207
|
+
})
|
|
208
|
+
updateItems(items: string[]): string[] {
|
|
209
|
+
this.orderItems = items;
|
|
210
|
+
return this.orderItems;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
```
|
|
159
214
|
|
|
160
|
-
|
|
161
|
-
const paymentId = await result;
|
|
215
|
+
### Scheduled Workflows
|
|
162
216
|
|
|
163
|
-
|
|
164
|
-
|
|
217
|
+
```typescript
|
|
218
|
+
import { ScheduledWorkflow, WorkflowMethod } from 'nestjs-temporal-core';
|
|
165
219
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
220
|
+
@ScheduledWorkflow({
|
|
221
|
+
taskQueue: 'scheduled-tasks',
|
|
222
|
+
schedule: {
|
|
223
|
+
cron: '0 0 * * *', // Run daily at midnight
|
|
224
|
+
},
|
|
225
|
+
description: 'Daily reporting workflow',
|
|
226
|
+
})
|
|
227
|
+
export class DailyReportWorkflow {
|
|
228
|
+
@WorkflowMethod()
|
|
229
|
+
async execute(): Promise<void> {
|
|
230
|
+
// Generate and send reports
|
|
231
|
+
}
|
|
232
|
+
}
|
|
170
233
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
234
|
+
@ScheduledWorkflow({
|
|
235
|
+
taskQueue: 'scheduled-tasks',
|
|
236
|
+
schedule: {
|
|
237
|
+
interval: {
|
|
238
|
+
hours: 1, // Run every hour
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
description: 'Hourly data processing',
|
|
242
|
+
})
|
|
243
|
+
export class HourlyProcessingWorkflow {
|
|
244
|
+
@WorkflowMethod()
|
|
245
|
+
async execute(): Promise<void> {
|
|
246
|
+
// Process data hourly
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Using the Schedule Service
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
import { Injectable } from '@nestjs/common';
|
|
255
|
+
import { TemporalScheduleService } from 'nestjs-temporal-core';
|
|
256
|
+
|
|
257
|
+
@Injectable()
|
|
258
|
+
export class ReportingService {
|
|
259
|
+
constructor(private readonly scheduleService: TemporalScheduleService) {}
|
|
260
|
+
|
|
261
|
+
async createDailyReportSchedule() {
|
|
262
|
+
return await this.scheduleService.createCronWorkflow(
|
|
263
|
+
'daily-sales-report',
|
|
264
|
+
'generateSalesReport',
|
|
265
|
+
'0 0 * * *', // Daily at midnight
|
|
266
|
+
'reports-queue',
|
|
267
|
+
[], // No arguments
|
|
268
|
+
'Daily sales report generation',
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
async createHourlyDataBackup() {
|
|
273
|
+
return await this.scheduleService.createIntervalWorkflow(
|
|
274
|
+
'hourly-data-backup',
|
|
275
|
+
'backupData',
|
|
276
|
+
{ hours: 1 },
|
|
277
|
+
'backup-queue',
|
|
278
|
+
[],
|
|
279
|
+
'Hourly data backup process',
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
async pauseReports() {
|
|
284
|
+
await this.scheduleService.pauseSchedule(
|
|
285
|
+
'daily-sales-report',
|
|
286
|
+
'Paused for system maintenance',
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
async listAllSchedules() {
|
|
291
|
+
return await this.scheduleService.listSchedules();
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Using Workflow Updates
|
|
297
|
+
|
|
298
|
+
```typescript
|
|
299
|
+
import { Injectable } from '@nestjs/common';
|
|
300
|
+
import { TemporalClientService } from 'nestjs-temporal-core';
|
|
301
|
+
|
|
302
|
+
@Injectable()
|
|
303
|
+
export class OrderService {
|
|
304
|
+
constructor(private readonly temporalClient: TemporalClientService) {}
|
|
305
|
+
|
|
306
|
+
async updateOrderItems(orderId: string, items: string[]) {
|
|
307
|
+
try {
|
|
308
|
+
// Use the updateWorkflow method to modify a running workflow
|
|
309
|
+
const updatedItems = await this.temporalClient.updateWorkflow<string[]>(
|
|
310
|
+
`order-${orderId}`,
|
|
311
|
+
'updateItems',
|
|
312
|
+
[items],
|
|
313
|
+
);
|
|
314
|
+
|
|
315
|
+
return { success: true, items: updatedItems };
|
|
316
|
+
} catch (error) {
|
|
317
|
+
return { success: false, error: error.message };
|
|
318
|
+
}
|
|
319
|
+
}
|
|
175
320
|
}
|
|
176
321
|
```
|
|
177
322
|
|
|
@@ -179,178 +324,209 @@ export class PaymentService {
|
|
|
179
324
|
|
|
180
325
|
### Async Configuration
|
|
181
326
|
|
|
327
|
+
Use factory patterns for dynamic configuration:
|
|
328
|
+
|
|
182
329
|
```typescript
|
|
183
330
|
TemporalWorkerModule.registerAsync({
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
331
|
+
imports: [ConfigModule],
|
|
332
|
+
useFactory: async (configService: ConfigService) => ({
|
|
333
|
+
connection: {
|
|
334
|
+
address: configService.get('TEMPORAL_ADDRESS'),
|
|
335
|
+
connectionTimeout: configService.get('TEMPORAL_CONNECTION_TIMEOUT', 5000),
|
|
336
|
+
},
|
|
337
|
+
namespace: configService.get('TEMPORAL_NAMESPACE'),
|
|
338
|
+
taskQueue: configService.get('TEMPORAL_TASK_QUEUE'),
|
|
339
|
+
workflowsPath: require.resolve('./workflows'),
|
|
340
|
+
activityClasses: [MyActivity],
|
|
341
|
+
autoStart: {
|
|
342
|
+
enabled: configService.get('TEMPORAL_WORKER_AUTOSTART', true),
|
|
343
|
+
delayMs: configService.get('TEMPORAL_WORKER_START_DELAY', 0),
|
|
344
|
+
},
|
|
345
|
+
allowWorkerFailure: configService.get('TEMPORAL_ALLOW_WORKER_FAILURE', true),
|
|
346
|
+
}),
|
|
347
|
+
inject: [ConfigService],
|
|
201
348
|
});
|
|
202
349
|
```
|
|
203
350
|
|
|
204
351
|
### TLS Configuration
|
|
205
352
|
|
|
353
|
+
Set up secure communications with TLS:
|
|
354
|
+
|
|
206
355
|
```typescript
|
|
207
356
|
TemporalClientModule.register({
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
357
|
+
connection: {
|
|
358
|
+
address: 'temporal.example.com:7233',
|
|
359
|
+
tls: {
|
|
360
|
+
clientCertPair: {
|
|
361
|
+
crt: Buffer.from('...'),
|
|
362
|
+
key: Buffer.from('...'),
|
|
363
|
+
ca: Buffer.from('...'), // Optional CA certificate
|
|
364
|
+
},
|
|
365
|
+
serverName: 'temporal.example.com', // Optional for SNI
|
|
366
|
+
verifyServer: true, // Optional, defaults to true
|
|
367
|
+
},
|
|
368
|
+
connectionTimeout: 10000, // 10 seconds
|
|
218
369
|
},
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
namespace: 'production',
|
|
222
|
-
allowConnectionFailure: true, // Allow application to start if Temporal connection fails
|
|
370
|
+
namespace: 'production',
|
|
371
|
+
allowConnectionFailure: true, // Allow application to start if Temporal connection fails
|
|
223
372
|
});
|
|
224
373
|
```
|
|
225
374
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
### Decorators
|
|
229
|
-
|
|
230
|
-
- `@Activity(options?)`: Marks a class as a Temporal activity with optional configuration
|
|
231
|
-
- `@ActivityMethod(options?)`: Marks a method as a Temporal activity implementation with optional configuration
|
|
232
|
-
- `@Workflow(options)`: Marks a class as a Temporal workflow with configuration
|
|
375
|
+
### Worker Versioning
|
|
233
376
|
|
|
234
|
-
|
|
377
|
+
Enable worker versioning for compatibility management:
|
|
235
378
|
|
|
236
|
-
|
|
379
|
+
```typescript
|
|
380
|
+
TemporalWorkerModule.register({
|
|
381
|
+
// ... other options
|
|
382
|
+
useVersioning: true,
|
|
383
|
+
buildId: 'v1.2.3-20230615', // Unique identifier for this worker's code version
|
|
384
|
+
});
|
|
385
|
+
```
|
|
237
386
|
|
|
238
|
-
|
|
239
|
-
- `signalWorkflow()`: Send a signal to a running workflow
|
|
240
|
-
- `queryWorkflow<T>()`: Query a running workflow
|
|
241
|
-
- `terminateWorkflow()`: Terminate a running workflow
|
|
242
|
-
- `cancelWorkflow()`: Request cancellation of a workflow
|
|
243
|
-
- `getWorkflowHandle()`: Get a handle to manage a workflow
|
|
244
|
-
- `getWorkflowClient()`: Get the underlying workflow client instance
|
|
387
|
+
### Worker Performance Tuning
|
|
245
388
|
|
|
246
|
-
|
|
389
|
+
Optimize worker performance with advanced options:
|
|
247
390
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
391
|
+
```typescript
|
|
392
|
+
TemporalWorkerModule.register({
|
|
393
|
+
// ... other options
|
|
394
|
+
reuseV8Context: true, // Significantly improves performance and reduces memory usage
|
|
395
|
+
maxConcurrentWorkflowTaskExecutions: 40,
|
|
396
|
+
maxConcurrentActivityTaskExecutions: 100,
|
|
397
|
+
maxConcurrentLocalActivityExecutions: 100,
|
|
398
|
+
workflowThreadPoolSize: 4,
|
|
399
|
+
maxActivitiesPerSecond: 50,
|
|
400
|
+
maxCachedWorkflows: 200,
|
|
401
|
+
});
|
|
402
|
+
```
|
|
251
403
|
|
|
252
|
-
###
|
|
404
|
+
### Worker Monitoring
|
|
253
405
|
|
|
254
|
-
|
|
406
|
+
Enable worker monitoring and metrics:
|
|
255
407
|
|
|
256
408
|
```typescript
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
monitoring?: {
|
|
271
|
-
statsIntervalMs?: number;
|
|
272
|
-
metrics?: {
|
|
273
|
-
enabled?: boolean;
|
|
274
|
-
prometheus?: {
|
|
275
|
-
enabled?: boolean;
|
|
276
|
-
port?: number;
|
|
277
|
-
};
|
|
278
|
-
};
|
|
279
|
-
};
|
|
280
|
-
}
|
|
409
|
+
TemporalWorkerModule.register({
|
|
410
|
+
// ... other options
|
|
411
|
+
monitoring: {
|
|
412
|
+
statsIntervalMs: 60000, // Log stats every minute
|
|
413
|
+
metrics: {
|
|
414
|
+
enabled: true,
|
|
415
|
+
prometheus: {
|
|
416
|
+
enabled: true,
|
|
417
|
+
port: 9464,
|
|
418
|
+
},
|
|
419
|
+
},
|
|
420
|
+
},
|
|
421
|
+
});
|
|
281
422
|
```
|
|
282
423
|
|
|
283
|
-
|
|
424
|
+
## API Reference
|
|
284
425
|
|
|
285
|
-
|
|
286
|
-
interface TemporalClientOptions {
|
|
287
|
-
connection: ConnectionOptions;
|
|
288
|
-
namespace?: string;
|
|
289
|
-
allowConnectionFailure?: boolean;
|
|
290
|
-
reconnect?: {
|
|
291
|
-
enabled?: boolean;
|
|
292
|
-
maxAttempts?: number;
|
|
293
|
-
initialDelayMs?: number;
|
|
294
|
-
maxDelayMs?: number;
|
|
295
|
-
backoffCoefficient?: number;
|
|
296
|
-
};
|
|
297
|
-
}
|
|
298
|
-
```
|
|
426
|
+
### Core Modules
|
|
299
427
|
|
|
300
|
-
|
|
428
|
+
- `TemporalClientModule` - Client connectivity for workflow operations
|
|
429
|
+
- `TemporalWorkerModule` - Worker process for running activities and workflows
|
|
430
|
+
- `TemporalScheduleModule` - Scheduling for recurring workflows
|
|
301
431
|
|
|
302
|
-
|
|
303
|
-
interface ActivityMethodOptions {
|
|
304
|
-
name?: string;
|
|
305
|
-
description?: string;
|
|
306
|
-
timeout?: {
|
|
307
|
-
startToClose?: string | number;
|
|
308
|
-
scheduleToStart?: string | number;
|
|
309
|
-
};
|
|
310
|
-
}
|
|
311
|
-
```
|
|
432
|
+
### Decorators
|
|
312
433
|
|
|
313
|
-
|
|
434
|
+
- `@Activity(options?)` - Marks a class as a Temporal activity
|
|
435
|
+
- `@ActivityMethod(options?)` - Marks a method as an activity implementation
|
|
436
|
+
- `@Workflow(options)` - Marks a class as a Temporal workflow
|
|
437
|
+
- `@WorkflowMethod(options?)` - Marks the primary workflow execution method
|
|
438
|
+
- `@Query(options?)` - Marks a method as a query handler
|
|
439
|
+
- `@Signal(options?)` - Marks a method as a signal handler
|
|
440
|
+
- `@Update(options?)` - Marks a method as an update handler
|
|
441
|
+
- `@ScheduledWorkflow(options)` - Defines a workflow with schedule configuration
|
|
314
442
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
443
|
+
### Services
|
|
444
|
+
|
|
445
|
+
#### TemporalClientService
|
|
446
|
+
|
|
447
|
+
- `startWorkflow<T, A>()` - Start a new workflow execution
|
|
448
|
+
- `signalWorkflow()` - Send a signal to a running workflow
|
|
449
|
+
- `queryWorkflow<T>()` - Query a running workflow
|
|
450
|
+
- `updateWorkflow<T>()` - Update a running workflow
|
|
451
|
+
- `terminateWorkflow()` - Terminate a running workflow
|
|
452
|
+
- `cancelWorkflow()` - Request cancellation of a workflow
|
|
453
|
+
- `getWorkflowHandle()` - Get a handle to manage a workflow
|
|
454
|
+
- `describeWorkflow()` - Get workflow execution details
|
|
455
|
+
- `listWorkflows()` - List workflows matching a query
|
|
456
|
+
- `countWorkflows()` - Count workflows matching a query
|
|
457
|
+
- `getWorkflowClient()` - Get the underlying workflow client
|
|
458
|
+
- `getRawClient()` - Get the raw Temporal client
|
|
459
|
+
|
|
460
|
+
#### TemporalScheduleService
|
|
461
|
+
|
|
462
|
+
- `createCronWorkflow()` - Create a workflow scheduled by cron expression
|
|
463
|
+
- `createIntervalWorkflow()` - Create a workflow scheduled by time interval
|
|
464
|
+
- `getSchedule()` - Get a handle to an existing schedule
|
|
465
|
+
- `pauseSchedule()` - Pause a schedule
|
|
466
|
+
- `resumeSchedule()` - Resume a paused schedule
|
|
467
|
+
- `deleteSchedule()` - Delete a schedule
|
|
468
|
+
- `triggerNow()` - Trigger an immediate execution
|
|
469
|
+
- `listSchedules()` - List all schedules
|
|
470
|
+
|
|
471
|
+
#### WorkerManager
|
|
472
|
+
|
|
473
|
+
- `startWorker()` - Manually start the worker
|
|
474
|
+
- `shutdown()` - Gracefully shutdown the worker
|
|
475
|
+
- `getWorker()` - Get the underlying worker instance
|
|
331
476
|
|
|
332
477
|
## Error Handling
|
|
333
478
|
|
|
334
479
|
The module includes comprehensive error handling:
|
|
335
480
|
|
|
336
|
-
- Worker initialization errors are logged and
|
|
481
|
+
- Worker initialization errors are logged and handled based on configuration
|
|
337
482
|
- Client operations include detailed error messages and proper error propagation
|
|
338
|
-
-
|
|
483
|
+
- Activities and workflow errors are properly captured and logged
|
|
339
484
|
- Connection errors are handled gracefully with automatic cleanup
|
|
340
485
|
- Configurable failure modes for both client and worker connections
|
|
486
|
+
- SDK version compatibility checks for feature availability
|
|
341
487
|
|
|
342
488
|
## Best Practices
|
|
343
489
|
|
|
344
|
-
1.
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
490
|
+
1. **Activity Design**
|
|
491
|
+
|
|
492
|
+
- Define activity interfaces for type safety
|
|
493
|
+
- Keep activities focused on single responsibilities
|
|
494
|
+
- Set appropriate timeouts for expected durations
|
|
495
|
+
- Use heartbeats for long-running activities
|
|
496
|
+
|
|
497
|
+
2. **Workflow Design**
|
|
498
|
+
|
|
499
|
+
- Make workflows deterministic
|
|
500
|
+
- Use signals for external events
|
|
501
|
+
- Use queries for retrieving workflow state
|
|
502
|
+
- Use updates for synchronous modifications
|
|
503
|
+
- Avoid side effects in workflow code
|
|
504
|
+
|
|
505
|
+
3. **Configuration**
|
|
506
|
+
|
|
507
|
+
- Use meaningful workflow IDs for tracking
|
|
508
|
+
- Configure appropriate timeouts for activities and workflows
|
|
509
|
+
- Use retry policies for transient failures
|
|
510
|
+
- Set up monitoring for production deployments
|
|
511
|
+
- Enable worker versioning in production
|
|
512
|
+
|
|
513
|
+
4. **Performance Optimization**
|
|
514
|
+
|
|
515
|
+
- Enable V8 context reuse for better performance
|
|
516
|
+
- Configure appropriate concurrency settings
|
|
517
|
+
- Use caching for frequently accessed workflows
|
|
518
|
+
- Balance worker thread pool size
|
|
519
|
+
|
|
520
|
+
5. **Lifecycle Management**
|
|
521
|
+
|
|
522
|
+
- Enable NestJS shutdown hooks
|
|
523
|
+
- Configure proper worker shutdown grace periods
|
|
524
|
+
- Use the WorkerManager service for controlling worker lifecycle
|
|
525
|
+
|
|
526
|
+
6. **Security**
|
|
527
|
+
- Implement proper TLS security for production environments
|
|
528
|
+
- Use namespaces to isolate different environments
|
|
529
|
+
- Use API keys for Temporal Cloud authentication
|
|
354
530
|
|
|
355
531
|
## Contributing
|
|
356
532
|
|