@happyvertical/jobs 0.74.8
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/AGENT.md +33 -0
- package/LICENSE +7 -0
- package/dist/adapters/bull.d.ts +103 -0
- package/dist/adapters/bull.d.ts.map +1 -0
- package/dist/adapters/bull.js +349 -0
- package/dist/adapters/bull.js.map +1 -0
- package/dist/adapters/bullmq.d.ts +85 -0
- package/dist/adapters/bullmq.d.ts.map +1 -0
- package/dist/adapters/bullmq.js +391 -0
- package/dist/adapters/bullmq.js.map +1 -0
- package/dist/adapters/cloud-tasks.d.ts +110 -0
- package/dist/adapters/cloud-tasks.d.ts.map +1 -0
- package/dist/adapters/cloud-tasks.js +336 -0
- package/dist/adapters/cloud-tasks.js.map +1 -0
- package/dist/adapters/postgres.d.ts +55 -0
- package/dist/adapters/postgres.d.ts.map +1 -0
- package/dist/adapters/postgres.js +437 -0
- package/dist/adapters/postgres.js.map +1 -0
- package/dist/adapters/sqlite.d.ts +44 -0
- package/dist/adapters/sqlite.d.ts.map +1 -0
- package/dist/adapters/sqlite.js +323 -0
- package/dist/adapters/sqlite.js.map +1 -0
- package/dist/adapters/sqs.d.ts +112 -0
- package/dist/adapters/sqs.d.ts.map +1 -0
- package/dist/adapters/sqs.js +411 -0
- package/dist/adapters/sqs.js.map +1 -0
- package/dist/base-store.d.ts +69 -0
- package/dist/base-store.d.ts.map +1 -0
- package/dist/chunks/base-store-DlNksWvQ.js +324 -0
- package/dist/chunks/base-store-DlNksWvQ.js.map +1 -0
- package/dist/cli/claude-context.d.ts +3 -0
- package/dist/cli/claude-context.d.ts.map +1 -0
- package/dist/cli/claude-context.js +21 -0
- package/dist/cli/claude-context.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +252 -0
- package/dist/index.js.map +1 -0
- package/dist/retry.d.ts +84 -0
- package/dist/retry.d.ts.map +1 -0
- package/dist/types.d.ts +311 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/worker.d.ts +74 -0
- package/dist/worker.d.ts.map +1 -0
- package/metadata.json +34 -0
- package/package.json +114 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/worker.ts"],"sourcesContent":["import { EventEmitter } from 'node:events';\nimport { createId } from '@happyvertical/utils';\nimport { fromConfig } from './retry.js';\nimport type {\n Worker as IWorker,\n Job,\n JobHandler,\n JobStore,\n WorkerConfig,\n} from './types.js';\n\n/**\n * Worker events\n */\nexport interface WorkerEvents {\n 'job:started': (job: Job) => void;\n 'job:completed': (job: Job, result: unknown) => void;\n 'job:failed': (job: Job, error: Error) => void;\n 'job:retrying': (job: Job, error: Error, delay: number) => void;\n 'worker:started': () => void;\n 'worker:stopped': () => void;\n 'worker:error': (error: Error) => void;\n}\n\n/**\n * Default worker configuration\n */\nconst DEFAULT_CONFIG: Required<WorkerConfig> = {\n id: '',\n concurrency: 5,\n queues: ['default'],\n pollInterval: 1000,\n heartbeatInterval: 30000,\n shutdownTimeout: 30000,\n};\n\n/**\n * Job worker that processes jobs from a store\n */\nexport class JobWorker extends EventEmitter implements IWorker {\n readonly id: string;\n private readonly store: JobStore;\n private readonly handler: JobHandler;\n private readonly config: Required<WorkerConfig>;\n private running = false;\n private activeJobs = new Map<string, Job>();\n private pollTimer: NodeJS.Timeout | null = null;\n private heartbeatTimer: NodeJS.Timeout | null = null;\n private shutdownPromise: Promise<void> | null = null;\n\n constructor(store: JobStore, handler: JobHandler, config: WorkerConfig = {}) {\n super();\n this.store = store;\n this.handler = handler;\n this.config = {\n ...DEFAULT_CONFIG,\n ...config,\n id: config.id || `worker_${createId().slice(0, 8)}`,\n };\n this.id = this.config.id;\n }\n\n /**\n * Start processing jobs\n */\n async start(): Promise<void> {\n if (this.running) return;\n\n this.running = true;\n\n // Subscribe to store events for push-based notifications\n this.store.subscribe(async (event) => {\n if (event.type === 'job.ready' && this.running) {\n // Immediately try to dequeue when a job becomes ready\n await this.poll();\n }\n });\n\n // Start polling loop\n this.startPolling();\n\n // Start heartbeat loop\n this.startHeartbeat();\n\n this.emit('worker:started');\n }\n\n /**\n * Stop processing jobs (graceful shutdown)\n */\n async stop(): Promise<void> {\n if (!this.running) return;\n if (this.shutdownPromise) return this.shutdownPromise;\n\n this.running = false;\n\n // Stop timers\n if (this.pollTimer) {\n clearTimeout(this.pollTimer);\n this.pollTimer = null;\n }\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n\n // Wait for active jobs to complete (with timeout)\n this.shutdownPromise = this.waitForActiveJobs();\n\n try {\n await this.shutdownPromise;\n } finally {\n this.shutdownPromise = null;\n this.emit('worker:stopped');\n }\n }\n\n /**\n * Check if worker is running\n */\n isRunning(): boolean {\n return this.running;\n }\n\n /**\n * Get count of active jobs\n */\n activeJobCount(): number {\n return this.activeJobs.size;\n }\n\n /**\n * Start the polling loop\n */\n private startPolling(): void {\n const scheduleNextPoll = () => {\n if (!this.running) return;\n\n if (!this.store.waitForUpdate) {\n this.pollTimer = setTimeout(poll, this.config.pollInterval);\n return;\n }\n\n this.pollTimer = setTimeout(() => {\n void waitThenPoll();\n }, 0);\n };\n\n const waitThenPoll = async () => {\n try {\n await this.store.waitForUpdate?.(this.config.pollInterval);\n } catch (error) {\n this.emit('worker:error', error as Error);\n }\n\n if (this.running) {\n await poll();\n }\n };\n\n const poll = async () => {\n if (!this.running) return;\n\n try {\n await this.poll();\n } catch (error) {\n this.emit('worker:error', error as Error);\n }\n\n // Schedule next poll\n scheduleNextPoll();\n };\n\n // Start immediately\n poll();\n }\n\n /**\n * Poll for and process jobs\n */\n private async poll(): Promise<void> {\n // Calculate how many jobs we can take\n const available = this.config.concurrency - this.activeJobs.size;\n if (available <= 0) return;\n\n // Dequeue jobs\n const jobs = await this.store.dequeue(\n this.config.queues,\n available,\n this.id,\n );\n\n // Process each job concurrently\n for (const job of jobs) {\n this.processJob(job);\n }\n }\n\n /**\n * Process a single job\n */\n private async processJob(job: Job): Promise<void> {\n this.activeJobs.set(job.id, job);\n this.emit('job:started', job);\n\n let timeoutId: NodeJS.Timeout | null = null;\n\n try {\n // Set up timeout with cleanup capability\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n reject(new Error(`Job timeout after ${job.timeout}ms`));\n }, job.timeout);\n });\n\n // Execute handler with timeout\n const result = await Promise.race([this.handler(job), timeoutPromise]);\n\n // Job completed successfully\n await this.store.update(job.id, {\n status: 'completed',\n completedAt: new Date(),\n resultPointer: result.resultPointer ?? null,\n });\n\n this.emit('job:completed', job, result.result);\n } catch (error) {\n await this.handleJobError(job, error as Error);\n } finally {\n // Clean up timeout timer to prevent memory leak\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n this.activeJobs.delete(job.id);\n }\n }\n\n /**\n * Handle job execution error\n */\n private async handleJobError(job: Job, error: Error): Promise<void> {\n const strategy = fromConfig(job.retryStrategy);\n const decision = strategy.shouldRetry(job.attempts, error);\n\n if (decision.shouldRetry && job.attempts < job.maxAttempts) {\n // Schedule retry\n const nextRunAt = new Date(Date.now() + decision.delay);\n\n await this.store.update(job.id, {\n status: 'pending',\n lastError: error.message,\n runAt: nextRunAt,\n workerId: null,\n workerHeartbeat: null,\n });\n\n this.emit('job:retrying', job, error, decision.delay);\n } else {\n // Job failed permanently\n await this.store.update(job.id, {\n status: 'failed',\n completedAt: new Date(),\n lastError: error.message,\n });\n\n this.emit('job:failed', job, error);\n }\n }\n\n /**\n * Start heartbeat loop to keep jobs alive\n */\n private startHeartbeat(): void {\n this.heartbeatTimer = setInterval(async () => {\n for (const [jobId] of this.activeJobs) {\n try {\n await this.store.heartbeat(jobId, this.id);\n } catch (error) {\n // Log heartbeat errors but don't interrupt job processing\n console.warn(`Heartbeat failed for job ${jobId}:`, error);\n }\n }\n }, this.config.heartbeatInterval);\n }\n\n /**\n * Wait for active jobs to complete with timeout\n */\n private async waitForActiveJobs(): Promise<void> {\n if (this.activeJobs.size === 0) return;\n\n return new Promise((resolve) => {\n const checkInterval = setInterval(() => {\n if (this.activeJobs.size === 0) {\n clearInterval(checkInterval);\n clearTimeout(timeout);\n resolve();\n }\n }, 100);\n\n const timeout = setTimeout(() => {\n clearInterval(checkInterval);\n console.warn(\n `Shutdown timeout: ${this.activeJobs.size} jobs still active`,\n );\n resolve();\n }, this.config.shutdownTimeout);\n });\n }\n}\n\n/**\n * Create a job worker\n */\nexport function createWorker(\n store: JobStore,\n handler: JobHandler,\n config?: WorkerConfig,\n): JobWorker {\n return new JobWorker(store, handler, config);\n}\n"],"names":[],"mappings":"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"}
|
package/dist/retry.d.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { RetryDecision, RetryStrategy, RetryStrategyConfig } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Options for exponential backoff retry strategy
|
|
4
|
+
*/
|
|
5
|
+
export interface ExponentialBackoffOptions {
|
|
6
|
+
/** Initial delay in milliseconds (default: 1000) */
|
|
7
|
+
initialDelay?: number;
|
|
8
|
+
/** Maximum delay in milliseconds (default: 300000 = 5 minutes) */
|
|
9
|
+
maxDelay?: number;
|
|
10
|
+
/** Multiplier for each attempt (default: 2) */
|
|
11
|
+
multiplier?: number;
|
|
12
|
+
/** Add random jitter to prevent thundering herd (default: true) */
|
|
13
|
+
jitter?: boolean;
|
|
14
|
+
/** Maximum attempts (optional, can also be set on job) */
|
|
15
|
+
maxAttempts?: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Options for linear retry strategy
|
|
19
|
+
*/
|
|
20
|
+
export interface LinearBackoffOptions {
|
|
21
|
+
/** Fixed delay between retries in milliseconds (default: 5000) */
|
|
22
|
+
delay?: number;
|
|
23
|
+
/** Maximum attempts (optional) */
|
|
24
|
+
maxAttempts?: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Custom retry decision function
|
|
28
|
+
*/
|
|
29
|
+
export type CustomRetryFn = (attempt: number, error: Error) => RetryDecision;
|
|
30
|
+
/**
|
|
31
|
+
* Create an exponential backoff retry strategy
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```typescript
|
|
35
|
+
* const strategy = exponential({
|
|
36
|
+
* initialDelay: 1000,
|
|
37
|
+
* maxDelay: 300000,
|
|
38
|
+
* multiplier: 2,
|
|
39
|
+
* jitter: true,
|
|
40
|
+
* });
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export declare function exponential(options?: ExponentialBackoffOptions): RetryStrategy;
|
|
44
|
+
/**
|
|
45
|
+
* Create a linear retry strategy with fixed delay
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* const strategy = linear({ delay: 5000 });
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export declare function linear(options?: LinearBackoffOptions): RetryStrategy;
|
|
53
|
+
/**
|
|
54
|
+
* Create a custom retry strategy
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* const strategy = custom((attempt, error) => {
|
|
59
|
+
* if (error.message.includes('RATE_LIMITED')) {
|
|
60
|
+
* return { shouldRetry: true, delay: 60000 };
|
|
61
|
+
* }
|
|
62
|
+
* return { shouldRetry: attempt < 3, delay: attempt * 1000 };
|
|
63
|
+
* });
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export declare function custom(fn: CustomRetryFn): RetryStrategy;
|
|
67
|
+
/**
|
|
68
|
+
* Create a no-retry strategy
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```typescript
|
|
72
|
+
* const strategy = noRetry();
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
export declare function noRetry(): RetryStrategy;
|
|
76
|
+
/**
|
|
77
|
+
* Reconstruct a retry strategy from its config
|
|
78
|
+
*/
|
|
79
|
+
export declare function fromConfig(config: RetryStrategyConfig): RetryStrategy;
|
|
80
|
+
/**
|
|
81
|
+
* Default retry strategy
|
|
82
|
+
*/
|
|
83
|
+
export declare const DEFAULT_RETRY_STRATEGY: RetryStrategy;
|
|
84
|
+
//# sourceMappingURL=retry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,aAAa,EACb,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAEpB;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,oDAAoD;IACpD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mEAAmE;IACnE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,0DAA0D;IAC1D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AA0DD;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAmCD;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,aAAa,CAAC;AAiD7E;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CACzB,OAAO,CAAC,EAAE,yBAAyB,GAClC,aAAa,CAEf;AAED;;;;;;;GAOG;AACH,wBAAgB,MAAM,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,aAAa,CAEpE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,MAAM,CAAC,EAAE,EAAE,aAAa,GAAG,aAAa,CAEvD;AAED;;;;;;;GAOG;AACH,wBAAgB,OAAO,IAAI,aAAa,CAEvC;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,mBAAmB,GAAG,aAAa,CAkBrE;AAED;;GAEG;AACH,eAAO,MAAM,sBAAsB,eAKjC,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Job status enum
|
|
3
|
+
*/
|
|
4
|
+
export type JobStatus = 'pending' | 'running' | 'completed' | 'failed' | 'cancelled';
|
|
5
|
+
/**
|
|
6
|
+
* Timeout behavior when a job exceeds its timeout
|
|
7
|
+
*/
|
|
8
|
+
export type TimeoutBehavior = 'fail' | 'kill' | 'warn';
|
|
9
|
+
/**
|
|
10
|
+
* Priority levels for jobs
|
|
11
|
+
*/
|
|
12
|
+
export type JobPriority = 'low' | 'normal' | 'high' | 'critical';
|
|
13
|
+
/**
|
|
14
|
+
* Retry strategy configuration
|
|
15
|
+
*/
|
|
16
|
+
export interface RetryStrategyConfig {
|
|
17
|
+
type: 'exponential' | 'linear' | 'custom';
|
|
18
|
+
config: Record<string, unknown>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Result of a retry strategy calculation
|
|
22
|
+
*/
|
|
23
|
+
export interface RetryDecision {
|
|
24
|
+
shouldRetry: boolean;
|
|
25
|
+
delay: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Retry strategy interface
|
|
29
|
+
*/
|
|
30
|
+
export interface RetryStrategy {
|
|
31
|
+
/**
|
|
32
|
+
* Determine whether to retry and how long to wait
|
|
33
|
+
* @param attempt Current attempt number (1-based)
|
|
34
|
+
* @param error The error that caused the failure
|
|
35
|
+
*/
|
|
36
|
+
shouldRetry(attempt: number, error: Error): RetryDecision;
|
|
37
|
+
/**
|
|
38
|
+
* Serialize the strategy for storage
|
|
39
|
+
*/
|
|
40
|
+
toConfig(): RetryStrategyConfig;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Job payload - what work to execute
|
|
44
|
+
*/
|
|
45
|
+
export interface JobPayload {
|
|
46
|
+
/** The type of object (e.g., 'Document', 'Agent') */
|
|
47
|
+
objectType: string;
|
|
48
|
+
/** Instance ID (null for singleton/static methods) */
|
|
49
|
+
objectId: string | null;
|
|
50
|
+
/** Method name to execute */
|
|
51
|
+
method: string;
|
|
52
|
+
/** Arguments to pass to the method */
|
|
53
|
+
args: Record<string, unknown>;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Core job interface
|
|
57
|
+
*/
|
|
58
|
+
export interface Job {
|
|
59
|
+
/** Unique job identifier */
|
|
60
|
+
id: string;
|
|
61
|
+
/** Queue name this job belongs to */
|
|
62
|
+
queue: string;
|
|
63
|
+
/** The work to execute */
|
|
64
|
+
payload: JobPayload;
|
|
65
|
+
/** Current job status */
|
|
66
|
+
status: JobStatus;
|
|
67
|
+
/** Priority (higher = more important) */
|
|
68
|
+
priority: number;
|
|
69
|
+
/** Number of execution attempts */
|
|
70
|
+
attempts: number;
|
|
71
|
+
/** Maximum attempts before giving up */
|
|
72
|
+
maxAttempts: number;
|
|
73
|
+
/** When to run the job (for delayed jobs) */
|
|
74
|
+
runAt: Date;
|
|
75
|
+
/** When the job started executing */
|
|
76
|
+
startedAt: Date | null;
|
|
77
|
+
/** When the job completed/failed */
|
|
78
|
+
completedAt: Date | null;
|
|
79
|
+
/** Timeout in milliseconds */
|
|
80
|
+
timeout: number;
|
|
81
|
+
/** What to do when timeout is exceeded */
|
|
82
|
+
timeoutBehavior: TimeoutBehavior;
|
|
83
|
+
/** Last error message if failed */
|
|
84
|
+
lastError: string | null;
|
|
85
|
+
/** URI pointer to result storage */
|
|
86
|
+
resultPointer: string | null;
|
|
87
|
+
/** Retry strategy configuration */
|
|
88
|
+
retryStrategy: RetryStrategyConfig;
|
|
89
|
+
/** Worker ID currently processing this job */
|
|
90
|
+
workerId: string | null;
|
|
91
|
+
/** Last heartbeat from worker */
|
|
92
|
+
workerHeartbeat: Date | null;
|
|
93
|
+
/** When the job was created */
|
|
94
|
+
createdAt: Date;
|
|
95
|
+
/** When the job was last updated */
|
|
96
|
+
updatedAt: Date;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Options for creating a new job
|
|
100
|
+
*/
|
|
101
|
+
export interface JobCreateOptions {
|
|
102
|
+
/** Queue name (default: 'default') */
|
|
103
|
+
queue?: string;
|
|
104
|
+
/** Job payload */
|
|
105
|
+
payload: JobPayload;
|
|
106
|
+
/** Priority level or number */
|
|
107
|
+
priority?: JobPriority | number;
|
|
108
|
+
/** When to run (default: now) */
|
|
109
|
+
runAt?: Date;
|
|
110
|
+
/** Maximum attempts (default: 3) */
|
|
111
|
+
maxAttempts?: number;
|
|
112
|
+
/** Timeout in ms (default: 300000) */
|
|
113
|
+
timeout?: number;
|
|
114
|
+
/** Timeout behavior (default: 'fail') */
|
|
115
|
+
timeoutBehavior?: TimeoutBehavior;
|
|
116
|
+
/** Retry strategy */
|
|
117
|
+
retryStrategy?: RetryStrategy | RetryStrategyConfig;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Filter options for listing jobs
|
|
121
|
+
*/
|
|
122
|
+
export interface JobFilter {
|
|
123
|
+
/** Filter by queue */
|
|
124
|
+
queue?: string;
|
|
125
|
+
/** Filter by status */
|
|
126
|
+
status?: JobStatus | JobStatus[];
|
|
127
|
+
/** Filter by object type */
|
|
128
|
+
objectType?: string;
|
|
129
|
+
/** Filter by method */
|
|
130
|
+
method?: string;
|
|
131
|
+
/** Jobs created after this date */
|
|
132
|
+
createdAfter?: Date;
|
|
133
|
+
/** Jobs created before this date */
|
|
134
|
+
createdBefore?: Date;
|
|
135
|
+
/** Maximum number of jobs to return */
|
|
136
|
+
limit?: number;
|
|
137
|
+
/** Offset for pagination */
|
|
138
|
+
offset?: number;
|
|
139
|
+
/** Order by field */
|
|
140
|
+
orderBy?: 'createdAt' | 'runAt' | 'priority' | 'attempts';
|
|
141
|
+
/** Order direction */
|
|
142
|
+
orderDir?: 'asc' | 'desc';
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Options for job cleanup
|
|
146
|
+
*/
|
|
147
|
+
export interface CleanupOptions {
|
|
148
|
+
/** Delete completed jobs older than this */
|
|
149
|
+
completedBefore?: Date;
|
|
150
|
+
/** Delete failed jobs older than this */
|
|
151
|
+
failedBefore?: Date;
|
|
152
|
+
/** Delete cancelled jobs older than this */
|
|
153
|
+
cancelledBefore?: Date;
|
|
154
|
+
/** Maximum jobs to delete in one operation */
|
|
155
|
+
limit?: number;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Job event types
|
|
159
|
+
*/
|
|
160
|
+
export type JobEventType = 'job.created' | 'job.ready' | 'job.started' | 'job.completed' | 'job.failed' | 'job.cancelled' | 'job.retrying';
|
|
161
|
+
/**
|
|
162
|
+
* Job event payload
|
|
163
|
+
*/
|
|
164
|
+
export interface JobEvent {
|
|
165
|
+
type: JobEventType;
|
|
166
|
+
job: Job;
|
|
167
|
+
timestamp: Date;
|
|
168
|
+
/** Error details for failed events */
|
|
169
|
+
error?: string;
|
|
170
|
+
/** Result pointer for completed events */
|
|
171
|
+
resultPointer?: string;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Job event listener callback
|
|
175
|
+
*/
|
|
176
|
+
export type JobEventListener = (event: JobEvent) => void | Promise<void>;
|
|
177
|
+
/**
|
|
178
|
+
* Unsubscribe function returned by subscribe
|
|
179
|
+
*/
|
|
180
|
+
export type Unsubscribe = () => void;
|
|
181
|
+
/**
|
|
182
|
+
* Job handle returned from enqueue operations
|
|
183
|
+
*/
|
|
184
|
+
export interface JobHandle {
|
|
185
|
+
/** Job ID */
|
|
186
|
+
id: string;
|
|
187
|
+
/** Get current job status */
|
|
188
|
+
status(): Promise<JobStatus>;
|
|
189
|
+
/** Get full job details */
|
|
190
|
+
get(): Promise<Job | null>;
|
|
191
|
+
/** Wait for job completion */
|
|
192
|
+
wait(options?: {
|
|
193
|
+
timeout?: number;
|
|
194
|
+
}): Promise<unknown>;
|
|
195
|
+
/** Cancel the job */
|
|
196
|
+
cancel(): Promise<void>;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Abstract job store interface that adapters implement
|
|
200
|
+
*/
|
|
201
|
+
export interface JobStore {
|
|
202
|
+
/**
|
|
203
|
+
* Initialize the store (create tables, etc.)
|
|
204
|
+
*/
|
|
205
|
+
initialize(): Promise<void>;
|
|
206
|
+
/**
|
|
207
|
+
* Enqueue a new job
|
|
208
|
+
*/
|
|
209
|
+
enqueue(options: JobCreateOptions): Promise<Job>;
|
|
210
|
+
/**
|
|
211
|
+
* Dequeue jobs ready for processing
|
|
212
|
+
* @param queues Queue names to dequeue from (in priority order)
|
|
213
|
+
* @param limit Maximum jobs to dequeue
|
|
214
|
+
* @param workerId Worker ID claiming the jobs
|
|
215
|
+
*/
|
|
216
|
+
dequeue(queues: string[], limit: number, workerId: string): Promise<Job[]>;
|
|
217
|
+
/**
|
|
218
|
+
* Update a job
|
|
219
|
+
*/
|
|
220
|
+
update(id: string, updates: Partial<Job>): Promise<Job>;
|
|
221
|
+
/**
|
|
222
|
+
* Get a job by ID
|
|
223
|
+
*/
|
|
224
|
+
get(id: string): Promise<Job | null>;
|
|
225
|
+
/**
|
|
226
|
+
* List jobs with filtering
|
|
227
|
+
*/
|
|
228
|
+
list(filter: JobFilter): Promise<Job[]>;
|
|
229
|
+
/**
|
|
230
|
+
* Cancel a job
|
|
231
|
+
*/
|
|
232
|
+
cancel(id: string): Promise<void>;
|
|
233
|
+
/**
|
|
234
|
+
* Clean up old jobs
|
|
235
|
+
*/
|
|
236
|
+
cleanup(options: CleanupOptions): Promise<number>;
|
|
237
|
+
/**
|
|
238
|
+
* Subscribe to job events
|
|
239
|
+
*/
|
|
240
|
+
subscribe(listener: JobEventListener): Unsubscribe;
|
|
241
|
+
/**
|
|
242
|
+
* Wait for a store-level update signal, if the adapter supports one.
|
|
243
|
+
* Adapters without push notifications may omit this and rely on polling.
|
|
244
|
+
*/
|
|
245
|
+
waitForUpdate?(timeoutMs?: number): Promise<boolean>;
|
|
246
|
+
/**
|
|
247
|
+
* Update worker heartbeat for a job
|
|
248
|
+
*/
|
|
249
|
+
heartbeat(jobId: string, workerId: string): Promise<void>;
|
|
250
|
+
/**
|
|
251
|
+
* Get queue statistics
|
|
252
|
+
*/
|
|
253
|
+
stats(queue?: string): Promise<QueueStats>;
|
|
254
|
+
/**
|
|
255
|
+
* Close the store and release resources
|
|
256
|
+
*/
|
|
257
|
+
close(): Promise<void>;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Queue statistics
|
|
261
|
+
*/
|
|
262
|
+
export interface QueueStats {
|
|
263
|
+
pending: number;
|
|
264
|
+
running: number;
|
|
265
|
+
completed: number;
|
|
266
|
+
failed: number;
|
|
267
|
+
cancelled: number;
|
|
268
|
+
avgDuration: number | null;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Worker configuration
|
|
272
|
+
*/
|
|
273
|
+
export interface WorkerConfig {
|
|
274
|
+
/** Unique worker ID */
|
|
275
|
+
id?: string;
|
|
276
|
+
/** Number of concurrent jobs */
|
|
277
|
+
concurrency?: number;
|
|
278
|
+
/** Queues to process (in priority order) */
|
|
279
|
+
queues?: string[];
|
|
280
|
+
/** Poll interval for non-push stores (ms) */
|
|
281
|
+
pollInterval?: number;
|
|
282
|
+
/** Heartbeat interval (ms) */
|
|
283
|
+
heartbeatInterval?: number;
|
|
284
|
+
/** Shutdown timeout (ms) */
|
|
285
|
+
shutdownTimeout?: number;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Job handler function
|
|
289
|
+
*/
|
|
290
|
+
export type JobHandler = (job: Job) => Promise<{
|
|
291
|
+
result?: unknown;
|
|
292
|
+
resultPointer?: string;
|
|
293
|
+
}>;
|
|
294
|
+
/**
|
|
295
|
+
* Worker interface
|
|
296
|
+
*/
|
|
297
|
+
export interface Worker {
|
|
298
|
+
/** Worker ID */
|
|
299
|
+
id: string;
|
|
300
|
+
/** Start processing jobs */
|
|
301
|
+
start(): Promise<void>;
|
|
302
|
+
/** Stop processing jobs (graceful shutdown) */
|
|
303
|
+
stop(): Promise<void>;
|
|
304
|
+
/** Check if worker is running */
|
|
305
|
+
isRunning(): boolean;
|
|
306
|
+
/** Register event listener */
|
|
307
|
+
on(event: string, listener: (...args: unknown[]) => void): void;
|
|
308
|
+
/** Remove event listener */
|
|
309
|
+
off(event: string, listener: (...args: unknown[]) => void): void;
|
|
310
|
+
}
|
|
311
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/worker.d.ts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import { Worker as IWorker, Job, JobHandler, JobStore, WorkerConfig } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Worker events
|
|
5
|
+
*/
|
|
6
|
+
export interface WorkerEvents {
|
|
7
|
+
'job:started': (job: Job) => void;
|
|
8
|
+
'job:completed': (job: Job, result: unknown) => void;
|
|
9
|
+
'job:failed': (job: Job, error: Error) => void;
|
|
10
|
+
'job:retrying': (job: Job, error: Error, delay: number) => void;
|
|
11
|
+
'worker:started': () => void;
|
|
12
|
+
'worker:stopped': () => void;
|
|
13
|
+
'worker:error': (error: Error) => void;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Job worker that processes jobs from a store
|
|
17
|
+
*/
|
|
18
|
+
export declare class JobWorker extends EventEmitter implements IWorker {
|
|
19
|
+
readonly id: string;
|
|
20
|
+
private readonly store;
|
|
21
|
+
private readonly handler;
|
|
22
|
+
private readonly config;
|
|
23
|
+
private running;
|
|
24
|
+
private activeJobs;
|
|
25
|
+
private pollTimer;
|
|
26
|
+
private heartbeatTimer;
|
|
27
|
+
private shutdownPromise;
|
|
28
|
+
constructor(store: JobStore, handler: JobHandler, config?: WorkerConfig);
|
|
29
|
+
/**
|
|
30
|
+
* Start processing jobs
|
|
31
|
+
*/
|
|
32
|
+
start(): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Stop processing jobs (graceful shutdown)
|
|
35
|
+
*/
|
|
36
|
+
stop(): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Check if worker is running
|
|
39
|
+
*/
|
|
40
|
+
isRunning(): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Get count of active jobs
|
|
43
|
+
*/
|
|
44
|
+
activeJobCount(): number;
|
|
45
|
+
/**
|
|
46
|
+
* Start the polling loop
|
|
47
|
+
*/
|
|
48
|
+
private startPolling;
|
|
49
|
+
/**
|
|
50
|
+
* Poll for and process jobs
|
|
51
|
+
*/
|
|
52
|
+
private poll;
|
|
53
|
+
/**
|
|
54
|
+
* Process a single job
|
|
55
|
+
*/
|
|
56
|
+
private processJob;
|
|
57
|
+
/**
|
|
58
|
+
* Handle job execution error
|
|
59
|
+
*/
|
|
60
|
+
private handleJobError;
|
|
61
|
+
/**
|
|
62
|
+
* Start heartbeat loop to keep jobs alive
|
|
63
|
+
*/
|
|
64
|
+
private startHeartbeat;
|
|
65
|
+
/**
|
|
66
|
+
* Wait for active jobs to complete with timeout
|
|
67
|
+
*/
|
|
68
|
+
private waitForActiveJobs;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Create a job worker
|
|
72
|
+
*/
|
|
73
|
+
export declare function createWorker(store: JobStore, handler: JobHandler, config?: WorkerConfig): JobWorker;
|
|
74
|
+
//# sourceMappingURL=worker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,OAAO,KAAK,EACV,MAAM,IAAI,OAAO,EACjB,GAAG,EACH,UAAU,EACV,QAAQ,EACR,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC;IAClC,eAAe,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACrD,YAAY,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAC/C,cAAc,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAChE,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,cAAc,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACxC;AAcD;;GAEG;AACH,qBAAa,SAAU,SAAQ,YAAa,YAAW,OAAO;IAC5D,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAW;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAa;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;IAChD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAA0B;IAC5C,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,eAAe,CAA8B;gBAEzC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,GAAE,YAAiB;IAY3E;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAsB5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA2B3B;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,cAAc,IAAI,MAAM;IAIxB;;OAEG;IACH,OAAO,CAAC,YAAY;IA2CpB;;OAEG;YACW,IAAI;IAkBlB;;OAEG;YACW,UAAU;IAoCxB;;OAEG;YACW,cAAc;IA6B5B;;OAEG;IACH,OAAO,CAAC,cAAc;IAatB;;OAEG;YACW,iBAAiB;CAqBhC;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,QAAQ,EACf,OAAO,EAAE,UAAU,EACnB,MAAM,CAAC,EAAE,YAAY,GACpB,SAAS,CAEX"}
|
package/metadata.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@happyvertical/jobs",
|
|
3
|
+
"path": "packages/jobs",
|
|
4
|
+
"position": {
|
|
5
|
+
"index": 16,
|
|
6
|
+
"count": 30
|
|
7
|
+
},
|
|
8
|
+
"description": "Job queue abstraction with multiple backend adapters (SQLite, PostgreSQL, Bull, SQS)",
|
|
9
|
+
"provides": [
|
|
10
|
+
"Job queue abstraction with multiple backend adapters (SQLite, PostgreSQL, Bull, SQS)"
|
|
11
|
+
],
|
|
12
|
+
"implements": [],
|
|
13
|
+
"requires": {
|
|
14
|
+
"workspace": [
|
|
15
|
+
"@happyvertical/sql",
|
|
16
|
+
"@happyvertical/utils"
|
|
17
|
+
],
|
|
18
|
+
"externalHappyVertical": [],
|
|
19
|
+
"external": [
|
|
20
|
+
"@aws-sdk/client-sqs",
|
|
21
|
+
"@google-cloud/tasks",
|
|
22
|
+
"bull",
|
|
23
|
+
"bullmq"
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
"dependents": [],
|
|
27
|
+
"stability": {
|
|
28
|
+
"level": "stable",
|
|
29
|
+
"reason": "Primary package surface is described as implemented and production-oriented."
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"jobs"
|
|
33
|
+
]
|
|
34
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@happyvertical/jobs",
|
|
3
|
+
"version": "0.74.8",
|
|
4
|
+
"description": "Job queue abstraction with multiple backend adapters (SQLite, PostgreSQL, Bull, SQS)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"README.md",
|
|
11
|
+
"LICENSE",
|
|
12
|
+
"AGENT.md",
|
|
13
|
+
"metadata.json"
|
|
14
|
+
],
|
|
15
|
+
"bin": {
|
|
16
|
+
"have-jobs-context": "./dist/cli/claude-context.js"
|
|
17
|
+
},
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"registry": "https://registry.npmjs.org",
|
|
20
|
+
"access": "public"
|
|
21
|
+
},
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "https://github.com/happyvertical/sdk.git",
|
|
25
|
+
"directory": "packages/jobs"
|
|
26
|
+
},
|
|
27
|
+
"bugs": {
|
|
28
|
+
"url": "https://github.com/happyvertical/sdk/issues"
|
|
29
|
+
},
|
|
30
|
+
"homepage": "https://github.com/happyvertical/sdk/tree/main/packages/jobs#readme",
|
|
31
|
+
"exports": {
|
|
32
|
+
".": {
|
|
33
|
+
"import": "./dist/index.js",
|
|
34
|
+
"types": "./dist/index.d.ts"
|
|
35
|
+
},
|
|
36
|
+
"./sqlite": {
|
|
37
|
+
"import": "./dist/adapters/sqlite.js",
|
|
38
|
+
"types": "./dist/adapters/sqlite.d.ts"
|
|
39
|
+
},
|
|
40
|
+
"./postgres": {
|
|
41
|
+
"import": "./dist/adapters/postgres.js",
|
|
42
|
+
"types": "./dist/adapters/postgres.d.ts"
|
|
43
|
+
},
|
|
44
|
+
"./bull": {
|
|
45
|
+
"import": "./dist/adapters/bull.js",
|
|
46
|
+
"types": "./dist/adapters/bull.d.ts"
|
|
47
|
+
},
|
|
48
|
+
"./bullmq": {
|
|
49
|
+
"import": "./dist/adapters/bullmq.js",
|
|
50
|
+
"types": "./dist/adapters/bullmq.d.ts"
|
|
51
|
+
},
|
|
52
|
+
"./sqs": {
|
|
53
|
+
"import": "./dist/adapters/sqs.js",
|
|
54
|
+
"types": "./dist/adapters/sqs.d.ts"
|
|
55
|
+
},
|
|
56
|
+
"./cloud-tasks": {
|
|
57
|
+
"import": "./dist/adapters/cloud-tasks.js",
|
|
58
|
+
"types": "./dist/adapters/cloud-tasks.d.ts"
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"keywords": [
|
|
62
|
+
"jobs",
|
|
63
|
+
"queue",
|
|
64
|
+
"background",
|
|
65
|
+
"worker",
|
|
66
|
+
"task"
|
|
67
|
+
],
|
|
68
|
+
"author": "willgriffin@gmail.com",
|
|
69
|
+
"license": "ISC",
|
|
70
|
+
"dependencies": {
|
|
71
|
+
"@happyvertical/sql": "0.74.8",
|
|
72
|
+
"@happyvertical/utils": "0.74.8"
|
|
73
|
+
},
|
|
74
|
+
"devDependencies": {
|
|
75
|
+
"@aws-sdk/client-sqs": "^3.1034.0",
|
|
76
|
+
"@google-cloud/tasks": "^6.2.1",
|
|
77
|
+
"@types/bull": "^4.10.4",
|
|
78
|
+
"@types/node": "25.0.10",
|
|
79
|
+
"bull": "^4.16.5",
|
|
80
|
+
"bullmq": "^5.76.0",
|
|
81
|
+
"typescript": "^5.9.3",
|
|
82
|
+
"vite": "7.3.2",
|
|
83
|
+
"vite-plugin-dts": "4.5.4",
|
|
84
|
+
"vitest": "^4.1.5"
|
|
85
|
+
},
|
|
86
|
+
"peerDependencies": {
|
|
87
|
+
"@aws-sdk/client-sqs": ">=3.1034.0",
|
|
88
|
+
"@google-cloud/tasks": ">=4.1.0",
|
|
89
|
+
"bull": ">=4.16.5",
|
|
90
|
+
"bullmq": ">=5.76.0"
|
|
91
|
+
},
|
|
92
|
+
"peerDependenciesMeta": {
|
|
93
|
+
"bull": {
|
|
94
|
+
"optional": true
|
|
95
|
+
},
|
|
96
|
+
"bullmq": {
|
|
97
|
+
"optional": true
|
|
98
|
+
},
|
|
99
|
+
"@aws-sdk/client-sqs": {
|
|
100
|
+
"optional": true
|
|
101
|
+
},
|
|
102
|
+
"@google-cloud/tasks": {
|
|
103
|
+
"optional": true
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
"scripts": {
|
|
107
|
+
"test": "npx vitest run",
|
|
108
|
+
"test:watch": "npx vitest",
|
|
109
|
+
"build": "vite build",
|
|
110
|
+
"build:watch": "vite build --watch",
|
|
111
|
+
"clean": "rm -rf dist *.tsbuildinfo",
|
|
112
|
+
"dev": "npm run build:watch & npm run test:watch"
|
|
113
|
+
}
|
|
114
|
+
}
|