@bumail/queue 0.10.0 → 0.11.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 (46) hide show
  1. package/README.md +27 -1
  2. package/dist/chunks/{index-sz13a17b.js → index-t6q7zxgj.js} +14 -3
  3. package/dist/chunks/{index-sz13a17b.js.map → index-t6q7zxgj.js.map} +4 -4
  4. package/dist/contract/checks.d.ts +4 -0
  5. package/dist/contract/checks.d.ts.map +1 -1
  6. package/dist/contract/queue-store.d.ts +15 -7
  7. package/dist/contract/queue-store.d.ts.map +1 -1
  8. package/dist/contract/types.d.ts +5 -0
  9. package/dist/contract/types.d.ts.map +1 -1
  10. package/dist/errors.d.ts +3 -1
  11. package/dist/errors.d.ts.map +1 -1
  12. package/dist/index.d.ts +1 -1
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +64 -26
  15. package/dist/index.js.map +4 -4
  16. package/dist/memory/index.js +10 -6
  17. package/dist/memory/index.js.map +3 -3
  18. package/dist/memory/store.d.ts +2 -2
  19. package/dist/memory/store.d.ts.map +1 -1
  20. package/dist/postgres/complete.d.ts +13 -0
  21. package/dist/postgres/complete.d.ts.map +1 -0
  22. package/dist/postgres/index.js +85 -74
  23. package/dist/postgres/index.js.map +6 -5
  24. package/dist/postgres/store.d.ts +2 -2
  25. package/dist/postgres/store.d.ts.map +1 -1
  26. package/dist/queue/deliver.d.ts.map +1 -1
  27. package/dist/queue/notify.d.ts +35 -6
  28. package/dist/queue/notify.d.ts.map +1 -1
  29. package/dist/redis/complete.d.ts +11 -0
  30. package/dist/redis/complete.d.ts.map +1 -0
  31. package/dist/redis/index.js +133 -110
  32. package/dist/redis/index.js.map +7 -6
  33. package/dist/redis/scripts.d.ts +8 -5
  34. package/dist/redis/scripts.d.ts.map +1 -1
  35. package/dist/redis/store.d.ts +2 -2
  36. package/dist/redis/store.d.ts.map +1 -1
  37. package/dist/sqlite/index.js +29 -20
  38. package/dist/sqlite/index.js.map +5 -4
  39. package/dist/sqlite/insert.d.ts +5 -0
  40. package/dist/sqlite/insert.d.ts.map +1 -0
  41. package/dist/sqlite/store.d.ts +2 -2
  42. package/dist/sqlite/store.d.ts.map +1 -1
  43. package/docs/guide.md +29 -0
  44. package/docs/roadmap.md +36 -10
  45. package/docs/troubleshooting.md +64 -1
  46. package/package.json +4 -4
package/README.md CHANGED
@@ -313,6 +313,31 @@ control character in it.
313
313
  - **It sends what you enqueue, to anyone.** The queue is not a relay
314
314
  policy: enqueue only what an authenticated user submitted, or what your
315
315
  own server writes, never what an unauthenticated client handed you.
316
+ - **A custom `QueueStore` must port `complete` (0.11, breaking).**
317
+ `complete(id, owner, result, dsns)` takes the DSN items the outcome
318
+ calls for and returns `{ item, dsns }`, or `undefined` for a lost lease.
319
+ Store the outcome and the DSNs in one step, so a crash cannot leave one
320
+ without the other; a store that returns the bare item still works, but
321
+ the queue reports `Queue store outdated` on the `error` event and adds
322
+ each DSN with `add`, outside that step. The stores of this package are
323
+ atomic. DSNs ignore `limits.maxItems`: a full queue still bounces, and the
324
+ count may exceed the limit by the DSNs it holds. They are delivered at least once; see [Writing a
325
+ store](./docs/guide.md#writing-a-store). The `this.*` calls below are
326
+ your store's own helpers, a sketch.
327
+
328
+ ```ts
329
+ async complete(id, owner, result, dsns) {
330
+ // refuse a bad DSN (INVALID) before opening a connection or a transaction
331
+ for (const dsn of dsns) this.check(dsn);
332
+ return this.transaction(async () => {
333
+ const item = await this.apply(id, owner, result); // undefined on a lost lease
334
+ if (!item) return undefined; // writes no DSN
335
+ const stored = [];
336
+ for (const dsn of dsns) stored.push(await this.insert(dsn)); // in order
337
+ return { item, dsns: stored };
338
+ });
339
+ }
340
+ ```
316
341
 
317
342
  ## API
318
343
 
@@ -324,7 +349,8 @@ control character in it.
324
349
  | `deliveredDsn(input)`, `DeliveredDsnInput`, `DeliveredRecipient` | the `delivered` DSN for a local delivery: the bytes to enqueue, or `undefined` when no recipient asked for `SUCCESS` |
325
350
  | `failedDsn(input)`, `FailedDsnInput`, `FailedRecipient`, `DEFAULT_MAX_RETURN` | the `failed` DSN for a recipient the application could not deliver locally: the bytes to enqueue, or `undefined` for a null reverse-path or when no recipient asked for failures; `DEFAULT_MAX_RETURN` is the 64 KiB a DSN returns of the original by default |
326
351
  | `QueueEvents`, `QueueListener`, `RecipientEvent` (`route`, `fallback`, `mxReply`, `mayHaveReachedMx`, `mayHaveReachedFallback`), `DeferredEvent`, `DsnEvent`, `QueueErrorEvent` | the events |
327
- | `QueueStore` | the contract a store answers: `add`, `get`, `list`, `count`, `readMessage`, `claim`, `renew`, `complete`, `reschedule`, `cancel` |
352
+ | `QueueStore` | the contract a store answers: `add`, `get`, `list`, `count`, `readMessage`, `claim`, `renew`, `complete(id, owner, result, dsns)`, `reschedule`, `cancel` |
353
+ | `Completed` (`item`, `dsns`) | what `complete` returns: the item as it now stands, and the DSN items it stored in the same step, in the order given; `undefined` when the lease was lost |
328
354
  | `QueueItem`, `RecipientState`, `RecipientStatus`, `FinalStatus`, `Diagnostic`, `Lease` | an item, and where each recipient stands |
329
355
  | `NewQueueItem`, `AddOptions`, `ClaimRequest`, `AttemptResult`, `RecipientUpdate`, `QueueListOptions` | what a store takes |
330
356
  | `QueueError`, `QueueErrorCode` | `INVALID`, `MESSAGE_TOO_BIG`, `TOO_MANY_RECIPIENTS`, `QUEUE_FULL`, `CLOSED`, `LEASE_LOST`, `MESSAGE_UNREADABLE` |
@@ -148,6 +148,17 @@ function checkUpdate(update) {
148
148
  checkStorable(`reply.${name}`, value);
149
149
  }
150
150
  }
