nestjs-temporal-core 3.0.8 → 3.0.9

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 (2) hide show
  1. package/README.md +109 -34
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -14,6 +14,20 @@ NestJS Temporal Core brings Temporal's durable execution to NestJS with familiar
14
14
 
15
15
  🔗 **[Complete Example Project](https://github.com/harsh-simform/nestjs-temporal-core-example)** - Check out our full working example repository to see NestJS Temporal Core in action with real-world use cases, configuration examples, and best practices.
16
16
 
17
+ ## 🏁 Getting Started: Recommendations
18
+
19
+ Welcome to NestJS Temporal Core! Here are some quick recommendations to help you get started smoothly:
20
+
21
+ - **Choose Your Workflow Style:** You can implement workflows as plain exported functions (recommended for most use cases) or as injectable classes with decorators for advanced scenarios. See the comparison below.
22
+ - **Parameter Injection:** Use `@WorkflowParam`, `@WorkflowId`, etc., only if you need advanced injection or metadata. For most workflows, plain parameters are simpler and preferred.
23
+ - **Scheduling:** Schedules trigger workflows, not service methods. Make sure your scheduled workflow is exported and available to the worker.
24
+ - **Signals & Queries:** Use signals to update workflow state and queries to fetch workflow status. See the expanded examples below for best practices.
25
+ - **Keep Activities Idempotent:** Activities should be safe to retry and handle errors gracefully.
26
+ - **Separate Concerns:** Keep workflows, activities, and schedules in separate files for clarity and maintainability.
27
+ - **Check the Example Repo:** For real-world patterns, see [nestjs-temporal-core-example](https://github.com/harsh-simform/nestjs-temporal-core-example).
28
+
29
+ ---
30
+
17
31
  ## 🚀 Key Features
18
32
 
19
33
  - **🎯 NestJS-Native** - Familiar patterns: `@Activity`, `@Cron`, `@Interval`, `@Scheduled`
@@ -141,90 +155,101 @@ export async function processEmailWorkflow(
141
155
 
142
156
  ### 4. Schedule Workflows
143
157
 
158
+ > **Note:** Schedules in NestJS Temporal Core trigger workflows, not service methods. The decorated method is used to define the schedule metadata, but the actual execution runs the workflow you specify.
159
+
144
160
  ```typescript
145
161
  // services/scheduled.service.ts
146
162
  import { Injectable } from '@nestjs/common';
147
163
  import {
148
164
  Scheduled,
149
- Cron,
150
- Interval,
151
165
  CRON_EXPRESSIONS,
152
- INTERVAL_EXPRESSIONS
153
166
  } from 'nestjs-temporal-core';
154
167
 
155
168
  @Injectable()
156
169
  export class ScheduledService {
157
-
158
170
  @Scheduled({
159
171
  scheduleId: 'daily-report',
160
172
  cron: CRON_EXPRESSIONS.DAILY_8AM,
161
173
  description: 'Generate daily sales report',
162
- taskQueue: 'reports'
174
+ taskQueue: 'reports',
175
+ workflowType: 'generateReportWorkflow', // Name of the workflow function to run
176
+ workflowArgs: [{ reportType: 'sales', date: new Date().toISOString() }], // Arguments passed to the workflow
163
177
  })
164
178
  async generateDailyReport(): Promise<void> {
165
- console.log('Generating daily report...');
166
- // Your report generation logic
167
- }
168
-
169
- @Cron(CRON_EXPRESSIONS.WEEKLY_MONDAY_9AM, {
170
- scheduleId: 'weekly-cleanup',
171
- description: 'Weekly system cleanup'
172
- })
173
- async performWeeklyCleanup(): Promise<void> {
174
- console.log('Performing weekly cleanup...');
175
- // Your cleanup logic
176
- }
177
-
178
- @Interval(INTERVAL_EXPRESSIONS.EVERY_5_MINUTES, {
179
- scheduleId: 'health-check',
180
- description: 'System health monitoring'
181
- })
182
- async performHealthCheck(): Promise<void> {
183
- console.log('Performing health check...');
184
- // Your health check logic
179
+ // This method is NOT executed directly. Instead, the schedule triggers the workflow specified above.
185
180
  }
186
181
  }
187
182
  ```
188
183
 
184
+ - The `@Scheduled` decorator registers a schedule with Temporal.
185
+ - The `workflowType` property specifies the workflow function to run (must be exported and available to the worker).
186
+ - The `workflowArgs` property allows you to pass arguments to the workflow when the schedule triggers.
187
+
188
+ > **Best Practice:** Keep your scheduled workflow logic in a dedicated workflow file, and use the schedule only to trigger it with the desired arguments.
189
+
189
190
  ### 5. Parameter Injection in Workflows
190
191
 
192
+ You can use parameter decorators to inject workflow metadata and context. This is most useful for advanced scenarios, such as handling signals and queries in a class-based workflow.
193
+
194
+ #### Comprehensive Example: Handling Signals and Workflow State
195
+
191
196
  ```typescript
192
197
  // workflows/order.workflow.ts
193
198
  import { Injectable } from '@nestjs/common';
194
- import {
195
- WorkflowParam,
196
- WorkflowContext,
197
- WorkflowId,
199
+ import {
200
+ WorkflowParam,
201
+ WorkflowContext,
202
+ WorkflowId,
198
203
  RunId,
199
- TaskQueue
204
+ TaskQueue,
205
+ Signal,
206
+ Query
200
207
  } from 'nestjs-temporal-core';
201
208
 
202
209
  @Injectable()
203
210
  export class OrderWorkflowController {
204
-
211
+ private updateData: any = null; // Store signal data in workflow state
212
+ private status: string = 'processing';
213
+
205
214
  async processOrder(
206
215
  @WorkflowParam(0) orderId: string,
207
216
  @WorkflowParam(1) customerData: any,
208
217
  @WorkflowId() workflowId: string,
209
218
  @WorkflowContext() context: any
210
219
  ): Promise<void> {
211
- console.log(`Processing order ${orderId} in workflow ${workflowId}`);
212
- // Your workflow logic
220
+ // Main workflow logic
221
+ // Wait for an update signal (example: polling or event-driven)
222
+ while (!this.updateData) {
223
+ // ...wait or yield...
224
+ // In real Temporal workflows, use condition() or similar for waiting
225
+ }
226
+ // Use updateData in your logic
227
+ // ...
228
+ this.status = 'completed';
213
229
  }
214
230
 
215
231
  @Signal('updateOrder')
216
232
  async updateOrder(@WorkflowParam() updateData: any): Promise<void> {
217
233
  // Handle order update signal
234
+ this.updateData = updateData; // Store for use in processOrder
235
+ this.status = 'updated';
218
236
  }
219
237
 
220
238
  @Query('getOrderStatus')
221
239
  getOrderStatus(@RunId() runId: string): string {
222
240
  // Return current order status
223
- return 'processing';
241
+ return this.status;
224
242
  }
225
243
  }
226
244
  ```
227
245
 
246
+ - **Signal Handling:** Use a class property to persist signal data (`updateData`) so it can be accessed by the main workflow logic.
247
+ - **Best Practice:** Always store signal data in workflow state (class property or closure variable) to ensure it is available after workflow replay.
248
+ - **Forwarding Data:** The main workflow function (`processOrder`) can access and use the updated data as needed.
249
+ - **Status Tracking:** Use a property like `status` to track and query workflow progress.
250
+
251
+ > **Tip:** In Temporal workflows, use `condition()` or similar mechanisms to wait for signals in a non-blocking, replay-safe way.
252
+
228
253
  ### 6. Use in Services
229
254
 
230
255
  ```typescript
@@ -898,3 +923,53 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
898
923
  ---
899
924
 
900
925
  Built with ❤️ for the NestJS and Temporal communities
926
+
927
+ ## Workflow Implementation Approaches
928
+
929
+ NestJS Temporal Core supports two main ways to define workflows:
930
+
931
+ ### 1. Function-Based Workflows (Recommended for Most Use Cases)
932
+ - **How:** Export a plain async function from your workflow file.
933
+ - **Benefits:**
934
+ - Simpler, more idiomatic Temporal style
935
+ - Fully compatible with Temporal's TypeScript SDK
936
+ - Easier to test and bundle
937
+ - **When to Use:**
938
+ - Most workflows, especially if you don't need dependency injection or advanced metadata
939
+
940
+ ```typescript
941
+ // workflows/email.workflow.ts
942
+ export async function processEmailWorkflow(userId: string, emailData: { to: string; subject: string; body: string }) {
943
+ // ...
944
+ }
945
+ ```
946
+
947
+ ### 2. Class-Based Workflows with Decorators (Advanced)
948
+ - **How:** Use an injectable class and parameter decorators like `@WorkflowParam`, `@WorkflowId`, etc.
949
+ - **Benefits:**
950
+ - Enables parameter injection (workflowId, context, etc.)
951
+ - Useful for advanced scenarios (e.g., dynamic metadata, dependency injection)
952
+ - Can organize signals/queries as class methods
953
+ - **When to Use:**
954
+ - When you need to access workflow context, IDs, or inject dependencies
955
+ - When you want to group signals/queries with workflow logic
956
+
957
+ ```typescript
958
+ @Injectable()
959
+ export class OrderWorkflowController {
960
+ async processOrder(
961
+ @WorkflowParam(0) orderId: string,
962
+ @WorkflowId() workflowId: string,
963
+ @WorkflowContext() context: any
964
+ ) {
965
+ // ...
966
+ }
967
+ }
968
+ ```
969
+
970
+ #### Which Should I Use?
971
+ - **Start with function-based workflows** for simplicity and compatibility.
972
+ - **Use class-based workflows** only if you need advanced features like parameter injection or grouping signals/queries.
973
+ - `@WorkflowParam` and related decorators are only needed for class-based workflows and provide access to workflow metadata or injected parameters.
974
+
975
+ ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nestjs-temporal-core",
3
- "version": "3.0.8",
3
+ "version": "3.0.9",
4
4
  "description": "Complete NestJS integration for Temporal.io with auto-discovery, declarative scheduling, enhanced monitoring, and enterprise-ready features",
5
5
  "author": "Harsh M",
6
6
  "license": "MIT",