@supergrowthai/tq 1.0.7 → 1.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.
@@ -48,6 +48,11 @@ export interface ITaskStorageAdapter<ID = any> {
48
48
  id: ID;
49
49
  updates: Partial<CronTask<ID>>;
50
50
  }>): Promise<void>;
51
+ /**
52
+ * Upsert tasks - insert if not exists, update if exists.
53
+ * Used for store_on_failure tasks that may not have been persisted yet.
54
+ */
55
+ upsertTasks(tasks: CronTask<ID>[]): Promise<void>;
51
56
  /**
52
57
  * Get stats for cleanup
53
58
  */
@@ -48,6 +48,11 @@ export interface ITaskStorageAdapter<ID = any> {
48
48
  id: ID;
49
49
  updates: Partial<CronTask<ID>>;
50
50
  }>): Promise<void>;
51
+ /**
52
+ * Upsert tasks - insert if not exists, update if exists.
53
+ * Used for store_on_failure tasks that may not have been persisted yet.
54
+ */
55
+ upsertTasks(tasks: CronTask<ID>[]): Promise<void>;
51
56
  /**
52
57
  * Get stats for cleanup
53
58
  */
@@ -37,6 +37,7 @@ declare class InMemoryAdapter implements ITaskStorageAdapter<string> {
37
37
  id: string;
38
38
  updates: Partial<CronTask<string>>;
39
39
  }>): Promise<void>;
40
+ upsertTasks(tasks: CronTask<string>[]): Promise<void>;
40
41
  getCleanupStats(): Promise<{
41
42
  orphanedTasks: number;
42
43
  expiredTasks: number;
@@ -37,6 +37,7 @@ declare class InMemoryAdapter implements ITaskStorageAdapter<string> {
37
37
  id: string;
38
38
  updates: Partial<CronTask<string>>;
39
39
  }>): Promise<void>;
40
+ upsertTasks(tasks: CronTask<string>[]): Promise<void>;
40
41
  getCleanupStats(): Promise<{
41
42
  orphanedTasks: number;
42
43
  expiredTasks: number;
@@ -51,6 +51,7 @@ export declare abstract class MongoDbAdapter implements ITaskStorageAdapter<Obje
51
51
  id: ObjectId;
52
52
  updates: Partial<CronTask<ObjectId>>;
53
53
  }>): Promise<void>;
54
+ upsertTasks(tasks: CronTask<ObjectId>[]): Promise<void>;
54
55
  generateId(): ObjectId;
55
56
  close(): Promise<void>;
56
57
  initialize(): Promise<void>;
@@ -51,6 +51,7 @@ export declare abstract class MongoDbAdapter implements ITaskStorageAdapter<Obje
51
51
  id: ObjectId;
52
52
  updates: Partial<CronTask<ObjectId>>;
53
53
  }>): Promise<void>;
54
+ upsertTasks(tasks: CronTask<ObjectId>[]): Promise<void>;
54
55
  generateId(): ObjectId;
55
56
  close(): Promise<void>;
56
57
  initialize(): Promise<void>;
@@ -76,6 +76,7 @@ export declare class PrismaAdapter<TId = any, K extends keyof PrismaClient = nev
76
76
  id: TId;
77
77
  updates: Partial<CronTask<TId>>;
78
78
  }>): Promise<void>;
79
+ upsertTasks(tasks: CronTask<TId>[]): Promise<void>;
79
80
  getCleanupStats(): Promise<{
80
81
  orphanedTasks: number;
81
82
  expiredTasks: number;
@@ -76,6 +76,7 @@ export declare class PrismaAdapter<TId = any, K extends keyof PrismaClient = nev
76
76
  id: TId;
77
77
  updates: Partial<CronTask<TId>>;
78
78
  }>): Promise<void>;
