@supergrowthai/tq 1.0.8 → 1.0.10
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 +33 -0
- package/dist/{PrismaAdapter-CT8dxOZX.cjs → PrismaAdapter-CvM_XNtE.cjs} +114 -19
- package/dist/PrismaAdapter-CvM_XNtE.cjs.map +1 -0
- package/dist/{PrismaAdapter-Z2vLslDJ.js → PrismaAdapter-Dy7MV090.js} +114 -19
- package/dist/PrismaAdapter-Dy7MV090.js.map +1 -0
- package/dist/adapters/index.cjs +1 -1
- package/dist/adapters/index.mjs +1 -1
- package/dist/index.cjs +79 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +79 -19
- package/dist/index.mjs.map +1 -1
- package/dist/src/adapters/ITaskStorageAdapter.d.cts +5 -0
- package/dist/src/adapters/ITaskStorageAdapter.d.ts +5 -0
- package/dist/src/adapters/InMemoryAdapter.d.cts +1 -0
- package/dist/src/adapters/InMemoryAdapter.d.ts +1 -0
- package/dist/src/adapters/MongoDbAdapter.d.cts +1 -0
- package/dist/src/adapters/MongoDbAdapter.d.ts +1 -0
- package/dist/src/adapters/PrismaAdapter.d.cts +25 -1
- package/dist/src/adapters/PrismaAdapter.d.ts +25 -1
- package/dist/src/core/TaskStore.d.cts +4 -2
- package/dist/src/core/TaskStore.d.ts +4 -2
- package/package.json +7 -7
- package/dist/PrismaAdapter-CT8dxOZX.cjs.map +0 -1
- package/dist/PrismaAdapter-Z2vLslDJ.js.map +0 -1
package/README.md
CHANGED
|
@@ -693,6 +693,39 @@ const mongoAdapter = new MongoDbAdapter(mongoCollection);
|
|
|
693
693
|
const memoryAdapter = new InMemoryAdapter();
|
|
694
694
|
```
|
|
695
695
|
|
|
696
|
+
### PrismaAdapter Performance Optimization
|
|
697
|
+
|
|
698
|
+
The default `PrismaAdapter.addTasksToScheduled()` uses sequential creates for maximum database compatibility
|
|
699
|
+
(SQLite, CockroachDB, etc.). For high-throughput Postgres/MySQL deployments, override with batch operations:
|
|
700
|
+
|
|
701
|
+
```typescript
|
|
702
|
+
import {PrismaAdapter} from '@supergrowthai/tq';
|
|
703
|
+
|
|
704
|
+
class OptimizedPrismaAdapter extends PrismaAdapter {
|
|
705
|
+
async addTasksToScheduled(tasks) {
|
|
706
|
+
if (!tasks.length) return [];
|
|
707
|
+
|
|
708
|
+
// Batch insert with duplicate handling (Postgres/MySQL only)
|
|
709
|
+
await this.delegate.createMany({
|
|
710
|
+
data: tasks.map(task => ({
|
|
711
|
+
...task,
|
|
712
|
+
id: task.id || this.generateId(),
|
|
713
|
+
status: task.status || 'scheduled',
|
|
714
|
+
retries: task.retries || 0,
|
|
715
|
+
created_at: task.created_at || new Date(),
|
|
716
|
+
updated_at: new Date(),
|
|
717
|
+
processing_started_at: task.processing_started_at || new Date()
|
|
718
|
+
})),
|
|
719
|
+
skipDuplicates: true
|
|
720
|
+
});
|
|
721
|
+
return tasks;
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
```
|
|
725
|
+
|
|
726
|
+
**Note:** `createMany` with `skipDuplicates` is not supported on all databases (e.g., SQLite).
|
|
727
|
+
The default implementation ensures compatibility at the cost of O(n) database round-trips.
|
|
728
|
+
|
|
696
729
|
### Custom Storage Adapter
|
|
697
730
|
|
|
698
731
|
Implement the `ITaskStorageAdapter` interface for custom storage backends:
|
|
@@ -171,9 +171,38 @@ class MongoDbAdapter {
|
|
|
171
171
|
}
|
|
172
172
|
}));
|
|
173
173
|
if (bulkOps.length > 0) {
|
|
174
|
-
await collection.bulkWrite(bulkOps);
|
|
174
|
+
await collection.bulkWrite(bulkOps, { ordered: false });
|
|
175
175
|
}
|
|
176
176
|
}
|
|
177
|
+
async upsertTasks(tasks) {
|
|
178
|
+
if (!tasks.length) return;
|
|
179
|
+
const collection = await this.collection;
|
|
180
|
+
const now = /* @__PURE__ */ new Date();
|
|
181
|
+
const bulkOps = tasks.map((task) => {
|
|
182
|
+
const id = task.id || this.generateId();
|
|
183
|
+
const { id: _id, status, execute_at, execution_stats, updated_at, ...rest } = task;
|
|
184
|
+
return {
|
|
185
|
+
updateOne: {
|
|
186
|
+
filter: { _id: id },
|
|
187
|
+
update: {
|
|
188
|
+
$set: {
|
|
189
|
+
status: task.status,
|
|
190
|
+
execute_at: task.execute_at,
|
|
191
|
+
execution_stats: task.execution_stats,
|
|
192
|
+
updated_at: now
|
|
193
|
+
},
|
|
194
|
+
$setOnInsert: {
|
|
195
|
+
...rest,
|
|
196
|
+
created_at: task.created_at || now,
|
|
197
|
+
processing_started_at: task.processing_started_at || now
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
upsert: true
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
});
|
|
204
|
+
await collection.bulkWrite(bulkOps, { ordered: false });
|
|
205
|
+
}
|
|
177
206
|
generateId() {
|
|
178
207
|
return new mongodb.ObjectId();
|
|
179
208
|
}
|
|
@@ -276,6 +305,22 @@ class InMemoryAdapter {
|
|
|
276
305
|
}
|
|
277
306
|
}
|
|
278
307
|
}
|
|
308
|
+
async upsertTasks(tasks) {
|
|
309
|
+
for (const task of tasks) {
|
|
310
|
+
const id = task.id || this.generateId();
|
|
311
|
+
const existing = this.scheduledTasks.get(id);
|
|
312
|
+
if (existing) {
|
|
313
|
+
Object.assign(existing, {
|
|
314
|
+
status: task.status,
|
|
315
|
+
execute_at: task.execute_at,
|
|
316
|
+
execution_stats: task.execution_stats,
|
|
317
|
+
updated_at: /* @__PURE__ */ new Date()
|
|
318
|
+
});
|
|
319
|
+
} else {
|
|
320
|
+
this.scheduledTasks.set(id, { ...task, id });
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
279
324
|
async getCleanupStats() {
|
|
280
325
|
let orphanedTasks = 0;
|
|
281
326
|
let expiredTasks = 0;
|
|
@@ -348,26 +393,54 @@ class PrismaAdapter {
|
|
|
348
393
|
get delegate() {
|
|
349
394
|
return this.config.prismaClient[this.config.messageModel];
|
|
350
395
|
}
|
|
396
|
+
/**
|
|
397
|
+
* Persist tasks to the database as scheduled.
|
|
398
|
+
*
|
|
399
|
+
* **Default implementation:** Uses individual creates with duplicate detection
|
|
400
|
+
* for maximum database compatibility (SQLite, Postgres, MySQL, etc.).
|
|
401
|
+
*
|
|
402
|
+
* **Performance note:** This is O(n) database round-trips. For high-throughput
|
|
403
|
+
* scenarios (100+ tasks/batch), override this method with a batch implementation:
|
|
404
|
+
*
|
|
405
|
+
* @example PostgreSQL/MySQL optimization:
|
|
406
|
+
* ```typescript
|
|
407
|
+
* class OptimizedPrismaAdapter extends PrismaAdapter {
|
|
408
|
+
* async addTasksToScheduled(tasks) {
|
|
409
|
+
* if (!tasks.length) return [];
|
|
410
|
+
* await this.delegate.createMany({
|
|
411
|
+
* data: tasks.map(t => ({ ...t, id: t.id || this.generateId() })),
|
|
412
|
+
* skipDuplicates: true
|
|
413
|
+
* });
|
|
414
|
+
* return tasks;
|
|
415
|
+
* }
|
|
416
|
+
* }
|
|
417
|
+
* ```
|
|
418
|
+
*/
|
|
351
419
|
async addTasksToScheduled(tasks) {
|
|
352
420
|
if (!tasks.length) return [];
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
data: tasks.map((task) => ({
|
|
356
|
-
...task,
|
|
357
|
-
id: task.id || this.generateId(),
|
|
358
|
-
status: task.status || "scheduled",
|
|
359
|
-
retries: task.retries || 0,
|
|
360
|
-
created_at: task.created_at || /* @__PURE__ */ new Date(),
|
|
361
|
-
updated_at: /* @__PURE__ */ new Date(),
|
|
362
|
-
processing_started_at: task.processing_started_at || /* @__PURE__ */ new Date()
|
|
363
|
-
})),
|
|
364
|
-
skipDuplicates: true
|
|
365
|
-
});
|
|
366
|
-
return tasks;
|
|
367
|
-
} catch (error) {
|
|
368
|
-
logger.warn(`Some tasks skipped due to duplicates: ${error}`);
|
|
369
|
-
return tasks;
|
|
421
|
+
if (tasks.length > 50) {
|
|
422
|
+
logger.warn(`[PrismaAdapter] Processing ${tasks.length} tasks sequentially (O(n) round-trips). For Postgres/MySQL, override addTasksToScheduled with createMany for better performance.`);
|
|
370
423
|
}
|
|
424
|
+
const results = [];
|
|
425
|
+
for (const task of tasks) {
|
|
426
|
+
try {
|
|
427
|
+
await this.delegate.create({
|
|
428
|
+
data: {
|
|
429
|
+
...task,
|
|
430
|
+
id: task.id || this.generateId(),
|
|
431
|
+
status: task.status || "scheduled",
|
|
432
|
+
retries: task.retries || 0,
|
|
433
|
+
created_at: task.created_at || /* @__PURE__ */ new Date(),
|
|
434
|
+
updated_at: /* @__PURE__ */ new Date(),
|
|
435
|
+
processing_started_at: task.processing_started_at || /* @__PURE__ */ new Date()
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
results.push(task);
|
|
439
|
+
} catch (error) {
|
|
440
|
+
logger.warn(`Task skipped (likely duplicate): ${error}`);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
return results;
|
|
371
444
|
}
|
|
372
445
|
async getMatureTasks(timestamp) {
|
|
373
446
|
const staleTimestamp = Date.now() - TWO_DAYS_MS;
|
|
@@ -450,6 +523,28 @@ class PrismaAdapter {
|
|
|
450
523
|
}
|
|
451
524
|
});
|
|
452
525
|
}
|
|
526
|
+
async upsertTasks(tasks) {
|
|
527
|
+
if (!tasks.length) return;
|
|
528
|
+
const now = /* @__PURE__ */ new Date();
|
|
529
|
+
const delegate = this.delegate;
|
|
530
|
+
await this.prismaClient.$transaction(
|
|
531
|
+
tasks.map((task) => delegate.upsert({
|
|
532
|
+
where: { id: task.id },
|
|
533
|
+
create: {
|
|
534
|
+
...task,
|
|
535
|
+
created_at: task.created_at || now,
|
|
536
|
+
updated_at: now,
|
|
537
|
+
processing_started_at: task.processing_started_at || now
|
|
538
|
+
},
|
|
539
|
+
update: {
|
|
540
|
+
status: task.status,
|
|
541
|
+
execute_at: task.execute_at,
|
|
542
|
+
execution_stats: task.execution_stats,
|
|
543
|
+
updated_at: now
|
|
544
|
+
}
|
|
545
|
+
}))
|
|
546
|
+
);
|
|
547
|
+
}
|
|
453
548
|
async getCleanupStats() {
|
|
454
549
|
const orphanedBefore = new Date(Date.now() - TWO_DAYS_MS);
|
|
455
550
|
const [orphanedTasks, expiredTasks] = await Promise.all([
|
|
@@ -489,4 +584,4 @@ class PrismaAdapter {
|
|
|
489
584
|
exports.InMemoryAdapter = InMemoryAdapter;
|
|
490
585
|
exports.MongoDbAdapter = MongoDbAdapter;
|
|
491
586
|
exports.PrismaAdapter = PrismaAdapter;
|
|
492
|
-
//# sourceMappingURL=PrismaAdapter-
|
|
587
|
+
//# sourceMappingURL=PrismaAdapter-CvM_XNtE.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PrismaAdapter-CvM_XNtE.cjs","sources":["../src/adapters/MongoDbAdapter.ts","../src/adapters/InMemoryAdapter.ts","../src/adapters/PrismaAdapter.ts"],"sourcesContent":["import {Collection, ObjectId} from \"mongodb\";\nimport {ITaskStorageAdapter, TaskStorageLifecycleConfig} from \"./ITaskStorageAdapter.js\";\nimport {CronTask} from \"./types.js\";\nimport {Logger, LogLevel} from \"@supergrowthai/utils\";\nimport type {ITaskLifecycleProvider} from \"../core/lifecycle.js\";\n\nconst logger = new Logger('MongoDbAdapter', LogLevel.INFO);\n\nconst TWO_DAYS_MS = 2 * 24 * 60 * 60 * 1000;\n\n/**\n * Convert MongoDB document with _id to CronTask with id\n */\nfunction toPublicTask<T>({_id, ...rest}: Omit<CronTask<T>, 'id'> & { _id: T }): CronTask<T> {\n return {...rest, id: _id} as CronTask<T>;\n}\n\n/**\n * MongoDB task storage adapter for @supergrowthai/tq.\n *\n * @description Persists scheduled tasks to MongoDB collection with status tracking.\n * Uses application-level locking designed for single-instance deployments.\n *\n * @use-case Single-instance production deployments\n * @multi-instance NOT SAFE - designed for single-instance use.\n * For multi-instance deployments, implement a distributed locking strategy\n * or use a Kinesis-based solution with Redis lock provider.\n * @persistence Full - tasks stored in MongoDB until processed/expired\n * @requires MongoDB connection via abstract `collection` getter\n *\n * @features\n * - Stale task recovery: tasks stuck in 'processing' for >2 days are reset\n * - Bulk operations for efficiency\n * - Task expiration cleanup\n *\n * @example\n * ```typescript\n * class MyTaskStorage extends MongoDbAdapter {\n * get collection() { return db.collection('scheduled_tasks'); }\n * }\n * const adapter = new MyTaskStorage();\n * ```\n */\nexport abstract class MongoDbAdapter implements ITaskStorageAdapter<ObjectId> {\n private lifecycleProvider?: ITaskLifecycleProvider;\n private lifecycleMode: 'sync' | 'async' = 'async';\n\n protected constructor() {\n }\n\n setLifecycleConfig(config: TaskStorageLifecycleConfig): void {\n this.lifecycleProvider = config.lifecycleProvider;\n this.lifecycleMode = config.mode || 'async';\n }\n\n private emitLifecycleEvent<T>(\n callback: ((ctx: T) => void | Promise<void>) | undefined,\n ctx: T\n ): void {\n if (!callback) return;\n try {\n const result = callback(ctx);\n if (result instanceof Promise) {\n result.catch(err => logger.error(`[TQ] Lifecycle callback error: ${err}`));\n }\n } catch (err) {\n logger.error(`[TQ] Lifecycle callback error: ${err}`);\n }\n }\n\n abstract get collection(): Promise<Collection<Omit<CronTask<ObjectId>, 'id'> & { _id?: ObjectId; }>> ;\n\n async addTasksToScheduled(tasks: CronTask<ObjectId>[]): Promise<CronTask<ObjectId>[]> {\n if (!tasks.length) return [];\n\n const collection = await this.collection;\n\n const transformedTasks = tasks.map((task) => ({\n _id: task.id,\n type: task.type,\n payload: task.payload,\n execute_at: task.execute_at,\n status: task.status || 'scheduled',\n retries: task.retries || 0,\n created_at: task.created_at || new Date(),\n updated_at: new Date(),\n queue_id: task.queue_id,\n processing_started_at: task.processing_started_at || new Date(),\n expires_at: task.expires_at,\n task_group: task.task_group,\n task_hash: task.task_hash,\n retry_after: task.retry_after,\n execution_stats: task.execution_stats,\n force_store: task.force_store\n }));\n\n try {\n await collection.insertMany(transformedTasks, {ordered: false});\n return transformedTasks.map(toPublicTask);\n } catch (error: unknown) {\n if (error && typeof error === 'object' && 'writeErrors' in error) {\n const mongoError = error as { writeErrors: Array<{ index: number }> };\n const successfulTasks = transformedTasks.filter((_, index) =>\n !mongoError.writeErrors.some((e) => e.index === index)\n );\n return successfulTasks.map(toPublicTask);\n }\n throw error;\n }\n }\n\n async getMatureTasks(timestamp: number): Promise<CronTask<ObjectId>[]> {\n const collection = await this.collection;\n\n // Phase 1: Reset stale processing tasks\n const staleTimestamp = Date.now() - TWO_DAYS_MS;\n await collection.updateMany(\n {\n status: 'processing',\n processing_started_at: {$lt: new Date(staleTimestamp)}\n },\n {\n $set: {status: 'scheduled'}\n }\n );\n\n // Phase 2: Fetch and mark mature tasks\n const filter = {\n status: 'scheduled' as const,\n execute_at: {$lte: new Date(timestamp)}\n };\n\n const tasks = await collection\n .find(filter)\n .limit(1000)\n .toArray();\n\n if (tasks.length > 0) {\n const taskIds = tasks.map(t => t._id);\n await collection.updateMany(\n {_id: {$in: taskIds}},\n {\n $set: {\n status: 'processing',\n processing_started_at: new Date()\n }\n }\n );\n }\n\n return tasks.map(toPublicTask);\n }\n\n async markTasksAsProcessing(tasks: CronTask<ObjectId>[], processingStartedAt: Date): Promise<void> {\n const collection = await this.collection;\n const taskIds = tasks.map(t => t.id).filter(Boolean) as ObjectId[];\n\n await collection.updateMany(\n {_id: {$in: taskIds}},\n {\n $set: {\n status: 'processing',\n processing_started_at: processingStartedAt,\n updated_at: new Date()\n }\n }\n );\n }\n\n async markTasksAsExecuted(tasks: CronTask<ObjectId>[]): Promise<void> {\n const collection = await this.collection;\n const taskIds = tasks.map(t => t.id).filter(Boolean) as ObjectId[];\n\n\n await collection.updateMany(\n {_id: {$in: taskIds}},\n {\n $set: {\n status: 'executed',\n updated_at: new Date()\n }\n }\n );\n }\n\n async markTasksAsFailed(tasks: CronTask<ObjectId>[]): Promise<void> {\n const collection = await this.collection;\n const taskIds = tasks.map(t => t.id).filter(Boolean) as ObjectId[];\n\n\n await collection.updateMany(\n {_id: {$in: taskIds}},\n {\n $set: {\n status: 'failed',\n updated_at: new Date()\n }\n }\n );\n }\n\n async getTasksByIds(taskIds: ObjectId[]): Promise<CronTask<ObjectId>[]> {\n const collection = await this.collection;\n\n return collection\n .find({_id: {$in: taskIds}})\n .toArray()\n .then(result => result.map(toPublicTask));\n }\n\n async getCleanupStats(): Promise<{ orphanedTasks: number; expiredTasks: number }> {\n const collection = await this.collection;\n\n const orphanedBefore = new Date(Date.now() - TWO_DAYS_MS);\n const orphanedTasks = await collection.countDocuments({\n status: 'processing',\n processing_started_at: {$lt: orphanedBefore}\n });\n\n const expiredTasks = await collection.countDocuments({\n expires_at: {$lt: new Date()}\n });\n\n return {orphanedTasks, expiredTasks};\n }\n\n async cleanupTasks(orphanedBefore: Date, expiredBefore: Date): Promise<void> {\n const collection = await this.collection;\n\n // Clean up orphaned tasks\n await collection.deleteMany({\n status: 'processing',\n processing_started_at: {$lt: orphanedBefore}\n });\n\n // Clean up expired tasks\n await collection.deleteMany({\n expires_at: {$lt: expiredBefore}\n });\n }\n\n async updateTasks(updates: Array<{ id: ObjectId; updates: Partial<CronTask<ObjectId>> }>): Promise<void> {\n const collection = await this.collection;\n\n const bulkOps = updates.map(({id, updates}) => ({\n updateOne: {\n filter: {_id: id},\n update: {\n $set: {\n ...updates,\n updated_at: new Date()\n }\n }\n }\n }));\n\n if (bulkOps.length > 0) {\n // ordered: false allows remaining ops to continue if one fails (e.g., duplicate key)\n await collection.bulkWrite(bulkOps, {ordered: false});\n }\n }\n\n async upsertTasks(tasks: CronTask<ObjectId>[]): Promise<void> {\n if (!tasks.length) return;\n const collection = await this.collection;\n const now = new Date();\n\n const bulkOps = tasks.map(task => {\n const id = task.id || this.generateId();\n const {id: _id, status, execute_at, execution_stats, updated_at, ...rest} = task;\n return {\n updateOne: {\n filter: {_id: id},\n update: {\n $set: {\n status: task.status,\n execute_at: task.execute_at,\n execution_stats: task.execution_stats,\n updated_at: now\n },\n $setOnInsert: {\n ...rest,\n created_at: task.created_at || now,\n processing_started_at: task.processing_started_at || now\n }\n },\n upsert: true\n }\n };\n });\n\n // ordered: false allows remaining ops to continue if one fails\n await collection.bulkWrite(bulkOps, {ordered: false});\n }\n\n generateId() {\n return new ObjectId();\n }\n\n async close() {\n }\n\n async initialize() {\n }\n\n async markTasksAsIgnored(tasks: CronTask<ObjectId>[]): Promise<void> {\n const collection = await this.collection;\n const taskIds = tasks.map(t => t.id).filter(Boolean) as ObjectId[];\n\n\n await collection.updateMany(\n {_id: {$in: taskIds}},\n {\n $set: {\n status: 'ignored',\n //update execution_stats\n updated_at: new Date()\n },\n }\n );\n }\n}","import {ITaskStorageAdapter, TaskStorageLifecycleConfig} from \"./ITaskStorageAdapter\";\nimport {CronTask} from \"./types\";\nimport type {ITaskLifecycleProvider} from \"../core/lifecycle.js\";\n\n/**\n * In-memory task storage adapter for @supergrowthai/tq.\n *\n * @description Stores scheduled tasks in memory using a Map.\n * Data is lost on process restart - use for development and testing only.\n *\n * @use-case Development, testing, and prototyping\n * @multi-instance NOT SAFE - data is not shared between processes\n * @persistence NONE - all tasks lost on restart\n *\n * @features\n * - Fast in-memory operations\n * - Simple cleanup implementation\n * - Auto-generated string IDs\n *\n * @example\n * ```typescript\n * const adapter = new InMemoryAdapter();\n * const taskHandler = new TaskHandler(queue, taskQueue, adapter, cache);\n * ```\n */\nclass InMemoryAdapter implements ITaskStorageAdapter<string> {\n private scheduledTasks: Map<string, CronTask<string>> = new Map();\n private lifecycleProvider?: ITaskLifecycleProvider;\n private lifecycleMode: 'sync' | 'async' = 'async';\n\n setLifecycleConfig(config: TaskStorageLifecycleConfig): void {\n this.lifecycleProvider = config.lifecycleProvider;\n this.lifecycleMode = config.mode || 'async';\n }\n\n private emitLifecycleEvent<T>(\n callback: ((ctx: T) => void | Promise<void>) | undefined,\n ctx: T\n ): void {\n if (!callback) return;\n try {\n const result = callback(ctx);\n if (result instanceof Promise) {\n result.catch(err => console.error(`[TQ] Lifecycle callback error: ${err}`));\n }\n } catch (err) {\n console.error(`[TQ] Lifecycle callback error: ${err}`);\n }\n }\n\n async addTasksToScheduled(tasks: CronTask<string>[]): Promise<CronTask<string>[]> {\n const addedTasks = tasks.map(task => {\n const id = task.id || this.generateId();\n const taskWithId = {...task, id};\n this.scheduledTasks.set(id, taskWithId);\n return taskWithId;\n });\n return addedTasks;\n }\n\n async getMatureTasks(timestamp: number): Promise<CronTask<string>[]> {\n const matureTasks: CronTask<string>[] = [];\n for (const [id, task] of Array.from(this.scheduledTasks.entries())) {\n if (task.execute_at.getTime() <= timestamp && task.status !== 'processing' && task.status !== 'executed') {\n matureTasks.push(task);\n }\n }\n return matureTasks;\n }\n\n async markTasksAsProcessing(tasks: CronTask<string>[], processingStartedAt: Date): Promise<void> {\n for (const task of tasks) {\n const existingTask = this.scheduledTasks.get(task.id!);\n if (existingTask) {\n existingTask.status = 'processing';\n existingTask.processing_started_at = processingStartedAt;\n this.scheduledTasks.set(task.id!, existingTask);\n }\n }\n }\n\n async markTasksAsExecuted(tasks: CronTask<string>[]): Promise<void> {\n for (const task of tasks) {\n const existingTask = this.scheduledTasks.get(task.id!);\n if (existingTask) {\n existingTask.status = 'executed';\n existingTask.execute_at = new Date();\n this.scheduledTasks.set(task.id!, existingTask);\n }\n }\n }\n\n async markTasksAsFailed(tasks: CronTask<string>[]): Promise<void> {\n for (const task of tasks) {\n const existingTask = this.scheduledTasks.get(task.id!);\n if (existingTask) {\n existingTask.status = 'failed';\n existingTask.execution_stats = {...existingTask.execution_stats, failed_at: new Date()};\n this.scheduledTasks.set(task.id!, existingTask);\n }\n }\n }\n\n async getTasksByIds(taskIds: string[]): Promise<CronTask<string>[]> {\n return taskIds.map(id => this.scheduledTasks.get(id)).filter(Boolean) as CronTask<string>[];\n }\n\n async updateTasks(updates: Array<{ id: string; updates: Partial<CronTask<string>> }>): Promise<void> {\n for (const {id, updates: taskUpdates} of updates) {\n const task = this.scheduledTasks.get(id);\n if (task) {\n Object.assign(task, taskUpdates);\n this.scheduledTasks.set(id, task);\n }\n }\n }\n\n async upsertTasks(tasks: CronTask<string>[]): Promise<void> {\n for (const task of tasks) {\n const id = task.id || this.generateId();\n const existing = this.scheduledTasks.get(id);\n if (existing) {\n Object.assign(existing, {\n status: task.status,\n execute_at: task.execute_at,\n execution_stats: task.execution_stats,\n updated_at: new Date()\n });\n } else {\n this.scheduledTasks.set(id, {...task, id});\n }\n }\n }\n\n async getCleanupStats(): Promise<{ orphanedTasks: number; expiredTasks: number }> {\n let orphanedTasks = 0;\n let expiredTasks = 0;\n const now = Date.now();\n\n for (const task of Array.from(this.scheduledTasks.values())) {\n if (task.status === 'processing' && task.processing_started_at && (now - task.processing_started_at.getTime()) > 300000) {\n orphanedTasks++;\n }\n if (task.expires_at && now > task.expires_at.getTime()) {\n expiredTasks++;\n }\n }\n\n return {orphanedTasks, expiredTasks};\n }\n\n async cleanupTasks(orphanedBefore: Date, expiredBefore: Date): Promise<void> {\n for (const [id, task] of Array.from(this.scheduledTasks.entries())) {\n const shouldDelete =\n (task.status === 'processing' && task.processing_started_at && task.processing_started_at < orphanedBefore) ||\n (task.expires_at && task.expires_at < expiredBefore);\n\n if (shouldDelete) {\n this.scheduledTasks.delete(id);\n }\n }\n }\n\n async initialize(): Promise<void> {\n // No initialization needed for memory adapter\n }\n\n async close(): Promise<void> {\n this.scheduledTasks.clear();\n }\n\n generateId(): string {\n return `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n }\n\n async markTasksAsIgnored(tasks: CronTask<string>[]) {\n for (const task of tasks) {\n const existingTask = this.scheduledTasks.get(task.id!);\n if (existingTask) {\n existingTask.status = 'ignored';\n existingTask.execution_stats = {...existingTask.execution_stats, ignore_reason: \"unknown type\"};\n this.scheduledTasks.set(task.id!, existingTask);\n }\n }\n }\n}\n\nexport {InMemoryAdapter}","import {ITaskStorageAdapter, TaskStorageLifecycleConfig} from \"./ITaskStorageAdapter.js\";\nimport {CronTask} from \"./types.js\";\nimport {Logger, LogLevel} from \"@supergrowthai/utils\";\nimport {PrismaClient} from \"@prisma/client/extension\";\nimport type {ITaskLifecycleProvider} from \"../core/lifecycle.js\";\n\nconst logger = new Logger('PrismaAdapter', LogLevel.INFO);\nconst TWO_DAYS_MS = 2 * 24 * 60 * 60 * 1000;\n\n\n// ---- Type utilities ----\n\n/** A Prisma client that is guaranteed to have model delegate K. */\nexport type ClientWithModel<K extends keyof PrismaClient> =\n Pick<PrismaClient, K>;\n\n/** Extract the entity (row) type from a model delegate. */\ntype EntityOf<D> =\n D extends { findUnique(args: any): Promise<infer U | null> } ? U :\n D extends { findFirst(args: any): Promise<infer U | null> } ? U :\n D extends { findMany(args?: any): Promise<(infer U)[]> } ? U :\n never;\n\n/** Compile-time guard: model's entity must be compatible with the shape you require. */\ntype EnsureModelShape<Delegate, Needed> =\n EntityOf<Delegate> extends Needed ? unknown : never;\n\n/**\n * Prisma task storage adapter for @supergrowthai/tq.\n *\n * @description Persists scheduled tasks to any Prisma model with status tracking.\n * Uses application-level locking designed for single-instance deployments.\n *\n * @use-case Single-instance production deployments with Prisma ORM\n * @multi-instance NOT SAFE - designed for single-instance use.\n * For multi-instance deployments, implement a distributed locking strategy\n * or use a Kinesis-based solution with Redis lock provider.\n * @persistence Full - tasks stored in database until processed/expired\n * @requires Prisma client with a model matching CronTask structure\n *\n * @features\n * - Stale task recovery: tasks stuck in 'processing' for >2 days are reset\n * - Transaction support for batch updates\n * - Task expiration cleanup\n *\n * @typeParam TId - The ID type (string, number, etc.)\n * @typeParam K - The Prisma model key (e.g. 'scheduledTask')\n * @typeParam Msg - The task type extending CronTask<TId>\n *\n * @example\n * ```typescript\n * const adapter = new PrismaAdapter({\n * prismaClient: prisma,\n * messageModel: 'scheduledTask'\n * });\n * ```\n */\nexport class PrismaAdapter<\n TId = any,\n K extends keyof PrismaClient = never,\n Msg extends CronTask<TId> = CronTask<TId>\n> implements ITaskStorageAdapter<TId> {\n private lifecycleProvider?: ITaskLifecycleProvider;\n private lifecycleMode: 'sync' | 'async' = 'async';\n\n constructor(\n private config: {\n prismaClient: ClientWithModel<K>;\n messageModel: K;\n /**\n * Phantom type param that enforces:\n * - client has model K\n * - entity type of client[K] extends Msg (which extends BaseMessage<TId>)\n * Do not pass at runtime.\n */\n _shapeCheck?: EnsureModelShape<PrismaClient[K], Msg> & (Msg extends CronTask<TId> & {\n id: TId\n } ? unknown : never);\n }\n ) {\n }\n\n setLifecycleConfig(config: TaskStorageLifecycleConfig): void {\n this.lifecycleProvider = config.lifecycleProvider;\n this.lifecycleMode = config.mode || 'async';\n }\n\n private emitLifecycleEvent<T>(\n callback: ((ctx: T) => void | Promise<void>) | undefined,\n ctx: T\n ): void {\n if (!callback) return;\n try {\n const result = callback(ctx);\n if (result instanceof Promise) {\n result.catch(err => logger.error(`[TQ] Lifecycle callback error: ${err}`));\n }\n } catch (err) {\n logger.error(`[TQ] Lifecycle callback error: ${err}`);\n }\n }\n\n get prismaClient(): PrismaClient {\n return this.config.prismaClient;\n }\n\n get taskTableName(): string {\n return String(this.config.messageModel);\n }\n\n protected get delegate(): PrismaClient[K] {\n return this.config.prismaClient[this.config.messageModel];\n }\n\n /**\n * Persist tasks to the database as scheduled.\n *\n * **Default implementation:** Uses individual creates with duplicate detection\n * for maximum database compatibility (SQLite, Postgres, MySQL, etc.).\n *\n * **Performance note:** This is O(n) database round-trips. For high-throughput\n * scenarios (100+ tasks/batch), override this method with a batch implementation:\n *\n * @example PostgreSQL/MySQL optimization:\n * ```typescript\n * class OptimizedPrismaAdapter extends PrismaAdapter {\n * async addTasksToScheduled(tasks) {\n * if (!tasks.length) return [];\n * await this.delegate.createMany({\n * data: tasks.map(t => ({ ...t, id: t.id || this.generateId() })),\n * skipDuplicates: true\n * });\n * return tasks;\n * }\n * }\n * ```\n */\n async addTasksToScheduled(tasks: CronTask<TId>[]): Promise<CronTask<TId>[]> {\n if (!tasks.length) return [];\n\n // Performance hint for high-throughput scenarios\n if (tasks.length > 50) {\n logger.warn(`[PrismaAdapter] Processing ${tasks.length} tasks sequentially (O(n) round-trips). For Postgres/MySQL, override addTasksToScheduled with createMany for better performance.`);\n }\n\n // Sequential creates for broad DB compatibility (SQLite, CockroachDB, etc.)\n // Override this method for batch optimization on Postgres/MySQL\n const results: CronTask<TId>[] = [];\n for (const task of tasks) {\n try {\n await this.delegate.create({\n data: {\n ...task,\n id: task.id || this.generateId(),\n status: task.status || 'scheduled',\n retries: task.retries || 0,\n created_at: task.created_at || new Date(),\n updated_at: new Date(),\n processing_started_at: task.processing_started_at || new Date()\n }\n });\n results.push(task);\n } catch (error: unknown) {\n logger.warn(`Task skipped (likely duplicate): ${error}`);\n }\n }\n return results;\n }\n\n async getMatureTasks(timestamp: number): Promise<CronTask<TId>[]> {\n const staleTimestamp = Date.now() - TWO_DAYS_MS;\n\n await this.delegate.updateMany({\n where: {\n status: 'processing',\n processing_started_at: {lt: new Date(staleTimestamp)}\n },\n data: {status: 'scheduled'}\n });\n\n const tasks = await this.delegate.findMany({\n where: {\n status: 'scheduled',\n execute_at: {lte: new Date(timestamp)}\n },\n take: 1000,\n orderBy: {execute_at: 'asc'}\n });\n\n if (tasks.length > 0) {\n const taskIds = tasks.map((t: any) => t.id);\n await this.delegate.updateMany({\n where: {id: {in: taskIds}},\n data: {\n status: 'processing',\n processing_started_at: new Date()\n }\n });\n }\n\n return tasks;\n }\n\n async markTasksAsProcessing(tasks: CronTask<TId>[], processingStartedAt: Date): Promise<void> {\n const taskIds = tasks.map(t => t.id).filter(Boolean);\n if (!taskIds.length) return;\n\n await this.delegate.updateMany({\n where: {id: {in: taskIds}},\n data: {\n status: 'processing',\n processing_started_at: processingStartedAt,\n updated_at: new Date()\n }\n });\n }\n\n async markTasksAsExecuted(tasks: CronTask<TId>[]): Promise<void> {\n const taskIds = tasks.map(t => t.id).filter(Boolean);\n if (!taskIds.length) return;\n\n await this.delegate.updateMany({\n where: {id: {in: taskIds}},\n data: {status: 'executed', updated_at: new Date()}\n });\n }\n\n async markTasksAsFailed(tasks: CronTask<TId>[]): Promise<void> {\n const taskIds = tasks.map(t => t.id).filter(Boolean);\n if (!taskIds.length) return;\n\n await this.delegate.updateMany({\n where: {id: {in: taskIds}},\n data: {status: 'failed', updated_at: new Date()}\n });\n }\n\n async markTasksAsIgnored(tasks: CronTask<TId>[]): Promise<void> {\n const taskIds = tasks.map(t => t.id).filter(Boolean);\n if (!taskIds.length) return;\n\n await this.delegate.updateMany({\n where: {id: {in: taskIds}},\n data: {status: 'ignored', updated_at: new Date()}\n });\n }\n\n async getTasksByIds(taskIds: TId[]): Promise<CronTask<TId>[]> {\n if (!taskIds.length) return [];\n\n return this.delegate.findMany({\n where: {id: {in: taskIds}}\n });\n }\n\n async updateTasks(updatesList: Array<{ id: TId; updates: Partial<CronTask<TId>> }>): Promise<void> {\n //fixme do we need a transaction. good but defo ?\n await this.prismaClient\n .$transaction(async (prisma) => {\n for (const {id, updates} of updatesList) {\n await (prisma as any)[this.taskTableName]\n .update({\n where: {id: id},\n data: {...updates, updated_at: new Date()}\n });\n }\n });\n }\n\n async upsertTasks(tasks: CronTask<TId>[]): Promise<void> {\n if (!tasks.length) return;\n\n const now = new Date();\n const delegate = this.delegate;\n\n // Each task may have different status/execute_at/execution_stats,\n // so per-task upsert is unavoidable. Wrapped in a transaction for atomicity.\n await this.prismaClient\n .$transaction(\n tasks.map(task => delegate.upsert({\n where: {id: task.id},\n create: {\n ...task,\n created_at: task.created_at || now,\n updated_at: now,\n processing_started_at: task.processing_started_at || now\n },\n update: {\n status: task.status,\n execute_at: task.execute_at,\n execution_stats: task.execution_stats,\n updated_at: now\n }\n }))\n );\n }\n\n async getCleanupStats(): Promise<{ orphanedTasks: number; expiredTasks: number }> {\n const orphanedBefore = new Date(Date.now() - TWO_DAYS_MS);\n\n const [orphanedTasks, expiredTasks] = await Promise.all([\n this.delegate.count({\n where: {\n status: 'processing',\n processing_started_at: {lt: orphanedBefore}\n }\n }),\n this.delegate.count({\n where: {expires_at: {lt: new Date()}}\n })\n ]);\n\n return {orphanedTasks, expiredTasks};\n }\n\n async cleanupTasks(orphanedBefore: Date, expiredBefore: Date): Promise<void> {\n await Promise.all([\n this.delegate.deleteMany({\n where: {\n status: 'processing',\n processing_started_at: {lt: orphanedBefore}\n }\n }),\n this.delegate.deleteMany({\n where: {expires_at: {lt: expiredBefore}}\n })\n ]);\n }\n\n generateId(): TId {\n //needs to be overriden when prisma client is of mongodb\n return crypto.randomUUID() as TId;\n }\n\n async initialize(): Promise<void> {\n }\n\n async close(): Promise<void> {\n }\n}"],"names":["logger","Logger","LogLevel","TWO_DAYS_MS","updates","ObjectId"],"mappings":"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"}
|
|
@@ -170,9 +170,38 @@ class MongoDbAdapter {
|
|
|
170
170
|
}
|
|
171
171
|
}));
|
|
172
172
|
if (bulkOps.length > 0) {
|
|
173
|
-
await collection.bulkWrite(bulkOps);
|
|
173
|
+
await collection.bulkWrite(bulkOps, { ordered: false });
|
|
174
174
|
}
|
|
175
175
|
}
|
|
176
|
+
async upsertTasks(tasks) {
|
|
177
|
+
if (!tasks.length) return;
|
|
178
|
+
const collection = await this.collection;
|
|
179
|
+
const now = /* @__PURE__ */ new Date();
|
|
180
|
+
const bulkOps = tasks.map((task) => {
|
|
181
|
+
const id = task.id || this.generateId();
|
|
182
|
+
const { id: _id, status, execute_at, execution_stats, updated_at, ...rest } = task;
|
|
183
|
+
return {
|
|
184
|
+
updateOne: {
|
|
185
|
+
filter: { _id: id },
|
|
186
|
+
update: {
|
|
187
|
+
$set: {
|
|
188
|
+
status: task.status,
|
|
189
|
+
execute_at: task.execute_at,
|
|
190
|
+
execution_stats: task.execution_stats,
|
|
191
|
+
updated_at: now
|
|
192
|
+
},
|
|
193
|
+
$setOnInsert: {
|
|
194
|
+
...rest,
|
|
195
|
+
created_at: task.created_at || now,
|
|
196
|
+
processing_started_at: task.processing_started_at || now
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
upsert: true
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
});
|
|
203
|
+
await collection.bulkWrite(bulkOps, { ordered: false });
|
|
204
|
+
}
|
|
176
205
|
generateId() {
|
|
177
206
|
return new ObjectId();
|
|
178
207
|
}
|
|
@@ -275,6 +304,22 @@ class InMemoryAdapter {
|
|
|
275
304
|
}
|
|
276
305
|
}
|
|
277
306
|
}
|
|
307
|
+
async upsertTasks(tasks) {
|
|
308
|
+
for (const task of tasks) {
|
|
309
|
+
const id = task.id || this.generateId();
|
|
310
|
+
const existing = this.scheduledTasks.get(id);
|
|
311
|
+
if (existing) {
|
|
312
|
+
Object.assign(existing, {
|
|
313
|
+
status: task.status,
|
|
314
|
+
execute_at: task.execute_at,
|
|
315
|
+
execution_stats: task.execution_stats,
|
|
316
|
+
updated_at: /* @__PURE__ */ new Date()
|
|
317
|
+
});
|
|
318
|
+
} else {
|
|
319
|
+
this.scheduledTasks.set(id, { ...task, id });
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
278
323
|
async getCleanupStats() {
|
|
279
324
|
let orphanedTasks = 0;
|
|
280
325
|
let expiredTasks = 0;
|
|
@@ -347,26 +392,54 @@ class PrismaAdapter {
|
|
|
347
392
|
get delegate() {
|
|
348
393
|
return this.config.prismaClient[this.config.messageModel];
|
|
349
394
|
}
|
|
395
|
+
/**
|
|
396
|
+
* Persist tasks to the database as scheduled.
|
|
397
|
+
*
|
|
398
|
+
* **Default implementation:** Uses individual creates with duplicate detection
|
|
399
|
+
* for maximum database compatibility (SQLite, Postgres, MySQL, etc.).
|
|
400
|
+
*
|
|
401
|
+
* **Performance note:** This is O(n) database round-trips. For high-throughput
|
|
402
|
+
* scenarios (100+ tasks/batch), override this method with a batch implementation:
|
|
403
|
+
*
|
|
404
|
+
* @example PostgreSQL/MySQL optimization:
|
|
405
|
+
* ```typescript
|
|
406
|
+
* class OptimizedPrismaAdapter extends PrismaAdapter {
|
|
407
|
+
* async addTasksToScheduled(tasks) {
|
|
408
|
+
* if (!tasks.length) return [];
|
|
409
|
+
* await this.delegate.createMany({
|
|
410
|
+
* data: tasks.map(t => ({ ...t, id: t.id || this.generateId() })),
|
|
411
|
+
* skipDuplicates: true
|
|
412
|
+
* });
|
|
413
|
+
* return tasks;
|
|
414
|
+
* }
|
|
415
|
+
* }
|
|
416
|
+
* ```
|
|
417
|
+
*/
|
|
350
418
|
async addTasksToScheduled(tasks) {
|
|
351
419
|
if (!tasks.length) return [];
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
data: tasks.map((task) => ({
|
|
355
|
-
...task,
|
|
356
|
-
id: task.id || this.generateId(),
|
|
357
|
-
status: task.status || "scheduled",
|
|
358
|
-
retries: task.retries || 0,
|
|
359
|
-
created_at: task.created_at || /* @__PURE__ */ new Date(),
|
|
360
|
-
updated_at: /* @__PURE__ */ new Date(),
|
|
361
|
-
processing_started_at: task.processing_started_at || /* @__PURE__ */ new Date()
|
|
362
|
-
})),
|
|
363
|
-
skipDuplicates: true
|
|
364
|
-
});
|
|
365
|
-
return tasks;
|
|
366
|
-
} catch (error) {
|
|
367
|
-
logger.warn(`Some tasks skipped due to duplicates: ${error}`);
|
|
368
|
-
return tasks;
|
|
420
|
+
if (tasks.length > 50) {
|
|
421
|
+
logger.warn(`[PrismaAdapter] Processing ${tasks.length} tasks sequentially (O(n) round-trips). For Postgres/MySQL, override addTasksToScheduled with createMany for better performance.`);
|
|
369
422
|
}
|
|
423
|
+
const results = [];
|
|
424
|
+
for (const task of tasks) {
|
|
425
|
+
try {
|
|
426
|
+
await this.delegate.create({
|
|
427
|
+
data: {
|
|
428
|
+
...task,
|
|
429
|
+
id: task.id || this.generateId(),
|
|
430
|
+
status: task.status || "scheduled",
|
|
431
|
+
retries: task.retries || 0,
|
|
432
|
+
created_at: task.created_at || /* @__PURE__ */ new Date(),
|
|
433
|
+
updated_at: /* @__PURE__ */ new Date(),
|
|
434
|
+
processing_started_at: task.processing_started_at || /* @__PURE__ */ new Date()
|
|
435
|
+
}
|
|
436
|
+
});
|
|
437
|
+
results.push(task);
|
|
438
|
+
} catch (error) {
|
|
439
|
+
logger.warn(`Task skipped (likely duplicate): ${error}`);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
return results;
|
|
370
443
|
}
|
|
371
444
|
async getMatureTasks(timestamp) {
|
|
372
445
|
const staleTimestamp = Date.now() - TWO_DAYS_MS;
|
|
@@ -449,6 +522,28 @@ class PrismaAdapter {
|
|
|
449
522
|
}
|
|
450
523
|
});
|
|
451
524
|
}
|
|
525
|
+
async upsertTasks(tasks) {
|
|
526
|
+
if (!tasks.length) return;
|
|
527
|
+
const now = /* @__PURE__ */ new Date();
|
|
528
|
+
const delegate = this.delegate;
|
|
529
|
+
await this.prismaClient.$transaction(
|
|
530
|
+
tasks.map((task) => delegate.upsert({
|
|
531
|
+
where: { id: task.id },
|
|
532
|
+
create: {
|
|
533
|
+
...task,
|
|
534
|
+
created_at: task.created_at || now,
|
|
535
|
+
updated_at: now,
|
|
536
|
+
processing_started_at: task.processing_started_at || now
|
|
537
|
+
},
|
|
538
|
+
update: {
|
|
539
|
+
status: task.status,
|
|
540
|
+
execute_at: task.execute_at,
|
|
541
|
+
execution_stats: task.execution_stats,
|
|
542
|
+
updated_at: now
|
|
543
|
+
}
|
|
544
|
+
}))
|
|
545
|
+
);
|
|
546
|
+
}
|
|
452
547
|
async getCleanupStats() {
|
|
453
548
|
const orphanedBefore = new Date(Date.now() - TWO_DAYS_MS);
|
|
454
549
|
const [orphanedTasks, expiredTasks] = await Promise.all([
|
|
@@ -490,4 +585,4 @@ export {
|
|
|
490
585
|
MongoDbAdapter as M,
|
|
491
586
|
PrismaAdapter as P
|
|
492
587
|
};
|
|
493
|
-
//# sourceMappingURL=PrismaAdapter-
|
|
588
|
+
//# sourceMappingURL=PrismaAdapter-Dy7MV090.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PrismaAdapter-Dy7MV090.js","sources":["../src/adapters/MongoDbAdapter.ts","../src/adapters/InMemoryAdapter.ts","../src/adapters/PrismaAdapter.ts"],"sourcesContent":["import {Collection, ObjectId} from \"mongodb\";\nimport {ITaskStorageAdapter, TaskStorageLifecycleConfig} from \"./ITaskStorageAdapter.js\";\nimport {CronTask} from \"./types.js\";\nimport {Logger, LogLevel} from \"@supergrowthai/utils\";\nimport type {ITaskLifecycleProvider} from \"../core/lifecycle.js\";\n\nconst logger = new Logger('MongoDbAdapter', LogLevel.INFO);\n\nconst TWO_DAYS_MS = 2 * 24 * 60 * 60 * 1000;\n\n/**\n * Convert MongoDB document with _id to CronTask with id\n */\nfunction toPublicTask<T>({_id, ...rest}: Omit<CronTask<T>, 'id'> & { _id: T }): CronTask<T> {\n return {...rest, id: _id} as CronTask<T>;\n}\n\n/**\n * MongoDB task storage adapter for @supergrowthai/tq.\n *\n * @description Persists scheduled tasks to MongoDB collection with status tracking.\n * Uses application-level locking designed for single-instance deployments.\n *\n * @use-case Single-instance production deployments\n * @multi-instance NOT SAFE - designed for single-instance use.\n * For multi-instance deployments, implement a distributed locking strategy\n * or use a Kinesis-based solution with Redis lock provider.\n * @persistence Full - tasks stored in MongoDB until processed/expired\n * @requires MongoDB connection via abstract `collection` getter\n *\n * @features\n * - Stale task recovery: tasks stuck in 'processing' for >2 days are reset\n * - Bulk operations for efficiency\n * - Task expiration cleanup\n *\n * @example\n * ```typescript\n * class MyTaskStorage extends MongoDbAdapter {\n * get collection() { return db.collection('scheduled_tasks'); }\n * }\n * const adapter = new MyTaskStorage();\n * ```\n */\nexport abstract class MongoDbAdapter implements ITaskStorageAdapter<ObjectId> {\n private lifecycleProvider?: ITaskLifecycleProvider;\n private lifecycleMode: 'sync' | 'async' = 'async';\n\n protected constructor() {\n }\n\n setLifecycleConfig(config: TaskStorageLifecycleConfig): void {\n this.lifecycleProvider = config.lifecycleProvider;\n this.lifecycleMode = config.mode || 'async';\n }\n\n private emitLifecycleEvent<T>(\n callback: ((ctx: T) => void | Promise<void>) | undefined,\n ctx: T\n ): void {\n if (!callback) return;\n try {\n const result = callback(ctx);\n if (result instanceof Promise) {\n result.catch(err => logger.error(`[TQ] Lifecycle callback error: ${err}`));\n }\n } catch (err) {\n logger.error(`[TQ] Lifecycle callback error: ${err}`);\n }\n }\n\n abstract get collection(): Promise<Collection<Omit<CronTask<ObjectId>, 'id'> & { _id?: ObjectId; }>> ;\n\n async addTasksToScheduled(tasks: CronTask<ObjectId>[]): Promise<CronTask<ObjectId>[]> {\n if (!tasks.length) return [];\n\n const collection = await this.collection;\n\n const transformedTasks = tasks.map((task) => ({\n _id: task.id,\n type: task.type,\n payload: task.payload,\n execute_at: task.execute_at,\n status: task.status || 'scheduled',\n retries: task.retries || 0,\n created_at: task.created_at || new Date(),\n updated_at: new Date(),\n queue_id: task.queue_id,\n processing_started_at: task.processing_started_at || new Date(),\n expires_at: task.expires_at,\n task_group: task.task_group,\n task_hash: task.task_hash,\n retry_after: task.retry_after,\n execution_stats: task.execution_stats,\n force_store: task.force_store\n }));\n\n try {\n await collection.insertMany(transformedTasks, {ordered: false});\n return transformedTasks.map(toPublicTask);\n } catch (error: unknown) {\n if (error && typeof error === 'object' && 'writeErrors' in error) {\n const mongoError = error as { writeErrors: Array<{ index: number }> };\n const successfulTasks = transformedTasks.filter((_, index) =>\n !mongoError.writeErrors.some((e) => e.index === index)\n );\n return successfulTasks.map(toPublicTask);\n }\n throw error;\n }\n }\n\n async getMatureTasks(timestamp: number): Promise<CronTask<ObjectId>[]> {\n const collection = await this.collection;\n\n // Phase 1: Reset stale processing tasks\n const staleTimestamp = Date.now() - TWO_DAYS_MS;\n await collection.updateMany(\n {\n status: 'processing',\n processing_started_at: {$lt: new Date(staleTimestamp)}\n },\n {\n $set: {status: 'scheduled'}\n }\n );\n\n // Phase 2: Fetch and mark mature tasks\n const filter = {\n status: 'scheduled' as const,\n execute_at: {$lte: new Date(timestamp)}\n };\n\n const tasks = await collection\n .find(filter)\n .limit(1000)\n .toArray();\n\n if (tasks.length > 0) {\n const taskIds = tasks.map(t => t._id);\n await collection.updateMany(\n {_id: {$in: taskIds}},\n {\n $set: {\n status: 'processing',\n processing_started_at: new Date()\n }\n }\n );\n }\n\n return tasks.map(toPublicTask);\n }\n\n async markTasksAsProcessing(tasks: CronTask<ObjectId>[], processingStartedAt: Date): Promise<void> {\n const collection = await this.collection;\n const taskIds = tasks.map(t => t.id).filter(Boolean) as ObjectId[];\n\n await collection.updateMany(\n {_id: {$in: taskIds}},\n {\n $set: {\n status: 'processing',\n processing_started_at: processingStartedAt,\n updated_at: new Date()\n }\n }\n );\n }\n\n async markTasksAsExecuted(tasks: CronTask<ObjectId>[]): Promise<void> {\n const collection = await this.collection;\n const taskIds = tasks.map(t => t.id).filter(Boolean) as ObjectId[];\n\n\n await collection.updateMany(\n {_id: {$in: taskIds}},\n {\n $set: {\n status: 'executed',\n updated_at: new Date()\n }\n }\n );\n }\n\n async markTasksAsFailed(tasks: CronTask<ObjectId>[]): Promise<void> {\n const collection = await this.collection;\n const taskIds = tasks.map(t => t.id).filter(Boolean) as ObjectId[];\n\n\n await collection.updateMany(\n {_id: {$in: taskIds}},\n {\n $set: {\n status: 'failed',\n updated_at: new Date()\n }\n }\n );\n }\n\n async getTasksByIds(taskIds: ObjectId[]): Promise<CronTask<ObjectId>[]> {\n const collection = await this.collection;\n\n return collection\n .find({_id: {$in: taskIds}})\n .toArray()\n .then(result => result.map(toPublicTask));\n }\n\n async getCleanupStats(): Promise<{ orphanedTasks: number; expiredTasks: number }> {\n const collection = await this.collection;\n\n const orphanedBefore = new Date(Date.now() - TWO_DAYS_MS);\n const orphanedTasks = await collection.countDocuments({\n status: 'processing',\n processing_started_at: {$lt: orphanedBefore}\n });\n\n const expiredTasks = await collection.countDocuments({\n expires_at: {$lt: new Date()}\n });\n\n return {orphanedTasks, expiredTasks};\n }\n\n async cleanupTasks(orphanedBefore: Date, expiredBefore: Date): Promise<void> {\n const collection = await this.collection;\n\n // Clean up orphaned tasks\n await collection.deleteMany({\n status: 'processing',\n processing_started_at: {$lt: orphanedBefore}\n });\n\n // Clean up expired tasks\n await collection.deleteMany({\n expires_at: {$lt: expiredBefore}\n });\n }\n\n async updateTasks(updates: Array<{ id: ObjectId; updates: Partial<CronTask<ObjectId>> }>): Promise<void> {\n const collection = await this.collection;\n\n const bulkOps = updates.map(({id, updates}) => ({\n updateOne: {\n filter: {_id: id},\n update: {\n $set: {\n ...updates,\n updated_at: new Date()\n }\n }\n }\n }));\n\n if (bulkOps.length > 0) {\n // ordered: false allows remaining ops to continue if one fails (e.g., duplicate key)\n await collection.bulkWrite(bulkOps, {ordered: false});\n }\n }\n\n async upsertTasks(tasks: CronTask<ObjectId>[]): Promise<void> {\n if (!tasks.length) return;\n const collection = await this.collection;\n const now = new Date();\n\n const bulkOps = tasks.map(task => {\n const id = task.id || this.generateId();\n const {id: _id, status, execute_at, execution_stats, updated_at, ...rest} = task;\n return {\n updateOne: {\n filter: {_id: id},\n update: {\n $set: {\n status: task.status,\n execute_at: task.execute_at,\n execution_stats: task.execution_stats,\n updated_at: now\n },\n $setOnInsert: {\n ...rest,\n created_at: task.created_at || now,\n processing_started_at: task.processing_started_at || now\n }\n },\n upsert: true\n }\n };\n });\n\n // ordered: false allows remaining ops to continue if one fails\n await collection.bulkWrite(bulkOps, {ordered: false});\n }\n\n generateId() {\n return new ObjectId();\n }\n\n async close() {\n }\n\n async initialize() {\n }\n\n async markTasksAsIgnored(tasks: CronTask<ObjectId>[]): Promise<void> {\n const collection = await this.collection;\n const taskIds = tasks.map(t => t.id).filter(Boolean) as ObjectId[];\n\n\n await collection.updateMany(\n {_id: {$in: taskIds}},\n {\n $set: {\n status: 'ignored',\n //update execution_stats\n updated_at: new Date()\n },\n }\n );\n }\n}","import {ITaskStorageAdapter, TaskStorageLifecycleConfig} from \"./ITaskStorageAdapter\";\nimport {CronTask} from \"./types\";\nimport type {ITaskLifecycleProvider} from \"../core/lifecycle.js\";\n\n/**\n * In-memory task storage adapter for @supergrowthai/tq.\n *\n * @description Stores scheduled tasks in memory using a Map.\n * Data is lost on process restart - use for development and testing only.\n *\n * @use-case Development, testing, and prototyping\n * @multi-instance NOT SAFE - data is not shared between processes\n * @persistence NONE - all tasks lost on restart\n *\n * @features\n * - Fast in-memory operations\n * - Simple cleanup implementation\n * - Auto-generated string IDs\n *\n * @example\n * ```typescript\n * const adapter = new InMemoryAdapter();\n * const taskHandler = new TaskHandler(queue, taskQueue, adapter, cache);\n * ```\n */\nclass InMemoryAdapter implements ITaskStorageAdapter<string> {\n private scheduledTasks: Map<string, CronTask<string>> = new Map();\n private lifecycleProvider?: ITaskLifecycleProvider;\n private lifecycleMode: 'sync' | 'async' = 'async';\n\n setLifecycleConfig(config: TaskStorageLifecycleConfig): void {\n this.lifecycleProvider = config.lifecycleProvider;\n this.lifecycleMode = config.mode || 'async';\n }\n\n private emitLifecycleEvent<T>(\n callback: ((ctx: T) => void | Promise<void>) | undefined,\n ctx: T\n ): void {\n if (!callback) return;\n try {\n const result = callback(ctx);\n if (result instanceof Promise) {\n result.catch(err => console.error(`[TQ] Lifecycle callback error: ${err}`));\n }\n } catch (err) {\n console.error(`[TQ] Lifecycle callback error: ${err}`);\n }\n }\n\n async addTasksToScheduled(tasks: CronTask<string>[]): Promise<CronTask<string>[]> {\n const addedTasks = tasks.map(task => {\n const id = task.id || this.generateId();\n const taskWithId = {...task, id};\n this.scheduledTasks.set(id, taskWithId);\n return taskWithId;\n });\n return addedTasks;\n }\n\n async getMatureTasks(timestamp: number): Promise<CronTask<string>[]> {\n const matureTasks: CronTask<string>[] = [];\n for (const [id, task] of Array.from(this.scheduledTasks.entries())) {\n if (task.execute_at.getTime() <= timestamp && task.status !== 'processing' && task.status !== 'executed') {\n matureTasks.push(task);\n }\n }\n return matureTasks;\n }\n\n async markTasksAsProcessing(tasks: CronTask<string>[], processingStartedAt: Date): Promise<void> {\n for (const task of tasks) {\n const existingTask = this.scheduledTasks.get(task.id!);\n if (existingTask) {\n existingTask.status = 'processing';\n existingTask.processing_started_at = processingStartedAt;\n this.scheduledTasks.set(task.id!, existingTask);\n }\n }\n }\n\n async markTasksAsExecuted(tasks: CronTask<string>[]): Promise<void> {\n for (const task of tasks) {\n const existingTask = this.scheduledTasks.get(task.id!);\n if (existingTask) {\n existingTask.status = 'executed';\n existingTask.execute_at = new Date();\n this.scheduledTasks.set(task.id!, existingTask);\n }\n }\n }\n\n async markTasksAsFailed(tasks: CronTask<string>[]): Promise<void> {\n for (const task of tasks) {\n const existingTask = this.scheduledTasks.get(task.id!);\n if (existingTask) {\n existingTask.status = 'failed';\n existingTask.execution_stats = {...existingTask.execution_stats, failed_at: new Date()};\n this.scheduledTasks.set(task.id!, existingTask);\n }\n }\n }\n\n async getTasksByIds(taskIds: string[]): Promise<CronTask<string>[]> {\n return taskIds.map(id => this.scheduledTasks.get(id)).filter(Boolean) as CronTask<string>[];\n }\n\n async updateTasks(updates: Array<{ id: string; updates: Partial<CronTask<string>> }>): Promise<void> {\n for (const {id, updates: taskUpdates} of updates) {\n const task = this.scheduledTasks.get(id);\n if (task) {\n Object.assign(task, taskUpdates);\n this.scheduledTasks.set(id, task);\n }\n }\n }\n\n async upsertTasks(tasks: CronTask<string>[]): Promise<void> {\n for (const task of tasks) {\n const id = task.id || this.generateId();\n const existing = this.scheduledTasks.get(id);\n if (existing) {\n Object.assign(existing, {\n status: task.status,\n execute_at: task.execute_at,\n execution_stats: task.execution_stats,\n updated_at: new Date()\n });\n } else {\n this.scheduledTasks.set(id, {...task, id});\n }\n }\n }\n\n async getCleanupStats(): Promise<{ orphanedTasks: number; expiredTasks: number }> {\n let orphanedTasks = 0;\n let expiredTasks = 0;\n const now = Date.now();\n\n for (const task of Array.from(this.scheduledTasks.values())) {\n if (task.status === 'processing' && task.processing_started_at && (now - task.processing_started_at.getTime()) > 300000) {\n orphanedTasks++;\n }\n if (task.expires_at && now > task.expires_at.getTime()) {\n expiredTasks++;\n }\n }\n\n return {orphanedTasks, expiredTasks};\n }\n\n async cleanupTasks(orphanedBefore: Date, expiredBefore: Date): Promise<void> {\n for (const [id, task] of Array.from(this.scheduledTasks.entries())) {\n const shouldDelete =\n (task.status === 'processing' && task.processing_started_at && task.processing_started_at < orphanedBefore) ||\n (task.expires_at && task.expires_at < expiredBefore);\n\n if (shouldDelete) {\n this.scheduledTasks.delete(id);\n }\n }\n }\n\n async initialize(): Promise<void> {\n // No initialization needed for memory adapter\n }\n\n async close(): Promise<void> {\n this.scheduledTasks.clear();\n }\n\n generateId(): string {\n return `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n }\n\n async markTasksAsIgnored(tasks: CronTask<string>[]) {\n for (const task of tasks) {\n const existingTask = this.scheduledTasks.get(task.id!);\n if (existingTask) {\n existingTask.status = 'ignored';\n existingTask.execution_stats = {...existingTask.execution_stats, ignore_reason: \"unknown type\"};\n this.scheduledTasks.set(task.id!, existingTask);\n }\n }\n }\n}\n\nexport {InMemoryAdapter}","import {ITaskStorageAdapter, TaskStorageLifecycleConfig} from \"./ITaskStorageAdapter.js\";\nimport {CronTask} from \"./types.js\";\nimport {Logger, LogLevel} from \"@supergrowthai/utils\";\nimport {PrismaClient} from \"@prisma/client/extension\";\nimport type {ITaskLifecycleProvider} from \"../core/lifecycle.js\";\n\nconst logger = new Logger('PrismaAdapter', LogLevel.INFO);\nconst TWO_DAYS_MS = 2 * 24 * 60 * 60 * 1000;\n\n\n// ---- Type utilities ----\n\n/** A Prisma client that is guaranteed to have model delegate K. */\nexport type ClientWithModel<K extends keyof PrismaClient> =\n Pick<PrismaClient, K>;\n\n/** Extract the entity (row) type from a model delegate. */\ntype EntityOf<D> =\n D extends { findUnique(args: any): Promise<infer U | null> } ? U :\n D extends { findFirst(args: any): Promise<infer U | null> } ? U :\n D extends { findMany(args?: any): Promise<(infer U)[]> } ? U :\n never;\n\n/** Compile-time guard: model's entity must be compatible with the shape you require. */\ntype EnsureModelShape<Delegate, Needed> =\n EntityOf<Delegate> extends Needed ? unknown : never;\n\n/**\n * Prisma task storage adapter for @supergrowthai/tq.\n *\n * @description Persists scheduled tasks to any Prisma model with status tracking.\n * Uses application-level locking designed for single-instance deployments.\n *\n * @use-case Single-instance production deployments with Prisma ORM\n * @multi-instance NOT SAFE - designed for single-instance use.\n * For multi-instance deployments, implement a distributed locking strategy\n * or use a Kinesis-based solution with Redis lock provider.\n * @persistence Full - tasks stored in database until processed/expired\n * @requires Prisma client with a model matching CronTask structure\n *\n * @features\n * - Stale task recovery: tasks stuck in 'processing' for >2 days are reset\n * - Transaction support for batch updates\n * - Task expiration cleanup\n *\n * @typeParam TId - The ID type (string, number, etc.)\n * @typeParam K - The Prisma model key (e.g. 'scheduledTask')\n * @typeParam Msg - The task type extending CronTask<TId>\n *\n * @example\n * ```typescript\n * const adapter = new PrismaAdapter({\n * prismaClient: prisma,\n * messageModel: 'scheduledTask'\n * });\n * ```\n */\nexport class PrismaAdapter<\n TId = any,\n K extends keyof PrismaClient = never,\n Msg extends CronTask<TId> = CronTask<TId>\n> implements ITaskStorageAdapter<TId> {\n private lifecycleProvider?: ITaskLifecycleProvider;\n private lifecycleMode: 'sync' | 'async' = 'async';\n\n constructor(\n private config: {\n prismaClient: ClientWithModel<K>;\n messageModel: K;\n /**\n * Phantom type param that enforces:\n * - client has model K\n * - entity type of client[K] extends Msg (which extends BaseMessage<TId>)\n * Do not pass at runtime.\n */\n _shapeCheck?: EnsureModelShape<PrismaClient[K], Msg> & (Msg extends CronTask<TId> & {\n id: TId\n } ? unknown : never);\n }\n ) {\n }\n\n setLifecycleConfig(config: TaskStorageLifecycleConfig): void {\n this.lifecycleProvider = config.lifecycleProvider;\n this.lifecycleMode = config.mode || 'async';\n }\n\n private emitLifecycleEvent<T>(\n callback: ((ctx: T) => void | Promise<void>) | undefined,\n ctx: T\n ): void {\n if (!callback) return;\n try {\n const result = callback(ctx);\n if (result instanceof Promise) {\n result.catch(err => logger.error(`[TQ] Lifecycle callback error: ${err}`));\n }\n } catch (err) {\n logger.error(`[TQ] Lifecycle callback error: ${err}`);\n }\n }\n\n get prismaClient(): PrismaClient {\n return this.config.prismaClient;\n }\n\n get taskTableName(): string {\n return String(this.config.messageModel);\n }\n\n protected get delegate(): PrismaClient[K] {\n return this.config.prismaClient[this.config.messageModel];\n }\n\n /**\n * Persist tasks to the database as scheduled.\n *\n * **Default implementation:** Uses individual creates with duplicate detection\n * for maximum database compatibility (SQLite, Postgres, MySQL, etc.).\n *\n * **Performance note:** This is O(n) database round-trips. For high-throughput\n * scenarios (100+ tasks/batch), override this method with a batch implementation:\n *\n * @example PostgreSQL/MySQL optimization:\n * ```typescript\n * class OptimizedPrismaAdapter extends PrismaAdapter {\n * async addTasksToScheduled(tasks) {\n * if (!tasks.length) return [];\n * await this.delegate.createMany({\n * data: tasks.map(t => ({ ...t, id: t.id || this.generateId() })),\n * skipDuplicates: true\n * });\n * return tasks;\n * }\n * }\n * ```\n */\n async addTasksToScheduled(tasks: CronTask<TId>[]): Promise<CronTask<TId>[]> {\n if (!tasks.length) return [];\n\n // Performance hint for high-throughput scenarios\n if (tasks.length > 50) {\n logger.warn(`[PrismaAdapter] Processing ${tasks.length} tasks sequentially (O(n) round-trips). For Postgres/MySQL, override addTasksToScheduled with createMany for better performance.`);\n }\n\n // Sequential creates for broad DB compatibility (SQLite, CockroachDB, etc.)\n // Override this method for batch optimization on Postgres/MySQL\n const results: CronTask<TId>[] = [];\n for (const task of tasks) {\n try {\n await this.delegate.create({\n data: {\n ...task,\n id: task.id || this.generateId(),\n status: task.status || 'scheduled',\n retries: task.retries || 0,\n created_at: task.created_at || new Date(),\n updated_at: new Date(),\n processing_started_at: task.processing_started_at || new Date()\n }\n });\n results.push(task);\n } catch (error: unknown) {\n logger.warn(`Task skipped (likely duplicate): ${error}`);\n }\n }\n return results;\n }\n\n async getMatureTasks(timestamp: number): Promise<CronTask<TId>[]> {\n const staleTimestamp = Date.now() - TWO_DAYS_MS;\n\n await this.delegate.updateMany({\n where: {\n status: 'processing',\n processing_started_at: {lt: new Date(staleTimestamp)}\n },\n data: {status: 'scheduled'}\n });\n\n const tasks = await this.delegate.findMany({\n where: {\n status: 'scheduled',\n execute_at: {lte: new Date(timestamp)}\n },\n take: 1000,\n orderBy: {execute_at: 'asc'}\n });\n\n if (tasks.length > 0) {\n const taskIds = tasks.map((t: any) => t.id);\n await this.delegate.updateMany({\n where: {id: {in: taskIds}},\n data: {\n status: 'processing',\n processing_started_at: new Date()\n }\n });\n }\n\n return tasks;\n }\n\n async markTasksAsProcessing(tasks: CronTask<TId>[], processingStartedAt: Date): Promise<void> {\n const taskIds = tasks.map(t => t.id).filter(Boolean);\n if (!taskIds.length) return;\n\n await this.delegate.updateMany({\n where: {id: {in: taskIds}},\n data: {\n status: 'processing',\n processing_started_at: processingStartedAt,\n updated_at: new Date()\n }\n });\n }\n\n async markTasksAsExecuted(tasks: CronTask<TId>[]): Promise<void> {\n const taskIds = tasks.map(t => t.id).filter(Boolean);\n if (!taskIds.length) return;\n\n await this.delegate.updateMany({\n where: {id: {in: taskIds}},\n data: {status: 'executed', updated_at: new Date()}\n });\n }\n\n async markTasksAsFailed(tasks: CronTask<TId>[]): Promise<void> {\n const taskIds = tasks.map(t => t.id).filter(Boolean);\n if (!taskIds.length) return;\n\n await this.delegate.updateMany({\n where: {id: {in: taskIds}},\n data: {status: 'failed', updated_at: new Date()}\n });\n }\n\n async markTasksAsIgnored(tasks: CronTask<TId>[]): Promise<void> {\n const taskIds = tasks.map(t => t.id).filter(Boolean);\n if (!taskIds.length) return;\n\n await this.delegate.updateMany({\n where: {id: {in: taskIds}},\n data: {status: 'ignored', updated_at: new Date()}\n });\n }\n\n async getTasksByIds(taskIds: TId[]): Promise<CronTask<TId>[]> {\n if (!taskIds.length) return [];\n\n return this.delegate.findMany({\n where: {id: {in: taskIds}}\n });\n }\n\n async updateTasks(updatesList: Array<{ id: TId; updates: Partial<CronTask<TId>> }>): Promise<void> {\n //fixme do we need a transaction. good but defo ?\n await this.prismaClient\n .$transaction(async (prisma) => {\n for (const {id, updates} of updatesList) {\n await (prisma as any)[this.taskTableName]\n .update({\n where: {id: id},\n data: {...updates, updated_at: new Date()}\n });\n }\n });\n }\n\n async upsertTasks(tasks: CronTask<TId>[]): Promise<void> {\n if (!tasks.length) return;\n\n const now = new Date();\n const delegate = this.delegate;\n\n // Each task may have different status/execute_at/execution_stats,\n // so per-task upsert is unavoidable. Wrapped in a transaction for atomicity.\n await this.prismaClient\n .$transaction(\n tasks.map(task => delegate.upsert({\n where: {id: task.id},\n create: {\n ...task,\n created_at: task.created_at || now,\n updated_at: now,\n processing_started_at: task.processing_started_at || now\n },\n update: {\n status: task.status,\n execute_at: task.execute_at,\n execution_stats: task.execution_stats,\n updated_at: now\n }\n }))\n );\n }\n\n async getCleanupStats(): Promise<{ orphanedTasks: number; expiredTasks: number }> {\n const orphanedBefore = new Date(Date.now() - TWO_DAYS_MS);\n\n const [orphanedTasks, expiredTasks] = await Promise.all([\n this.delegate.count({\n where: {\n status: 'processing',\n processing_started_at: {lt: orphanedBefore}\n }\n }),\n this.delegate.count({\n where: {expires_at: {lt: new Date()}}\n })\n ]);\n\n return {orphanedTasks, expiredTasks};\n }\n\n async cleanupTasks(orphanedBefore: Date, expiredBefore: Date): Promise<void> {\n await Promise.all([\n this.delegate.deleteMany({\n where: {\n status: 'processing',\n processing_started_at: {lt: orphanedBefore}\n }\n }),\n this.delegate.deleteMany({\n where: {expires_at: {lt: expiredBefore}}\n })\n ]);\n }\n\n generateId(): TId {\n //needs to be overriden when prisma client is of mongodb\n return crypto.randomUUID() as TId;\n }\n\n async initialize(): Promise<void> {\n }\n\n async close(): Promise<void> {\n }\n}"],"names":["logger","TWO_DAYS_MS","updates"],"mappings":"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"}
|
package/dist/adapters/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const PrismaAdapter = require("../PrismaAdapter-
|
|
3
|
+
const PrismaAdapter = require("../PrismaAdapter-CvM_XNtE.cjs");
|
|
4
4
|
exports.InMemoryAdapter = PrismaAdapter.InMemoryAdapter;
|
|
5
5
|
exports.MongoDbAdapter = PrismaAdapter.MongoDbAdapter;
|
|
6
6
|
exports.PrismaAdapter = PrismaAdapter.PrismaAdapter;
|
package/dist/adapters/index.mjs
CHANGED