@cloud-copilot/job 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/cjs/ConcurrentJobQueue.d.ts +63 -0
  2. package/dist/cjs/ConcurrentJobQueue.d.ts.map +1 -0
  3. package/dist/cjs/ConcurrentJobQueue.js +158 -0
  4. package/dist/cjs/ConcurrentJobQueue.js.map +1 -0
  5. package/dist/cjs/StreamingJobQueue.d.ts +61 -0
  6. package/dist/cjs/StreamingJobQueue.d.ts.map +1 -0
  7. package/dist/cjs/StreamingJobQueue.js +157 -0
  8. package/dist/cjs/StreamingJobQueue.js.map +1 -0
  9. package/dist/cjs/index.d.ts +5 -0
  10. package/dist/cjs/index.d.ts.map +1 -0
  11. package/dist/cjs/index.js +10 -0
  12. package/dist/cjs/index.js.map +1 -0
  13. package/dist/cjs/job.d.ts +39 -0
  14. package/dist/cjs/job.d.ts.map +1 -0
  15. package/dist/cjs/job.js +3 -0
  16. package/dist/cjs/job.js.map +1 -0
  17. package/dist/cjs/package.json +3 -0
  18. package/dist/cjs/runJobs.d.ts +7 -0
  19. package/dist/cjs/runJobs.d.ts.map +1 -0
  20. package/dist/cjs/runJobs.js +47 -0
  21. package/dist/cjs/runJobs.js.map +1 -0
  22. package/dist/cjs/util.d.ts +7 -0
  23. package/dist/cjs/util.d.ts.map +1 -0
  24. package/dist/cjs/util.js +13 -0
  25. package/dist/cjs/util.js.map +1 -0
  26. package/dist/esm/ConcurrentJobQueue.d.ts +63 -0
  27. package/dist/esm/ConcurrentJobQueue.d.ts.map +1 -0
  28. package/dist/esm/ConcurrentJobQueue.js +152 -0
  29. package/dist/esm/ConcurrentJobQueue.js.map +1 -0
  30. package/dist/esm/StreamingJobQueue.d.ts +61 -0
  31. package/dist/esm/StreamingJobQueue.d.ts.map +1 -0
  32. package/dist/esm/StreamingJobQueue.js +150 -0
  33. package/dist/esm/StreamingJobQueue.js.map +1 -0
  34. package/dist/esm/index.d.ts +5 -0
  35. package/dist/esm/index.d.ts.map +1 -0
  36. package/dist/esm/index.js +4 -0
  37. package/dist/esm/index.js.map +1 -0
  38. package/dist/esm/job.d.ts +39 -0
  39. package/dist/esm/job.d.ts.map +1 -0
  40. package/dist/esm/job.js +2 -0
  41. package/dist/esm/job.js.map +1 -0
  42. package/dist/esm/package.json +3 -0
  43. package/dist/esm/runJobs.d.ts +7 -0
  44. package/dist/esm/runJobs.d.ts.map +1 -0
  45. package/dist/esm/runJobs.js +44 -0
  46. package/dist/esm/runJobs.js.map +1 -0
  47. package/dist/esm/util.d.ts +7 -0
  48. package/dist/esm/util.d.ts.map +1 -0
  49. package/dist/esm/util.js +10 -0
  50. package/dist/esm/util.js.map +1 -0
  51. package/package.json +109 -0
