@supergrowthai/tq 1.0.1-canary.a2ffe03

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 ADDED
@@ -0,0 +1,426 @@
1
+ # @supergrowthai/tq
2
+
3
+ A task queue management library with multiple executor types and async task handling. Built on top of @supergrowthai/mq
4
+ for flexible message queue backends.
5
+
6
+ ## Features
7
+
8
+ - **Multiple Executor Types**: Single task (parallel/non-parallel) and multi-task executors
9
+ - **Async Task Management**: Handle long-running tasks with configurable timeouts
10
+ - **Type-Safe**: Full TypeScript support with generic task types
11
+ - **Queue Integration**: Works with any message queue backend via @supergrowthai/mq
12
+ - **Flexible Registration**: Register task executors for different queue types
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install @supergrowthai/tq @supergrowthai/mq
18
+ ```
19
+
20
+ ## Basic Usage
21
+
22
+ ### Setting Up Task Executors
23
+
24
+ ```typescript
25
+ import taskQueue from '@supergrowthai/tq';
26
+ import messageQueue from '@supergrowthai/mq';
27
+ import {ISingleTaskNonParallel} from '@supergrowthai/tq/core/base/interfaces';
28
+
29
+ // Define a simple task executor
30
+ const emailExecutor: ISingleTaskNonParallel<EmailTaskData> = {
31
+ multiple: false,
32
+ parallel: false,
33
+ default_retries: 3,
34
+ store_on_failure: true,
35
+
36
+ async onTask(task, actions) {
37
+ try {
38
+ await sendEmail(task.data.to, task.data.subject, task.data.body);
39
+ actions.success(task);
40
+ } catch (error) {
41
+ console.error('Failed to send email:', error);
42
+ actions.fail(task);
43
+ }
44
+ }
45
+ };
46
+
47
+ // Register the executor
48
+ taskQueue.register(
49
+ messageQueue, // Message queue instance
50
+ 'email-queue', // Queue name
51
+ 'send-email', // Task type
52
+ emailExecutor // Executor implementation
53
+ );
54
+ ```
55
+
56
+ ### Task Types and Interfaces
57
+
58
+ #### Single Task Non-Parallel Executor
59
+
60
+ For tasks that should be processed one at a time:
61
+
62
+ ```typescript
63
+ import {ISingleTaskNonParallel} from '@supergrowthai/tq/core/base/interfaces';
64
+
65
+ const reportExecutor: ISingleTaskNonParallel<ReportData> = {
66
+ multiple: false,
67
+ parallel: false,
68
+ default_retries: 2,
69
+ store_on_failure: true,
70
+
71
+ async onTask(task, actions) {
72
+ console.log(`Generating report: ${task.data.reportId}`);
73
+
74
+ try {
75
+ const report = await generateReport(task.data);
76
+ actions.success(task);
77
+ } catch (error) {
78
+ actions.fail(task);
79
+ }
80
+ }
81
+ };
82
+ ```
83
+
84
+ #### Single Task Parallel Executor
85
+
86
+ For tasks that can be processed in parallel batches:
87
+
88
+ ```typescript
89
+ import {ISingleTaskParallel} from '@supergrowthai/tq/core/base/interfaces';
90
+
91
+ const imageProcessorExecutor: ISingleTaskParallel<ImageData> = {
92
+ multiple: false,
93
+ parallel: true,
94
+ chunkSize: 5, // Process 5 images at a time
95
+ default_retries: 3,
96
+ store_on_failure: true,
97
+
98
+ async onTask(task, actions) {
99
+ try {
100
+ await processImage(task.data.imageUrl, task.data.filters);
101
+ actions.success(task);
102
+ } catch (error) {
103
+ console.error('Image processing failed:', error);
104
+ actions.fail(task);
105
+ }
106
+ }
107
+ };
108
+ ```
109
+
110
+ #### Multi-Task Executor
111
+
112
+ For processing multiple tasks together as a batch:
113
+
114
+ ```typescript
115
+ import {IMultiTaskExecutor} from '@supergrowthai/tq/core/base/interfaces';
116
+
117
+ const batchProcessorExecutor: IMultiTaskExecutor<BatchData> = {
118
+ multiple: true,
119
+ default_retries: 2,
120
+ store_on_failure: true,
121
+
122
+ async onTasks(tasks, actions) {
123
+ console.log(`Processing batch of ${tasks.length} tasks`);
124
+
125
+ for (const task of tasks) {
126
+ try {
127
+ await processBatchItem(task.data);
128
+ actions.success(task);
129
+ } catch (error) {
130
+ console.error('Batch item failed:', error);
131
+ actions.fail(task);
132
+
133
+ // Optionally add retry tasks
134
+ if (task.retries < 3) {
135
+ actions.addTasks([{
136
+ ...task,
137
+ retries: (task.retries || 0) + 1,
138
+ execute_at: new Date(Date.now() + 60000) // Retry in 1 minute
139
+ }]);
140
+ }
141
+ }
142
+ }
143
+ }
144
+ };
145
+ ```
146
+
147
+ ### Async Task Management
148
+
149
+ For long-running tasks that might exceed normal timeouts:
150
+
151
+ ```typescript
152
+ const heavyProcessingExecutor: ISingleTaskNonParallel<ProcessingData> = {
153
+ multiple: false,
154
+ parallel: false,
155
+ default_retries: 1,
156
+ store_on_failure: true,
157
+
158
+ // Configure async handoff for tasks taking longer than 30 seconds
159
+ asyncConfig: {
160
+ handoffTimeout: 30000, // 30 seconds
161
+ maxConcurrentAsync: 2 // Max 2 concurrent heavy tasks
162
+ },
163
+
164
+ async onTask(task, actions) {
165
+ try {
166
+ // This might take a very long time
167
+ const result = await performHeavyComputation(task.data);
168
+ actions.success(task);
169
+ } catch (error) {
170
+ actions.fail(task);
171
+ }
172
+ }
173
+ };
174
+ ```
175
+
176
+ ## Advanced Usage
177
+
178
+ ### Task Queue Management
179
+
180
+ ```typescript
181
+ import {TaskQueue} from '@supergrowthai/tq';
182
+
183
+ // Create a custom task queue instance
184
+ const customTaskQueue = new TaskQueue();
185
+
186
+ // Get information about registered queues
187
+ const queues = taskQueue.getQueues();
188
+ console.log('Registered queues:', queues);
189
+
190
+ // Get task types for a specific queue
191
+ const taskTypes = taskQueue.getTasksForQueue('email-queue');
192
+ console.log('Email queue task types:', taskTypes);
193
+
194
+ // Get a specific executor
195
+ const executor = taskQueue.getExecutor('email-queue', 'send-email');
196
+ if (executor) {
197
+ console.log('Found email executor');
198
+ }
199
+ ```
200
+
201
+ ### Error Handling and Retries
202
+
203
+ ```typescript
204
+ const resilientExecutor: ISingleTaskNonParallel<ApiCallData> = {
205
+ multiple: false,
206
+ parallel: false,
207
+ default_retries: 5,
208
+ store_on_failure: true,
209
+
210
+ async onTask(task, actions) {
211
+ const maxRetries = task.retries || this.default_retries;
212
+
213
+ try {
214
+ const response = await callExternalAPI(task.data.endpoint, task.data.payload);
215
+
216
+ if (response.status === 200) {
217
+ actions.success(task);
218
+ } else {
219
+ throw new Error(`API returned status: ${response.status}`);
220
+ }
221
+ } catch (error) {
222
+ console.error(`API call failed (attempt ${task.retries || 0 + 1}/${maxRetries}):`, error);
223
+
224
+ if ((task.retries || 0) < maxRetries) {
225
+ // Create retry task with exponential backoff
226
+ const retryDelay = Math.pow(2, task.retries || 0) * 1000; // 1s, 2s, 4s, 8s, 16s
227
+
228
+ actions.addTasks([{
229
+ ...task,
230
+ retries: (task.retries || 0) + 1,
231
+ execute_at: new Date(Date.now() + retryDelay)
232
+ }]);
233
+ } else {
234
+ actions.fail(task);
235
+ }
236
+ }
237
+ }
238
+ };
239
+ ```
240
+
241
+ ### Working with Different Message Queue Providers
242
+
243
+ ```typescript
244
+ import {QueueFactory} from '@supergrowthai/mq';
245
+ import {MemoryCacheAdapter} from '@supergrowthai/mq/adapters';
246
+
247
+ // Use with MongoDB queue
248
+ const mongoQueue = QueueFactory.create({
249
+ provider: 'mongodb',
250
+ cacheAdapter: new MemoryCacheAdapter()
251
+ });
252
+
253
+ taskQueue.register(mongoQueue, 'heavy-processing', 'compute', heavyProcessingExecutor);
254
+
255
+ // Use with Kinesis queue
256
+ const kinesisQueue = QueueFactory.create({
257
+ provider: 'kinesis',
258
+ kinesis: {instanceId: 'worker-1'}
259
+ });
260
+
261
+ taskQueue.register(kinesisQueue, 'real-time', 'notification', notificationExecutor);
262
+ ```
263
+
264
+ ## TypeScript Support
265
+
266
+ The library provides full TypeScript support with generic task types:
267
+
268
+ ```typescript
269
+ import {TaskExecutor, ExecutorActions} from '@supergrowthai/tq/core/base/interfaces';
270
+ import {CronTask} from '@supergrowthai/database/types.server';
271
+ import {WithId} from 'mongodb';
272
+
273
+ // Define your task data type
274
+ interface EmailTaskData {
275
+ to: string;
276
+ subject: string;
277
+ body: string;
278
+ attachments?: string[];
279
+ }
280
+
281
+ // Type-safe executor
282
+ const typedExecutor: ISingleTaskNonParallel<EmailTaskData> = {
283
+ multiple: false,
284
+ parallel: false,
285
+ default_retries: 3,
286
+ store_on_failure: true,
287
+
288
+ async onTask(
289
+ task: WithId<CronTask<EmailTaskData>>,
290
+ actions: ExecutorActions<EmailTaskData>
291
+ ) {
292
+ // task.data is properly typed as EmailTaskData
293
+ console.log(`Sending email to: ${task.data.to}`);
294
+
295
+ try {
296
+ await sendEmail(task.data);
297
+ actions.success(task);
298
+ } catch (error) {
299
+ actions.fail(task);
300
+ }
301
+ }
302
+ };
303
+ ```
304
+
305
+ ## Environment Integration
306
+
307
+ Task queue automatically handles environment-specific queue naming:
308
+
309
+ ```typescript
310
+ // Queue names are automatically prefixed based on environment
311
+ // Development: 'dev-email-queue'
312
+ // Production: 'prod-email-queue'
313
+ // Test: 'test-email-queue'
314
+
315
+ taskQueue.register(messageQueue, 'email-queue', 'send', emailExecutor);
316
+ ```
317
+
318
+ ## Best Practices
319
+
320
+ ### 1. Task Idempotency
321
+
322
+ Ensure your tasks can be safely retried:
323
+
324
+ ```typescript
325
+ const idempotentExecutor: ISingleTaskNonParallel<UserUpdateData> = {
326
+ multiple: false,
327
+ parallel: false,
328
+ default_retries: 3,
329
+ store_on_failure: true,
330
+
331
+ async onTask(task, actions) {
332
+ try {
333
+ // Check if already processed
334
+ const user = await getUser(task.data.userId);
335
+ if (user.lastUpdated >= task.data.timestamp) {
336
+ console.log('Update already applied, skipping');
337
+ actions.success(task);
338
+ return;
339
+ }
340
+
341
+ await updateUser(task.data.userId, task.data.updates);
342
+ actions.success(task);
343
+ } catch (error) {
344
+ actions.fail(task);
345
+ }
346
+ }
347
+ };
348
+ ```
349
+
350
+ ### 2. Resource Management
351
+
352
+ Use parallel executors wisely to avoid overwhelming external services:
353
+
354
+ ```typescript
355
+ const apiExecutor: ISingleTaskParallel<ApiTaskData> = {
356
+ multiple: false,
357
+ parallel: true,
358
+ chunkSize: 3, // Limit concurrent API calls
359
+ default_retries: 3,
360
+ store_on_failure: true,
361
+
362
+ async onTask(task, actions) {
363
+ // Rate limiting logic here
364
+ await rateLimiter.acquire();
365
+
366
+ try {
367
+ const result = await callAPI(task.data);
368
+ actions.success(task);
369
+ } catch (error) {
370
+ actions.fail(task);
371
+ } finally {
372
+ rateLimiter.release();
373
+ }
374
+ }
375
+ };
376
+ ```
377
+
378
+ ### 3. Monitoring and Observability
379
+
380
+ Add logging and metrics to your executors:
381
+
382
+ ```typescript
383
+ const monitoredExecutor: ISingleTaskNonParallel<TaskData> = {
384
+ multiple: false,
385
+ parallel: false,
386
+ default_retries: 3,
387
+ store_on_failure: true,
388
+
389
+ async onTask(task, actions) {
390
+ const startTime = Date.now();
391
+ const taskId = task._id.toString();
392
+
393
+ console.log(`Starting task ${taskId} of type ${task.type}`);
394
+
395
+ try {
396
+ await processTask(task.data);
397
+
398
+ const duration = Date.now() - startTime;
399
+ console.log(`Task ${taskId} completed in ${duration}ms`);
400
+
401
+ // Send metrics to your monitoring system
402
+ metrics.histogram('task.duration', duration, {type: task.type, status: 'success'});
403
+
404
+ actions.success(task);
405
+ } catch (error) {
406
+ const duration = Date.now() - startTime;
407
+ console.error(`Task ${taskId} failed after ${duration}ms:`, error);
408
+
409
+ metrics.histogram('task.duration', duration, {type: task.type, status: 'failure'});
410
+ metrics.increment('task.failures', {type: task.type});
411
+
412
+ actions.fail(task);
413
+ }
414
+ }
415
+ };
416
+ ```
417
+
418
+ ## Integration with @supergrowthai/mq
419
+
420
+ This library requires @supergrowthai/mq for message queue functionality. See
421
+ the [@supergrowthai/mq documentation](../mq/README.md) for details on configuring different queue providers and cache
422
+ adapters.
423
+
424
+ ## License
425
+
426
+ MIT
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ //# sourceMappingURL=interfaces.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interfaces.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+
2
+ //# sourceMappingURL=interfaces.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interfaces.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ export * from './src/index'
2
+ export {}
3
+ import SupergrowthAITQ from './src/index'
4
+ export default SupergrowthAITQ
5
+ export * from './src/index'
6
+ export {}