pg-boss 7.1.0 → 7.3.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.
package/README.md CHANGED
@@ -38,6 +38,7 @@ pg-boss relies on [SKIP LOCKED](http://blog.2ndquadrant.com/what-is-select-skip-
38
38
  This will likely cater the most to teams already familiar with the simplicity of relational database semantics and operations (SQL, querying, and backups). It will be especially useful to those already relying on PostgreSQL that want to limit how many systems are required to monitor and support in their architecture.
39
39
 
40
40
  ## Features
41
+ * Exactly-once job delivery
41
42
  * Backpressure-compatible polling workers
42
43
  * Cron scheduling
43
44
  * Pub/sub API for fan-out queue relationships
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pg-boss",
3
- "version": "7.1.0",
3
+ "version": "7.3.0",
4
4
  "description": "Queueing jobs in Node.js using PostgreSQL like a boss",
5
5
  "main": "./src/index.js",
6
6
  "engines": {
package/src/manager.js CHANGED
@@ -56,6 +56,7 @@ class Manager extends EventEmitter {
56
56
  this.insertJobsCommand = plans.insertJobs(config.schema)
57
57
  this.completeJobsCommand = plans.completeJobs(config.schema)
58
58
  this.cancelJobsCommand = plans.cancelJobs(config.schema)
59
+ this.resumeJobsCommand = plans.resumeJobs(config.schema)
59
60
  this.failJobsCommand = plans.failJobs(config.schema)
60
61
  this.getJobByIdCommand = plans.getJobById(config.schema)
61
62
  this.getArchivedJobByIdCommand = plans.getArchivedJobById(config.schema)
@@ -67,11 +68,13 @@ class Manager extends EventEmitter {
67
68
  this.functions = [
68
69
  this.complete,
69
70
  this.cancel,
71
+ this.resume,
70
72
  this.fail,
71
73
  this.fetch,
72
74
  this.fetchCompleted,
73
75
  this.work,
74
76
  this.offWork,
77
+ this.notifyWorker,
75
78
  this.onComplete,
76
79
  this.offComplete,
77
80
  this.publish,
@@ -292,6 +295,12 @@ class Manager extends EventEmitter {
292
295
  })
293
296
  }
294
297
 
298
+ notifyWorker (workerId) {
299
+ if (this.workers.has(workerId)) {
300
+ this.workers.get(workerId).notify()
301
+ }
302
+ }
303
+
295
304
  async subscribe (event, name) {
296
305
  assert(event, 'Missing required argument')
297
306
  assert(name, 'Missing required argument')
@@ -541,6 +550,12 @@ class Manager extends EventEmitter {
541
550
  return this.mapCompletionResponse(ids, result)
542
551
  }
543
552
 
553
+ async resume (id) {
554
+ const ids = this.mapCompletionIdArg(id, 'resume')
555
+ const result = await this.db.executeSql(this.resumeJobsCommand, [ids])
556
+ return this.mapCompletionResponse(ids, result)
557
+ }
558
+
544
559
  async deleteQueue (queue, options) {
545
560
  assert(queue, 'Missing queue name argument')
546
561
  const sql = plans.deleteQueue(this.config.schema, options)
package/src/plans.js CHANGED
@@ -26,6 +26,7 @@ module.exports = {
26
26
  fetchNextJob,
27
27
  completeJobs,
28
28
  cancelJobs,
29
+ resumeJobs,
29
30
  failJobs,
30
31
  insertJob,
31
32
  insertJobs,
@@ -497,6 +498,19 @@ function cancelJobs (schema) {
497
498
  `
498
499
  }
499
500
 
501
+ function resumeJobs (schema) {
502
+ return `
503
+ with results as (
504
+ UPDATE ${schema}.job
505
+ SET completedOn = NULL,
506
+ state = '${states.created}'
507
+ WHERE id IN (SELECT UNNEST($1::uuid[]))
508
+ RETURNING 1
509
+ )
510
+ SELECT COUNT(*) from results
511
+ `
512
+ }
513
+
500
514
  function insertJob (schema) {
501
515
  return `
502
516
  INSERT INTO ${schema}.job (
package/src/worker.js CHANGED
@@ -27,6 +27,15 @@ class Worker {
27
27
  this.stopping = false
28
28
  this.stopped = false
29
29
  this.loopDelayPromise = null
30
+ this.beenNotified = false
31
+ }
32
+
33
+ notify () {
34
+ this.beenNotified = true
35
+
36
+ if (this.loopDelayPromise) {
37
+ this.loopDelayPromise.clear()
38
+ }
30
39
  }
31
40
 
32
41
  async start () {
@@ -36,6 +45,7 @@ class Worker {
36
45
  const started = Date.now()
37
46
 
38
47
  try {
48
+ this.beenNotified = false
39
49
  const jobs = await this.fetch()
40
50
 
41
51
  this.lastFetchedOn = Date.now()
@@ -64,7 +74,7 @@ class Worker {
64
74
 
65
75
  this.lastJobDuration = duration
66
76
 
67
- if (!this.stopping && duration < this.interval) {
77
+ if (!this.stopping && !this.beenNotified && duration < this.interval) {
68
78
  this.loopDelayPromise = delay(this.interval - duration)
69
79
  await this.loopDelayPromise
70
80
  this.loopDelayPromise = null
package/types.d.ts CHANGED
@@ -102,6 +102,7 @@ declare namespace PgBoss {
102
102
  interface JobFetchOptions {
103
103
  teamSize?: number;
104
104
  teamConcurrency?: number;
105
+ teamRefill?: boolean;
105
106
  batchSize?: number;
106
107
  includeMetadata?: boolean;
107
108
  }
@@ -307,6 +308,12 @@ declare class PgBoss extends EventEmitter {
307
308
  offWork(name: string): Promise<void>;
308
309
  offWork(options: PgBoss.OffWorkOptions): Promise<void>;
309
310
 
311
+ /**
312
+ * Notify worker that something has changed
313
+ * @param workerId
314
+ */
315
+ notifyWorker(workerId: string): void;
316
+
310
317
  subscribe(event: string, name: string): Promise<void>;
311
318
  unsubscribe(event: string, name: string): Promise<void>;
312
319
  publish(event: string): Promise<string[]>;
@@ -329,6 +336,9 @@ declare class PgBoss extends EventEmitter {
329
336
  cancel(id: string): Promise<void>;
330
337
  cancel(ids: string[]): Promise<void>;
331
338
 
339
+ resume(id: string): Promise<void>;
340
+ resume(ids: string[]): Promise<void>;
341
+
332
342
  complete(id: string): Promise<void>;
333
343
  complete(id: string, data: object): Promise<void>;
334
344
  complete(ids: string[]): Promise<void>;