@@ -0,0 +1,63 @@
1
+ import { Job, JobResult, Logger } from './job.js';
2
+ /**
3
+ * Creates a queue that runs jobs concurrently up to a specified limit.
4
+ * This will wait for jobs to be added to it and run them up the
5
+ * maximum concurrency.
6
+ *
7
+ * Results are available via `getResults()`.
8
+ */
9
+ export declare class ConcurrentJobQueue<T = void, P = Record<string, unknown>> {
10
+ private concurrency;
11
+ private logger;
12
+ private queue;
13
+ private results;
14
+ private activeJobs;
15
+ private waitingResolvers;
16
+ private workers;
17
+ private isAcceptingWork;
18
+ private workAvailablePromise;
19
+ private resolveWorkAvailable;
20
+ /**
21
+ * Create a new runner with the specified concurrency.
22
+ *
23
+ * @param concurrency - The maximum number of jobs to run concurrently.
24
+ */
25
+ constructor(concurrency: number, logger: Logger);
26
+ private worker;
27
+ private waitForWorkAvailable;
28
+ private ensureWorkers;
29
+ private notifyWorkersOfNewWork;
30
+ private checkIfIdle;
31
+ /**
32
+ * Add a job to the queue
33
+ */
34
+ enqueue(job: Job<T, P>): void;
35
+ /**
36
+ * Add multiple jobs to the queue
37
+ */
38
+ enqueueAll(jobs: Job<T, P>[]): void;
39
+ /**
40
+ * Returns a promise that resolves when all queued work is complete
41
+ */
42
+ waitForIdle(): Promise<void>;
43
+ /**
44
+ * Get all results accumulated so far
45
+ */
46
+ getResults(): JobResult<T, P>[];
47
+ /**
48
+ * Shutdown the queue - no new jobs will be accepted, but existing jobs will complete.
49
+ *
50
+ * Returns when a promise that resolves when all jobs have been processed and
51
+ * are available in `getResults()`.
52
+ */
53
+ finishAllWork(): Promise<void>;
54
+ /**
55
+ * Get the current queue length
56
+ */
57
+ get queueLength(): number;
58
+ /**
59
+ * Get the number of currently active jobs
60
+ */
61
+ get activeJobCount(): number;
62
+ }
63
+ //# sourceMappingURL=ConcurrentJobQueue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConcurrentJobQueue.d.ts","sourceRoot":"","sources":["../../src/ConcurrentJobQueue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAc,SAAS,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAE7D;;;;;;GAMG;AAEH,qBAAa,kBAAkB,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAgBjE,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,MAAM;IAhBhB,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,UAAU,CAAI;IACtB,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,eAAe,CAAO;IAC9B,OAAO,CAAC,oBAAoB,CAA6B;IACzD,OAAO,CAAC,oBAAoB,CAA4B;IAExD;;;;OAIG;gBAEO,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM;YAGV,MAAM;IAsCpB,OAAO,CAAC,oBAAoB;IAS5B,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,sBAAsB;IAS9B,OAAO,CAAC,WAAW;IAQnB;;OAEG;IACH,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI;IAS7B;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI;IAInC;;OAEG;IACH,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAW5B;;OAEG;IACH,UAAU,IAAI,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE;IAI/B;;;;;OAKG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IASpC;;OAEG;IACH,IAAI,WAAW,IAAI,MAAM,CAExB;IAED;;OAEG;IACH,IAAI,cAAc,IAAI,MAAM,CAE3B;CACF"}
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Creates a queue that runs jobs concurrently up to a specified limit.
3
+ * This will wait for jobs to be added to it and run them up the
4
+ * maximum concurrency.
5
+ *
6
+ * Results are available via `getResults()`.
7
+ */
8
+ export class ConcurrentJobQueue {
9
+ /**
10
+ * Create a new runner with the specified concurrency.
11
+ *
12
+ * @param concurrency - The maximum number of jobs to run concurrently.
13
+ */
14
+ constructor(concurrency, logger) {
15
+ this.concurrency = concurrency;
16
+ this.logger = logger;
17
+ this.queue = [];
18
+ this.results = [];
19
+ this.activeJobs = 0;
20
+ this.waitingResolvers = [];
21
+ this.workers = [];
22
+ this.isAcceptingWork = true;
23
+ this.workAvailablePromise = null;
24
+ this.resolveWorkAvailable = null;
25
+ }
26
+ async worker(workerId) {
27
+ while (this.isAcceptingWork || this.queue.length > 0) {
28
+ const job = this.queue.shift();
29
+ if (!job) {
30
+ if (!this.isAcceptingWork) {
31
+ // No longer accepting work and no jobs left, exit immediately
32
+ return;
33
+ }
34
+ // No work available, wait for new work to be added
35
+ await this.waitForWorkAvailable();
36
+ continue;
37
+ }
38
+ this.activeJobs++;
39
+ const context = { workerId };
40
+ const startTime = Date.now();
41
+ const interval = setInterval(() => {
42
+ this.logger.warn(`Long-running job detected.`, { minutes: Math.floor((Date.now() - startTime) / 60000) }, { ...context, ...job.properties });
43
+ }, 60000);
44
+ try {
45
+ const value = await job.execute({ ...context, properties: job.properties });
46
+ this.results.push({ status: 'fulfilled', value, properties: job.properties });
47
+ }
48
+ catch (reason) {
49
+ this.results.push({ status: 'rejected', reason, properties: job.properties });
50
+ }
51
+ finally {
52
+ clearInterval(interval);
53
+ this.activeJobs--;
54
+ this.checkIfIdle();
55
+ }
56
+ }
57
+ }
58
+ waitForWorkAvailable() {
59
+ if (!this.workAvailablePromise) {
60
+ this.workAvailablePromise = new Promise((resolve) => {
61
+ this.resolveWorkAvailable = resolve;
62
+ });
63
+ }
64
+ return this.workAvailablePromise;
65
+ }
66
+ ensureWorkers() {
67
+ if (this.workers.length === 0 && this.isAcceptingWork) {
68
+ for (let i = 0; i < this.concurrency; i++) {
69
+ this.workers.push(this.worker(i + 1));
70
+ }
71
+ }
72
+ }
73
+ notifyWorkersOfNewWork() {
74
+ // Wake up waiting workers
75
+ if (this.resolveWorkAvailable) {
76
+ this.resolveWorkAvailable();
77
+ this.workAvailablePromise = null;
78
+ this.resolveWorkAvailable = null;
79
+ }
80
+ }
81
+ checkIfIdle() {
82
+ if (this.activeJobs === 0 && this.queue.length === 0) {
83
+ // Notify all waiting resolvers
84
+ this.waitingResolvers.forEach((resolve) => resolve());
85
+ this.waitingResolvers = [];
86
+ }
87
+ }
88
+ /**
89
+ * Add a job to the queue
90
+ */
91
+ enqueue(job) {
92
+ if (!this.isAcceptingWork) {
93
+ throw new Error('Cannot enqueue jobs after shutdown');
94
+ }
95
+ this.queue.push(job);
96
+ this.ensureWorkers();
97
+ this.notifyWorkersOfNewWork();
98
+ }
99
+ /**
100
+ * Add multiple jobs to the queue
101
+ */
102
+ enqueueAll(jobs) {
103
+ jobs.forEach((job) => this.enqueue(job));
104
+ }
105
+ /**
106
+ * Returns a promise that resolves when all queued work is complete
107
+ */
108
+ waitForIdle() {
109
+ // log.debug('waitForIdle called', this.activeJobs, this.queue.length)
110
+ return new Promise((resolve) => {
111
+ if (this.activeJobs === 0 && this.queue.length === 0) {
112
+ resolve();
113
+ }
114
+ else {
115
+ this.waitingResolvers.push(resolve);
116
+ }
117
+ });
118
+ }
119
+ /**
120
+ * Get all results accumulated so far
121
+ */
122
+ getResults() {
123
+ return this.results;
124
+ }
125
+ /**
126
+ * Shutdown the queue - no new jobs will be accepted, but existing jobs will complete.
127
+ *
128
+ * Returns when a promise that resolves when all jobs have been processed and
129
+ * are available in `getResults()`.
130
+ */
131
+ async finishAllWork() {
132
+ this.isAcceptingWork = false;
133
+ // Wake up any sleeping workers so they can process remaining jobs or exit
134
+ this.notifyWorkersOfNewWork();
135
+ // Check if we're already idle and notify any waiting resolvers
136
+ await Promise.all(this.workers);
137
+ this.workers = [];
138
+ }
139
+ /**
140
+ * Get the current queue length
141
+ */
142
+ get queueLength() {
143
+ return this.queue.length;
144
+ }
145
+ /**
146
+ * Get the number of currently active jobs
147
+ */
148
+ get activeJobCount() {
149
+ return this.activeJobs;
150
+ }
151
+ }
152
+ //# sourceMappingURL=ConcurrentJobQueue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConcurrentJobQueue.js","sourceRoot":"","sources":["../../src/ConcurrentJobQueue.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ import { Job, JobResult, Logger } from './job.js';
2
+ /**
3
+ * Creates a queue that runs jobs concurrently up to a specified limit.
4
+ * This will wait for jobs to be added to it and run them up the
5
+ * maximum concurrency.
6
+ *
7
+ * Results are available via `getResults()`.
8
+ */
9
+ export declare class ConcurrentJobQueue<T = void, P = Record<string, unknown>> {
10
+ private concurrency;
11
+ private logger;
12
+ private onComplete;
13
+ private queue;
14
+ private activeJobs;
15
+ private waitingResolvers;
16
+ private workers;
17
+ private isAcceptingWork;
18
+ private workAvailablePromise;
19
+ private resolveWorkAvailable;
20
+ /**
21
+ * Create a new runner with the specified concurrency.
22
+ *
23
+ * @param concurrency - The maximum number of jobs to run concurrently.
24
+ * @param logger - Logger instance for logging long-running jobs.
25
+ * @param onComplete - Callback to handle job completion, receives the job result.
26
+ */
27
+ constructor(concurrency: number, logger: Logger, onComplete: (response: JobResult<T, P>) => Promise<void>);
28
+ private worker;
29
+ private waitForWorkAvailable;
30
+ private ensureWorkers;
31
+ private notifyWorkersOfNewWork;
32
+ private checkIfIdle;
33
+ /**
34
+ * Add a job to the queue
35
+ */
36
+ enqueue(job: Job<T, P>): void;
37
+ /**
38
+ * Add multiple jobs to the queue
39
+ */
40
+ enqueueAll(jobs: Job<T, P>[]): void;
41
+ /**
42
+ * Returns a promise that resolves when all queued work is complete
43
+ */
44
+ waitForIdle(): Promise<void>;
45
+ /**
46
+ * Shutdown the queue - no new jobs will be accepted, but existing jobs will complete.
47
+ *
48
+ * Returns when a promise that resolves when all jobs have been processed and
49
+ * are available in `getResults()`.
50
+ */
51
+ finishAllWork(): Promise<void>;
52
+ /**
53
+ * Get the current queue length
54
+ */
55
+ get queueLength(): number;
56
+ /**
57
+ * Get the number of currently active jobs
58
+ */
59
+ get activeJobCount(): number;
60
+ }
61
+ //# sourceMappingURL=StreamingJobQueue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StreamingJobQueue.d.ts","sourceRoot":"","sources":["../../src/StreamingJobQueue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAc,SAAS,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAE7D;;;;;;GAMG;AAEH,qBAAa,kBAAkB,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAiBjE,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,UAAU;IAlBpB,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,UAAU,CAAI;IACtB,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,eAAe,CAAO;IAC9B,OAAO,CAAC,oBAAoB,CAA6B;IACzD,OAAO,CAAC,oBAAoB,CAA4B;IAExD;;;;;;OAMG;gBAEO,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC;YAGpD,MAAM;IAwCpB,OAAO,CAAC,oBAAoB;IAS5B,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,sBAAsB;IAS9B,OAAO,CAAC,WAAW;IAQnB;;OAEG;IACH,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI;IAS7B;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI;IAInC;;OAEG;IACH,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAW5B;;;;;OAKG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IASpC;;OAEG;IACH,IAAI,WAAW,IAAI,MAAM,CAExB;IAED;;OAEG;IACH,IAAI,cAAc,IAAI,MAAM,CAE3B;CACF"}
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Creates a queue that runs jobs concurrently up to a specified limit.
3
+ * This will wait for jobs to be added to it and run them up the
4
+ * maximum concurrency.
5
+ *
6
+ * Results are available via `getResults()`.
7
+ */
8
+ export class ConcurrentJobQueue {
9
+ /**
10
+ * Create a new runner with the specified concurrency.
11
+ *
12
+ * @param concurrency - The maximum number of jobs to run concurrently.
13
+ * @param logger - Logger instance for logging long-running jobs.
14
+ * @param onComplete - Callback to handle job completion, receives the job result.
15
+ */
16
+ constructor(concurrency, logger, onComplete) {
17
+ this.concurrency = concurrency;
18
+ this.logger = logger;
19
+ this.onComplete = onComplete;
20
+ this.queue = [];
21
+ this.activeJobs = 0;
22
+ this.waitingResolvers = [];
23
+ this.workers = [];
24
+ this.isAcceptingWork = true;
25
+ this.workAvailablePromise = null;
26
+ this.resolveWorkAvailable = null;
27
+ }
28
+ async worker(workerId) {
29
+ while (this.isAcceptingWork || this.queue.length > 0) {
30
+ const job = this.queue.shift();
31
+ if (!job) {
32
+ if (!this.isAcceptingWork) {
33
+ // No longer accepting work and no jobs left, exit immediately
34
+ return;
35
+ }
36
+ // No work available, wait for new work to be added
37
+ await this.waitForWorkAvailable();
38
+ continue;
39
+ }
40
+ this.activeJobs++;
41
+ const context = { workerId };
42
+ const startTime = Date.now();
43
+ const interval = setInterval(() => {
44
+ this.logger.warn(`Long-running job detected.`, { minutes: Math.floor((Date.now() - startTime) / 60000) }, { ...context, ...job.properties });
45
+ }, 60000);
46
+ try {
47
+ const value = await job.execute({ ...context, properties: job.properties });
48
+ // this.results.push({ status: 'fulfilled', value, properties: job.properties })
49
+ await this.onComplete({ status: 'fulfilled', value, properties: job.properties });
50
+ }
51
+ catch (reason) {
52
+ // this.results.push({ status: 'rejected', reason, properties: job.properties })
53
+ await this.onComplete({ status: 'rejected', reason, properties: job.properties });
54
+ }
55
+ finally {
56
+ clearInterval(interval);
57
+ this.activeJobs--;
58
+ this.checkIfIdle();
59
+ }
60
+ }
61
+ }
62
+ waitForWorkAvailable() {
63
+ if (!this.workAvailablePromise) {
64
+ this.workAvailablePromise = new Promise((resolve) => {
65
+ this.resolveWorkAvailable = resolve;
66
+ });
67
+ }
68
+ return this.workAvailablePromise;
69
+ }
70
+ ensureWorkers() {
71
+ if (this.workers.length === 0 && this.isAcceptingWork) {
72
+ for (let i = 0; i < this.concurrency; i++) {
73
+ this.workers.push(this.worker(i + 1));
74
+ }
75
+ }
76
+ }
77
+ notifyWorkersOfNewWork() {
78
+ // Wake up waiting workers
79
+ if (this.resolveWorkAvailable) {
80
+ this.resolveWorkAvailable();
81
+ this.workAvailablePromise = null;
82
+ this.resolveWorkAvailable = null;
83
+ }
84
+ }
85
+ checkIfIdle() {
86
+ if (this.activeJobs === 0 && this.queue.length === 0) {
87
+ // Notify all waiting resolvers
88
+ this.waitingResolvers.forEach((resolve) => resolve());
89
+ this.waitingResolvers = [];
90
+ }
91
+ }
92
+ /**
93
+ * Add a job to the queue
94
+ */
95
+ enqueue(job) {
96
+ if (!this.isAcceptingWork) {
97
+ throw new Error('Cannot enqueue jobs after shutdown');
98
+ }
99
+ this.queue.push(job);
100
+ this.ensureWorkers();
101
+ this.notifyWorkersOfNewWork();
102
+ }
103
+ /**
104
+ * Add multiple jobs to the queue
105
+ */
106
+ enqueueAll(jobs) {
107
+ jobs.forEach((job) => this.enqueue(job));
108
+ }
109
+ /**
110
+ * Returns a promise that resolves when all queued work is complete
111
+ */
112
+ waitForIdle() {
113
+ // log.debug('waitForIdle called', this.activeJobs, this.queue.length)
114
+ return new Promise((resolve) => {
115
+ if (this.activeJobs === 0 && this.queue.length === 0) {
116
+ resolve();
117
+ }
118
+ else {
119
+ this.waitingResolvers.push(resolve);
120
+ }
121
+ });
122
+ }
123
+ /**
124
+ * Shutdown the queue - no new jobs will be accepted, but existing jobs will complete.
125
+ *
126
+ * Returns when a promise that resolves when all jobs have been processed and
127
+ * are available in `getResults()`.
128
+ */
129
+ async finishAllWork() {
130
+ this.isAcceptingWork = false;
131
+ // Wake up any sleeping workers so they can process remaining jobs or exit
132
+ this.notifyWorkersOfNewWork();
133
+ // Check if we're already idle and notify any waiting resolvers
134
+ await Promise.all(this.workers);
135
+ this.workers = [];
136
+ }
137
+ /**
138
+ * Get the current queue length
139
+ */
140
+ get queueLength() {
141
+ return this.queue.length;
142
+ }
143
+ /**
144
+ * Get the number of currently active jobs
145
+ */
146
+ get activeJobCount() {
147
+ return this.activeJobs;
148
+ }
149
+ }
150
+ //# sourceMappingURL=StreamingJobQueue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StreamingJobQueue.js","sourceRoot":"","sources":["../../src/StreamingJobQueue.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { ConcurrentJobQueue } from './ConcurrentJobQueue.js';
2
+ export type { Job, JobContext, JobResult, Logger } from './job.js';
3
+ export { runJobs } from './runJobs.js';
4
+ export { numberOfCpus } from './util.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAC5D,YAAY,EAAE,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAClE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA"}
@@ -0,0 +1,4 @@
1
+ export { ConcurrentJobQueue } from './ConcurrentJobQueue.js';
2
+ export { runJobs } from './runJobs.js';
3
+ export { numberOfCpus } from './util.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAE5D,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Represents the outcome of a job:
3
+ * - `fulfilled` with a `value` if it succeeded
4
+ * - `rejected` with a `reason` if it threw.
5
+ */
6
+ export type JobResult<T, P> = {
7
+ status: 'fulfilled';
8
+ value: T;
9
+ properties: P;
10
+ } | {
11
+ status: 'rejected';
12
+ reason: any;
13
+ properties: P;
14
+ };
15
+ export interface JobContext {
16
+ workerId: number;
17
+ }
18
+ /**
19
+ * Represents a job that can be executed
20
+ */
21
+ export interface Job<T = void, P = Record<string, unknown>> {
22
+ /**
23
+ * Execute the job with the given context.
24
+ *
25
+ * @param context - The context for the job execution, see @link JobContext
26
+ * @returns A promise that is resolved by the job's worker
27
+ */
28
+ execute: (props: JobContext & {
29
+ properties: P;
30
+ }) => Promise<T>;
31
+ /**
32
+ * Properties associated with the job, useful for logging or tracking.
33
+ */
34
+ properties: P;
35
+ }
36
+ export interface Logger {
37
+ warn: (...args: unknown[]) => void;
38
+ }
39
+ //# sourceMappingURL=job.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job.d.ts","sourceRoot":"","sources":["../../src/job.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,MAAM,SAAS,CAAC,CAAC,EAAE,CAAC,IACtB;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,CAAC,CAAC;IAAC,UAAU,EAAE,CAAC,CAAA;CAAE,GAChD;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,GAAG,CAAC;IAAC,UAAU,EAAE,CAAC,CAAA;CAAE,CAAA;AAEtD,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,GAAG,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACxD;;;;;OAKG;IACH,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,GAAG;QAAE,UAAU,EAAE,CAAC,CAAA;KAAE,KAAK,OAAO,CAAC,CAAC,CAAC,CAAA;IAE9D;;OAEG;IACH,UAAU,EAAE,CAAC,CAAA;CACd;AAED,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;CACnC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=job.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job.js","sourceRoot":"","sources":["../../src/job.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "module"
3
+ }
@@ -0,0 +1,7 @@
1
+ import { Job, JobResult, Logger } from './job.js';
2
+ /**
3
+ * Runs the given jobs with up to `concurrency` tasks in flight at once.
4
+ * Resolves with an array of results in the same order as the jobs.
5
+ */
6
+ export declare function runJobs<T = void, P = Record<string, unknown>>(jobs: Job<T, P>[], concurrency: number, logger: Logger): Promise<JobResult<T, P>[]>;
7
+ //# sourceMappingURL=runJobs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runJobs.d.ts","sourceRoot":"","sources":["../../src/runJobs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAc,SAAS,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAE7D;;;GAGG;AACH,wBAAsB,OAAO,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjE,IAAI,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EACjB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CA6C5B"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Runs the given jobs with up to `concurrency` tasks in flight at once.
3
+ * Resolves with an array of results in the same order as the jobs.
4
+ */
5
+ export async function runJobs(jobs, concurrency, logger) {
6
+ const results = [];
7
+ let nextIndex = 0;
8
+ if (concurrency == null || concurrency === undefined || concurrency <= 0) {
9
+ throw new Error(`Invalid concurrency: ${concurrency}. Must be a positive integer.`);
10
+ }
11
+ // Each worker pulls the next available job, runs it, stores the result, then loops.
12
+ async function worker(workerId) {
13
+ while (true) {
14
+ const i = nextIndex++;
15
+ if (i >= jobs.length)
16
+ return;
17
+ const context = {
18
+ workerId
19
+ };
20
+ const startTime = Date.now();
21
+ const interval = setInterval(() => {
22
+ logger.warn(`Long-running job detected.`, { minutes: Math.floor((Date.now() - startTime) / 60000) }, { ...context, ...jobs[i].properties });
23
+ }, 60000);
24
+ try {
25
+ const value = await jobs[i].execute({ ...context, properties: jobs[i].properties });
26
+ results[i] = { status: 'fulfilled', value, properties: jobs[i].properties };
27
+ }
28
+ catch (reason) {
29
+ results[i] = { status: 'rejected', reason, properties: jobs[i].properties };
30
+ }
31
+ finally {
32
+ clearInterval(interval);
33
+ }
34
+ }
35
+ }
36
+ // Create a pool of workers maxed at `concurrency` up to the number of jobs.
37
+ const workers = Array(Math.min(concurrency, jobs.length))
38
+ .fill(null)
39
+ .map((_, idx) => worker(idx + 1));
40
+ // Wait for all workers to finish
41
+ await Promise.all(workers);
42
+ return results;
43
+ }
44
+ //# sourceMappingURL=runJobs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runJobs.js","sourceRoot":"","sources":["../../src/runJobs.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,IAAiB,EACjB,WAAmB,EACnB,MAAc;IAEd,MAAM,OAAO,GAAsB,EAAE,CAAA;IACrC,IAAI,SAAS,GAAG,CAAC,CAAA;IACjB,IAAI,WAAW,IAAI,IAAI,IAAI,WAAW,KAAK,SAAS,IAAI,WAAW,IAAI,CAAC,EAAE,CAAC;QACzE,MAAM,IAAI,KAAK,CAAC,wBAAwB,WAAW,+BAA+B,CAAC,CAAA;IACrF,CAAC;IAED,oFAAoF;IACpF,KAAK,UAAU,MAAM,CAAC,QAAgB;QACpC,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,CAAC,GAAG,SAAS,EAAE,CAAA;YACrB,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM;gBAAE,OAAM;YAE5B,MAAM,OAAO,GAAe;gBAC1B,QAAQ;aACT,CAAA;YAED,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;YAC5B,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE;gBAChC,MAAM,CAAC,IAAI,CACT,4BAA4B,EAC5B,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,GAAG,KAAK,CAAC,EAAE,EACzD,EAAE,GAAG,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,CACtC,CAAA;YACH,CAAC,EAAE,KAAM,CAAC,CAAA;YACV,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,GAAG,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAA;gBACnF,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,CAAA;YAC7E,CAAC;YAAC,OAAO,MAAM,EAAE,CAAC;gBAChB,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,CAAA;YAC7E,CAAC;oBAAS,CAAC;gBACT,aAAa,CAAC,QAAQ,CAAC,CAAA;YACzB,CAAC;QACH,CAAC;IACH,CAAC;IAED,4EAA4E;IAC5E,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;SACtD,IAAI,CAAC,IAAI,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAA;IAEnC,iCAAiC;IACjC,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IAE1B,OAAO,OAAO,CAAA;AAChB,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Get the number of CPU cores available on the system.
3
+ *
4
+ * @returns The number of CPU cores, or 1 if the system cannot determine it.
5
+ */
6
+ export declare function numberOfCpus(): number;
7
+ //# sourceMappingURL=util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/util.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC"}
@@ -0,0 +1,10 @@
1
+ import { cpus } from 'os';
2
+ /**
3
+ * Get the number of CPU cores available on the system.
4
+ *
5
+ * @returns The number of CPU cores, or 1 if the system cannot determine it.
6
+ */
7
+ export function numberOfCpus() {
8
+ return cpus().length || 1;
9
+ }
10
+ //# sourceMappingURL=util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../../src/util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAA;AAEzB;;;;GAIG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,IAAI,EAAE,CAAC,MAAM,IAAI,CAAC,CAAA;AAC3B,CAAC"}