pg-boss 10.0.0-beta15 → 10.0.0-beta17

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pg-boss",
3
- "version": "10.0.0-beta15",
3
+ "version": "10.0.0-beta17",
4
4
  "description": "Queueing jobs in Postgres from Node.js like a boss",
5
5
  "main": "./src/index.js",
6
6
  "engines": {
package/src/manager.js CHANGED
@@ -56,15 +56,13 @@ class Manager extends EventEmitter {
56
56
  this.subscribeCommand = plans.subscribe(config.schema)
57
57
  this.unsubscribeCommand = plans.unsubscribe(config.schema)
58
58
  this.getQueuesCommand = plans.getQueues(config.schema)
59
- this.getQueuesForEventCommand = plans.getQueuesForEvent(config.schema)
60
59
  this.getQueueByNameCommand = plans.getQueueByName(config.schema)
61
- this.deleteQueueRecordsCommand = plans.deleteQueueRecords(config.schema)
62
- this.insertQueueCommand = plans.insertQueue(config.schema)
60
+ this.getQueuesForEventCommand = plans.getQueuesForEvent(config.schema)
61
+ this.createQueueCommand = plans.createQueue(config.schema)
63
62
  this.updateQueueCommand = plans.updateQueue(config.schema)
64
- this.createPartitionCommand = plans.createPartition(config.schema)
65
- this.dropPartitionCommand = plans.dropPartition(config.schema)
66
- this.clearStorageCommand = plans.clearStorage(config.schema)
67
63
  this.purgeQueueCommand = plans.purgeQueue(config.schema)
64
+ this.deleteQueueCommand = plans.deleteQueue(config.schema)
65
+ this.clearStorageCommand = plans.clearStorage(config.schema)
68
66
 
69
67
  // exported api to index
70
68
  this.functions = [
@@ -572,10 +570,7 @@ class Manager extends EventEmitter {
572
570
  Attorney.assertQueueName(deadLetter)
573
571
  }
574
572
 
575
- await this.db.executeSql(this.createPartitionCommand, [name])
576
-
577
- const params = [
578
- name,
573
+ const data = {
579
574
  policy,
580
575
  retryLimit,
581
576
  retryDelay,
@@ -583,9 +578,9 @@ class Manager extends EventEmitter {
583
578
  expireInSeconds,
584
579
  retentionMinutes,
585
580
  deadLetter
586
- ]
581
+ }
587
582
 
588
- await this.db.executeSql(this.insertQueueCommand, params)
583
+ await this.db.executeSql(this.createQueueCommand, [name, data])
589
584
  }
590
585
 
591
586
  async getQueues () {
@@ -626,32 +621,9 @@ class Manager extends EventEmitter {
626
621
  async getQueue (name) {
627
622
  Attorney.assertQueueName(name)
628
623
 
629
- const result = await this.db.executeSql(this.getQueueByNameCommand, [name])
630
-
631
- if (result.rows.length === 0) {
632
- return null
633
- }
634
-
635
- const {
636
- policy,
637
- retry_limit: retryLimit,
638
- retry_delay: retryDelay,
639
- retry_backoff: retryBackoff,
640
- expire_seconds: expireInSeconds,
641
- retention_minutes: retentionMinutes,
642
- dead_letter: deadLetter
643
- } = result.rows[0]
624
+ const { rows } = await this.db.executeSql(this.getQueueByNameCommand, [name])
644
625
 
645
- return {
646
- name,
647
- policy,
648
- retryLimit,
649
- retryDelay,
650
- retryBackoff,
651
- expireInSeconds,
652
- retentionMinutes,
653
- deadLetter
654
- }
626
+ return rows[0] || null
655
627
  }
656
628
 
657
629
  async deleteQueue (name) {
@@ -659,9 +631,8 @@ class Manager extends EventEmitter {
659
631
 
660
632
  const { rows } = await this.db.executeSql(this.getQueueByNameCommand, [name])
661
633
 
662
- if (rows.length) {
663
- await this.db.executeSql(this.dropPartitionCommand, [name])
664
- await this.db.executeSql(this.deleteQueueRecordsCommand, [name])
634
+ if (rows.length === 1) {
635
+ await this.db.executeSql(this.deleteQueueCommand, [name])
665
636
  }
666
637
  }
667
638
 
package/src/plans.js CHANGED
@@ -42,11 +42,9 @@ module.exports = {
42
42
  archive,
43
43
  drop,
44
44
  countStates,
45
- insertQueue,
46
45
  updateQueue,
47
- createPartition,
48
- dropPartition,
49
- deleteQueueRecords,
46
+ createQueue,
47
+ deleteQueue,
50
48
  getQueues,
51
49
  getQueueByName,
52
50
  getQueueSize,
@@ -85,9 +83,8 @@ function create (schema, version) {
85
83
  createColumnArchiveArchivedOn(schema),
86
84
  createIndexArchiveArchivedOn(schema),
87
85
 
88
- getPartitionFunction(schema),
89
- createPartitionFunction(schema),
90
- dropPartitionFunction(schema),
86
+ createQueueFunction(schema),
87
+ deleteQueueFunction(schema),
91
88
 
92
89
  insertVersion(schema, version)
93
90
  ]
@@ -137,8 +134,10 @@ function createTableQueue (schema) {
137
134
  retry_backoff bool,
138
135
  expire_seconds int,
139
136
  retention_minutes int,
140
- dead_letter text,
137
+ dead_letter text REFERENCES ${schema}.queue (name),
138
+ partition_name text,
141
139
  created_on timestamp with time zone not null default now(),
140
+ updated_on timestamp with time zone not null default now(),
142
141
  PRIMARY KEY (name)
143
142
  )
144
143
  `
@@ -199,7 +198,10 @@ function createTableJob (schema) {
199
198
  }
200
199
 
201
200
  const baseJobColumns = 'id, name, data, EXTRACT(epoch FROM expire_in) as "expireInSeconds"'
202
- const allJobColumns = `${baseJobColumns}, policy, state, priority,
201
+ const allJobColumns = `${baseJobColumns},
202
+ policy,
203
+ state,
204
+ priority,
203
205
  retry_limit as "retryLimit",
204
206
  retry_count as "retryCount",
205
207
  retry_delay as "retryDelay",
@@ -216,29 +218,38 @@ const allJobColumns = `${baseJobColumns}, policy, state, priority,
216
218
  output
217
219
  `
218
220
 
219
- function createPartition (schema) {
220
- return `SELECT ${schema}.create_partition($1)`
221
- }
222
-
223
- function getPartitionFunction (schema) {
221
+ function createQueueFunction (schema) {
224
222
  return `
225
- CREATE FUNCTION ${schema}.get_partition(queue_name text, out name text) AS
226
- $$
227
- SELECT 'j' || left(regexp_replace(queue_name, '\\W', '', 'g'),10) || left(encode(sha224(queue_name::bytea), 'hex'),10);
228
- $$
229
- LANGUAGE SQL
230
- IMMUTABLE
231
- `
232
- }
233
-
234
- function createPartitionFunction (schema) {
235
- return `
236
- CREATE FUNCTION ${schema}.create_partition(queue_name text)
223
+ CREATE FUNCTION ${schema}.create_queue(queue_name text, options json)
237
224
  RETURNS VOID AS
238
225
  $$
239
226
  DECLARE
240
- table_name varchar := ${schema}.get_partition(queue_name);
227
+ table_name varchar := 'j' || encode(sha224(queue_name::bytea), 'hex');
241
228
  BEGIN
229
+
230
+ INSERT INTO ${schema}.queue (
231
+ name,
232
+ policy,
233
+ retry_limit,
234
+ retry_delay,
235
+ retry_backoff,
236
+ expire_seconds,
237
+ retention_minutes,
238
+ dead_letter,
239
+ partition_name
240
+ )
241
+ VALUES (
242
+ queue_name,
243
+ options->>'policy',
244
+ (options->>'retryLimit')::int,
245
+ (options->>'retryDelay')::int,
246
+ (options->>'retryBackoff')::bool,
247
+ (options->>'expireInSeconds')::int,
248
+ (options->>'retentionMinutes')::int,
249
+ options->>'deadLetter',
250
+ table_name
251
+ );
252
+
242
253
  EXECUTE format('CREATE TABLE ${schema}.%I (LIKE ${schema}.job INCLUDING DEFAULTS)', table_name);
243
254
 
244
255
  EXECUTE format('${formatPartitionCommand(createPrimaryKeyJob(schema))}', table_name);
@@ -259,24 +270,37 @@ function createPartitionFunction (schema) {
259
270
  }
260
271
 
261
272
  function formatPartitionCommand (command) {
262
- return command.replace('.job', '.%1$I').replace('job_idx', '%1$s_idx').replaceAll('\'', '\'\'')
273
+ return command.replace('.job', '.%1$I').replace('job_i', '%1$s_i').replaceAll('\'', '\'\'')
263
274
  }
264
275
 
265
- function dropPartitionFunction (schema) {
276
+ function deleteQueueFunction (schema) {
266
277
  return `
267
- CREATE FUNCTION ${schema}.drop_partition(queue_name text)
278
+ CREATE FUNCTION ${schema}.delete_queue(queue_name text)
268
279
  RETURNS VOID AS
269
280
  $$
281
+ DECLARE
282
+ table_name varchar;
270
283
  BEGIN
271
- EXECUTE format('DROP TABLE IF EXISTS ${schema}.%I', ${schema}.get_partition(queue_name));
284
+ WITH deleted as (
285
+ DELETE FROM ${schema}.queue
286
+ WHERE name = queue_name
287
+ RETURNING partition_name
288
+ )
289
+ SELECT partition_name from deleted INTO table_name;
290
+
291
+ EXECUTE format('DROP TABLE IF EXISTS ${schema}.%I', table_name);
272
292
  END;
273
293
  $$
274
294
  LANGUAGE plpgsql;
275
295
  `
276
296
  }
277
297
 
278
- function dropPartition (schema) {
279
- return `SELECT ${schema}.drop_partition($1)`
298
+ function createQueue (schema) {
299
+ return `SELECT ${schema}.create_queue($1, $2)`
300
+ }
301
+
302
+ function deleteQueue (schema) {
303
+ return `SELECT ${schema}.delete_queue($1)`
280
304
  }
281
305
 
282
306
  function createPrimaryKeyJob (schema) {
@@ -284,11 +308,11 @@ function createPrimaryKeyJob (schema) {
284
308
  }
285
309
 
286
310
  function createQueueForeignKeyJob (schema) {
287
- return `ALTER TABLE ${schema}.job ADD CONSTRAINT q_fkey FOREIGN KEY (name) REFERENCES ${schema}.queue (name) ON DELETE RESTRICT`
311
+ return `ALTER TABLE ${schema}.job ADD CONSTRAINT q_fkey FOREIGN KEY (name) REFERENCES ${schema}.queue (name) ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED`
288
312
  }
289
313
 
290
314
  function createQueueForeignKeyJobDeadLetter (schema) {
291
- return `ALTER TABLE ${schema}.job ADD CONSTRAINT dlq_fkey FOREIGN KEY (dead_letter) REFERENCES ${schema}.queue (name) ON DELETE RESTRICT`
315
+ return `ALTER TABLE ${schema}.job ADD CONSTRAINT dlq_fkey FOREIGN KEY (dead_letter) REFERENCES ${schema}.queue (name) ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED`
292
316
  }
293
317
 
294
318
  function createPrimaryKeyArchive (schema) {
@@ -296,23 +320,23 @@ function createPrimaryKeyArchive (schema) {
296
320
  }
297
321
 
298
322
  function createIndexJobPolicyShort (schema) {
299
- return `CREATE UNIQUE INDEX job_idx_psh ON ${schema}.job (name, COALESCE(singleton_key, '')) WHERE state = '${JOB_STATES.created}' AND policy = '${QUEUE_POLICIES.short}';`
323
+ return `CREATE UNIQUE INDEX job_i1 ON ${schema}.job (name, COALESCE(singleton_key, '')) WHERE state = '${JOB_STATES.created}' AND policy = '${QUEUE_POLICIES.short}';`
300
324
  }
301
325
 
302
326
  function createIndexJobPolicySingleton (schema) {
303
- return `CREATE UNIQUE INDEX job_idx_psi ON ${schema}.job (name, COALESCE(singleton_key, '')) WHERE state = '${JOB_STATES.active}' AND policy = '${QUEUE_POLICIES.singleton}'`
327
+ return `CREATE UNIQUE INDEX job_i2 ON ${schema}.job (name, COALESCE(singleton_key, '')) WHERE state = '${JOB_STATES.active}' AND policy = '${QUEUE_POLICIES.singleton}'`
304
328
  }
305
329
 
306
330
  function createIndexJobPolicyStately (schema) {
307
- return `CREATE UNIQUE INDEX job_idx_pst ON ${schema}.job (name, state, COALESCE(singleton_key, '')) WHERE state <= '${JOB_STATES.active}' AND policy = '${QUEUE_POLICIES.stately}'`
331
+ return `CREATE UNIQUE INDEX job_i3 ON ${schema}.job (name, state, COALESCE(singleton_key, '')) WHERE state <= '${JOB_STATES.active}' AND policy = '${QUEUE_POLICIES.stately}'`
308
332
  }
309
333
 
310
334
  function createIndexJobThrottle (schema) {
311
- return `CREATE UNIQUE INDEX job_idx_to ON ${schema}.job (name, singleton_on, COALESCE(singleton_key, '')) WHERE state <> '${JOB_STATES.cancelled}' AND singleton_on IS NOT NULL`
335
+ return `CREATE UNIQUE INDEX job_i4 ON ${schema}.job (name, singleton_on, COALESCE(singleton_key, '')) WHERE state <> '${JOB_STATES.cancelled}' AND singleton_on IS NOT NULL`
312
336
  }
313
337
 
314
338
  function createIndexJobFetch (schema) {
315
- return `CREATE INDEX job_idx_f ON ${schema}.job (name, start_after) INCLUDE (priority, created_on, id) WHERE state < '${JOB_STATES.active}'`
339
+ return `CREATE INDEX job_i5 ON ${schema}.job (name, start_after) INCLUDE (priority, created_on, id) WHERE state < '${JOB_STATES.active}'`
316
340
  }
317
341
 
318
342
  function createTableArchive (schema) {
@@ -324,7 +348,7 @@ function createColumnArchiveArchivedOn (schema) {
324
348
  }
325
349
 
326
350
  function createIndexArchiveArchivedOn (schema) {
327
- return `CREATE INDEX archive_idx_ao ON ${schema}.archive(archived_on)`
351
+ return `CREATE INDEX archive_i1 ON ${schema}.archive(archived_on)`
328
352
  }
329
353
 
330
354
  function trySetMaintenanceTime (schema) {
@@ -347,13 +371,6 @@ function trySetTimestamp (schema, column) {
347
371
  `
348
372
  }
349
373
 
350
- function insertQueue (schema) {
351
- return `
352
- INSERT INTO ${schema}.queue (name, policy, retry_limit, retry_delay, retry_backoff, expire_seconds, retention_minutes, dead_letter)
353
- VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
354
- `
355
- }
356
-
357
374
  function updateQueue (schema) {
358
375
  return `
359
376
  UPDATE ${schema}.queue SET
@@ -363,21 +380,28 @@ function updateQueue (schema) {
363
380
  retry_backoff = COALESCE($5, retry_backoff),
364
381
  expire_seconds = COALESCE($6, expire_seconds),
365
382
  retention_minutes = COALESCE($7, retention_minutes),
366
- dead_letter = COALESCE($8, dead_letter)
383
+ dead_letter = COALESCE($8, dead_letter),
384
+ updated_on = now()
367
385
  WHERE name = $1
368
386
  `
369
387
  }
370
388
 
371
389
  function getQueues (schema) {
372
- return `SELECT * FROM ${schema}.queue`
390
+ return `
391
+ SELECT
392
+ policy,
393
+ retry_limit as "retryLimit",
394
+ retry_delay as "retryDelay",
395
+ retry_backoff as "retryBackoff",
396
+ expire_seconds as "expireInSeconds",
397
+ retention_minutes as "retentionMinutes",
398
+ dead_letter as "deadLetter"
399
+ FROM ${schema}.queue
400
+ `
373
401
  }
374
402
 
375
403
  function getQueueByName (schema) {
376
- return `SELECT * FROM ${schema}.queue WHERE name = $1`
377
- }
378
-
379
- function deleteQueueRecords (schema) {
380
- return `DELETE FROM ${schema}.queue WHERE name = $1`
404
+ return `${getQueues(schema)} WHERE name = $1`
381
405
  }
382
406
 
383
407
  function purgeQueue (schema) {
@@ -779,7 +803,7 @@ function locked (schema, query) {
779
803
  }
780
804
 
781
805
  function advisoryLock (schema, key) {
782
- return `SELECT pg_advisory_xact_lock(
806
+ return `SELECT pg_advisory_xact_lock(
783
807
  ('x' || encode(sha224((current_database() || '.pgboss.${schema}${key || ''}')::bytea), 'hex'))::bit(64)::bigint
784
808
  )`
785
809
  }