@bumail/queue 0.10.0 → 0.12.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 (68) hide show
  1. package/README.md +52 -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/conformance/claims.d.ts +4 -0
  5. package/dist/conformance/claims.d.ts.map +1 -0
  6. package/dist/conformance/complete-dsns.d.ts +4 -0
  7. package/dist/conformance/complete-dsns.d.ts.map +1 -0
  8. package/dist/conformance/concurrency.d.ts +4 -0
  9. package/dist/conformance/concurrency.d.ts.map +1 -0
  10. package/dist/conformance/describe-queue-store.d.ts +11 -0
  11. package/dist/conformance/describe-queue-store.d.ts.map +1 -0
  12. package/dist/conformance/doubt.d.ts +5 -0
  13. package/dist/conformance/doubt.d.ts.map +1 -0
  14. package/dist/conformance/dsn.d.ts +4 -0
  15. package/dist/conformance/dsn.d.ts.map +1 -0
  16. package/dist/conformance/index.d.ts +3 -0
  17. package/dist/conformance/index.d.ts.map +1 -0
  18. package/dist/conformance/index.js +820 -0
  19. package/dist/conformance/index.js.map +18 -0
  20. package/dist/conformance/items.d.ts +4 -0
  21. package/dist/conformance/items.d.ts.map +1 -0
  22. package/dist/conformance/outcomes.d.ts +4 -0
  23. package/dist/conformance/outcomes.d.ts.map +1 -0
  24. package/dist/conformance/setup.d.ts +40 -0
  25. package/dist/conformance/setup.d.ts.map +1 -0
  26. package/dist/contract/checks.d.ts +4 -0
  27. package/dist/contract/checks.d.ts.map +1 -1
  28. package/dist/contract/queue-store.d.ts +15 -7
  29. package/dist/contract/queue-store.d.ts.map +1 -1
  30. package/dist/contract/types.d.ts +5 -0
  31. package/dist/contract/types.d.ts.map +1 -1
  32. package/dist/errors.d.ts +3 -1
  33. package/dist/errors.d.ts.map +1 -1
  34. package/dist/index.d.ts +1 -1
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +64 -26
  37. package/dist/index.js.map +4 -4
  38. package/dist/memory/index.js +10 -6
  39. package/dist/memory/index.js.map +3 -3
  40. package/dist/memory/store.d.ts +2 -2
  41. package/dist/memory/store.d.ts.map +1 -1
  42. package/dist/postgres/complete.d.ts +13 -0
  43. package/dist/postgres/complete.d.ts.map +1 -0
  44. package/dist/postgres/index.js +85 -74
  45. package/dist/postgres/index.js.map +6 -5
  46. package/dist/postgres/store.d.ts +2 -2
  47. package/dist/postgres/store.d.ts.map +1 -1
  48. package/dist/queue/deliver.d.ts.map +1 -1
  49. package/dist/queue/notify.d.ts +35 -6
  50. package/dist/queue/notify.d.ts.map +1 -1
  51. package/dist/redis/complete.d.ts +11 -0
  52. package/dist/redis/complete.d.ts.map +1 -0
  53. package/dist/redis/index.js +133 -110
  54. package/dist/redis/index.js.map +7 -6
  55. package/dist/redis/scripts.d.ts +8 -5
  56. package/dist/redis/scripts.d.ts.map +1 -1
  57. package/dist/redis/store.d.ts +2 -2
  58. package/dist/redis/store.d.ts.map +1 -1
  59. package/dist/sqlite/index.js +29 -20
  60. package/dist/sqlite/index.js.map +5 -4
  61. package/dist/sqlite/insert.d.ts +5 -0
  62. package/dist/sqlite/insert.d.ts.map +1 -0
  63. package/dist/sqlite/store.d.ts +2 -2
  64. package/dist/sqlite/store.d.ts.map +1 -1
  65. package/docs/guide.md +113 -2
  66. package/docs/roadmap.md +46 -12
  67. package/docs/troubleshooting.md +106 -1
  68. package/package.json +11 -5
