@bumail/queue 0.1.0 → 0.2.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 +37 -5
- package/dist/chunks/{index-xhsw4xcz.js → index-vg971acr.js} +70 -6
- package/dist/chunks/index-vg971acr.js.map +12 -0
- package/dist/contract/checks.d.ts +6 -0
- package/dist/contract/checks.d.ts.map +1 -1
- package/dist/index.js +14 -33
- package/dist/index.js.map +5 -6
- package/dist/memory/index.js +3 -5
- package/dist/memory/index.js.map +2 -2
- package/dist/postgres/connect.d.ts +17 -0
- package/dist/postgres/connect.d.ts.map +1 -0
- package/dist/postgres/index.d.ts +2 -0
- package/dist/postgres/index.d.ts.map +1 -0
- package/dist/postgres/index.js +383 -0
- package/dist/postgres/index.js.map +14 -0
- package/dist/postgres/options.d.ts +37 -0
- package/dist/postgres/options.d.ts.map +1 -0
- package/dist/postgres/rows.d.ts +21 -0
- package/dist/postgres/rows.d.ts.map +1 -0
- package/dist/postgres/schema.d.ts +20 -0
- package/dist/postgres/schema.d.ts.map +1 -0
- package/dist/postgres/statements.d.ts +54 -0
- package/dist/postgres/statements.d.ts.map +1 -0
- package/dist/postgres/store.d.ts +38 -0
- package/dist/postgres/store.d.ts.map +1 -0
- package/dist/queue/outcome.d.ts.map +1 -1
- package/dist/queue/settings/index.d.ts.map +1 -1
- package/dist/sqlite/index.js +3 -5
- package/dist/sqlite/index.js.map +2 -2
- package/dist/text.d.ts +9 -3
- package/dist/text.d.ts.map +1 -1
- package/docs/README.md +1 -1
- package/docs/guide.md +130 -2
- package/docs/roadmap.md +50 -19
- package/docs/troubleshooting.md +99 -5
- package/package.json +9 -3
- package/dist/chunks/index-p4k4rjb7.js +0 -15
- package/dist/chunks/index-p4k4rjb7.js.map +0 -10
- package/dist/chunks/index-xhsw4xcz.js.map +0 -10
package/docs/troubleshooting.md
CHANGED
|
@@ -36,6 +36,7 @@ parts shown as … vary.
|
|
|
36
36
|
- [`QueueError: The lease on … was lost while it was delivered`](#queueerror-the-lease-on--was-lost-while-it-was-delivered)
|
|
37
37
|
- [`SmtpError: sendMail(): …` (`INVALID_OPTION`), with recipients deferred as `4.3.5`](#smtperror-sendmail--invalid_option-with-recipients-deferred-as-435)
|
|
38
38
|
- [`SQLiteError: database is locked`, or another store error, during a delivery](#sqliteerror-database-is-locked-or-another-store-error-during-a-delivery)
|
|
39
|
+
- [`PostgresError: …`, or a connection error, during a delivery](#postgreserror--or-a-connection-error-during-a-delivery)
|
|
39
40
|
|
|
40
41
|
**The `bun:sqlite` store** (`@bumail/queue/sqlite`)
|
|
41
42
|
|
|
@@ -45,6 +46,15 @@ parts shown as … vary.
|
|
|
45
46
|
- [`QueueError: busyTimeout must be an integer of at least 0, not …`](#queueerror-busytimeout-must-be-an-integer-of-at-least-0-not-)
|
|
46
47
|
- [`QueueError: The queue store is closed`](#queueerror-the-queue-store-is-closed)
|
|
47
48
|
|
|
49
|
+
**The PostgreSQL store** (`@bumail/queue/postgres`)
|
|
50
|
+
|
|
51
|
+
- [`QueueError: A PostgreSQL queue store needs sql: a Bun.SQL client or a postgres:// URL`](#queueerror-a-postgresql-queue-store-needs-sql-a-bunsql-client-or-a-postgres-url)
|
|
52
|
+
- [`QueueError: sql is a … client; the queue needs a PostgreSQL one`](#queueerror-sql-is-a--client-the-queue-needs-a-postgresql-one)
|
|
53
|
+
- [`QueueError: tablePrefix must be lowercase letters, digits and underscores, starting with a letter or an underscore, at most 40 characters, not …`](#queueerror-tableprefix-must-be-lowercase-letters-digits-and-underscores-starting-with-a-letter-or-an-underscore-at-most-40-characters-not-)
|
|
54
|
+
- [`QueueError: The URL in sql cannot be opened: …`](#queueerror-the-url-in-sql-cannot-be-opened-)
|
|
55
|
+
- [`QueueError: The PostgreSQL queue cannot be set up: …`](#queueerror-the-postgresql-queue-cannot-be-set-up-)
|
|
56
|
+
- [`QueueError: The database is at schema version …, newer than this store's …`](#queueerror-the-database-is-at-schema-version--newer-than-this-stores-), and [`QueueError: The queue store is closed`](#queueerror-the-queue-store-is-closed), as for `bun:sqlite`
|
|
57
|
+
|
|
48
58
|
**Listing** (`list`)
|
|
49
59
|
|
|
50
60
|
- [`QueueError: limit must be an integer from 1 to 1000, not …`](#queueerror-limit-must-be-an-integer-from-1-to-1000-not-)
|
|
@@ -228,8 +238,9 @@ or `… must be a number from … to …, not …`. A number option out of its r
|
|
|
228
238
|
|
|
229
239
|
### `QueueError: owner must be a non-empty string`
|
|
230
240
|
|
|
231
|
-
**Code:** `INVALID
|
|
232
|
-
|
|
241
|
+
**Code:** `INVALID`, also as `owner holds a NUL or a lone surrogate,
|
|
242
|
+
which a store cannot keep`. Leave `owner` out for a random one, or give
|
|
243
|
+
each worker its own name.
|
|
233
244
|
|
|
234
245
|
## The `error` event
|
|
235
246
|
|
|
@@ -271,6 +282,22 @@ tries again; only a renewal that finds the lease taken stops (as
|
|
|
271
282
|
**Fix:** a longer `busyTimeout` when several processes write a lot; a
|
|
272
283
|
store that keeps failing will lose the lease once it expires.
|
|
273
284
|
|
|
285
|
+
### `PostgresError: …`, or a connection error, during a delivery
|
|
286
|
+
|
|
287
|
+
**When:** the `error` event, with the item's `id`, while it is delivered,
|
|
288
|
+
on `@bumail/queue/postgres`.
|
|
289
|
+
**Why:** a lease renewal failed: the database restarted, a connection
|
|
290
|
+
dropped, or the server refused one past its `max_connections`. As on
|
|
291
|
+
`bun:sqlite`, the next renewal tries again, and only a lease taken by
|
|
292
|
+
another instance stops them. A claim that fails the same way rejects
|
|
293
|
+
`deliverDue()`, or is told on `error` under `start()`, which tries again
|
|
294
|
+
at its next pass. An outcome that cannot be recorded is told on `error`
|
|
295
|
+
with the item's `id`; the item stays as it was, and is claimed again once
|
|
296
|
+
its lease expires — its recipients may then get the message twice.
|
|
297
|
+
**Fix:** check the database is up and reachable; when the server counts
|
|
298
|
+
too many connections, give each instance's client a smaller `max` (see
|
|
299
|
+
the guide's Pool size) or raise `max_connections`.
|
|
300
|
+
|
|
274
301
|
## The `bun:sqlite` store
|
|
275
302
|
|
|
276
303
|
### `QueueError: A SQLite queue store needs a directory`
|
|
@@ -287,8 +314,8 @@ should read the queue.
|
|
|
287
314
|
|
|
288
315
|
### `QueueError: The database is at schema version …, newer than this store's …`
|
|
289
316
|
|
|
290
|
-
**Code:** `INVALID`. A newer version of the package wrote the database
|
|
291
|
-
upgrade this one.
|
|
317
|
+
**Code:** `INVALID`. A newer version of the package wrote the database
|
|
318
|
+
(`queue.sqlite`, or on PostgreSQL the prefix's tables): upgrade this one.
|
|
292
319
|
|
|
293
320
|
### `QueueError: busyTimeout must be an integer of at least 0, not …`
|
|
294
321
|
|
|
@@ -297,7 +324,68 @@ upgrade this one.
|
|
|
297
324
|
### `QueueError: The queue store is closed`
|
|
298
325
|
|
|
299
326
|
**Code:** `CLOSED`. The store was used after `close()`: call
|
|
300
|
-
`queue.stop()` first, then `store.close()`.
|
|
327
|
+
`queue.stop()` first, then `store.close()`. The PostgreSQL store says the
|
|
328
|
+
same.
|
|
329
|
+
|
|
330
|
+
## The PostgreSQL store
|
|
331
|
+
|
|
332
|
+
### `QueueError: A PostgreSQL queue store needs sql: a Bun.SQL client or a postgres:// URL`
|
|
333
|
+
|
|
334
|
+
**Code:** `INVALID`.
|
|
335
|
+
**When:** `PostgresQueueStore.open` without `sql`, or with a string that
|
|
336
|
+
is not a `postgres://` or `postgresql://` URL, or an object without
|
|
337
|
+
`unsafe`, `begin` and `close`. The message never repeats the URL, which
|
|
338
|
+
may hold a password.
|
|
339
|
+
**Fix:**
|
|
340
|
+
|
|
341
|
+
```ts
|
|
342
|
+
PostgresQueueStore.open({ sql: 'postgres://bumail:secret@db.internal:5432/mail' });
|
|
343
|
+
// or a client of yours, sized as you need:
|
|
344
|
+
PostgresQueueStore.open({ sql: new Bun.SQL({ url, max: 10 }) });
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### `QueueError: sql is a … client; the queue needs a PostgreSQL one`
|
|
348
|
+
|
|
349
|
+
**Code:** `INVALID`. A `Bun.SQL` client made for SQLite or MySQL
|
|
350
|
+
(`adapter: 'sqlite'`, a `mysql://` URL). For SQLite, use
|
|
351
|
+
`@bumail/queue/sqlite`; otherwise give a PostgreSQL client.
|
|
352
|
+
|
|
353
|
+
### `QueueError: tablePrefix must be lowercase letters, digits and underscores, starting with a letter or an underscore, at most 40 characters, not …`
|
|
354
|
+
|
|
355
|
+
**Code:** `INVALID`.
|
|
356
|
+
**Why:** the prefix is written into every statement, never bound as a
|
|
357
|
+
value, so anything that is not a plain name is refused — and 40
|
|
358
|
+
characters keep the longest name built on it within PostgreSQL's 63.
|
|
359
|
+
**Fix:** `tablePrefix: 'mail_queue_'`. To put the tables in another
|
|
360
|
+
schema, set the connection's `search_path` rather than a dotted prefix.
|
|
361
|
+
|
|
362
|
+
### `QueueError: The URL in sql cannot be opened: …`
|
|
363
|
+
|
|
364
|
+
**Code:** `INVALID`.
|
|
365
|
+
**When:** `PostgresQueueStore.open` with a URL `Bun.SQL` refuses before
|
|
366
|
+
connecting, such as a `sslmode` it does not know. The rest is Bun's
|
|
367
|
+
reason (`The argument 'sslmode' must be one of: disable, allow, prefer,
|
|
368
|
+
require, verify-ca, verify-full. Received '…'`); the URL is never
|
|
369
|
+
repeated, and the password is masked should the reason name it.
|
|
370
|
+
**Fix:** correct the parameter: `?sslmode=require`, or `verify-full` to
|
|
371
|
+
check the server's certificate.
|
|
372
|
+
|
|
373
|
+
### `QueueError: The PostgreSQL queue cannot be set up: …`
|
|
374
|
+
|
|
375
|
+
**Code:** `INVALID`.
|
|
376
|
+
**When:** the first call on a store, or `migrate()`, when the tables
|
|
377
|
+
cannot be made or brought up to date. The rest of the message is the
|
|
378
|
+
database's: `Failed to connect`, `password authentication failed for
|
|
379
|
+
user "…"`, `permission denied for schema public`.
|
|
380
|
+
**Why:** the database is out of reach, the credentials are wrong, or the
|
|
381
|
+
tables are missing or behind and the role may not create them: a role
|
|
382
|
+
without `CREATE` can use tables that are current, never make them.
|
|
383
|
+
**Fix:** check the URL and that the server answers. For `permission
|
|
384
|
+
denied`, run `migrate()` once with an owner's role — on a new database,
|
|
385
|
+
and after an upgrade that adds a migration — and keep the workers on
|
|
386
|
+
their narrower role (the guide's [Migrations](guide.md#migrations)); or
|
|
387
|
+
give the role `CREATE` on the schema. The next call tries again: nothing is left half made,
|
|
388
|
+
since a migration is one transaction.
|
|
301
389
|
|
|
302
390
|
## Listing
|
|
303
391
|
|
|
@@ -337,6 +425,12 @@ never gives it. Each message names what is wrong:
|
|
|
337
425
|
- `QueueError: delayNotified must be true or false`
|
|
338
426
|
- `QueueError: recipients must be an array of { address, status:
|
|
339
427
|
delivered, deferred or failed }`
|
|
428
|
+
- `QueueError: A reply is an object with a text`, `reply.status must be
|
|
429
|
+
a string`, `reply.host must be a string`
|
|
430
|
+
- `QueueError: … holds a NUL or a lone surrogate, which a store cannot
|
|
431
|
+
keep` (`from`, `A recipient`, `owner`, `reply.text`, `reply.status`,
|
|
432
|
+
`reply.host`): every store refuses them, since PostgreSQL cannot keep
|
|
433
|
+
them; the queue's own replies never hold one
|
|
340
434
|
|
|
341
435
|
A list's `offset` and `limit` are checked as under [Listing](#listing).
|
|
342
436
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bumail/queue",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "The outbound mail queue of a mail server: every recipient's state, retries with back-off, delivery status notifications (RFC 3464), leases for several workers, and a memory
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "The outbound mail queue of a mail server: every recipient's state, retries with back-off, delivery status notifications (RFC 3464), leases for several workers, and a memory, a bun:sqlite and a PostgreSQL (Bun.sql) store, delivering through @bumail/smtp/client",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/index.js",
|
|
@@ -29,6 +29,11 @@
|
|
|
29
29
|
"import": "./dist/sqlite/index.js",
|
|
30
30
|
"default": "./dist/sqlite/index.js"
|
|
31
31
|
},
|
|
32
|
+
"./postgres": {
|
|
33
|
+
"types": "./dist/postgres/index.d.ts",
|
|
34
|
+
"import": "./dist/postgres/index.js",
|
|
35
|
+
"default": "./dist/postgres/index.js"
|
|
36
|
+
},
|
|
32
37
|
"./package.json": "./package.json"
|
|
33
38
|
},
|
|
34
39
|
"repository": {
|
|
@@ -49,7 +54,8 @@
|
|
|
49
54
|
"entrypoints": [
|
|
50
55
|
"src/index.ts",
|
|
51
56
|
"src/memory/index.ts",
|
|
52
|
-
"src/sqlite/index.ts"
|
|
57
|
+
"src/sqlite/index.ts",
|
|
58
|
+
"src/postgres/index.ts"
|
|
53
59
|
]
|
|
54
60
|
},
|
|
55
61
|
"devDependencies": {
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
// src/errors.ts
|
|
2
|
-
class QueueError2 extends Error {
|
|
3
|
-
name = "QueueError";
|
|
4
|
-
code;
|
|
5
|
-
constructor(code, message) {
|
|
6
|
-
super(message);
|
|
7
|
-
this.code = code;
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
var invalid = (message) => new QueueError2("INVALID", message);
|
|
11
|
-
|
|
12
|
-
export { QueueError2, invalid };
|
|
13
|
-
|
|
14
|
-
//# debugId=465D2E3985AB194764756E2164756E21
|
|
15
|
-
//# sourceMappingURL=index-p4k4rjb7.js.map
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/errors.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"/**\n * Why the queue or a store refused a call. `INVALID`: an option or an\n * argument it cannot take. `MESSAGE_TOO_BIG`, `TOO_MANY_RECIPIENTS` and\n * `QUEUE_FULL`: a limit `enqueue` enforces. `CLOSED`: a store used after\n * `close()`. `LEASE_LOST`: given to the `error` event when another worker\n * took an item before its outcome was recorded.\n */\nexport type QueueErrorCode =\n\t| 'INVALID'\n\t| 'MESSAGE_TOO_BIG'\n\t| 'TOO_MANY_RECIPIENTS'\n\t| 'QUEUE_FULL'\n\t| 'CLOSED'\n\t| 'LEASE_LOST';\n\n/** Thrown by the queue and by every store, whichever answers the contract, with the same codes. */\nexport class QueueError extends Error {\n\toverride readonly name = 'QueueError';\n\treadonly code: QueueErrorCode;\n\n\tconstructor(code: QueueErrorCode, message: string) {\n\t\tsuper(message);\n\t\tthis.code = code;\n\t}\n}\n\n/** `INVALID`, for an option or an argument. */\nexport const invalid = (message: string) => new QueueError('INVALID', message);\n"
|
|
6
|
-
],
|
|
7
|
-
"mappings": ";AAgBO,MAAM,oBAAmB,MAAM;AAAA,EACnB,OAAO;AAAA,EAChB;AAAA,EAET,WAAW,CAAC,MAAsB,SAAiB;AAAA,IAClD,MAAM,OAAO;AAAA,IACb,KAAK,OAAO;AAAA;AAEd;AAGO,IAAM,UAAU,CAAC,YAAoB,IAAI,YAAW,WAAW,OAAO;",
|
|
8
|
-
"debugId": "465D2E3985AB194764756E2164756E21",
|
|
9
|
-
"names": []
|
|
10
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/contract/checks.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"import { invalid } from '../errors';\nimport type {\n\tAttemptResult,\n\tClaimRequest,\n\tNewQueueItem,\n\tQueueItem,\n\tQueueListOptions,\n\tRecipientState,\n} from './types';\n\n/** What every store checks the same way, so each refuses the same input with the same error. */\n\nconst isTime = (value: unknown): value is number =>\n\ttypeof value === 'number' && Number.isFinite(value);\n\n/** A time in milliseconds since the epoch, or `INVALID` naming it. */\nexport function checkTime(name: string, value: unknown): number {\n\tif (!isTime(value)) throw invalid(`${name} must be a finite number`);\n\treturn value;\n}\n\n/** A lease owner: a non-empty string. */\nexport function checkOwner(owner: unknown): string {\n\tif (typeof owner !== 'string' || owner === '') {\n\t\tthrow invalid('owner must be a non-empty string');\n\t}\n\treturn owner;\n}\n\nexport function checkNewItem(item: NewQueueItem): void {\n\tif (typeof item !== 'object' || item === null) {\n\t\tthrow invalid('A new item is an object');\n\t}\n\tif (typeof item.from !== 'string') throw invalid('from must be a string');\n\tconst to = item.to as unknown;\n\tif (\n\t\t!Array.isArray(to) ||\n\t\tto.length === 0 ||\n\t\t!to.every((a) => typeof a === 'string' && a !== '')\n\t) {\n\t\tthrow invalid('to must be a non-empty array of addresses');\n\t}\n\tif (!(item.message instanceof Uint8Array)) {\n\t\tthrow invalid('message must be a Uint8Array');\n\t}\n\tcheckTime('createdAt', item.createdAt);\n}\n\n/** `maxItems`: a positive integer, or nothing. */\nexport function checkMaxItems(max: unknown): number | undefined {\n\tif (max === undefined) return undefined;\n\tif (typeof max !== 'number' || !Number.isInteger(max) || max < 1) {\n\t\tthrow invalid(`maxItems must be an integer of at least 1, not ${max}`);\n\t}\n\treturn max;\n}\n\nexport function checkClaim(request: ClaimRequest): void {\n\tif (typeof request !== 'object' || request === null) {\n\t\tthrow invalid('A claim is an object');\n\t}\n\tcheckOwner(request.owner);\n\tcheckTime('now', request.now);\n\tif (!isTime(request.leaseMs) || request.leaseMs <= 0) {\n\t\tthrow invalid('leaseMs must be a positive number');\n\t}\n}\n\nexport function checkResult(result: AttemptResult): void {\n\tif (typeof result !== 'object' || result === null) {\n\t\tthrow invalid('An attempt result is an object');\n\t}\n\tcheckTime('now', result.now);\n\tcheckTime('nextAttemptAt', result.nextAttemptAt);\n\tif (!Number.isInteger(result.attempts) || result.attempts < 0) {\n\t\tthrow invalid('attempts must be an integer of at least 0');\n\t}\n\tif (typeof result.delayNotified !== 'boolean') {\n\t\tthrow invalid('delayNotified must be true or false');\n\t}\n\tconst statuses = ['delivered', 'deferred', 'failed'];\n\tif (\n\t\t!Array.isArray(result.recipients) ||\n\t\t!result.recipients.every(\n\t\t\t(u) => typeof u?.address === 'string' && statuses.includes(u.status),\n\t\t)\n\t) {\n\t\tthrow invalid(\n\t\t\t'recipients must be an array of { address, status: delivered, deferred or failed }',\n\t\t);\n\t}\n}\n\n/** The offset and limit of a list: integers, the limit 1 to 1000. */\nexport function checkList(options: QueueListOptions = {}): {\n\toffset: number;\n\tlimit: number;\n} {\n\tconst offset = options.offset ?? 0;\n\tconst limit = options.limit ?? 100;\n\tif (!Number.isInteger(offset) || offset < 0) {\n\t\tthrow invalid(`offset must be an integer of at least 0, not ${offset}`);\n\t}\n\tif (!Number.isInteger(limit) || limit < 1 || limit > 1000) {\n\t\tthrow invalid(`limit must be an integer from 1 to 1000, not ${limit}`);\n\t}\n\treturn { offset, limit };\n}\n\n/** Every recipient is `delivered` or `failed`. */\nexport const isDone = (item: Pick<QueueItem, 'recipients'>): boolean =>\n\titem.recipients.every(\n\t\t(r) => r.status === 'delivered' || r.status === 'failed',\n\t);\n\n/**\n * The item once an attempt is recorded: its recipients' outcomes, a final\n * state never changed again, the schedule, and no lease.\n */\nexport function applyAttempt(\n\titem: QueueItem,\n\tresult: AttemptResult,\n): QueueItem {\n\tconst updates = new Map(result.recipients.map((u) => [u.address, u]));\n\tconst recipients = item.recipients.map((r): RecipientState => {\n\t\tconst update = updates.get(r.address);\n\t\tif (!update || r.status === 'delivered' || r.status === 'failed') return r;\n\t\treturn {\n\t\t\taddress: r.address,\n\t\t\tstatus: update.status,\n\t\t\t...(update.reply ? { reply: update.reply } : {}),\n\t\t\tupdatedAt: result.now,\n\t\t};\n\t});\n\tconst { lease: _, ...rest } = item;\n\treturn {\n\t\t...rest,\n\t\trecipients,\n\t\tnextAttemptAt: result.nextAttemptAt,\n\t\tattempts: result.attempts,\n\t\tdelayNotified: result.delayNotified,\n\t};\n}\n\n/** A new item as a store first keeps it. */\nexport function newItem(id: string, item: NewQueueItem): QueueItem {\n\treturn {\n\t\tid,\n\t\tfrom: item.from,\n\t\trecipients: item.to.map((address) => ({ address, status: 'pending' })),\n\t\tsize: item.message.length,\n\t\tcreatedAt: item.createdAt,\n\t\tnextAttemptAt: item.createdAt,\n\t\tattempts: 0,\n\t\tdelayNotified: false,\n\t};\n}\n\n/** Whether a lease, if any, leaves the item free to claim at `now`. */\nexport const claimable = (item: QueueItem, now: number): boolean =>\n\titem.nextAttemptAt <= now &&\n\t(item.lease === undefined || item.lease.expiresAt <= now);\n"
|
|
6
|
-
],
|
|
7
|
-
"mappings": "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",
|
|
8
|
-
"debugId": "70E823C3942B47A164756E2164756E21",
|
|
9
|
-
"names": []
|
|
10
|
-
}
|