151
+ function checkDsns(dsns) {
152
+ if (!Array.isArray(dsns))
153
+ throw invalid("dsns must be an array");
154
+ for (const dsn of dsns)
155
+ checkNewItem(dsn);
156
+ }
157
+ function checkComplete(owner, result, dsns) {
158
+ checkOwner(owner);
159
+ checkResult(result);
160
+ checkDsns(dsns);
161
+ }
151
162
  function checkNewItem(item) {
152
163
  if (typeof item !== "object" || item === null) {
153
164
  throw invalid("A new item is an object");
@@ -267,7 +278,7 @@ function newItem(id, item) {
267
278
  }
268
279
  var claimable = (item, now) => item.nextAttemptAt <= now && (item.lease === undefined || item.lease.expiresAt <= now);
269
280
 
270
- export { hasControl, replaceControls, cleanText, isStorable, asciiText, QueueError2, invalid, checkTime, checkOwner, checkNewItem, checkMaxItems, checkClaim, checkResult, checkList, isDone, applyAttempt, newItem, claimable };
281
+ export { hasControl, replaceControls, cleanText, isStorable, asciiText, QueueError2, invalid, checkTime, checkOwner, checkComplete, checkNewItem, checkMaxItems, checkClaim, checkList, isDone, applyAttempt, newItem, claimable };
271
282
 
272
- //# debugId=6F0F13A4EBC138E164756E2164756E21
273
- //# sourceMappingURL=index-sz13a17b.js.map
283
+ //# debugId=17F888FDC5191A2364756E2164756E21
284
+ //# sourceMappingURL=index-t6q7zxgj.js.map
@@ -3,12 +3,12 @@
3
3
  "sources": ["../src/text.ts", "../src/errors.ts", "../src/contract/storable.ts", "../src/contract/dsn-checks.ts", "../src/contract/checks.ts"],
4
4
  "sourcesContent": [
5
5
  "/** Text from the other side, made safe to keep and to write in a header field. */\n\n/** C0, DEL and C1: every control character, CR, LF and TAB included. */\nconst isControl = (code: number) =>\n\tcode < 0x20 || (code >= 0x7f && code <= 0x9f);\n\n/** Whether the text holds a control character. */\nexport function hasControl(text: string): boolean {\n\tfor (let i = 0; i < text.length; i++) {\n\t\tif (isControl(text.charCodeAt(i))) return true;\n\t}\n\treturn false;\n}\n\n/** Each control character replaced by `by`. */\nexport function replaceControls(text: string, by: string): string {\n\tlet out = '';\n\tfor (let i = 0; i < text.length; i++) {\n\t\tout += isControl(text.charCodeAt(i)) ? by : (text[i] as string);\n\t}\n\treturn out;\n}\n\n/**\n * Every control character (CR and LF included) as a space, a lone\n * surrogate as U+FFFD, runs of space as one, cut at `max` characters with\n * `...`, never inside a surrogate pair: what a reply leaves in an item,\n * an event and a DSN.\n */\nexport function cleanText(text: string, max: number): string {\n\tconst clean = replaceControls(text.toWellFormed(), ' ')\n\t\t.replace(/ {2,}/g, ' ')\n\t\t.trim();\n\treturn clean.length > max ? `${cut(clean, max - 3)}...` : clean;\n}\n\n/**\n * The first `length` UTF-16 units, never ending inside a surrogate pair:\n * a lone surrogate is text no store can keep (PostgreSQL's `jsonb` refuses\n * it), nor any UTF-8 encode.\n */\nfunction cut(text: string, length: number): string {\n\tconst head = text.slice(0, length);\n\tconst last = head.charCodeAt(head.length - 1);\n\treturn last >= 0xd800 && last <= 0xdbff ? head.slice(0, -1) : head;\n}\n\n/**\n * Text every store can keep: no NUL (PostgreSQL's `text` and `jsonb` hold\n * none) and no lone surrogate. `cleanText`'s output always is.\n */\nexport const isStorable = (text: string): boolean =>\n\ttext.isWellFormed() && !text.includes('\\0');\n\n/** `cleanText`, then anything not printable ASCII as `?`: for a `message/delivery-status` field. */\nexport const asciiText = (text: string, max: number): string =>\n\tcleanText(text, max).replace(/[^ -~]/g, '?');\n",
6
- "/**\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 — or, once the lease's\n * expiry passed, when the item is gone: lost or cancelled.\n * `MESSAGE_UNREADABLE`: given to the `error` event when the store holds an\n * item but not its message, whose pending recipients then fail.\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\t| 'MESSAGE_UNREADABLE';\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
+ "/**\n * Why the queue or a store refused a call. `INVALID`: an option or an\n * argument it cannot take, or, given to the `error` event, a store that\n * answers an older contract (`complete` returning the item alone, without\n * the DSNs). `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 — or, once the lease's\n * expiry passed, when the item is gone: lost or cancelled.\n * `MESSAGE_UNREADABLE`: given to the `error` event when the store holds an\n * item but not its message, whose pending recipients then fail.\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\t| 'MESSAGE_UNREADABLE';\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",
7
7
  "import { invalid } from '../errors';\nimport { isStorable } from '../text';\n\n/**\n * Text a store keeps: refused, the same way by every store, when it holds\n * a NUL or a lone surrogate, which PostgreSQL cannot keep and no UTF-8\n * encode can carry.\n */\nexport function checkStorable(name: string, text: string): void {\n\tif (!isStorable(text)) {\n\t\tthrow invalid(\n\t\t\t`${name} holds a NUL or a lone surrogate, which a store cannot keep`,\n\t\t);\n\t}\n}\n",
8
8
  "// The value rules (and utf8OrcptLength, RFC 6533) repeat packages/smtp/src/server/dsn-params.ts, packages/smtp/src/client/dsn.ts and\n// packages/jmap/src/submission/dsn.ts (AGENTS.md, Deliberate duplications); this copy guards the contract.\nimport { invalid } from '../errors';\nimport { checkStorable } from './storable';\nimport type { NewQueueItem, RecipientDsn } from './types';\n\nconst EVENTS: readonly unknown[] = ['SUCCESS', 'FAILURE', 'DELAY'];\n\n/**\n * The length the xtext of `text` takes on the wire (RFC 3461 §4): one\n * character for each byte of its UTF-8 form in `!` to `~` but `+` and `=`,\n * three for any other.\n */\nfunction xtextLength(text: string): number {\n\tlet length = 0;\n\tfor (const byte of new TextEncoder().encode(text)) {\n\t\tlength +=\n\t\t\tbyte >= 33 && byte <= 126 && byte !== 0x2b && byte !== 0x3d ? 1 : 3;\n\t}\n\treturn length;\n}\n\n/**\n * The length of a `utf-8` ORCPT address in its `utf-8-addr-unitext` form (RFC\n * 6533 §3), the shortest one: raw UTF-8 octets for a non-ASCII character, one\n * for printable ASCII but `\\`, `+` and `=`, and `\\x{HH}` (6) for the rest.\n * The SMTP server counts the value as sent, which is this for a unitext one.\n */\nfunction utf8OrcptLength(text: string): number {\n\tlet length = 0;\n\tfor (const char of text) {\n\t\tconst code = char.codePointAt(0) as number;\n\t\tif (code > 0x7f) length += new TextEncoder().encode(char).length;\n\t\telse\n\t\t\tlength +=\n\t\t\t\tcode >= 0x21 &&\n\t\t\t\tcode !== 0x5c &&\n\t\t\t\tcode !== 0x2b &&\n\t\t\t\tcode !== 0x3d &&\n\t\t\t\tcode < 0x7f\n\t\t\t\t\t? 1\n\t\t\t\t\t: 6;\n\t}\n\treturn length;\n}\n\n/** One recipient's `NOTIFY` (RFC 3461 §4.1) and `ORCPT` (§4.2). */\nfunction checkRecipientDsn(entry: RecipientDsn, to: readonly string[]): void {\n\tconst { address, notify, orcpt } = entry ?? {};\n\tif (typeof address !== 'string' || !to.includes(address)) {\n\t\tthrow invalid(\n\t\t\t`recipients names ${JSON.stringify(address)}, which is not in to`,\n\t\t);\n\t}\n\tif (notify !== undefined && notify !== 'NEVER') {\n\t\tconst events: readonly unknown[] = Array.isArray(notify) ? notify : [];\n\t\tif (\n\t\t\tevents.length === 0 ||\n\t\t\tevents.some((e, i) => !EVENTS.includes(e) || events.indexOf(e) !== i)\n\t\t) {\n\t\t\tthrow invalid(\n\t\t\t\t`notify of ${address} must be 'NEVER' or a list of 'SUCCESS', 'FAILURE', 'DELAY', each once`,\n\t\t\t);\n\t\t}\n\t}\n\tif (orcpt === undefined) return;\n\tif (\n\t\ttypeof orcpt !== 'object' ||\n\t\torcpt === null ||\n\t\ttypeof orcpt.type !== 'string' ||\n\t\t!/^[A-Za-z0-9-]+$/.test(orcpt.type) ||\n\t\ttypeof orcpt.address !== 'string' ||\n\t\torcpt.address === ''\n\t) {\n\t\tthrow invalid(`orcpt of ${address} must be { type, address }`);\n\t}\n\t// RFC 3461 §4.2: \"The entire ORCPT parameter MAY be up to 500 characters in length\", as sent.\n\tconst encoded =\n\t\torcpt.type.toLowerCase() === 'utf-8'\n\t\t\t? utf8OrcptLength(orcpt.address)\n\t\t\t: xtextLength(orcpt.address);\n\tif (orcpt.type.length + 1 + encoded > 500) {\n\t\tthrow invalid(`orcpt of ${address} is over 500 characters once encoded`);\n\t}\n\tcheckStorable('orcpt.type', orcpt.type);\n\tcheckStorable('orcpt.address', orcpt.address);\n}\n\n/** `ret`, `envid` and `recipients` of a new item. */\nexport function checkDsnParams(item: NewQueueItem): void {\n\tconst { ret, envid, recipients } = item;\n\tif (ret !== undefined && ret !== 'FULL' && ret !== 'HDRS') {\n\t\tthrow invalid(`ret must be 'FULL' or 'HDRS', not ${String(ret)}`);\n\t}\n\tif (\n\t\tenvid !== undefined &&\n\t\t(typeof envid !== 'string' ||\n\t\t\t!/^[ -~]{1,100}$/.test(envid) ||\n\t\t\t// RFC 3461 §4.4: \"The ENVID parameter MAY be up to 100 characters in length\", as sent.\n\t\t\txtextLength(envid) > 100)\n\t) {\n\t\tthrow invalid(\n\t\t\t'envid must be 1 to 100 printable ASCII characters, at most 100 once encoded as xtext',\n\t\t);\n\t}\n\tif (recipients === undefined) return;\n\tif (!Array.isArray(recipients)) {\n\t\tthrow invalid('recipients must be an array of { address, notify, orcpt }');\n\t}\n\tconst seen = new Set<string>();\n\tfor (const entry of recipients) {\n\t\tcheckRecipientDsn(entry, item.to);\n\t\tif (seen.has(entry.address)) {\n\t\t\tthrow invalid(`recipients names ${entry.address} twice`);\n\t\t}\n\t\tseen.add(entry.address);\n\t}\n}\n",
9
- "import { invalid } from '../errors';\nimport { checkDsnParams } from './dsn-checks';\nimport { checkStorable } from './storable';\n\nexport { checkStorable };\n\nimport type {\n\tAttemptResult,\n\tClaimRequest,\n\tDiagnostic,\n\tNewQueueItem,\n\tQueueItem,\n\tQueueListOptions,\n\tRecipientState,\n\tRecipientUpdate,\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\tcheckStorable('owner', owner);\n\treturn owner;\n}\n\n/** Every text of a recipient's outcome. */\nfunction checkUpdate(update: RecipientUpdate): void {\n\tcheckStorable('A recipient', update.address);\n\tfor (const key of ['mayHaveReachedMx', 'mayHaveReachedFallback'] as const) {\n\t\tconst mark = update[key] as unknown;\n\t\tif (mark !== undefined && mark !== true) {\n\t\t\tthrow invalid(`${key} must be true or absent`);\n\t\t}\n\t}\n\tconst reply = update.reply as Partial<Diagnostic> | undefined;\n\tif (reply === undefined) return;\n\tif (\n\t\ttypeof reply !== 'object' ||\n\t\treply === null ||\n\t\ttypeof reply.text !== 'string'\n\t) {\n\t\tthrow invalid('A reply is an object with a text');\n\t}\n\tcheckStorable('reply.text', reply.text);\n\tfor (const name of ['status', 'host'] as const) {\n\t\tconst value = reply[name];\n\t\tif (value === undefined) continue;\n\t\tif (typeof value !== 'string')\n\t\t\tthrow invalid(`reply.${name} must be a string`);\n\t\tcheckStorable(`reply.${name}`, value);\n\t}\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\tcheckStorable('from', item.from);\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\tfor (const address of to as string[]) checkStorable('A recipient', address);\n\tif (!(item.message instanceof Uint8Array)) {\n\t\tthrow invalid('message must be a Uint8Array');\n\t}\n\tcheckTime('createdAt', item.createdAt);\n\tcheckDsnParams(item);\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\tfor (const update of result.recipients) checkUpdate(update);\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...(r.notify === undefined ? {} : { notify: r.notify }),\n\t\t\t...(r.orcpt === undefined ? {} : { orcpt: r.orcpt }),\n\t\t\t...(update.reply ? { reply: update.reply } : {}),\n\t\t\tupdatedAt: result.now,\n\t\t\t...(r.mayHaveReachedMx || update.mayHaveReachedMx\n\t\t\t\t? { mayHaveReachedMx: true as const }\n\t\t\t\t: {}),\n\t\t\t...(r.mayHaveReachedFallback || update.mayHaveReachedFallback\n\t\t\t\t? { mayHaveReachedFallback: true as const }\n\t\t\t\t: {}),\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\tconst dsn = new Map(item.recipients?.map((r) => [r.address, r]));\n\treturn {\n\t\tid,\n\t\tfrom: item.from,\n\t\trecipients: item.to.map((address): RecipientState => {\n\t\t\tconst { notify, orcpt } = dsn.get(address) ?? {};\n\t\t\treturn {\n\t\t\t\taddress,\n\t\t\t\tstatus: 'pending',\n\t\t\t\t...(notify === undefined\n\t\t\t\t\t? {}\n\t\t\t\t\t: { notify: notify === 'NEVER' ? notify : [...notify] }),\n\t\t\t\t...(orcpt === undefined\n\t\t\t\t\t? {}\n\t\t\t\t\t: { orcpt: { type: orcpt.type, address: orcpt.address } }),\n\t\t\t};\n\t\t}),\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\t...(item.ret === undefined ? {} : { ret: item.ret }),\n\t\t...(item.envid === undefined ? {} : { envid: item.envid }),\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"
9
+ "import { invalid } from '../errors';\nimport { checkDsnParams } from './dsn-checks';\nimport { checkStorable } from './storable';\n\nexport { checkStorable };\n\nimport type {\n\tAttemptResult,\n\tClaimRequest,\n\tDiagnostic,\n\tNewQueueItem,\n\tQueueItem,\n\tQueueListOptions,\n\tRecipientState,\n\tRecipientUpdate,\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\tcheckStorable('owner', owner);\n\treturn owner;\n}\n\n/** Every text of a recipient's outcome. */\nfunction checkUpdate(update: RecipientUpdate): void {\n\tcheckStorable('A recipient', update.address);\n\tfor (const key of ['mayHaveReachedMx', 'mayHaveReachedFallback'] as const) {\n\t\tconst mark = update[key] as unknown;\n\t\tif (mark !== undefined && mark !== true) {\n\t\t\tthrow invalid(`${key} must be true or absent`);\n\t\t}\n\t}\n\tconst reply = update.reply as Partial<Diagnostic> | undefined;\n\tif (reply === undefined) return;\n\tif (\n\t\ttypeof reply !== 'object' ||\n\t\treply === null ||\n\t\ttypeof reply.text !== 'string'\n\t) {\n\t\tthrow invalid('A reply is an object with a text');\n\t}\n\tcheckStorable('reply.text', reply.text);\n\tfor (const name of ['status', 'host'] as const) {\n\t\tconst value = reply[name];\n\t\tif (value === undefined) continue;\n\t\tif (typeof value !== 'string')\n\t\t\tthrow invalid(`reply.${name} must be a string`);\n\t\tcheckStorable(`reply.${name}`, value);\n\t}\n}\n\n/** The DSN items `complete` takes: an array, each as `add` checks an item. */\nexport function checkDsns(dsns: readonly NewQueueItem[]): void {\n\tif (!Array.isArray(dsns)) throw invalid('dsns must be an array');\n\tfor (const dsn of dsns) checkNewItem(dsn);\n}\n\n/** What `complete` checks before any I/O, in this order: the owner, the result, the DSNs. */\nexport function checkComplete(\n\towner: unknown,\n\tresult: AttemptResult,\n\tdsns: readonly NewQueueItem[],\n): void {\n\tcheckOwner(owner);\n\tcheckResult(result);\n\tcheckDsns(dsns);\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\tcheckStorable('from', item.from);\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\tfor (const address of to as string[]) checkStorable('A recipient', address);\n\tif (!(item.message instanceof Uint8Array)) {\n\t\tthrow invalid('message must be a Uint8Array');\n\t}\n\tcheckTime('createdAt', item.createdAt);\n\tcheckDsnParams(item);\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\tfor (const update of result.recipients) checkUpdate(update);\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...(r.notify === undefined ? {} : { notify: r.notify }),\n\t\t\t...(r.orcpt === undefined ? {} : { orcpt: r.orcpt }),\n\t\t\t...(update.reply ? { reply: update.reply } : {}),\n\t\t\tupdatedAt: result.now,\n\t\t\t...(r.mayHaveReachedMx || update.mayHaveReachedMx\n\t\t\t\t? { mayHaveReachedMx: true as const }\n\t\t\t\t: {}),\n\t\t\t...(r.mayHaveReachedFallback || update.mayHaveReachedFallback\n\t\t\t\t? { mayHaveReachedFallback: true as const }\n\t\t\t\t: {}),\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\tconst dsn = new Map(item.recipients?.map((r) => [r.address, r]));\n\treturn {\n\t\tid,\n\t\tfrom: item.from,\n\t\trecipients: item.to.map((address): RecipientState => {\n\t\t\tconst { notify, orcpt } = dsn.get(address) ?? {};\n\t\t\treturn {\n\t\t\t\taddress,\n\t\t\t\tstatus: 'pending',\n\t\t\t\t...(notify === undefined\n\t\t\t\t\t? {}\n\t\t\t\t\t: { notify: notify === 'NEVER' ? notify : [...notify] }),\n\t\t\t\t...(orcpt === undefined\n\t\t\t\t\t? {}\n\t\t\t\t\t: { orcpt: { type: orcpt.type, address: orcpt.address } }),\n\t\t\t};\n\t\t}),\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\t...(item.ret === undefined ? {} : { ret: item.ret }),\n\t\t...(item.envid === undefined ? {} : { envid: item.envid }),\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"
10
10
  ],
11
- "mappings": "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",
12
- "debugId": "6F0F13A4EBC138E164756E2164756E21",
11
+ "mappings": "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",
12
+ "debugId": "17F888FDC5191A2364756E2164756E21",
13
13
  "names": []
14
14
  }
@@ -5,6 +5,10 @@ import type { AttemptResult, ClaimRequest, NewQueueItem, QueueItem, QueueListOpt
5
5
  export declare function checkTime(name: string, value: unknown): number;
6
6
  /** A lease owner: a non-empty string. */
7
7
  export declare function checkOwner(owner: unknown): string;
8
+ /** The DSN items `complete` takes: an array, each as `add` checks an item. */
9
+ export declare function checkDsns(dsns: readonly NewQueueItem[]): void;
10
+ /** What `complete` checks before any I/O, in this order: the owner, the result, the DSNs. */
11
+ export declare function checkComplete(owner: unknown, result: AttemptResult, dsns: readonly NewQueueItem[]): void;
8
12
  export declare function checkNewItem(item: NewQueueItem): void;
9
13
  /** `maxItems`: a positive integer, or nothing. */
10
14
  export declare function checkMaxItems(max: unknown): number | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../../src/contract/checks.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,OAAO,EAAE,aAAa,EAAE,CAAC;AAEzB,OAAO,KAAK,EACX,aAAa,EACb,YAAY,EAEZ,YAAY,EACZ,SAAS,EACT,gBAAgB,EAGhB,MAAM,SAAS,CAAC;AAOjB,sEAAsE;AACtE,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAG9D;AAED,yCAAyC;AACzC,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAMjD;AA8BD,wBAAgB,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAoBrD;AAED,kDAAkD;AAClD,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAM9D;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAStD;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAwBvD;AAED,qEAAqE;AACrE,wBAAgB,SAAS,CAAC,OAAO,GAAE,gBAAqB,GAAG;IAC1D,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACd,CAUA;AAED,kDAAkD;AAClD,eAAO,MAAM,MAAM,GAAI,MAAM,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,KAAG,OAG3D,CAAC;AAEH;;;GAGG;AACH,wBAAgB,YAAY,CAC3B,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,aAAa,GACnB,SAAS,CA4BX;AAED,4CAA4C;AAC5C,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,SAAS,CA0BjE;AAED,uEAAuE;AACvE,eAAO,MAAM,SAAS,GAAI,MAAM,SAAS,EAAE,KAAK,MAAM,KAAG,OAEC,CAAC"}
1
+ {"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../../src/contract/checks.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,OAAO,EAAE,aAAa,EAAE,CAAC;AAEzB,OAAO,KAAK,EACX,aAAa,EACb,YAAY,EAEZ,YAAY,EACZ,SAAS,EACT,gBAAgB,EAGhB,MAAM,SAAS,CAAC;AAOjB,sEAAsE;AACtE,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAG9D;AAED,yCAAyC;AACzC,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAMjD;AA8BD,8EAA8E;AAC9E,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,YAAY,EAAE,GAAG,IAAI,CAG7D;AAED,6FAA6F;AAC7F,wBAAgB,aAAa,CAC5B,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,SAAS,YAAY,EAAE,GAC3B,IAAI,CAIN;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAoBrD;AAED,kDAAkD;AAClD,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAM9D;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAStD;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAwBvD;AAED,qEAAqE;AACrE,wBAAgB,SAAS,CAAC,OAAO,GAAE,gBAAqB,GAAG;IAC1D,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACd,CAUA;AAED,kDAAkD;AAClD,eAAO,MAAM,MAAM,GAAI,MAAM,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,KAAG,OAG3D,CAAC;AAEH;;;GAGG;AACH,wBAAgB,YAAY,CAC3B,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,aAAa,GACnB,SAAS,CA4BX;AAED,4CAA4C;AAC5C,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,SAAS,CA0BjE;AAED,uEAAuE;AACvE,eAAO,MAAM,SAAS,GAAI,MAAM,SAAS,EAAE,KAAK,MAAM,KAAG,OAEC,CAAC"}
@@ -1,4 +1,4 @@
1
- import type { AddOptions, AttemptResult, ClaimRequest, NewQueueItem, QueueItem, QueueListOptions } from './types';
1
+ import type { AddOptions, AttemptResult, ClaimRequest, Completed, NewQueueItem, QueueItem, QueueListOptions } from './types';
2
2
  /**
3
3
  * Where the queue keeps its items, made for several workers, in one
4
4
  * process or many, sharing one store. A worker **claims** a due item: it
@@ -48,13 +48,21 @@ export interface QueueStore {
48
48
  renew(id: string, owner: string, expiresAt: number): Promise<boolean>;
49
49
  /**
50
50
  * Records an attempt: each recipient's outcome, the next attempt and the
51
- * count, and lets go of the lease — in one step, while `owner` holds it.
52
- * Returns the item as it now stands, done (every recipient final, and
53
- * the item dropped) or not; `undefined` when `owner` no longer holds it.
54
- * A recipient's `mayHaveReachedMx` and `mayHaveReachedFallback` marks, once
55
- * recorded, are kept.
51
+ * count, and lets go of the lease — and inserts `dsns`, the DSN items
52
+ * the outcome calls for — in one step, while `owner` holds it: the
53
+ * outcome and its DSNs are both stored, or neither is. Returns the item
54
+ * as it now stands, done (every recipient final, and the item dropped) or
55
+ * not, with the inserted DSN items in the order given; `undefined` when
56
+ * `owner` no longer holds the lease, and then nothing is inserted: the
57
+ * lease is the idempotency token, so a DSN is inserted once per outcome.
58
+ *
59
+ * The DSNs ignore `maxItems`: a full queue loses no bounce. Each goes
60
+ * through the checks of `add`; one that fails them refuses the whole call
61
+ * with `INVALID`, with nothing recorded. The store gives them their ids.
62
+ * A recipient's `mayHaveReachedMx` and `mayHaveReachedFallback` marks,
63
+ * once recorded, are kept.
56
64
  */
57
- complete(id: string, owner: string, result: AttemptResult): Promise<QueueItem | undefined>;
65
+ complete(id: string, owner: string, result: AttemptResult, dsns: readonly NewQueueItem[]): Promise<Completed | undefined>;
58
66
  /**
59
67
  * Moves the next attempt to `at`. With `owner`, only while that owner
60
68
  * holds the lease, which it lets go of: a worker giving an item back.
@@ -1 +1 @@
1
- {"version":3,"file":"queue-store.d.ts","sourceRoot":"","sources":["../../src/contract/queue-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,UAAU,EACV,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,gBAAgB,EAChB,MAAM,SAAS,CAAC;AAEjB;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,UAAU;IAC1B;;;;;;OAMG;IACH,GAAG,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAElE,gGAAgG;IAChG,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;IAEhD,0DAA0D;IAC1D,IAAI,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IAEvD,sCAAsC;IACtC,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAEzB;;;;OAIG;IACH,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;IAEzD;;;;;OAKG;IACH,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;IAE7D;;;OAGG;IACH,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEtE;;;;;;;OAOG;IACH,QAAQ,CACP,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,aAAa,GACnB,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;IAElC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAErE,0FAA0F;IAC1F,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;CACnD"}
1
+ {"version":3,"file":"queue-store.d.ts","sourceRoot":"","sources":["../../src/contract/queue-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,UAAU,EACV,aAAa,EACb,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,SAAS,EACT,gBAAgB,EAChB,MAAM,SAAS,CAAC;AAEjB;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,UAAU;IAC1B;;;;;;OAMG;IACH,GAAG,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAElE,gGAAgG;IAChG,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;IAEhD,0DAA0D;IAC1D,IAAI,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IAEvD,sCAAsC;IACtC,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAEzB;;;;OAIG;IACH,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;IAEzD;;;;;OAKG;IACH,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;IAE7D;;;OAGG;IACH,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEtE;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CACP,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,SAAS,YAAY,EAAE,GAC3B,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;IAElC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAErE,0FAA0F;IAC1F,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;CACnD"}
@@ -101,6 +101,11 @@ export interface QueueItem {
101
101
  /** Present while a worker holds the item. */
102
102
  readonly lease?: Lease;
103
103
  }
104
+ /** What `complete` returns: the item as it now stands, and the DSN items it inserted in the same step, in the order given. */
105
+ export interface Completed {
106
+ readonly item: QueueItem;
107
+ readonly dsns: readonly QueueItem[];
108
+ }
104
109
  /** What `add` takes. */
105
110
  export interface NewQueueItem {
106
111
  readonly from: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/contract/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/contract/types.ts"],"names":[],"mappings":"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"}
package/dist/errors.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  /**
2
2
  * Why the queue or a store refused a call. `INVALID`: an option or an
3
- * argument it cannot take. `MESSAGE_TOO_BIG`, `TOO_MANY_RECIPIENTS` and
3
+ * argument it cannot take, or, given to the `error` event, a store that
4
+ * answers an older contract (`complete` returning the item alone, without
5
+ * the DSNs). `MESSAGE_TOO_BIG`, `TOO_MANY_RECIPIENTS` and
4
6
  * `QUEUE_FULL`: a limit `enqueue` enforces. `CLOSED`: a store used after
5
7
  * `close()`. `LEASE_LOST`: given to the `error` event when another worker
6
8
  * took an item before its outcome was recorded — or, once the lease's
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,MAAM,cAAc,GACvB,SAAS,GACT,iBAAiB,GACjB,qBAAqB,GACrB,YAAY,GACZ,QAAQ,GACR,YAAY,GACZ,oBAAoB,CAAC;AAExB,mGAAmG;AACnG,qBAAa,UAAW,SAAQ,KAAK;IACpC,SAAkB,IAAI,gBAAgB;IACtC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;gBAElB,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM;CAIjD;AAED,+CAA+C;AAC/C,eAAO,MAAM,OAAO,GAAI,SAAS,MAAM,eAAuC,CAAC"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,cAAc,GACvB,SAAS,GACT,iBAAiB,GACjB,qBAAqB,GACrB,YAAY,GACZ,QAAQ,GACR,YAAY,GACZ,oBAAoB,CAAC;AAExB,mGAAmG;AACnG,qBAAa,UAAW,SAAQ,KAAK;IACpC,SAAkB,IAAI,gBAAgB;IACtC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;gBAElB,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM;CAIjD;AAED,+CAA+C;AAC/C,eAAO,MAAM,OAAO,GAAI,SAAS,MAAM,eAAuC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export type { QueueStore } from './contract/queue-store';
2
- export type { AddOptions, AttemptResult, ClaimRequest, Diagnostic, FinalStatus, Lease, NewQueueItem, NotifyEvent, OriginalRecipient, QueueItem, QueueListOptions, RecipientDsn, RecipientNotify, RecipientState, RecipientStatus, RecipientUpdate, RetMode, } from './contract/types';
2
+ export type { AddOptions, AttemptResult, ClaimRequest, Completed, Diagnostic, FinalStatus, Lease, NewQueueItem, NotifyEvent, OriginalRecipient, QueueItem, QueueListOptions, RecipientDsn, RecipientNotify, RecipientState, RecipientStatus, RecipientUpdate, RetMode, } from './contract/types';
3
3
  export { type DeliveredDsnInput, type DeliveredRecipient, deliveredDsn, } from './dsn/delivered';
4
4
  export { type FailedDsnInput, type FailedRecipient, failedDsn, } from './dsn/failed';
5
5
  export { DEFAULT_MAX_RETURN } from './dsn/policy';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,YAAY,EACX,UAAU,EACV,aAAa,EACb,YAAY,EACZ,UAAU,EACV,WAAW,EACX,KAAK,EACL,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,eAAe,EACf,cAAc,EACd,eAAe,EACf,eAAe,EACf,OAAO,GACP,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACN,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,YAAY,GACZ,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACN,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,SAAS,GACT,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,KAAK,cAAc,EAAE,MAAM,UAAU,CAAC;AAC3D,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACrE,YAAY,EACX,aAAa,EACb,QAAQ,EACR,eAAe,EACf,WAAW,EACX,aAAa,EACb,cAAc,GACd,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACX,KAAK,EACL,UAAU,EACV,WAAW,EACX,YAAY,EACZ,aAAa,EACb,KAAK,EACL,MAAM,EACN,SAAS,GACT,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,WAAW,EAAE,KAAK,KAAK,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,YAAY,EACX,UAAU,EACV,aAAa,EACb,YAAY,EACZ,SAAS,EACT,UAAU,EACV,WAAW,EACX,KAAK,EACL,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,eAAe,EACf,cAAc,EACd,eAAe,EACf,eAAe,EACf,OAAO,GACP,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACN,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,YAAY,GACZ,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACN,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,SAAS,GACT,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,KAAK,cAAc,EAAE,MAAM,UAAU,CAAC;AAC3D,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACrE,YAAY,EACX,aAAa,EACb,QAAQ,EACR,eAAe,EACf,WAAW,EACX,aAAa,EACb,cAAc,GACd,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACX,KAAK,EACL,UAAU,EACV,WAAW,EACX,YAAY,EACZ,aAAa,EACb,KAAK,EACL,MAAM,EACN,SAAS,GACT,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,WAAW,EAAE,KAAK,KAAK,EAAE,MAAM,eAAe,CAAC"}
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  QueueError2,
7
7
  invalid,
8
8
  checkOwner
9
- } from "./chunks/index-sz13a17b.js";
9
+ } from "./chunks/index-t6q7zxgj.js";
10
10
 
11
11
  // src/dsn/build.ts
12
12
  import {
@@ -938,12 +938,12 @@ function reported(r, kind) {
938
938
  text: [reply.text, ...said].filter((t) => t !== "").join(" ")
939
939
  };
940
940
  }
941
- async function notify(ctx, item, message, kind, recipients, now) {
941
+ function dsnsFor(ctx, item, message, kind, recipients, now, failures) {
942
942
  const states = new Map(item.recipients.map((r) => [r.address, r]));
943
943
  const wanted = recipients.filter((r) => asked(kind, states.get(r.address)?.notify));
944
944
  if (item.from === "" || wanted.length === 0)
945
- return;
946
- const { settings, store, events } = ctx;
945
+ return [];
946
+ const { settings } = ctx;
947
947
  try {
948
948
  const lastAttempt = new Date(now);
949
949
  const dsn = buildDsn({
@@ -969,21 +969,61 @@ async function notify(ctx, item, message, kind, recipients, now) {
969
969
  returnContent: kind === "relayed" ? "headers" : returnOf(item.ret, settings.dsn.returnContent),
970
970
  maxReturn: settings.limits.maxDsnReturn
971
971
  });
972
- const added = await store.add({
973
- from: "",
974
- to: [item.from],
975
- message: dsn,
976
- createdAt: now
977
- });
972
+ return [
973
+ {
974
+ item: { from: "", to: [item.from], message: dsn, createdAt: now },
975
+ kind,
976
+ to: item.from,
977
+ recipients: wanted.map((r) => r.address)
978
+ }
979
+ ];
980
+ } catch (error) {
981
+ failures.push(error);
982
+ return [];
983
+ }
984
+ }
985
+ function dsnsOf(ctx, item, message, settled, now) {
986
+ const failures = [];
987
+ const build = (kind, recipients) => dsnsFor(ctx, item, message, kind, recipients, now, failures);
988
+ const pending = [
989
+ ...build("failed", settled.failed),
990
+ ...build("relayed", settled.delivered.filter((u) => u.dsnOffered === false)),
991
+ ...settled.delayDsn ? build("delayed", settled.deferred) : []
992
+ ];
993
+ return { pending, failures };
994
+ }
995
+ async function tellDsns(ctx, item, pending, completed) {
996
+ const { store, events } = ctx;
997
+ const stored = completed.dsns;
998
+ const outdated = !Array.isArray(stored);
999
+ if (outdated && pending.length > 0) {
1000
+ const error = new QueueError2("INVALID", "Queue store outdated: complete returned the item alone, not { item, dsns }; its DSNs are added one by one, outside the step that records the outcome");
1001
+ events.emit("error", { error, id: item.id });
1002
+ }
1003
+ for (const [index, dsn] of pending.entries()) {
1004
+ let id;
1005
+ if (outdated) {
1006
+ try {
1007
+ id = (await store.add(dsn.item)).id;
1008
+ } catch (error) {
1009
+ events.emit("error", { error, id: item.id });
1010
+ continue;
1011
+ }
1012
+ } else {
1013
+ id = stored[index]?.id;
1014
+ if (id === undefined) {
1015
+ const error = new QueueError2("INVALID", `The queue store stored ${stored.length} of the ${pending.length} DSNs of ${item.id}: a ${dsn.kind} DSN to ${dsn.to} is lost`);
1016
+ events.emit("error", { error, id: item.id });
1017
+ continue;
1018
+ }
1019
+ }
978
1020
  events.emit("dsn", {
979
- kind,
980
- id: added.id,
1021
+ kind: dsn.kind,
1022
+ id,
981
1023
  of: item.id,
982
- to: item.from,
983
- recipients: wanted.map((r) => r.address)
1024
+ to: dsn.to,
1025
+ recipients: dsn.recipients
984
1026
  });
985
- } catch (error) {
986
- events.emit("error", { error, id: item.id });
987
1027
  }
988
1028
  }
989
1029
 
@@ -1116,9 +1156,10 @@ async function record(ctx, item, updates, skipped, message, used) {
1116
1156
  const { settings, store, events } = ctx;
1117
1157
  const now = settings.now();
1118
1158
  const settled = settle(item, updates, skipped, now, settings);
1119
- const after = await store.complete(item.id, settings.owner, settled.result);
1159
+ const { pending, failures } = dsnsOf(ctx, item, message, settled, now);
1160
+ const completed = await store.complete(item.id, settings.owner, settled.result, pending.map((p) => p.item));
1120
1161
  ctx.recorded();
1121
- if (!after && await store.get(item.id) === undefined) {
1162
+ if (!completed && await store.get(item.id) === undefined) {
1122
1163
  const lapse = await ctx.leaseLapsed(now);
1123
1164
  if (lapse) {
1124
1165
  events.emit("error", { error: goneAfter(lapse, item.id), id: item.id });
@@ -1129,7 +1170,7 @@ async function record(ctx, item, updates, skipped, message, used) {
1129
1170
  emitOutcomes(events, item, settled, used);
1130
1171
  return;
1131
1172
  }
1132
- if (!after) {
1173
+ if (!completed) {
1133
1174
  const error = new QueueError2("LEASE_LOST", `The lease on ${item.id} was lost before its outcome was recorded; another worker will try it again`);
1134
1175
  events.emit("error", { error, id: item.id });
1135
1176
  return;
@@ -1138,12 +1179,9 @@ async function record(ctx, item, updates, skipped, message, used) {
1138
1179
  events.emit("error", { error: unreadableError(item.id), id: item.id });
1139
1180
  }
1140
1181
  emitOutcomes(events, item, settled, used);
1141
- await notify(ctx, item, message, "failed", settled.failed, now);
1142
- const relayed = settled.delivered.filter((u) => u.dsnOffered === false);
1143
- await notify(ctx, item, message, "relayed", relayed, now);
1144
- if (settled.delayDsn) {
1145
- await notify(ctx, item, message, "delayed", settled.deferred, now);
1146
- }
1182
+ for (const error of failures)
1183
+ events.emit("error", { error, id: item.id });
1184
+ await tellDsns(ctx, item, pending, completed);
1147
1185
  }
1148
1186
 
1149
1187
  // src/queue/lease.ts
@@ -1438,5 +1476,5 @@ export {
1438
1476
  failedDsn
1439
1477
  };
1440
1478
 
1441
- //# debugId=9F6E913A6461985264756E2164756E21
1479
+ //# debugId=9190A6EB36D3FC0664756E2164756E21
1442
1480
  //# sourceMappingURL=index.js.map