@@ -0,0 +1,18 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/conformance/describe-queue-store.ts", "../src/conformance/claims.ts", "../src/conformance/setup.ts", "../src/conformance/concurrency.ts", "../src/conformance/items.ts", "../src/conformance/dsn.ts", "../src/conformance/outcomes.ts", "../src/conformance/complete-dsns.ts", "../src/conformance/doubt.ts"],
4
+ "sourcesContent": [
5
+ "import { afterEach, describe } from 'bun:test';\nimport type { QueueStore } from '../contract/queue-store';\nimport { describeClaims } from './claims';\nimport { describeConcurrency } from './concurrency';\nimport { describeItems } from './items';\nimport { describeOutcomes } from './outcomes';\nimport type { QueueStoreHarness } from './setup';\n\n/**\n * The specs every `QueueStore` must pass, to call from a spec file run by\n * `bun test`. The harness builds an empty store with `create`; `share` is\n * another handle on the same queue (a second connection, as a second\n * process opens), so the claim's atomicity is checked across handles, not\n * only within one: without it those tests are registered as skipped.\n * `dispose` runs after every test with the stores that test created.\n */\nexport function describeQueueStore(\n\tname: string,\n\tharness: QueueStoreHarness,\n): void {\n\tdescribe(`${name}: the QueueStore contract`, () => {\n\t\tconst created: QueueStore[] = [];\n\t\tconst factories = {\n\t\t\tshare: harness.share,\n\t\t\tcreate: async () => {\n\t\t\t\tconst store = await harness.create();\n\t\t\t\tcreated.push(store);\n\t\t\t\treturn store;\n\t\t\t},\n\t\t};\n\t\tafterEach(async () => {\n\t\t\tconst stores = created.splice(0);\n\t\t\tconst settled = await Promise.allSettled(\n\t\t\t\tstores.map(async (store) => harness.dispose?.(store)),\n\t\t\t);\n\t\t\tconst failed = settled.filter((r) => r.status === 'rejected');\n\t\t\tif (failed.length === 1) throw failed[0]?.reason;\n\t\t\tif (failed.length > 1)\n\t\t\t\tthrow new AggregateError(\n\t\t\t\t\tfailed.map((r) => r.reason),\n\t\t\t\t\t'several stores failed to dispose',\n\t\t\t\t);\n\t\t});\n\t\tdescribeItems(factories);\n\t\tdescribeClaims(factories);\n\t\tdescribeOutcomes(factories);\n\t\tdescribeConcurrency(factories);\n\t});\n}\n",
6
+ "import { describe, expect, test } from 'bun:test';\nimport type { AttemptResult } from '../contract/types';\nimport { entry, MINUTE, rejects, type StoreFactories, T0 } from './setup';\n\nconst lease = { leaseMs: 10 * MINUTE };\n\nconst result = (overrides: Partial<AttemptResult> = {}): AttemptResult => ({\n\tnow: T0 + MINUTE,\n\trecipients: [],\n\tnextAttemptAt: T0 + 30 * MINUTE,\n\tattempts: 1,\n\tdelayNotified: false,\n\t...overrides,\n});\n\n/** Claims, leases and schedules. */\nexport function describeClaims(factories: StoreFactories): void {\n\tdescribe('claims and leases', () => {\n\t\tclaiming(factories);\n\t\tleasing(factories);\n\t\trescheduling(factories);\n\t});\n}\n\nfunction claiming({ create }: StoreFactories): void {\n\ttest('claim takes a due item with a lease; nothing else is due', async () => {\n\t\tconst store = await create();\n\t\tconst item = await store.add(entry());\n\t\tconst claimed = await store.claim({ owner: 'w1', now: T0, ...lease });\n\t\texpect(claimed?.id).toBe(item.id);\n\t\texpect(claimed?.lease).toEqual({\n\t\t\towner: 'w1',\n\t\t\texpiresAt: T0 + 10 * MINUTE,\n\t\t});\n\t\texpect((await store.get(item.id))?.lease?.owner).toBe('w1');\n\t\texpect(\n\t\t\tawait store.claim({ owner: 'w2', now: T0, ...lease }),\n\t\t).toBeUndefined();\n\t});\n\n\ttest('an item not yet due is not claimed', async () => {\n\t\tconst store = await create();\n\t\tawait store.add(entry({ createdAt: T0 + MINUTE }));\n\t\texpect(\n\t\t\tawait store.claim({ owner: 'w1', now: T0, ...lease }),\n\t\t).toBeUndefined();\n\t\texpect(\n\t\t\tawait store.claim({ owner: 'w1', now: T0 + MINUTE, ...lease }),\n\t\t).toBeDefined();\n\t});\n\n\ttest('the earliest due is claimed first, then the oldest', async () => {\n\t\tconst store = await create();\n\t\tconst late = await store.add(entry({ createdAt: T0 + MINUTE }));\n\t\tconst first = await store.add(entry());\n\t\tconst second = await store.add(entry());\n\t\tconst now = T0 + MINUTE;\n\t\tconst order = [];\n\t\tfor (let i = 0; i < 3; i++) {\n\t\t\torder.push((await store.claim({ owner: 'w', now, ...lease }))?.id);\n\t\t}\n\t\texpect(order).toEqual([first.id, second.id, late.id]);\n\t});\n}\n\nfunction leasing({ create }: StoreFactories): void {\n\ttest('an expired lease is claimed again, and its old owner has lost it', async () => {\n\t\tconst store = await create();\n\t\tconst item = await store.add(entry());\n\t\tawait store.claim({ owner: 'crashed', now: T0, leaseMs: MINUTE });\n\t\texpect(\n\t\t\tawait store.claim({ owner: 'w2', now: T0 + MINUTE - 1, ...lease }),\n\t\t).toBeUndefined();\n\t\tconst again = await store.claim({\n\t\t\towner: 'w2',\n\t\t\tnow: T0 + MINUTE,\n\t\t\t...lease,\n\t\t});\n\t\texpect(again?.id).toBe(item.id);\n\t\texpect(again?.lease?.owner).toBe('w2');\n\t\texpect(await store.renew(item.id, 'crashed', T0 + 5 * MINUTE)).toBe(false);\n\t\texpect(\n\t\t\tawait store.complete(item.id, 'crashed', result(), []),\n\t\t).toBeUndefined();\n\t\texpect(await store.reschedule(item.id, T0, 'crashed')).toBe(false);\n\t\texpect((await store.get(item.id))?.lease?.owner).toBe('w2');\n\t});\n\n\ttest('renew moves the expiry while the owner holds the lease', async () => {\n\t\tconst store = await create();\n\t\tconst item = await store.add(entry());\n\t\tawait store.claim({ owner: 'w1', now: T0, leaseMs: MINUTE });\n\t\texpect(await store.renew(item.id, 'w1', T0 + 3 * MINUTE)).toBe(true);\n\t\texpect(\n\t\t\tawait store.claim({ owner: 'w2', now: T0 + 2 * MINUTE, ...lease }),\n\t\t).toBeUndefined();\n\t\texpect(await store.renew('nope', 'w1', T0)).toBe(false);\n\t});\n}\n\nfunction rescheduling({ create }: StoreFactories): void {\n\ttest('reschedule with the owner gives the item back, due at the new time', async () => {\n\t\tconst store = await create();\n\t\tconst item = await store.add(entry());\n\t\tawait store.claim({ owner: 'w1', now: T0, ...lease });\n\t\texpect(await store.reschedule(item.id, T0 + MINUTE, 'w2')).toBe(false);\n\t\texpect(await store.reschedule(item.id, T0 + MINUTE, 'w1')).toBe(true);\n\t\tconst stored = await store.get(item.id);\n\t\texpect(stored?.lease).toBeUndefined();\n\t\texpect(stored?.nextAttemptAt).toBe(T0 + MINUTE);\n\t\texpect(stored?.attempts).toBe(0);\n\t});\n\n\ttest('reschedule without an owner moves the time and leaves the lease alone', async () => {\n\t\tconst store = await create();\n\t\tconst item = await store.add(entry());\n\t\tawait store.claim({ owner: 'w1', now: T0, ...lease });\n\t\tawait store.complete(item.id, 'w1', result(), []);\n\t\texpect(await store.reschedule(item.id, T0 + MINUTE)).toBe(true);\n\t\texpect(\n\t\t\t(await store.claim({ owner: 'w2', now: T0 + MINUTE, ...lease }))?.id,\n\t\t).toBe(item.id);\n\t\texpect(await store.reschedule(item.id, T0)).toBe(true);\n\t\texpect((await store.get(item.id))?.lease?.owner).toBe('w2');\n\t});\n\n\ttest('claim refuses a bad request', async () => {\n\t\tconst store = await create();\n\t\tawait rejects(store.claim({ owner: '', now: T0, ...lease }), 'INVALID');\n\t\tawait rejects(store.claim({ owner: 'w', now: T0, leaseMs: 0 }), 'INVALID');\n\t\tawait rejects(\n\t\t\tstore.claim({ owner: 'w', now: Number.NaN, ...lease }),\n\t\t\t'INVALID',\n\t\t);\n\t\tawait rejects(store.reschedule('nope', T0, ''), 'INVALID');\n\t});\n}\n",
7
+ "import { expect } from 'bun:test';\nimport type { QueueStore } from '../contract/queue-store';\nimport type { AttemptResult, NewQueueItem } from '../contract/types';\n\n/** A new store, empty. */\nexport type CreateQueueStore = () => Promise<QueueStore> | QueueStore;\n\n/**\n * Another handle on the same queue as `store`: a second connection to the\n * same database, as a second process would open. A harness with no second\n * handle omits `share`, and the two several-workers tests are then skipped.\n */\nexport type ShareStore = (store: QueueStore) => QueueStore;\n\n/** What a store's spec hands the suite. */\nexport interface QueueStoreHarness {\n\t/** A new store, empty. */\n\treadonly create: CreateQueueStore;\n\t/** Another handle on the same queue; without it the share tests are skipped. */\n\treadonly share?: ShareStore | undefined;\n\t/**\n\t * Closes a store `create` made, after the test that used it. Handles\n\t * returned by `share` are the harness's to close.\n\t */\n\treadonly dispose?: ((store: QueueStore) => Promise<void> | void) | undefined;\n}\n\n/** What the suite is handed: how to build a store, and what the harness can do beyond that. */\nexport interface StoreFactories {\n\treadonly create: CreateQueueStore;\n\t/** Absent when the harness has no second handle: the share tests are skipped. */\n\treadonly share?: ShareStore | undefined;\n}\n\nexport const bytes = (text: string) => new TextEncoder().encode(text);\n\nexport const T0 = Date.UTC(2026, 9, 1, 12);\nexport const MINUTE = 60_000;\n\nexport const lease = { leaseMs: 10 * MINUTE };\n\nexport const result = (\n\toverrides: Partial<AttemptResult> = {},\n): AttemptResult => ({\n\tnow: T0 + MINUTE,\n\trecipients: [],\n\tnextAttemptAt: T0 + 30 * MINUTE,\n\tattempts: 1,\n\tdelayNotified: false,\n\t...overrides,\n});\n\n/** A new item from mary to two recipients, created at `T0` unless told otherwise. */\nexport function entry(overrides: Partial<NewQueueItem> = {}): NewQueueItem {\n\treturn {\n\t\tfrom: 'mary@example.net',\n\t\tto: ['joe@example.com', 'ann@example.org'],\n\t\tmessage: bytes('Subject: Hi\\r\\n\\r\\nHello\\r\\n'),\n\t\tcreatedAt: T0,\n\t\t...overrides,\n\t};\n}\n\n/** Expects a promise to reject with a QueueError of this code. */\nexport async function rejects(promise: Promise<unknown>, code: string) {\n\tawait expect(promise).rejects.toMatchObject({ name: 'QueueError', code });\n}\n",
8
+ "import { describe, expect, test } from 'bun:test';\nimport type { QueueStore } from '../contract/queue-store';\nimport { entry, MINUTE, type StoreFactories, T0 } from './setup';\n\nconst delivered = (now: number) => ({\n\tnow,\n\trecipients: [\n\t\t{ address: 'joe@example.com', status: 'delivered' as const },\n\t\t{ address: 'ann@example.org', status: 'delivered' as const },\n\t],\n\tnextAttemptAt: now,\n\tattempts: 1,\n\tdelayNotified: false,\n});\n\n/** A worker: claims and delivers until nothing is due, yielding between steps. */\nasync function work(store: QueueStore, owner: string, now: number) {\n\tconst taken: string[] = [];\n\tfor (;;) {\n\t\tawait new Promise((resolve) => setTimeout(resolve, Math.random() * 2));\n\t\tconst item = await store.claim({ owner, now, leaseMs: 10 * MINUTE });\n\t\tif (!item) return taken;\n\t\ttaken.push(item.id);\n\t\tawait new Promise((resolve) => setTimeout(resolve, Math.random() * 2));\n\t\tconst done = await store.complete(item.id, owner, delivered(now), []);\n\t\texpect(done).toBeDefined();\n\t}\n}\n\n/** Several claimers on one queue, and a claimer that crashed. */\nexport function describeConcurrency({ create, share }: StoreFactories): void {\n\t// A harness with no second handle cannot prove atomicity across handles:\n\t// the test is registered as skipped, with the reason in its name.\n\tconst shared = share ? test : test.skip;\n\tconst note = share ? '' : ' (skipped: harness has no share)';\n\tdescribe('several workers', () => {\n\t\tshared(\n\t\t\t`many claimers race: every item is delivered once${note}`,\n\t\t\tasync () => {\n\t\t\t\tconst store = await create();\n\t\t\t\tconst ids = new Set<string>();\n\t\t\t\tfor (let i = 0; i < 60; i++) ids.add((await store.add(entry())).id);\n\t\t\t\tconst workers = Array.from({ length: 8 }, (_, i) =>\n\t\t\t\t\twork(share?.(store) ?? store, `w${i}`, T0),\n\t\t\t\t);\n\t\t\t\tconst taken = (await Promise.all(workers)).flat();\n\t\t\t\texpect(taken.length).toBe(60);\n\t\t\t\texpect(new Set(taken)).toEqual(ids);\n\t\t\t\texpect(await store.count()).toBe(0);\n\t\t\t},\n\t\t);\n\n\t\tshared(\n\t\t\t`a crashed worker’s items are claimed again once its leases expire${note}`,\n\t\t\tasync () => {\n\t\t\t\tconst store = await create();\n\t\t\t\tfor (let i = 0; i < 5; i++) await store.add(entry());\n\t\t\t\tconst crashed: string[] = [];\n\t\t\t\tfor (let i = 0; i < 5; i++) {\n\t\t\t\t\tconst item = await store.claim({\n\t\t\t\t\t\towner: 'crashed',\n\t\t\t\t\t\tnow: T0,\n\t\t\t\t\t\tleaseMs: MINUTE,\n\t\t\t\t\t});\n\t\t\t\t\tif (item) crashed.push(item.id);\n\t\t\t\t}\n\t\t\t\texpect(crashed.length).toBe(5);\n\t\t\t\tconst other = share?.(store) ?? store;\n\t\t\t\texpect(await work(other, 'w2', T0 + MINUTE - 1)).toEqual([]);\n\t\t\t\tconst recovered = await work(other, 'w2', T0 + MINUTE);\n\t\t\t\texpect(new Set(recovered)).toEqual(new Set(crashed));\n\t\t\t\tfor (const id of crashed) {\n\t\t\t\t\texpect(\n\t\t\t\t\t\tawait store.complete(id, 'crashed', delivered(T0), []),\n\t\t\t\t\t).toBeUndefined();\n\t\t\t\t}\n\t\t\t\texpect(await store.count()).toBe(0);\n\t\t\t},\n\t\t);\n\t});\n}\n",
9
+ "import { describe, expect, test } from 'bun:test';\nimport { dsnParameters } from './dsn';\nimport {\n\tbytes,\n\tentry,\n\tMINUTE,\n\trejects,\n\ttype StoreFactories,\n\tT0,\n} from './setup';\n\n/** Adding, reading, listing and cancelling items. */\nexport function describeItems(factories: StoreFactories): void {\n\tdescribe('items', () => {\n\t\tadding(factories);\n\t\tlisting(factories);\n\t\tdsnParameters(factories);\n\t});\n}\n\nfunction adding({ create }: StoreFactories): void {\n\ttest('add keeps the envelope, every recipient pending, due at once', async () => {\n\t\tconst store = await create();\n\t\tconst item = await store.add(entry());\n\t\texpect(item).toMatchObject({\n\t\t\tfrom: 'mary@example.net',\n\t\t\trecipients: [\n\t\t\t\t{ address: 'joe@example.com', status: 'pending' },\n\t\t\t\t{ address: 'ann@example.org', status: 'pending' },\n\t\t\t],\n\t\t\tsize: 22,\n\t\t\tcreatedAt: T0,\n\t\t\tnextAttemptAt: T0,\n\t\t\tattempts: 0,\n\t\t\tdelayNotified: false,\n\t\t});\n\t\texpect(item.lease).toBeUndefined();\n\t\texpect(await store.get(item.id)).toEqual(item);\n\t\texpect(await store.count()).toBe(1);\n\t});\n\n\ttest('the null sender is kept as the empty string', async () => {\n\t\tconst store = await create();\n\t\tconst item = await store.add(entry({ from: '' }));\n\t\texpect((await store.get(item.id))?.from).toBe('');\n\t});\n\n\ttest('readMessage gives the bytes back, a copy each time', async () => {\n\t\tconst store = await create();\n\t\tconst message = bytes('Subject: x\\r\\n\\r\\nbody\\r\\n');\n\t\tconst item = await store.add(entry({ message }));\n\t\tmessage[0] = 0;\n\t\tconst read = await store.readMessage(item.id);\n\t\texpect(new TextDecoder().decode(read)).toBe('Subject: x\\r\\n\\r\\nbody\\r\\n');\n\t\tif (read) read[0] = 0;\n\t\texpect((await store.readMessage(item.id))?.[0]).toBe(83);\n\t});\n\n\ttest('an item returned is a copy', async () => {\n\t\tconst store = await create();\n\t\tconst item = await store.add(entry());\n\t\tconst first = (item.recipients as unknown as { status: string }[])[0];\n\t\tif (first) first.status = 'failed';\n\t\texpect((await store.get(item.id))?.recipients[0]?.status).toBe('pending');\n\t});\n\n\ttest('an unknown id is undefined, not an error', async () => {\n\t\tconst store = await create();\n\t\texpect(await store.get('nope')).toBeUndefined();\n\t\texpect(await store.readMessage('nope')).toBeUndefined();\n\t\texpect(await store.cancel('nope')).toBeUndefined();\n\t\texpect(await store.reschedule('nope', T0)).toBe(false);\n\t});\n\n\ttest('an id no store could hold, a NUL or a lone surrogate in it, is unknown too', async () => {\n\t\tconst store = await create();\n\t\tawait store.add(entry());\n\t\tfor (const id of ['a\\u0000b', 'a\\ud83d']) {\n\t\t\texpect(await store.get(id)).toBeUndefined();\n\t\t\texpect(await store.readMessage(id)).toBeUndefined();\n\t\t\texpect(await store.renew(id, 'w1', T0)).toBe(false);\n\t\t\texpect(await store.reschedule(id, T0)).toBe(false);\n\t\t\texpect(await store.cancel(id)).toBeUndefined();\n\t\t}\n\t\texpect(await store.count()).toBe(1);\n\t});\n}\n\nfunction listing({ create }: StoreFactories): void {\n\ttest('list gives the next due first, then the oldest, a page at a time', async () => {\n\t\tconst store = await create();\n\t\tconst a = await store.add(entry({ createdAt: T0 + 2 * MINUTE }));\n\t\tconst b = await store.add(entry({ createdAt: T0 }));\n\t\tconst c = await store.add(entry({ createdAt: T0 }));\n\t\tconst ids = (await store.list()).map((i) => i.id);\n\t\texpect(ids).toEqual([b.id, c.id, a.id]);\n\t\tconst page = await store.list({ offset: 1, limit: 1 });\n\t\texpect(page.map((i) => i.id)).toEqual([c.id]);\n\t});\n\n\ttest('list refuses a bad page', async () => {\n\t\tconst store = await create();\n\t\tawait rejects(store.list({ limit: 0 }), 'INVALID');\n\t\tawait rejects(store.list({ offset: -1 }), 'INVALID');\n\t});\n\n\ttest('cancel drops the item and its message, leased or not', async () => {\n\t\tconst store = await create();\n\t\tconst item = await store.add(entry());\n\t\tawait store.claim({ owner: 'w1', now: T0, leaseMs: MINUTE });\n\t\tconst cancelled = await store.cancel(item.id);\n\t\texpect(cancelled?.id).toBe(item.id);\n\t\texpect(await store.get(item.id)).toBeUndefined();\n\t\texpect(await store.readMessage(item.id)).toBeUndefined();\n\t\texpect(await store.count()).toBe(0);\n\t});\n\n\ttest('maxItems refuses an add past the limit with QUEUE_FULL', async () => {\n\t\tconst store = await create();\n\t\tawait store.add(entry(), { maxItems: 2 });\n\t\tawait store.add(entry(), { maxItems: 2 });\n\t\tawait rejects(store.add(entry(), { maxItems: 2 }), 'QUEUE_FULL');\n\t\texpect(await store.count()).toBe(2);\n\t\tawait rejects(store.add(entry(), { maxItems: 0 }), 'INVALID');\n\t});\n\n\ttest('add refuses what is not an item', async () => {\n\t\tconst store = await create();\n\t\tawait rejects(store.add(entry({ to: [] })), 'INVALID');\n\t\tawait rejects(\n\t\t\tstore.add(entry({ message: 'text' as unknown as Uint8Array })),\n\t\t\t'INVALID',\n\t\t);\n\t\tawait rejects(store.add(entry({ createdAt: Number.NaN })), 'INVALID');\n\t\tawait rejects(store.add(entry({ from: 'a\\u0000@example.net' })), 'INVALID');\n\t\tawait rejects(\n\t\t\tstore.add(entry({ to: ['jo\\ud83d@example.com'] })),\n\t\t\t'INVALID',\n\t\t);\n\t\texpect(await store.count()).toBe(0);\n\t});\n}\n",
10
+ "import { expect, test } from 'bun:test';\nimport {\n\tentry,\n\tlease,\n\trejects,\n\tresult,\n\ttype StoreFactories,\n\tT0,\n} from './setup';\n\n/** RFC 3461's parameters: kept as given, for the item's whole life. */\nexport function dsnParameters({ create }: StoreFactories): void {\n\tconst asked = {\n\t\tret: 'HDRS' as const,\n\t\tenvid: 'QQ314159 + x=',\n\t\trecipients: [\n\t\t\t{\n\t\t\t\taddress: 'joe@example.com',\n\t\t\t\tnotify: ['SUCCESS', 'DELAY'] as ('SUCCESS' | 'DELAY')[],\n\t\t\t\torcpt: { type: 'rfc822', address: 'Joe.Original@example.com' },\n\t\t\t},\n\t\t\t{ address: 'ann@example.org', notify: 'NEVER' as const },\n\t\t],\n\t};\n\n\ttest('RFC 3461 §4: ret, envid, notify and orcpt are kept by add, get, list and claim', async () => {\n\t\tconst store = await create();\n\t\tconst item = await store.add(entry(asked));\n\t\tconst kept = {\n\t\t\tret: 'HDRS',\n\t\t\tenvid: 'QQ314159 + x=',\n\t\t\trecipients: [\n\t\t\t\t{\n\t\t\t\t\taddress: 'joe@example.com',\n\t\t\t\t\tnotify: ['SUCCESS', 'DELAY'],\n\t\t\t\t\torcpt: { type: 'rfc822', address: 'Joe.Original@example.com' },\n\t\t\t\t},\n\t\t\t\t{ address: 'ann@example.org', notify: 'NEVER' },\n\t\t\t],\n\t\t};\n\t\texpect(item).toMatchObject(kept);\n\t\texpect(await store.get(item.id)).toEqual(item);\n\t\texpect((await store.list())[0]).toEqual(item);\n\t\texpect(await store.claim({ owner: 'w1', now: T0, ...lease })).toMatchObject(\n\t\t\tkept,\n\t\t);\n\t});\n\n\ttest('complete keeps them: the notify and orcpt of a deferred recipient, and the item level', async () => {\n\t\tconst store = await create();\n\t\tconst item = await store.add(entry(asked));\n\t\tawait store.claim({ owner: 'w1', now: T0, ...lease });\n\t\tconst done = await store.complete(\n\t\t\titem.id,\n\t\t\t'w1',\n\t\t\tresult({\n\t\t\t\trecipients: [\n\t\t\t\t\t{\n\t\t\t\t\t\taddress: 'joe@example.com',\n\t\t\t\t\t\tstatus: 'deferred',\n\t\t\t\t\t\treply: { text: 'try later' },\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t}),\n\t\t\t[],\n\t\t);\n\t\texpect(done?.item.recipients[0]).toMatchObject({\n\t\t\tnotify: ['SUCCESS', 'DELAY'],\n\t\t\torcpt: { type: 'rfc822', address: 'Joe.Original@example.com' },\n\t\t});\n\t\tconst again = await store.get(item.id);\n\t\texpect(again?.ret).toBe('HDRS');\n\t\texpect(again?.envid).toBe('QQ314159 + x=');\n\t\texpect(again?.recipients[1]?.notify).toBe('NEVER');\n\t});\n\n\ttest('an item added with none carries none: the fields are absent, as before', async () => {\n\t\tconst store = await create();\n\t\tconst item = await store.add(entry());\n\t\tconst read = await store.get(item.id);\n\t\tfor (const key of ['ret', 'envid'] as const) {\n\t\t\texpect(read).not.toHaveProperty(key);\n\t\t}\n\t\tfor (const r of read?.recipients ?? []) {\n\t\t\texpect(r).not.toHaveProperty('notify');\n\t\t\texpect(r).not.toHaveProperty('orcpt');\n\t\t}\n\t});\n\n\ttest('RFC 6533: 50 emoji in a utf-8 ORCPT are within 500 characters, as the server counts them', async () => {\n\t\tconst store = await create();\n\t\tconst orcpt = { type: 'utf-8', address: `${'😀'.repeat(50)}@x` };\n\t\tconst item = await store.add(\n\t\t\tentry({ recipients: [{ address: 'joe@example.com', orcpt }] }),\n\t\t);\n\t\texpect(item.recipients[0]?.orcpt).toEqual(orcpt);\n\t\tawait expect(\n\t\t\tstore.add(\n\t\t\t\tentry({\n\t\t\t\t\trecipients: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taddress: 'joe@example.com',\n\t\t\t\t\t\t\torcpt: { type: 'rfc822', address: orcpt.address },\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t}),\n\t\t\t),\n\t\t).rejects.toMatchObject({ code: 'INVALID' });\n\t});\n\n\ttest('RFC 6533: a utf-8 ORCPT of 500 characters (82 escapes) is kept, 506 is INVALID', async () => {\n\t\tconst store = await create();\n\t\tconst orcpt = (n: number) => ({\n\t\t\ttype: 'utf-8',\n\t\t\taddress: `${'+'.repeat(n)}@x`,\n\t\t});\n\t\tconst item = await store.add(\n\t\t\tentry({ recipients: [{ address: 'joe@example.com', orcpt: orcpt(82) }] }),\n\t\t);\n\t\texpect(item.recipients[0]?.orcpt).toEqual(orcpt(82));\n\t\tawait rejects(\n\t\t\tstore.add(\n\t\t\t\tentry({\n\t\t\t\t\trecipients: [{ address: 'joe@example.com', orcpt: orcpt(83) }],\n\t\t\t\t}),\n\t\t\t),\n\t\t\t'INVALID',\n\t\t);\n\t});\n\n\ttest('what is not a parameter is INVALID, the same for every store', async () => {\n\t\tconst store = await create();\n\t\tconst bad: Record<string, unknown>[] = [\n\t\t\t{ ret: 'ALL' },\n\t\t\t{ envid: '' },\n\t\t\t{ envid: 'a\\r\\nb' },\n\t\t\t{ envid: 'x'.repeat(101) },\n\t\t\t{ recipients: [{ address: 'zed@example.com', notify: 'NEVER' }] },\n\t\t\t{ recipients: [{ address: 'joe@example.com', notify: 'SOMETIMES' }] },\n\t\t\t{ recipients: [{ address: 'joe@example.com', notify: [] }] },\n\t\t\t{\n\t\t\t\trecipients: [\n\t\t\t\t\t{ address: 'joe@example.com', notify: ['DELAY', 'DELAY'] },\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\trecipients: [{ address: 'joe@example.com', orcpt: { type: 'rfc822' } }],\n\t\t\t},\n\t\t\t{\n\t\t\t\trecipients: [\n\t\t\t\t\t{ address: 'joe@example.com' },\n\t\t\t\t\t{ address: 'joe@example.com' },\n\t\t\t\t],\n\t\t\t},\n\t\t];\n\t\tfor (const params of bad) {\n\t\t\tawait rejects(store.add(entry(params as never)), 'INVALID');\n\t\t}\n\t\texpect(await store.count()).toBe(0);\n\t});\n}\n",
11
+ "import { describe, expect, test } from 'bun:test';\nimport { completeDsns } from './complete-dsns';\nimport { doubt, fallbackDoubt } from './doubt';\nimport {\n\tentry,\n\tlease,\n\tMINUTE,\n\trejects,\n\tresult,\n\ttype StoreFactories,\n\tT0,\n} from './setup';\n\n/** What `complete` records. */\nexport function describeOutcomes(factories: StoreFactories): void {\n\tdescribe('outcomes', () => {\n\t\trecording(factories);\n\t\trefusing(factories);\n\t\tfinality(factories);\n\t\tcompleteDsns(factories);\n\t\tdoubt(factories);\n\t\tfallbackDoubt(factories);\n\t});\n}\n\nfunction recording({ create }: StoreFactories): void {\n\ttest('complete records each outcome, the schedule, and lets go of the lease', async () => {\n\t\tconst store = await create();\n\t\tconst item = await store.add(entry());\n\t\tawait store.claim({ owner: 'w1', now: T0, ...lease });\n\t\tconst reply = {\n\t\t\tcode: 451,\n\t\t\tstatus: '4.3.0',\n\t\t\ttext: 'try later',\n\t\t\thost: 'mx.example.com',\n\t\t};\n\t\tconst done = await store.complete(\n\t\t\titem.id,\n\t\t\t'w1',\n\t\t\tresult({\n\t\t\t\trecipients: [{ address: 'joe@example.com', status: 'deferred', reply }],\n\t\t\t}),\n\t\t\t[],\n\t\t);\n\t\texpect(done?.item.recipients).toEqual([\n\t\t\t{\n\t\t\t\taddress: 'joe@example.com',\n\t\t\t\tstatus: 'deferred',\n\t\t\t\treply,\n\t\t\t\tupdatedAt: T0 + MINUTE,\n\t\t\t},\n\t\t\t{ address: 'ann@example.org', status: 'pending' },\n\t\t]);\n\t\tconst stored = await store.get(item.id);\n\t\texpect(stored).toEqual(done?.item);\n\t\texpect(stored).toMatchObject({\n\t\t\tnextAttemptAt: T0 + 30 * MINUTE,\n\t\t\tattempts: 1,\n\t\t});\n\t\texpect(stored?.lease).toBeUndefined();\n\t\texpect(\n\t\t\tawait store.claim({ owner: 'w2', now: T0 + 29 * MINUTE, ...lease }),\n\t\t).toBeUndefined();\n\t\texpect(\n\t\t\tawait store.claim({ owner: 'w2', now: T0 + 30 * MINUTE, ...lease }),\n\t\t).toBeDefined();\n\t});\n\n\ttest('an item whose every recipient is final is dropped with its message', async () => {\n\t\tconst store = await create();\n\t\tconst item = await store.add(entry());\n\t\tawait store.claim({ owner: 'w1', now: T0, ...lease });\n\t\tconst done = await store.complete(\n\t\t\titem.id,\n\t\t\t'w1',\n\t\t\tresult({\n\t\t\t\trecipients: [\n\t\t\t\t\t{\n\t\t\t\t\t\taddress: 'joe@example.com',\n\t\t\t\t\t\tstatus: 'delivered',\n\t\t\t\t\t\treply: { code: 250, text: 'ok' },\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\taddress: 'ann@example.org',\n\t\t\t\t\t\tstatus: 'failed',\n\t\t\t\t\t\treply: { code: 550, text: 'no' },\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdelayNotified: true,\n\t\t\t}),\n\t\t\t[],\n\t\t);\n\t\texpect(done?.item.recipients.map((r) => r.status)).toEqual([\n\t\t\t'delivered',\n\t\t\t'failed',\n\t\t]);\n\t\texpect(done?.item.delayNotified).toBe(true);\n\t\texpect(await store.get(item.id)).toBeUndefined();\n\t\texpect(await store.readMessage(item.id)).toBeUndefined();\n\t\texpect(await store.count()).toBe(0);\n\t});\n}\n\nfunction refusing({ create }: StoreFactories): void {\n\ttest('an outcome holding a NUL or a lone surrogate is refused, and the item stays as it was', async () => {\n\t\tconst store = await create();\n\t\tconst item = await store.add(entry());\n\t\tawait store.claim({ owner: 'w1', now: T0, ...lease });\n\t\tconst bad = [\n\t\t\t{ code: 451, text: `${'a'.repeat(8)}\\ud83d` },\n\t\t\t{ code: 451, text: 'nul \\u0000 here' },\n\t\t\t{ code: 451, text: 'ok', host: 'mx\\udc00.example.com' },\n\t\t\t{ code: 451, status: '4.3.0\\u0000', text: 'ok' },\n\t\t];\n\t\tfor (const reply of bad) {\n\t\t\tawait rejects(\n\t\t\t\tstore.complete(\n\t\t\t\t\titem.id,\n\t\t\t\t\t'w1',\n\t\t\t\t\tresult({\n\t\t\t\t\t\trecipients: [\n\t\t\t\t\t\t\t{ address: 'joe@example.com', status: 'deferred', reply },\n\t\t\t\t\t\t],\n\t\t\t\t\t}),\n\t\t\t\t\t[],\n\t\t\t\t),\n\t\t\t\t'INVALID',\n\t\t\t);\n\t\t}\n\t\tawait rejects(\n\t\t\tstore.claim({ owner: 'w\\ud800', now: T0, ...lease }),\n\t\t\t'INVALID',\n\t\t);\n\t\tconst stored = await store.get(item.id);\n\t\texpect(stored?.attempts).toBe(0);\n\t\texpect(stored?.lease?.owner).toBe('w1');\n\t\tconst done = await store.complete(\n\t\t\titem.id,\n\t\t\t'w1',\n\t\t\tresult({\n\t\t\t\trecipients: [\n\t\t\t\t\t{\n\t\t\t\t\t\taddress: 'joe@example.com',\n\t\t\t\t\t\tstatus: 'deferred',\n\t\t\t\t\t\treply: { code: 451, text: 'Try later 😀' },\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t}),\n\t\t\t[],\n\t\t);\n\t\texpect(done?.item.recipients[0]?.reply?.text).toBe('Try later 😀');\n\t\texpect((await store.get(item.id))?.recipients[0]?.reply?.text).toBe(\n\t\t\t'Try later 😀',\n\t\t);\n\t});\n}\n\nfunction finality({ create }: StoreFactories): void {\n\ttest('a final state is never changed by a later outcome', async () => {\n\t\tconst store = await create();\n\t\tconst item = await store.add(entry());\n\t\tawait store.claim({ owner: 'w1', now: T0, ...lease });\n\t\tawait store.complete(\n\t\t\titem.id,\n\t\t\t'w1',\n\t\t\tresult({\n\t\t\t\trecipients: [{ address: 'joe@example.com', status: 'delivered' }],\n\t\t\t}),\n\t\t\t[],\n\t\t);\n\t\tawait store.claim({ owner: 'w1', now: T0 + 30 * MINUTE, ...lease });\n\t\tconst after = await store.complete(\n\t\t\titem.id,\n\t\t\t'w1',\n\t\t\tresult({\n\t\t\t\trecipients: [{ address: 'joe@example.com', status: 'failed' }],\n\t\t\t\tattempts: 2,\n\t\t\t}),\n\t\t\t[],\n\t\t);\n\t\texpect(after?.item.recipients[0]?.status).toBe('delivered');\n\t});\n}\n",
12
+ "import { expect, test } from 'bun:test';\nimport type { NewQueueItem } from '../contract/types';\nimport {\n\tbytes,\n\tentry,\n\tlease,\n\tMINUTE,\n\trejects,\n\tresult,\n\ttype StoreFactories,\n\tT0,\n} from './setup';\n\nconst dsn = (text: string): NewQueueItem =>\n\tentry({\n\t\tfrom: '',\n\t\tto: ['mary@example.net'],\n\t\tmessage: bytes(`Subject: ${text}\\r\\n\\r\\n${text}\\r\\n`),\n\t});\n\nconst delivered = result({\n\trecipients: [\n\t\t{ address: 'joe@example.com', status: 'delivered' },\n\t\t{ address: 'ann@example.org', status: 'failed' },\n\t],\n});\n\n/** The DSNs `complete` takes: stored with the outcome, or not at all. */\nexport function completeDsns(factories: StoreFactories): void {\n\tstored(factories);\n\tleaseHeld(factories);\n\trefused(factories);\n\tnotFinal(factories);\n}\n\nfunction stored({ create }: StoreFactories): void {\n\ttest('complete stores its DSNs with the outcome: new ids, in the order given, due at once', async () => {\n\t\tconst store = await create();\n\t\tconst item = await store.add(entry());\n\t\tawait store.claim({ owner: 'w1', now: T0, ...lease });\n\t\tconst done = await store.complete(item.id, 'w1', delivered, [\n\t\t\tdsn('failed'),\n\t\t\tdsn('relayed'),\n\t\t]);\n\t\texpect(done?.item.id).toBe(item.id);\n\t\texpect(done?.dsns).toHaveLength(2);\n\t\tconst [first, second] = done?.dsns ?? [];\n\t\texpect(first?.id).not.toBe(second?.id);\n\t\texpect([first?.id, second?.id]).not.toContain(item.id);\n\t\texpect(first).toMatchObject({ from: '', attempts: 0 });\n\t\texpect(await store.get(item.id)).toBeUndefined();\n\t\tfor (const [kept, subject] of [\n\t\t\t[first, 'failed'],\n\t\t\t[second, 'relayed'],\n\t\t] as const) {\n\t\t\texpect(await store.get(kept?.id ?? '')).toEqual(kept);\n\t\t\texpect(\n\t\t\t\tnew TextDecoder().decode(await store.readMessage(kept?.id ?? '')),\n\t\t\t).toContain(`Subject: ${subject}`);\n\t\t}\n\t\t// Due at once, the first stored first.\n\t\texpect(\n\t\t\t(await store.claim({ owner: 'w2', now: T0 + MINUTE, ...lease }))?.id,\n\t\t).toBe(first?.id);\n\t\texpect(await store.count()).toBe(2);\n\t});\n}\n\nfunction leaseHeld({ create }: StoreFactories): void {\n\ttest('complete by an owner that no longer holds the lease stores no DSN, and a second one by the first stores none twice', async () => {\n\t\tconst store = await create();\n\t\tconst item = await store.add(entry());\n\t\tawait store.claim({ owner: 'w1', now: T0, ...lease });\n\t\texpect(\n\t\t\tawait store.complete(item.id, 'w2', delivered, [dsn('failed')]),\n\t\t).toBeUndefined();\n\t\texpect(await store.count()).toBe(1);\n\t\texpect(\n\t\t\tawait store.complete(item.id, 'w1', delivered, [dsn('failed')]),\n\t\t).toBeDefined();\n\t\texpect(await store.count()).toBe(1);\n\t\texpect(\n\t\t\tawait store.complete(item.id, 'w1', delivered, [dsn('failed')]),\n\t\t).toBeUndefined();\n\t\texpect(await store.count()).toBe(1);\n\t});\n}\n\nfunction refused({ create }: StoreFactories): void {\n\ttest('a DSN that fails the checks of add refuses the whole call with INVALID: no outcome, no DSN', async () => {\n\t\tconst store = await create();\n\t\tconst item = await store.add(entry());\n\t\tawait store.claim({ owner: 'w1', now: T0, ...lease });\n\t\tawait rejects(\n\t\t\tstore.complete(item.id, 'w1', delivered, [\n\t\t\t\tdsn('failed'),\n\t\t\t\t{ ...dsn('bad'), to: [] },\n\t\t\t]),\n\t\t\t'INVALID',\n\t\t);\n\t\texpect(await store.count()).toBe(1);\n\t\texpect(await store.get(item.id)).toMatchObject({\n\t\t\tattempts: 0,\n\t\t\tlease: { owner: 'w1' },\n\t\t});\n\t});\n\n\ttest('dsns that are not an array refuse the call with INVALID, nothing recorded', async () => {\n\t\tconst store = await create();\n\t\tconst item = await store.add(entry());\n\t\tawait store.claim({ owner: 'w1', now: T0, ...lease });\n\t\tawait rejects(\n\t\t\tstore.complete(item.id, 'w1', delivered, undefined as never),\n\t\t\t'INVALID',\n\t\t);\n\t\texpect(await store.get(item.id)).toMatchObject({ attempts: 0 });\n\t});\n}\n\nfunction notFinal({ create }: StoreFactories): void {\n\ttest('complete with no DSN returns an empty list; a not-final item stays with its DSNs beside it', async () => {\n\t\tconst store = await create();\n\t\tconst item = await store.add(entry());\n\t\tawait store.claim({ owner: 'w1', now: T0, ...lease });\n\t\tconst none = await store.complete(item.id, 'w1', result(), []);\n\t\texpect(none?.dsns).toEqual([]);\n\t\tawait store.claim({ owner: 'w1', now: T0 + 30 * MINUTE, ...lease });\n\t\tconst deferred = result({\n\t\t\trecipients: [{ address: 'joe@example.com', status: 'deferred' }],\n\t\t\tattempts: 2,\n\t\t\tdelayNotified: true,\n\t\t});\n\t\tconst done = await store.complete(item.id, 'w1', deferred, [\n\t\t\tdsn('delayed'),\n\t\t]);\n\t\texpect(done?.item.delayNotified).toBe(true);\n\t\texpect(done?.dsns).toHaveLength(1);\n\t\texpect(await store.count()).toBe(2);\n\t\texpect(await store.get(item.id)).toEqual(done?.item);\n\t});\n}\n",
13
+ "import { expect, test } from 'bun:test';\nimport type { AttemptResult } from '../contract/types';\nimport {\n\tentry,\n\tlease,\n\tMINUTE,\n\trejects,\n\tresult,\n\ttype StoreFactories,\n\tT0,\n} from './setup';\n\n/** The marks a recipient keeps when a server may hold a copy. */\nexport function doubt({ create }: StoreFactories): void {\n\tconst deferred = (mayHaveReachedMx?: unknown) =>\n\t\t({\n\t\t\taddress: 'joe@example.com',\n\t\t\tstatus: 'deferred',\n\t\t\treply: { status: '4.4.2', text: 'no reply to the final dot' },\n\t\t\t...(mayHaveReachedMx === undefined ? {} : { mayHaveReachedMx }),\n\t\t}) as AttemptResult['recipients'][number];\n\n\ttest('mayHaveReachedMx: recorded, read by get and list, and kept by a later outcome without it', async () => {\n\t\tconst store = await create();\n\t\tconst item = await store.add(entry());\n\t\tawait store.claim({ owner: 'w1', now: T0, ...lease });\n\t\tconst done = await store.complete(\n\t\t\titem.id,\n\t\t\t'w1',\n\t\t\tresult({ recipients: [deferred(true)] }),\n\t\t\t[],\n\t\t);\n\t\texpect(done?.item.recipients[0]?.mayHaveReachedMx).toBe(true);\n\t\texpect(done?.item.recipients[1]).not.toHaveProperty('mayHaveReachedMx');\n\t\texpect((await store.get(item.id))?.recipients[0]?.mayHaveReachedMx).toBe(\n\t\t\ttrue,\n\t\t);\n\t\texpect((await store.list())[0]?.recipients[0]?.mayHaveReachedMx).toBe(true);\n\t\tawait store.claim({ owner: 'w1', now: T0 + 30 * MINUTE, ...lease });\n\t\tconst again = await store.complete(\n\t\t\titem.id,\n\t\t\t'w1',\n\t\t\tresult({ recipients: [deferred()], attempts: 2 }),\n\t\t\t[],\n\t\t);\n\t\texpect(again?.item.recipients[0]?.mayHaveReachedMx).toBe(true);\n\t\texpect((await store.get(item.id))?.recipients[0]?.mayHaveReachedMx).toBe(\n\t\t\ttrue,\n\t\t);\n\t});\n\n\ttest('mayHaveReachedMx: an unmarked recipient has no such key', async () => {\n\t\tconst store = await create();\n\t\tconst item = await store.add(entry());\n\t\tawait store.claim({ owner: 'w1', now: T0, ...lease });\n\t\tawait store.complete(\n\t\t\titem.id,\n\t\t\t'w1',\n\t\t\tresult({ recipients: [deferred()] }),\n\t\t\t[],\n\t\t);\n\t\tfor (const r of (await store.get(item.id))?.recipients ?? []) {\n\t\t\texpect(r).not.toHaveProperty('mayHaveReachedMx');\n\t\t}\n\t});\n\n\ttest('mayHaveReachedMx: a value other than true is INVALID, and the item stays as it was', async () => {\n\t\tconst store = await create();\n\t\tconst item = await store.add(entry());\n\t\tawait store.claim({ owner: 'w1', now: T0, ...lease });\n\t\tfor (const bad of [false, 'true', 1, null]) {\n\t\t\tawait rejects(\n\t\t\t\tstore.complete(\n\t\t\t\t\titem.id,\n\t\t\t\t\t'w1',\n\t\t\t\t\tresult({ recipients: [deferred(bad)] }),\n\t\t\t\t\t[],\n\t\t\t\t),\n\t\t\t\t'INVALID',\n\t\t\t);\n\t\t}\n\t\tconst kept = await store.get(item.id);\n\t\texpect(kept?.recipients[0]?.status).toBe('pending');\n\t\texpect(kept?.lease?.owner).toBe('w1');\n\t});\n}\n\nexport function fallbackDoubt({ create }: StoreFactories): void {\n\tconst deferred = (mayHaveReachedFallback?: unknown) =>\n\t\t({\n\t\t\taddress: 'joe@example.com',\n\t\t\tstatus: 'deferred',\n\t\t\treply: { status: '4.4.2', text: 'no reply to the final dot' },\n\t\t\t...(mayHaveReachedFallback === undefined\n\t\t\t\t? {}\n\t\t\t\t: { mayHaveReachedFallback }),\n\t\t}) as AttemptResult['recipients'][number];\n\n\ttest('mayHaveReachedFallback: recorded, read by get and list, and kept by a later outcome without it', async () => {\n\t\tconst store = await create();\n\t\tconst item = await store.add(entry());\n\t\tawait store.claim({ owner: 'w1', now: T0, ...lease });\n\t\tconst done = await store.complete(\n\t\t\titem.id,\n\t\t\t'w1',\n\t\t\tresult({ recipients: [deferred(true)] }),\n\t\t\t[],\n\t\t);\n\t\texpect(done?.item.recipients[0]?.mayHaveReachedFallback).toBe(true);\n\t\texpect(done?.item.recipients[1]).not.toHaveProperty(\n\t\t\t'mayHaveReachedFallback',\n\t\t);\n\t\texpect(\n\t\t\t(await store.get(item.id))?.recipients[0]?.mayHaveReachedFallback,\n\t\t).toBe(true);\n\t\texpect((await store.list())[0]?.recipients[0]?.mayHaveReachedFallback).toBe(\n\t\t\ttrue,\n\t\t);\n\t\tawait store.claim({ owner: 'w1', now: T0 + 30 * MINUTE, ...lease });\n\t\tconst again = await store.complete(\n\t\t\titem.id,\n\t\t\t'w1',\n\t\t\tresult({ recipients: [deferred()], attempts: 2 }),\n\t\t\t[],\n\t\t);\n\t\texpect(again?.item.recipients[0]?.mayHaveReachedFallback).toBe(true);\n\t\texpect(\n\t\t\t(await store.get(item.id))?.recipients[0]?.mayHaveReachedFallback,\n\t\t).toBe(true);\n\t});\n\n\ttest('mayHaveReachedFallback: an unmarked recipient has no such key', async () => {\n\t\tconst store = await create();\n\t\tconst item = await store.add(entry());\n\t\tawait store.claim({ owner: 'w1', now: T0, ...lease });\n\t\tawait store.complete(\n\t\t\titem.id,\n\t\t\t'w1',\n\t\t\tresult({ recipients: [deferred()] }),\n\t\t\t[],\n\t\t);\n\t\tfor (const r of (await store.get(item.id))?.recipients ?? []) {\n\t\t\texpect(r).not.toHaveProperty('mayHaveReachedFallback');\n\t\t}\n\t});\n\n\ttest('mayHaveReachedFallback: a value other than true is INVALID, and the item stays as it was', async () => {\n\t\tconst store = await create();\n\t\tconst item = await store.add(entry());\n\t\tawait store.claim({ owner: 'w1', now: T0, ...lease });\n\t\tfor (const bad of [false, 'true', 1, null]) {\n\t\t\tawait rejects(\n\t\t\t\tstore.complete(\n\t\t\t\t\titem.id,\n\t\t\t\t\t'w1',\n\t\t\t\t\tresult({ recipients: [deferred(bad)] }),\n\t\t\t\t\t[],\n\t\t\t\t),\n\t\t\t\t'INVALID',\n\t\t\t);\n\t\t}\n\t\tconst kept = await store.get(item.id);\n\t\texpect(kept?.recipients[0]?.status).toBe('pending');\n\t\texpect(kept?.lease?.owner).toBe('w1');\n\t});\n}\n"
14
+ ],
15
+ "mappings": "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",
16
+ "debugId": "434F5188249F7D1F64756E2164756E21",
17
+ "names": []
18
+ }
@@ -0,0 +1,4 @@
1
+ import { type StoreFactories } from './setup';
2
+ /** Adding, reading, listing and cancelling items. */
3
+ export declare function describeItems(factories: StoreFactories): void;
4
+ //# sourceMappingURL=items.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"items.d.ts","sourceRoot":"","sources":["../../src/conformance/items.ts"],"names":[],"mappings":"AAEA,OAAO,EAKN,KAAK,cAAc,EAEnB,MAAM,SAAS,CAAC;AAEjB,qDAAqD;AACrD,wBAAgB,aAAa,CAAC,SAAS,EAAE,cAAc,GAAG,IAAI,CAM7D"}
@@ -0,0 +1,4 @@
1
+ import { type StoreFactories } from './setup';
2
+ /** What `complete` records. */
3
+ export declare function describeOutcomes(factories: StoreFactories): void;
4
+ //# sourceMappingURL=outcomes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outcomes.d.ts","sourceRoot":"","sources":["../../src/conformance/outcomes.ts"],"names":[],"mappings":"AAGA,OAAO,EAMN,KAAK,cAAc,EAEnB,MAAM,SAAS,CAAC;AAEjB,+BAA+B;AAC/B,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,cAAc,GAAG,IAAI,CAShE"}
@@ -0,0 +1,40 @@
1
+ import type { QueueStore } from '../contract/queue-store';
2
+ import type { AttemptResult, NewQueueItem } from '../contract/types';
3
+ /** A new store, empty. */
4
+ export type CreateQueueStore = () => Promise<QueueStore> | QueueStore;
5
+ /**
6
+ * Another handle on the same queue as `store`: a second connection to the
7
+ * same database, as a second process would open. A harness with no second
8
+ * handle omits `share`, and the two several-workers tests are then skipped.
9
+ */
10
+ export type ShareStore = (store: QueueStore) => QueueStore;
11
+ /** What a store's spec hands the suite. */
12
+ export interface QueueStoreHarness {
13
+ /** A new store, empty. */
14
+ readonly create: CreateQueueStore;
15
+ /** Another handle on the same queue; without it the share tests are skipped. */
16
+ readonly share?: ShareStore | undefined;
17
+ /**
18
+ * Closes a store `create` made, after the test that used it. Handles
19
+ * returned by `share` are the harness's to close.
20
+ */
21
+ readonly dispose?: ((store: QueueStore) => Promise<void> | void) | undefined;
22
+ }
23
+ /** What the suite is handed: how to build a store, and what the harness can do beyond that. */
24
+ export interface StoreFactories {
25
+ readonly create: CreateQueueStore;
26
+ /** Absent when the harness has no second handle: the share tests are skipped. */
27
+ readonly share?: ShareStore | undefined;
28
+ }
29
+ export declare const bytes: (text: string) => Uint8Array<ArrayBuffer>;
30
+ export declare const T0: number;
31
+ export declare const MINUTE = 60000;
32
+ export declare const lease: {
33
+ leaseMs: number;
34
+ };
35
+ export declare const result: (overrides?: Partial<AttemptResult>) => AttemptResult;
36
+ /** A new item from mary to two recipients, created at `T0` unless told otherwise. */
37
+ export declare function entry(overrides?: Partial<NewQueueItem>): NewQueueItem;
38
+ /** Expects a promise to reject with a QueueError of this code. */
39
+ export declare function rejects(promise: Promise<unknown>, code: string): Promise<void>;
40
+ //# sourceMappingURL=setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/conformance/setup.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAErE,0BAA0B;AAC1B,MAAM,MAAM,gBAAgB,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,GAAG,UAAU,CAAC;AAEtE;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,KAAK,EAAE,UAAU,KAAK,UAAU,CAAC;AAE3D,2CAA2C;AAC3C,MAAM,WAAW,iBAAiB;IACjC,0BAA0B;IAC1B,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,gFAAgF;IAChF,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IACxC;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,SAAS,CAAC;CAC7E;AAED,+FAA+F;AAC/F,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,iFAAiF;IACjF,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;CACxC;AAED,eAAO,MAAM,KAAK,GAAI,MAAM,MAAM,4BAAmC,CAAC;AAEtE,eAAO,MAAM,EAAE,QAA2B,CAAC;AAC3C,eAAO,MAAM,MAAM,QAAS,CAAC;AAE7B,eAAO,MAAM,KAAK;;CAA2B,CAAC;AAE9C,eAAO,MAAM,MAAM,GAClB,YAAW,OAAO,CAAC,aAAa,CAAM,KACpC,aAOD,CAAC;AAEH,qFAAqF;AACrF,wBAAgB,KAAK,CAAC,SAAS,GAAE,OAAO,CAAC,YAAY,CAAM,GAAG,YAAY,CAQzE;AAED,kEAAkE;AAClE,wBAAsB,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,iBAEpE"}
@@ -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":"AAAA;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,QAAQ,CAAC;AAE9E,sEAAsE;AACtE,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG,QAAQ,CAAC;AAEjD;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IAC1B,sDAAsD;IACtD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,yCAAyC;IACzC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,2DAA2D;IAC3D,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,+DAA+D;AAC/D,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAE1D;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,SAAS,WAAW,EAAE,CAAC;AAE/D,2EAA2E;AAC3E,MAAM,WAAW,iBAAiB;IACjC,0DAA0D;IAC1D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,4BAA4B;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACzB;AAED,2EAA2E;AAC3E,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAEtC,oEAAoE;AACpE,MAAM,WAAW,YAAY;IAC5B,kDAAkD;IAClD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,iBAAiB,CAAC;CACnC;AAED,MAAM,WAAW,cAAc;IAC9B,mCAAmC;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,sFAAsF;IACtF,QAAQ,CAAC,MAAM,CAAC,EAAE,eAAe,CAAC;IAClC,uFAAuF;IACvF,QAAQ,CAAC,KAAK,CAAC,EAAE,iBAAiB,CAAC;IACnC,0CAA0C;IAC1C,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAC5B,qEAAqE;IACrE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;;OAKG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,IAAI,CAAC;IACjC;;;;;;OAMG;IACH,QAAQ,CAAC,sBAAsB,CAAC,EAAE,IAAI,CAAC;CACvC;AAED,6CAA6C;AAC7C,MAAM,WAAW,KAAK;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,gFAAgF;IAChF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC3B;AAED,uEAAuE;AACvE,MAAM,WAAW,SAAS;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,SAAS,cAAc,EAAE,CAAC;IAC/C,mCAAmC;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,oCAAoC;IACpC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,kEAAkE;IAClE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,mCAAmC;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,yCAAyC;IACzC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,yDAAyD;IACzD,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;IACvB,sEAAsE;IACtE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,6CAA6C;IAC7C,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;CACvB;AAED,wBAAwB;AACxB,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,6CAA6C;IAC7C,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,iDAAiD;IACjD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,6BAA6B;IAC7B,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;IACvB,oEAAoE;IACpE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,0FAA0F;IAC1F,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;CAC9C;AAED,MAAM,WAAW,UAAU;IAC1B,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,kEAAkE;AAClE,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,oCAAoC;IACpC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACzB;AAED,6CAA6C;AAC7C,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC;IACrD,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAC5B,8FAA8F;IAC9F,QAAQ,CAAC,gBAAgB,CAAC,EAAE,IAAI,CAAC;IACjC,oGAAoG;IACpG,QAAQ,CAAC,sBAAsB,CAAC,EAAE,IAAI,CAAC;IACvC;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,8EAA8E;AAC9E,MAAM,WAAW,aAAa;IAC7B,kEAAkE;IAClE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,QAAQ,CAAC,UAAU,EAAE,SAAS,eAAe,EAAE,CAAC;IAChD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;CAChC;AAED,MAAM,WAAW,gBAAgB;IAChC,iBAAiB;IACjB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB;IACnB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACxB"}
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