79
+ upsertTasks(tasks: CronTask<TId>[]): Promise<void>;
79
80
  getCleanupStats(): Promise<{
80
81
  orphanedTasks: number;
81
82
  expiredTasks: number;
@@ -22,7 +22,8 @@ declare class TaskStore<ID> {
22
22
  */
23
23
  markTasksAsExecuted(tasks: CronTask<ID>[]): Promise<void>;
24
24
  /**
25
- * Marks tasks as failed and increments retry count
25
+ * Marks tasks as failed uses upsert to handle store_on_failure tasks
26
+ * that were never persisted to DB
26
27
  */
27
28
  markTasksAsFailed(tasks: CronTask<ID>[]): Promise<void>;
28
29
  /**
@@ -56,7 +57,8 @@ declare class TaskStore<ID> {
56
57
  */
57
58
  cleanupTasks(): Promise<void>;
58
59
  /**
59
- * Updates tasks for retry with new execution time and retry count
60
+ * Updates tasks for retry uses upsert to handle store_on_failure tasks
61
+ * that were never persisted to DB
60
62
  */
61
63
  updateTasksForRetry(tasks: CronTask<ID>[]): Promise<void>;
62
64
  }
@@ -22,7 +22,8 @@ declare class TaskStore<ID> {
22
22
  */
23
23
  markTasksAsExecuted(tasks: CronTask<ID>[]): Promise<void>;
24
24
  /**
25
- * Marks tasks as failed and increments retry count
25
+ * Marks tasks as failed uses upsert to handle store_on_failure tasks
26
+ * that were never persisted to DB
26
27
  */
27
28
  markTasksAsFailed(tasks: CronTask<ID>[]): Promise<void>;
28
29
  /**
@@ -56,7 +57,8 @@ declare class TaskStore<ID> {
56
57
  */
57
58
  cleanupTasks(): Promise<void>;
58
59
  /**
59
- * Updates tasks for retry with new execution time and retry count
60
+ * Updates tasks for retry uses upsert to handle store_on_failure tasks
61
+ * that were never persisted to DB
60
62
  */
61
63
  updateTasksForRetry(tasks: CronTask<ID>[]): Promise<void>;
62
64
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@supergrowthai/tq",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "Task queue management library with multiple executor types and async task handling",
5
5
  "repository": "git+https://github.com/captadexp/next-blog.git",
6
6
  "homepage": "https://github.com/captadexp/next-blog/tree/main#readme",
@@ -107,7 +107,7 @@
107
107
  "author": "Capt ADExp <tech@developer.toys>",
108
108
  "license": "MIT",
109
109
  "dependencies": {
110
- "@supergrowthai/mq": "1.0.7",
110
+ "@supergrowthai/mq": "1.0.9",
111
111
  "lodash": "^4.17.23",
112
112
  "moment": "^2.30.1",
113
113
  "mongodb": "^7.0.0"
@@ -1 +0,0 @@
1
- {"version":3,"file":"PrismaAdapter-CT8dxOZX.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 await collection.bulkWrite(bulkOps);\n }\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 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 private get delegate(): PrismaClient[K] {\n return this.config.prismaClient[this.config.messageModel];\n }\n\n async addTasksToScheduled(tasks: CronTask<TId>[]): Promise<CronTask<TId>[]> {\n if (!tasks.length) return [];\n\n try {\n await this.delegate.createMany({\n data: tasks.map(task => ({\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 skipDuplicates: true\n });\n return tasks;\n } catch (error: unknown) {\n logger.warn(`Some tasks skipped due to duplicates: ${error}`);\n return tasks;\n }\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 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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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"PrismaAdapter-Z2vLslDJ.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 await collection.bulkWrite(bulkOps);\n }\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 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 private get delegate(): PrismaClient[K] {\n return this.config.prismaClient[this.config.messageModel];\n }\n\n async addTasksToScheduled(tasks: CronTask<TId>[]): Promise<CronTask<TId>[]> {\n if (!tasks.length) return [];\n\n try {\n await this.delegate.createMany({\n data: tasks.map(task => ({\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 skipDuplicates: true\n });\n return tasks;\n } catch (error: unknown) {\n logger.warn(`Some tasks skipped due to duplicates: ${error}`);\n return tasks;\n }\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 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":";;AAMA,MAAMA,WAAS,IAAI,OAAO,kBAAkB,SAAS,IAAI;AAEzD,MAAMC,gBAAc,IAAI,KAAK,KAAK,KAAK;AAKvC,SAAS,aAAgB,EAAC,KAAK,GAAG,QAA0D;AACxF,SAAO,EAAC,GAAG,MAAM,IAAI,IAAA;AACzB;AA4BO,MAAe,eAAwD;AAAA,EAIhE,cAAc;AAFxB,SAAQ,gBAAkC;AAAA,EAG1C;AAAA,EAEA,mBAAmB,QAA0C;AACzD,SAAK,oBAAoB,OAAO;AAChC,SAAK,gBAAgB,OAAO,QAAQ;AAAA,EACxC;AAAA,EAEQ,mBACJ,UACA,KACI;AACJ,QAAI,CAAC,SAAU;AACf,QAAI;AACA,YAAM,SAAS,SAAS,GAAG;AAC3B,UAAI,kBAAkB,SAAS;AAC3B,eAAO,MAAM,CAAA,QAAOD,SAAO,MAAM,kCAAkC,GAAG,EAAE,CAAC;AAAA,MAC7E;AAAA,IACJ,SAAS,KAAK;AACVA,eAAO,MAAM,kCAAkC,GAAG,EAAE;AAAA,IACxD;AAAA,EACJ;AAAA,EAIA,MAAM,oBAAoB,OAA4D;AAClF,QAAI,CAAC,MAAM,OAAQ,QAAO,CAAA;AAE1B,UAAM,aAAa,MAAM,KAAK;AAE9B,UAAM,mBAAmB,MAAM,IAAI,CAAC,UAAU;AAAA,MAC1C,KAAK,KAAK;AAAA,MACV,MAAM,KAAK;AAAA,MACX,SAAS,KAAK;AAAA,MACd,YAAY,KAAK;AAAA,MACjB,QAAQ,KAAK,UAAU;AAAA,MACvB,SAAS,KAAK,WAAW;AAAA,MACzB,YAAY,KAAK,cAAc,oBAAI,KAAA;AAAA,MACnC,gCAAgB,KAAA;AAAA,MAChB,UAAU,KAAK;AAAA,MACf,uBAAuB,KAAK,yBAAyB,oBAAI,KAAA;AAAA,MACzD,YAAY,KAAK;AAAA,MACjB,YAAY,KAAK;AAAA,MACjB,WAAW,KAAK;AAAA,MAChB,aAAa,KAAK;AAAA,MAClB,iBAAiB,KAAK;AAAA,MACtB,aAAa,KAAK;AAAA,IAAA,EACpB;AAEF,QAAI;AACA,YAAM,WAAW,WAAW,kBAAkB,EAAC,SAAS,OAAM;AAC9D,aAAO,iBAAiB,IAAI,YAAY;AAAA,IAC5C,SAAS,OAAgB;AACrB,UAAI,SAAS,OAAO,UAAU,YAAY,iBAAiB,OAAO;AAC9D,cAAM,aAAa;AACnB,cAAM,kBAAkB,iBAAiB;AAAA,UAAO,CAAC,GAAG,UAChD,CAAC,WAAW,YAAY,KAAK,CAAC,MAAM,EAAE,UAAU,KAAK;AAAA,QAAA;AAEzD,eAAO,gBAAgB,IAAI,YAAY;AAAA,MAC3C;AACA,YAAM;AAAA,IACV;AAAA,EACJ;AAAA,EAEA,MAAM,eAAe,WAAkD;AACnE,UAAM,aAAa,MAAM,KAAK;AAG9B,UAAM,iBAAiB,KAAK,IAAA,IAAQC;AACpC,UAAM,WAAW;AAAA,MACb;AAAA,QACI,QAAQ;AAAA,QACR,uBAAuB,EAAC,KAAK,IAAI,KAAK,cAAc,EAAA;AAAA,MAAC;AAAA,MAEzD;AAAA,QACI,MAAM,EAAC,QAAQ,YAAA;AAAA,MAAW;AAAA,IAC9B;AAIJ,UAAM,SAAS;AAAA,MACX,QAAQ;AAAA,MACR,YAAY,EAAC,MAAM,IAAI,KAAK,SAAS,EAAA;AAAA,IAAC;AAG1C,UAAM,QAAQ,MAAM,WACf,KAAK,MAAM,EACX,MAAM,GAAI,EACV,QAAA;AAEL,QAAI,MAAM,SAAS,GAAG;AAClB,YAAM,UAAU,MAAM,IAAI,CAAA,MAAK,EAAE,GAAG;AACpC,YAAM,WAAW;AAAA,QACb,EAAC,KAAK,EAAC,KAAK,UAAO;AAAA,QACnB;AAAA,UACI,MAAM;AAAA,YACF,QAAQ;AAAA,YACR,2CAA2B,KAAA;AAAA,UAAK;AAAA,QACpC;AAAA,MACJ;AAAA,IAER;AAEA,WAAO,MAAM,IAAI,YAAY;AAAA,EACjC;AAAA,EAEA,MAAM,sBAAsB,OAA6B,qBAA0C;AAC/F,UAAM,aAAa,MAAM,KAAK;AAC9B,UAAM,UAAU,MAAM,IAAI,CAAA,MAAK,EAAE,EAAE,EAAE,OAAO,OAAO;AAEnD,UAAM,WAAW;AAAA,MACb,EAAC,KAAK,EAAC,KAAK,UAAO;AAAA,MACnB;AAAA,QACI,MAAM;AAAA,UACF,QAAQ;AAAA,UACR,uBAAuB;AAAA,UACvB,gCAAgB,KAAA;AAAA,QAAK;AAAA,MACzB;AAAA,IACJ;AAAA,EAER;AAAA,EAEA,MAAM,oBAAoB,OAA4C;AAClE,UAAM,aAAa,MAAM,KAAK;AAC9B,UAAM,UAAU,MAAM,IAAI,CAAA,MAAK,EAAE,EAAE,EAAE,OAAO,OAAO;AAGnD,UAAM,WAAW;AAAA,MACb,EAAC,KAAK,EAAC,KAAK,UAAO;AAAA,MACnB;AAAA,QACI,MAAM;AAAA,UACF,QAAQ;AAAA,UACR,gCAAgB,KAAA;AAAA,QAAK;AAAA,MACzB;AAAA,IACJ;AAAA,EAER;AAAA,EAEA,MAAM,kBAAkB,OAA4C;AAChE,UAAM,aAAa,MAAM,KAAK;AAC9B,UAAM,UAAU,MAAM,IAAI,CAAA,MAAK,EAAE,EAAE,EAAE,OAAO,OAAO;AAGnD,UAAM,WAAW;AAAA,MACb,EAAC,KAAK,EAAC,KAAK,UAAO;AAAA,MACnB;AAAA,QACI,MAAM;AAAA,UACF,QAAQ;AAAA,UACR,gCAAgB,KAAA;AAAA,QAAK;AAAA,MACzB;AAAA,IACJ;AAAA,EAER;AAAA,EAEA,MAAM,cAAc,SAAoD;AACpE,UAAM,aAAa,MAAM,KAAK;AAE9B,WAAO,WACF,KAAK,EAAC,KAAK,EAAC,KAAK,UAAO,CAAE,EAC1B,UACA,KAAK,YAAU,OAAO,IAAI,YAAY,CAAC;AAAA,EAChD;AAAA,EAEA,MAAM,kBAA4E;AAC9E,UAAM,aAAa,MAAM,KAAK;AAE9B,UAAM,iBAAiB,IAAI,KAAK,KAAK,IAAA,IAAQA,aAAW;AACxD,UAAM,gBAAgB,MAAM,WAAW,eAAe;AAAA,MAClD,QAAQ;AAAA,MACR,uBAAuB,EAAC,KAAK,eAAA;AAAA,IAAc,CAC9C;AAED,UAAM,eAAe,MAAM,WAAW,eAAe;AAAA,MACjD,YAAY,EAAC,KAAK,oBAAI,OAAK;AAAA,IAAC,CAC/B;AAED,WAAO,EAAC,eAAe,aAAA;AAAA,EAC3B;AAAA,EAEA,MAAM,aAAa,gBAAsB,eAAoC;AACzE,UAAM,aAAa,MAAM,KAAK;AAG9B,UAAM,WAAW,WAAW;AAAA,MACxB,QAAQ;AAAA,MACR,uBAAuB,EAAC,KAAK,eAAA;AAAA,IAAc,CAC9C;AAGD,UAAM,WAAW,WAAW;AAAA,MACxB,YAAY,EAAC,KAAK,cAAA;AAAA,IAAa,CAClC;AAAA,EACL;AAAA,EAEA,MAAM,YAAY,SAAuF;AACrG,UAAM,aAAa,MAAM,KAAK;AAE9B,UAAM,UAAU,QAAQ,IAAI,CAAC,EAAC,IAAI,SAAAC,gBAAc;AAAA,MAC5C,WAAW;AAAA,QACP,QAAQ,EAAC,KAAK,GAAA;AAAA,QACd,QAAQ;AAAA,UACJ,MAAM;AAAA,YACF,GAAGA;AAAAA,YACH,gCAAgB,KAAA;AAAA,UAAK;AAAA,QACzB;AAAA,MACJ;AAAA,IACJ,EACF;AAEF,QAAI,QAAQ,SAAS,GAAG;AACpB,YAAM,WAAW,UAAU,OAAO;AAAA,IACtC;AAAA,EACJ;AAAA,EAEA,aAAa;AACT,WAAO,IAAI,SAAA;AAAA,EACf;AAAA,EAEA,MAAM,QAAQ;AAAA,EACd;AAAA,EAEA,MAAM,aAAa;AAAA,EACnB;AAAA,EAEA,MAAM,mBAAmB,OAA4C;AACjE,UAAM,aAAa,MAAM,KAAK;AAC9B,UAAM,UAAU,MAAM,IAAI,CAAA,MAAK,EAAE,EAAE,EAAE,OAAO,OAAO;AAGnD,UAAM,WAAW;AAAA,MACb,EAAC,KAAK,EAAC,KAAK,UAAO;AAAA,MACnB;AAAA,QACI,MAAM;AAAA,UACF,QAAQ;AAAA;AAAA,UAER,gCAAgB,KAAA;AAAA,QAAK;AAAA,MACzB;AAAA,IACJ;AAAA,EAER;AACJ;ACtQA,MAAM,gBAAuD;AAAA,EAA7D,cAAA;AACI,SAAQ,qCAAoD,IAAA;AAE5D,SAAQ,gBAAkC;AAAA,EAAA;AAAA,EAE1C,mBAAmB,QAA0C;AACzD,SAAK,oBAAoB,OAAO;AAChC,SAAK,gBAAgB,OAAO,QAAQ;AAAA,EACxC;AAAA,EAEQ,mBACJ,UACA,KACI;AACJ,QAAI,CAAC,SAAU;AACf,QAAI;AACA,YAAM,SAAS,SAAS,GAAG;AAC3B,UAAI,kBAAkB,SAAS;AAC3B,eAAO,MAAM,CAAA,QAAO,QAAQ,MAAM,kCAAkC,GAAG,EAAE,CAAC;AAAA,MAC9E;AAAA,IACJ,SAAS,KAAK;AACV,cAAQ,MAAM,kCAAkC,GAAG,EAAE;AAAA,IACzD;AAAA,EACJ;AAAA,EAEA,MAAM,oBAAoB,OAAwD;AAC9E,UAAM,aAAa,MAAM,IAAI,CAAA,SAAQ;AACjC,YAAM,KAAK,KAAK,MAAM,KAAK,WAAA;AAC3B,YAAM,aAAa,EAAC,GAAG,MAAM,GAAA;AAC7B,WAAK,eAAe,IAAI,IAAI,UAAU;AACtC,aAAO;AAAA,IACX,CAAC;AACD,WAAO;AAAA,EACX;AAAA,EAEA,MAAM,eAAe,WAAgD;AACjE,UAAM,cAAkC,CAAA;AACxC,eAAW,CAAC,IAAI,IAAI,KAAK,MAAM,KAAK,KAAK,eAAe,QAAA,CAAS,GAAG;AAChE,UAAI,KAAK,WAAW,QAAA,KAAa,aAAa,KAAK,WAAW,gBAAgB,KAAK,WAAW,YAAY;AACtG,oBAAY,KAAK,IAAI;AAAA,MACzB;AAAA,IACJ;AACA,WAAO;AAAA,EACX;AAAA,EAEA,MAAM,sBAAsB,OAA2B,qBAA0C;AAC7F,eAAW,QAAQ,OAAO;AACtB,YAAM,eAAe,KAAK,eAAe,IAAI,KAAK,EAAG;AACrD,UAAI,cAAc;AACd,qBAAa,SAAS;AACtB,qBAAa,wBAAwB;AACrC,aAAK,eAAe,IAAI,KAAK,IAAK,YAAY;AAAA,MAClD;AAAA,IACJ;AAAA,EACJ;AAAA,EAEA,MAAM,oBAAoB,OAA0C;AAChE,eAAW,QAAQ,OAAO;AACtB,YAAM,eAAe,KAAK,eAAe,IAAI,KAAK,EAAG;AACrD,UAAI,cAAc;AACd,qBAAa,SAAS;AACtB,qBAAa,iCAAiB,KAAA;AAC9B,aAAK,eAAe,IAAI,KAAK,IAAK,YAAY;AAAA,MAClD;AAAA,IACJ;AAAA,EACJ;AAAA,EAEA,MAAM,kBAAkB,OAA0C;AAC9D,eAAW,QAAQ,OAAO;AACtB,YAAM,eAAe,KAAK,eAAe,IAAI,KAAK,EAAG;AACrD,UAAI,cAAc;AACd,qBAAa,SAAS;AACtB,qBAAa,kBAAkB,EAAC,GAAG,aAAa,iBAAiB,WAAW,oBAAI,OAAK;AACrF,aAAK,eAAe,IAAI,KAAK,IAAK,YAAY;AAAA,MAClD;AAAA,IACJ;AAAA,EACJ;AAAA,EAEA,MAAM,cAAc,SAAgD;AAChE,WAAO,QAAQ,IAAI,CAAA,OAAM,KAAK,eAAe,IAAI,EAAE,CAAC,EAAE,OAAO,OAAO;AAAA,EACxE;AAAA,EAEA,MAAM,YAAY,SAAmF;AACjG,eAAW,EAAC,IAAI,SAAS,YAAA,KAAgB,SAAS;AAC9C,YAAM,OAAO,KAAK,eAAe,IAAI,EAAE;AACvC,UAAI,MAAM;AACN,eAAO,OAAO,MAAM,WAAW;AAC/B,aAAK,eAAe,IAAI,IAAI,IAAI;AAAA,MACpC;AAAA,IACJ;AAAA,EACJ;AAAA,EAEA,MAAM,kBAA4E;AAC9E,QAAI,gBAAgB;AACpB,QAAI,eAAe;AACnB,UAAM,MAAM,KAAK,IAAA;AAEjB,eAAW,QAAQ,MAAM,KAAK,KAAK,eAAe,OAAA,CAAQ,GAAG;AACzD,UAAI,KAAK,WAAW,gBAAgB,KAAK,yBAA0B,MAAM,KAAK,sBAAsB,QAAA,IAAa,KAAQ;AACrH;AAAA,MACJ;AACA,UAAI,KAAK,cAAc,MAAM,KAAK,WAAW,WAAW;AACpD;AAAA,MACJ;AAAA,IACJ;AAEA,WAAO,EAAC,eAAe,aAAA;AAAA,EAC3B;AAAA,EAEA,MAAM,aAAa,gBAAsB,eAAoC;AACzE,eAAW,CAAC,IAAI,IAAI,KAAK,MAAM,KAAK,KAAK,eAAe,QAAA,CAAS,GAAG;AAChE,YAAM,eACD,KAAK,WAAW,gBAAgB,KAAK,yBAAyB,KAAK,wBAAwB,kBAC3F,KAAK,cAAc,KAAK,aAAa;AAE1C,UAAI,cAAc;AACd,aAAK,eAAe,OAAO,EAAE;AAAA,MACjC;AAAA,IACJ;AAAA,EACJ;AAAA,EAEA,MAAM,aAA4B;AAAA,EAElC;AAAA,EAEA,MAAM,QAAuB;AACzB,SAAK,eAAe,MAAA;AAAA,EACxB;AAAA,EAEA,aAAqB;AACjB,WAAO,GAAG,KAAK,IAAA,CAAK,IAAI,KAAK,OAAA,EAAS,SAAS,EAAE,EAAE,UAAU,GAAG,CAAC,CAAC;AAAA,EACtE;AAAA,EAEA,MAAM,mBAAmB,OAA2B;AAChD,eAAW,QAAQ,OAAO;AACtB,YAAM,eAAe,KAAK,eAAe,IAAI,KAAK,EAAG;AACrD,UAAI,cAAc;AACd,qBAAa,SAAS;AACtB,qBAAa,kBAAkB,EAAC,GAAG,aAAa,iBAAiB,eAAe,eAAA;AAChF,aAAK,eAAe,IAAI,KAAK,IAAK,YAAY;AAAA,MAClD;AAAA,IACJ;AAAA,EACJ;AACJ;AClKA,MAAM,SAAS,IAAI,OAAO,iBAAiB,SAAS,IAAI;AACxD,MAAM,cAAc,IAAI,KAAK,KAAK,KAAK;AAkDhC,MAAM,cAIyB;AAAA,EAIlC,YACY,QAaV;AAbU,SAAA,SAAA;AAHZ,SAAQ,gBAAkC;AAAA,EAiB1C;AAAA,EAEA,mBAAmB,QAA0C;AACzD,SAAK,oBAAoB,OAAO;AAChC,SAAK,gBAAgB,OAAO,QAAQ;AAAA,EACxC;AAAA,EAEQ,mBACJ,UACA,KACI;AACJ,QAAI,CAAC,SAAU;AACf,QAAI;AACA,YAAM,SAAS,SAAS,GAAG;AAC3B,UAAI,kBAAkB,SAAS;AAC3B,eAAO,MAAM,CAAA,QAAO,OAAO,MAAM,kCAAkC,GAAG,EAAE,CAAC;AAAA,MAC7E;AAAA,IACJ,SAAS,KAAK;AACV,aAAO,MAAM,kCAAkC,GAAG,EAAE;AAAA,IACxD;AAAA,EACJ;AAAA,EAEA,IAAI,eAA6B;AAC7B,WAAO,KAAK,OAAO;AAAA,EACvB;AAAA,EAEA,IAAI,gBAAwB;AACxB,WAAO,OAAO,KAAK,OAAO,YAAY;AAAA,EAC1C;AAAA,EAEA,IAAY,WAA4B;AACpC,WAAO,KAAK,OAAO,aAAa,KAAK,OAAO,YAAY;AAAA,EAC5D;AAAA,EAEA,MAAM,oBAAoB,OAAkD;AACxE,QAAI,CAAC,MAAM,OAAQ,QAAO,CAAA;AAE1B,QAAI;AACA,YAAM,KAAK,SAAS,WAAW;AAAA,QAC3B,MAAM,MAAM,IAAI,CAAA,UAAS;AAAA,UACrB,GAAG;AAAA,UACH,IAAI,KAAK,MAAM,KAAK,WAAA;AAAA,UACpB,QAAQ,KAAK,UAAU;AAAA,UACvB,SAAS,KAAK,WAAW;AAAA,UACzB,YAAY,KAAK,cAAc,oBAAI,KAAA;AAAA,UACnC,gCAAgB,KAAA;AAAA,UAChB,uBAAuB,KAAK,yBAAyB,oBAAI,KAAA;AAAA,QAAK,EAChE;AAAA,QACF,gBAAgB;AAAA,MAAA,CACnB;AACD,aAAO;AAAA,IACX,SAAS,OAAgB;AACrB,aAAO,KAAK,yCAAyC,KAAK,EAAE;AAC5D,aAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEA,MAAM,eAAe,WAA6C;AAC9D,UAAM,iBAAiB,KAAK,IAAA,IAAQ;AAEpC,UAAM,KAAK,SAAS,WAAW;AAAA,MAC3B,OAAO;AAAA,QACH,QAAQ;AAAA,QACR,uBAAuB,EAAC,IAAI,IAAI,KAAK,cAAc,EAAA;AAAA,MAAC;AAAA,MAExD,MAAM,EAAC,QAAQ,YAAA;AAAA,IAAW,CAC7B;AAED,UAAM,QAAQ,MAAM,KAAK,SAAS,SAAS;AAAA,MACvC,OAAO;AAAA,QACH,QAAQ;AAAA,QACR,YAAY,EAAC,KAAK,IAAI,KAAK,SAAS,EAAA;AAAA,MAAC;AAAA,MAEzC,MAAM;AAAA,MACN,SAAS,EAAC,YAAY,MAAA;AAAA,IAAK,CAC9B;AAED,QAAI,MAAM,SAAS,GAAG;AAClB,YAAM,UAAU,MAAM,IAAI,CAAC,MAAW,EAAE,EAAE;AAC1C,YAAM,KAAK,SAAS,WAAW;AAAA,QAC3B,OAAO,EAAC,IAAI,EAAC,IAAI,UAAO;AAAA,QACxB,MAAM;AAAA,UACF,QAAQ;AAAA,UACR,2CAA2B,KAAA;AAAA,QAAK;AAAA,MACpC,CACH;AAAA,IACL;AAEA,WAAO;AAAA,EACX;AAAA,EAEA,MAAM,sBAAsB,OAAwB,qBAA0C;AAC1F,UAAM,UAAU,MAAM,IAAI,CAAA,MAAK,EAAE,EAAE,EAAE,OAAO,OAAO;AACnD,QAAI,CAAC,QAAQ,OAAQ;AAErB,UAAM,KAAK,SAAS,WAAW;AAAA,MAC3B,OAAO,EAAC,IAAI,EAAC,IAAI,UAAO;AAAA,MACxB,MAAM;AAAA,QACF,QAAQ;AAAA,QACR,uBAAuB;AAAA,QACvB,gCAAgB,KAAA;AAAA,MAAK;AAAA,IACzB,CACH;AAAA,EACL;AAAA,EAEA,MAAM,oBAAoB,OAAuC;AAC7D,UAAM,UAAU,MAAM,IAAI,CAAA,MAAK,EAAE,EAAE,EAAE,OAAO,OAAO;AACnD,QAAI,CAAC,QAAQ,OAAQ;AAErB,UAAM,KAAK,SAAS,WAAW;AAAA,MAC3B,OAAO,EAAC,IAAI,EAAC,IAAI,UAAO;AAAA,MACxB,MAAM,EAAC,QAAQ,YAAY,YAAY,oBAAI,OAAK;AAAA,IAAC,CACpD;AAAA,EACL;AAAA,EAEA,MAAM,kBAAkB,OAAuC;AAC3D,UAAM,UAAU,MAAM,IAAI,CAAA,MAAK,EAAE,EAAE,EAAE,OAAO,OAAO;AACnD,QAAI,CAAC,QAAQ,OAAQ;AAErB,UAAM,KAAK,SAAS,WAAW;AAAA,MAC3B,OAAO,EAAC,IAAI,EAAC,IAAI,UAAO;AAAA,MACxB,MAAM,EAAC,QAAQ,UAAU,YAAY,oBAAI,OAAK;AAAA,IAAC,CAClD;AAAA,EACL;AAAA,EAEA,MAAM,mBAAmB,OAAuC;AAC5D,UAAM,UAAU,MAAM,IAAI,CAAA,MAAK,EAAE,EAAE,EAAE,OAAO,OAAO;AACnD,QAAI,CAAC,QAAQ,OAAQ;AAErB,UAAM,KAAK,SAAS,WAAW;AAAA,MAC3B,OAAO,EAAC,IAAI,EAAC,IAAI,UAAO;AAAA,MACxB,MAAM,EAAC,QAAQ,WAAW,YAAY,oBAAI,OAAK;AAAA,IAAC,CACnD;AAAA,EACL;AAAA,EAEA,MAAM,cAAc,SAA0C;AAC1D,QAAI,CAAC,QAAQ,OAAQ,QAAO,CAAA;AAE5B,WAAO,KAAK,SAAS,SAAS;AAAA,MAC1B,OAAO,EAAC,IAAI,EAAC,IAAI,UAAO;AAAA,IAAC,CAC5B;AAAA,EACL;AAAA,EAEA,MAAM,YAAY,aAAiF;AAE/F,UAAM,KAAK,aACN,aAAa,OAAO,WAAW;AAC5B,iBAAW,EAAC,IAAI,QAAA,KAAY,aAAa;AACrC,cAAO,OAAe,KAAK,aAAa,EACnC,OAAO;AAAA,UACJ,OAAO,EAAC,GAAA;AAAA,UACR,MAAM,EAAC,GAAG,SAAS,YAAY,oBAAI,OAAK;AAAA,QAAC,CAC5C;AAAA,MACT;AAAA,IACJ,CAAC;AAAA,EACT;AAAA,EAEA,MAAM,kBAA4E;AAC9E,UAAM,iBAAiB,IAAI,KAAK,KAAK,IAAA,IAAQ,WAAW;AAExD,UAAM,CAAC,eAAe,YAAY,IAAI,MAAM,QAAQ,IAAI;AAAA,MACpD,KAAK,SAAS,MAAM;AAAA,QAChB,OAAO;AAAA,UACH,QAAQ;AAAA,UACR,uBAAuB,EAAC,IAAI,eAAA;AAAA,QAAc;AAAA,MAC9C,CACH;AAAA,MACD,KAAK,SAAS,MAAM;AAAA,QAChB,OAAO,EAAC,YAAY,EAAC,IAAI,oBAAI,KAAA,IAAM;AAAA,MAAC,CACvC;AAAA,IAAA,CACJ;AAED,WAAO,EAAC,eAAe,aAAA;AAAA,EAC3B;AAAA,EAEA,MAAM,aAAa,gBAAsB,eAAoC;AACzE,UAAM,QAAQ,IAAI;AAAA,MACd,KAAK,SAAS,WAAW;AAAA,QACrB,OAAO;AAAA,UACH,QAAQ;AAAA,UACR,uBAAuB,EAAC,IAAI,eAAA;AAAA,QAAc;AAAA,MAC9C,CACH;AAAA,MACD,KAAK,SAAS,WAAW;AAAA,QACrB,OAAO,EAAC,YAAY,EAAC,IAAI,gBAAa;AAAA,MAAC,CAC1C;AAAA,IAAA,CACJ;AAAA,EACL;AAAA,EAEA,aAAkB;AAEd,WAAO,OAAO,WAAA;AAAA,EAClB;AAAA,EAEA,MAAM,aAA4B;AAAA,EAClC;AAAA,EAEA,MAAM,QAAuB;AAAA,EAC7B;AACJ;"}