pg-boss 10.0.0-beta8 → 10.0.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
@@ -19,7 +19,7 @@ async function readme() {
19
19
 
20
20
  console.log(`created job ${id} in queue ${queue}`)
21
21
 
22
- await boss.work(queue, async job => {
22
+ await boss.work(queue, async ([ job ]) => {
23
23
  console.log(`received job ${job.id} with data ${JSON.stringify(job.data)}`)
24
24
  })
25
25
  }
@@ -27,19 +27,21 @@ async function readme() {
27
27
 
28
28
  pg-boss is a job queue built in Node.js on top of PostgreSQL in order to provide background processing and reliable asynchronous execution to Node.js applications.
29
29
 
30
- pg-boss relies on [SKIP LOCKED](https://www.2ndquadrant.com/en/blog/what-is-select-skip-locked-for-in-postgresql-9-5/), a feature added to postgres specifically for message queues, in order to resolve record locking challenges inherent with relational databases. This brings the safety of guaranteed atomic commits of a relational database to your asynchronous job processing.
30
+ pg-boss relies on [SKIP LOCKED](https://www.2ndquadrant.com/en/blog/what-is-select-skip-locked-for-in-postgresql-9-5/), a feature built specifically for message queues to resolve record locking challenges inherent with relational databases. This provides exactly-once delivery and the safety of guaranteed atomic commits to asynchronous job processing.
31
31
 
32
32
  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.
33
33
 
34
- ## Features
34
+
35
+ ## Summary
35
36
  * Exactly-once job delivery
36
37
  * Backpressure-compatible polling workers
37
38
  * Cron scheduling
39
+ * Queue storage policies to support a variety of rate limiting, debouncing, and concurrency use cases
40
+ * Priority queues, dead letter queues, job deferral, automatic retries with exponential backoff
38
41
  * Pub/sub API for fan-out queue relationships
39
- * Priority queues, deferral, retries (with exponential backoff), rate limiting, debouncing
40
- * Table operations via SQL for bulk loads via COPY or INSERT
42
+ * Raw SQL support for non-Node.js runtimes via INSERT or COPY
43
+ * Serverless function compatible
41
44
  * Multi-master compatible (for example, in a Kubernetes ReplicaSet)
42
- * Dead letter queues
43
45
 
44
46
  ## Requirements
45
47
  * Node 20 or higher
@@ -47,7 +49,7 @@ This will likely cater the most to teams already familiar with the simplicity of
47
49
 
48
50
  ## Installation
49
51
 
50
- ``` bash
52
+ ```bash
51
53
  # npm
52
54
  npm install pg-boss
53
55
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pg-boss",
3
- "version": "10.0.0-beta8",
3
+ "version": "10.0.0",
4
4
  "description": "Queueing jobs in Postgres from Node.js like a boss",
5
5
  "main": "./src/index.js",
6
6
  "engines": {
@@ -8,8 +8,6 @@
8
8
  },
9
9
  "dependencies": {
10
10
  "cron-parser": "^4.0.0",
11
- "lodash.debounce": "^4.0.8",
12
- "p-map": "^4.0.0",
13
11
  "pg": "^8.5.1",
14
12
  "serialize-error": "^8.1.0"
15
13
  },
package/src/attorney.js CHANGED
@@ -122,26 +122,25 @@ function checkWorkArgs (name, args, defaults) {
122
122
 
123
123
  options = { ...options }
124
124
 
125
- applyNewJobCheckInterval(options, defaults)
125
+ applyPollingInterval(options, defaults)
126
126
 
127
- assert(!('teamConcurrency' in options) ||
128
- (Number.isInteger(options.teamConcurrency) && options.teamConcurrency >= 1 && options.teamConcurrency <= 1000),
129
- 'teamConcurrency must be an integer between 1 and 1000')
130
-
131
- assert(!('teamSize' in options) || (Number.isInteger(options.teamSize) && options.teamSize >= 1), 'teamSize must be an integer > 0')
132
127
  assert(!('batchSize' in options) || (Number.isInteger(options.batchSize) && options.batchSize >= 1), 'batchSize must be an integer > 0')
133
128
  assert(!('includeMetadata' in options) || typeof options.includeMetadata === 'boolean', 'includeMetadata must be a boolean')
129
+ assert(!('priority' in options) || typeof options.priority === 'boolean', 'priority must be a boolean')
130
+
131
+ options.batchSize = options.batchSize || 1
134
132
 
135
133
  return { options, callback }
136
134
  }
137
135
 
138
- function checkFetchArgs (name, batchSize, options) {
136
+ function checkFetchArgs (name, options) {
139
137
  assert(name, 'missing queue name')
140
138
 
141
- assert(!batchSize || (Number.isInteger(batchSize) && batchSize >= 1), 'batchSize must be an integer > 0')
139
+ assert(!('batchSize' in options) || (Number.isInteger(options.batchSize) && options.batchSize >= 1), 'batchSize must be an integer > 0')
142
140
  assert(!('includeMetadata' in options) || typeof options.includeMetadata === 'boolean', 'includeMetadata must be a boolean')
141
+ assert(!('priority' in options) || typeof options.priority === 'boolean', 'priority must be a boolean')
143
142
 
144
- return { name }
143
+ options.batchSize = options.batchSize || 1
145
144
  }
146
145
 
147
146
  function getConfig (value) {
@@ -163,7 +162,7 @@ function getConfig (value) {
163
162
  applyDeleteConfig(config)
164
163
  applyMonitoringConfig(config)
165
164
 
166
- applyNewJobCheckInterval(config)
165
+ applyPollingInterval(config)
167
166
  applyExpirationConfig(config)
168
167
  applyRetentionConfig(config)
169
168
 
@@ -186,8 +185,8 @@ function assertPostgresObjectName (name) {
186
185
  }
187
186
 
188
187
  function assertQueueName (name) {
188
+ assert(name, 'Name is required')
189
189
  assert(typeof name === 'string', 'Name must be a string')
190
- assert(name.length <= 50, 'Name cannot exceed 50 characters')
191
190
  assert(/[\w-]/.test(name), 'Name can only contain alphanumeric characters, underscores, or hyphens')
192
191
  }
193
192
 
@@ -279,18 +278,13 @@ function applyRetryConfig (config, defaults) {
279
278
  config.retryBackoffDefault = defaults?.retryBackoff
280
279
  }
281
280
 
282
- function applyNewJobCheckInterval (config, defaults) {
283
- assert(!('newJobCheckInterval' in config) || config.newJobCheckInterval >= 500,
284
- 'configuration assert: newJobCheckInterval must be at least every 500ms')
285
-
286
- assert(!('newJobCheckIntervalSeconds' in config) || config.newJobCheckIntervalSeconds >= 1,
287
- 'configuration assert: newJobCheckIntervalSeconds must be at least every second')
281
+ function applyPollingInterval (config, defaults) {
282
+ assert(!('pollingIntervalSeconds' in config) || config.pollingIntervalSeconds >= 0.5,
283
+ 'configuration assert: pollingIntervalSeconds must be at least every 500ms')
288
284
 
289
- config.newJobCheckInterval = ('newJobCheckIntervalSeconds' in config)
290
- ? config.newJobCheckIntervalSeconds * 1000
291
- : ('newJobCheckInterval' in config)
292
- ? config.newJobCheckInterval
293
- : defaults?.newJobCheckInterval || 2000
285
+ config.pollingInterval = ('pollingIntervalSeconds' in config)
286
+ ? config.pollingIntervalSeconds * 1000
287
+ : defaults?.pollingInterval || 2000
294
288
  }
295
289
 
296
290
  function applyMaintenanceConfig (config) {
package/src/boss.js CHANGED
@@ -171,34 +171,6 @@ class Boss extends EventEmitter {
171
171
  async drop () {
172
172
  await this.db.executeSql(this.dropCommand)
173
173
  }
174
-
175
- async setMaintenanceTime () {
176
- await this.db.executeSql(this.setMaintenanceTimeCommand)
177
- }
178
-
179
- async getMaintenanceTime () {
180
- const { rows } = await this.db.executeSql(this.getMaintenanceTimeCommand)
181
-
182
- let { maintained_on: maintainedOn, seconds_ago: secondsAgo } = rows[0]
183
-
184
- secondsAgo = secondsAgo !== null ? parseFloat(secondsAgo) : 999_999_999
185
-
186
- return { maintainedOn, secondsAgo }
187
- }
188
-
189
- async setMonitorTime () {
190
- await this.db.executeSql(this.setMonitorTimeCommand)
191
- }
192
-
193
- async getMonitorTime () {
194
- const { rows } = await this.db.executeSql(this.getMonitorTimeCommand)
195
-
196
- let { monitored_on: monitoredOn, seconds_ago: secondsAgo } = rows[0]
197
-
198
- secondsAgo = secondsAgo !== null ? parseFloat(secondsAgo) : 999_999_999
199
-
200
- return { monitoredOn, secondsAgo }
201
- }
202
174
  }
203
175
 
204
176
  module.exports = Boss
package/src/contractor.js CHANGED
@@ -86,15 +86,15 @@ class Contractor {
86
86
  }
87
87
  }
88
88
 
89
- async next (version) {
90
- const commands = migrationStore.next(this.config.schema, version, this.migrations)
91
- await this.db.executeSql(commands)
92
- }
93
-
94
- async rollback (version) {
95
- const commands = migrationStore.rollback(this.config.schema, version, this.migrations)
96
- await this.db.executeSql(commands)
97
- }
89
+ // async next (version) {
90
+ // const commands = migrationStore.next(this.config.schema, version, this.migrations)
91
+ // await this.db.executeSql(commands)
92
+ // }
93
+
94
+ // async rollback (version) {
95
+ // const commands = migrationStore.rollback(this.config.schema, version, this.migrations)
96
+ // await this.db.executeSql(commands)
97
+ // }
98
98
  }
99
99
 
100
100
  module.exports = Contractor
package/src/db.js CHANGED
@@ -29,15 +29,15 @@ class Db extends EventEmitter {
29
29
 
30
30
  async executeSql (text, values) {
31
31
  if (this.opened) {
32
- if (this.config.debug === true) {
33
- console.log(`${new Date().toISOString()}: DEBUG SQL`)
34
- console.log(text)
35
-
36
- if (values) {
37
- console.log(`${new Date().toISOString()}: DEBUG VALUES`)
38
- console.log(values)
39
- }
40
- }
32
+ // if (this.config.debug === true) {
33
+ // console.log(`${new Date().toISOString()}: DEBUG SQL`)
34
+ // console.log(text)
35
+
36
+ // if (values) {
37
+ // console.log(`${new Date().toISOString()}: DEBUG VALUES`)
38
+ // console.log(values)
39
+ // }
40
+ // }
41
41
 
42
42
  return await this.pool.query(text, values)
43
43
  }
package/src/index.js CHANGED
@@ -149,7 +149,7 @@ class PgBoss extends EventEmitter {
149
149
  return
150
150
  }
151
151
 
152
- let { destroy = false, graceful = true, timeout = 30000, wait = true } = options
152
+ let { close = true, graceful = true, timeout = 30000, wait = true } = options
153
153
 
154
154
  timeout = Math.max(timeout, 1000)
155
155
 
@@ -168,7 +168,7 @@ class PgBoss extends EventEmitter {
168
168
 
169
169
  await this.#manager.failWip()
170
170
 
171
- if (this.#db.isOurs && this.#db.opened && destroy) {
171
+ if (this.#db.isOurs && this.#db.opened && close) {
172
172
  await this.#db.close()
173
173
  }
174
174