@fedify/fedify 2.4.0-dev.1504 → 2.4.0-dev.1528

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 (109) hide show
  1. package/README.md +10 -7
  2. package/dist/{assert-DvVHoIZ0.mjs → assert-OguE97r2.mjs} +1 -1
  3. package/dist/{assert_instance_of-CxoC8bVq.mjs → assert_instance_of-DBC5X09g.mjs} +1 -1
  4. package/dist/{assert_not_equals-C8vcTTA3.mjs → assert_not_equals-DkVK8oqV.mjs} +1 -1
  5. package/dist/{assert_rejects-DAdaaIWM.mjs → assert_rejects-DN60FHPX.mjs} +2 -2
  6. package/dist/{assert_strict_equals-BzqyKuYL.mjs → assert_strict_equals-XEgZAlrj.mjs} +1 -1
  7. package/dist/{assert_throws-zN79lgIC.mjs → assert_throws-BOkhLGYc.mjs} +1 -1
  8. package/dist/{builder-Ck0Fl_a5.mjs → builder-B6myMguW.mjs} +3 -23
  9. package/dist/compat/mod.d.cts +1 -1
  10. package/dist/compat/mod.d.ts +1 -1
  11. package/dist/compat/outgoing-jsonld.test.mjs +3 -3
  12. package/dist/compat/public-audience.test.mjs +3 -3
  13. package/dist/compat/transformers.test.mjs +5 -5
  14. package/dist/{context-CYF8X0ft.d.cts → context-BBVLF7lx.d.cts} +272 -543
  15. package/dist/{context-BF5B4ZDk.d.ts → context-BU6jSQdo.d.ts} +272 -542
  16. package/dist/{context-BBRTgkrs.mjs → context-DVoTs_wM.mjs} +2 -8
  17. package/dist/{deno-D3gb4X9v.mjs → deno-CVNsRJe9.mjs} +1 -1
  18. package/dist/{docloader-DUKu0GzG.mjs → docloader-CB8AGpw3.mjs} +3 -3
  19. package/dist/federation/builder.test.mjs +5 -5
  20. package/dist/federation/circuit-breaker.test.mjs +5 -5
  21. package/dist/federation/collection.test.mjs +3 -3
  22. package/dist/federation/handler.test.mjs +13 -13
  23. package/dist/federation/idempotency.test.mjs +6 -6
  24. package/dist/federation/inbox.test.mjs +3 -3
  25. package/dist/federation/keycache.test.mjs +5 -5
  26. package/dist/federation/kv.test.mjs +3 -3
  27. package/dist/federation/metrics.test.mjs +4 -4
  28. package/dist/federation/middleware.test.mjs +19 -200
  29. package/dist/federation/mod.cjs +259 -3
  30. package/dist/federation/mod.d.cts +4 -4
  31. package/dist/federation/mod.d.ts +4 -4
  32. package/dist/federation/mod.js +257 -1
  33. package/dist/federation/mq.test.mjs +261 -103
  34. package/dist/federation/negotiation.test.mjs +4 -4
  35. package/dist/federation/retry.test.mjs +3 -3
  36. package/dist/federation/router.test.mjs +5 -5
  37. package/dist/federation/send.test.mjs +10 -10
  38. package/dist/federation/temporal.test.mjs +4 -4
  39. package/dist/federation/webfinger.test.mjs +6 -6
  40. package/dist/{http-CrZzUAtV.js → http-B0-9u_1F.js} +17 -7
  41. package/dist/{http-D9p2_d2X.cjs → http-EkV7OslM.cjs} +17 -7
  42. package/dist/{http-BNFQkiEZ.mjs → http-L7wqkbZR.mjs} +4 -4
  43. package/dist/{key-BM_SRwBV.mjs → key-Ct8zNgGk.mjs} +18 -8
  44. package/dist/{kv-cache-BE1QIPdL.mjs → kv-cache-CUT9OGpX.mjs} +1 -1
  45. package/dist/{kv-cache-Cna211RR.cjs → kv-cache-CbB50co6.cjs} +1 -1
  46. package/dist/{kv-cache-Ch_Zv5Yq.js → kv-cache-Dh8ZoQfC.js} +1 -1
  47. package/dist/{ld-ubkf03eb.mjs → ld-D6I7H18J.mjs} +3 -3
  48. package/dist/{metrics-BXR36qzu.mjs → metrics-DvClPYaE.mjs} +1 -1
  49. package/dist/{middleware-DUNeIkXN.cjs → middleware-B0ujKP-0.cjs} +51 -694
  50. package/dist/{middleware-pzCP79He.mjs → middleware-CGqUj4XY.mjs} +1 -1
  51. package/dist/{middleware-lB4vtShP.js → middleware-DX9Fd37u.js} +52 -683
  52. package/dist/{middleware-iP9VRMus.mjs → middleware-RxFBNV2C.mjs} +67 -310
  53. package/dist/{mod-BHEB3xhE.d.cts → mod-C0F6kvgS.d.cts} +1 -1
  54. package/dist/{mod-4WGAuR6X.d.ts → mod-vPYVoa5n.d.ts} +1 -1
  55. package/dist/mod.cjs +6 -6
  56. package/dist/mod.d.cts +5 -5
  57. package/dist/mod.d.ts +5 -5
  58. package/dist/mod.js +5 -5
  59. package/dist/{mq-DXMt_qCY.d.cts → mq-D-nlpY04.d.ts} +0 -34
  60. package/dist/{mq-B5_hohs7.d.ts → mq-D8uSFzxe.d.cts} +0 -34
  61. package/dist/nodeinfo/client.test.mjs +3 -3
  62. package/dist/nodeinfo/handler.test.mjs +5 -5
  63. package/dist/nodeinfo/types.test.mjs +4 -4
  64. package/dist/otel/exporter.test.mjs +3 -3
  65. package/dist/{outgoing-jsonld-BNL8AC14.mjs → outgoing-jsonld-L_DbOaFe.mjs} +1 -1
  66. package/dist/{owner-Bf1KkncT.mjs → owner-BqPUA8Z6.mjs} +2 -2
  67. package/dist/{proof-Q781Ks5q.mjs → proof-BJKoRFBc.mjs} +5 -5
  68. package/dist/{proof-BMcsi8q_.js → proof-DCCmmEuJ.js} +1 -1
  69. package/dist/{proof-yeAU1MyT.cjs → proof-eZme7HYR.cjs} +1 -1
  70. package/dist/{send-DFV0S_n9.mjs → send-DVtEjoJ6.mjs} +3 -3
  71. package/dist/sig/accept.test.mjs +1 -1
  72. package/dist/sig/http.test.mjs +8 -8
  73. package/dist/sig/key.test.mjs +56 -6
  74. package/dist/sig/ld.test.mjs +7 -7
  75. package/dist/sig/mod.cjs +2 -2
  76. package/dist/sig/mod.js +2 -2
  77. package/dist/sig/owner.test.mjs +6 -6
  78. package/dist/sig/proof.test.mjs +8 -8
  79. package/dist/{std__assert-Dh6uLf_q.mjs → std__assert-BBjXFNOb.mjs} +4 -4
  80. package/dist/{temporal-CyOjsqPj.mjs → temporal-B06FcmVK.mjs} +1 -1
  81. package/dist/testing/mod.d.mts +8 -1037
  82. package/dist/testing/mod.mjs +2 -3
  83. package/dist/utils/docloader.test.mjs +6 -6
  84. package/dist/utils/kv-cache.test.mjs +1 -1
  85. package/dist/utils/mod.cjs +1 -1
  86. package/dist/utils/mod.js +1 -1
  87. package/package.json +7 -12
  88. package/dist/codec-CmlPqjNX.mjs +0 -103
  89. package/dist/federation/tasks/codec.test.d.mts +0 -2
  90. package/dist/federation/tasks/codec.test.mjs +0 -292
  91. package/dist/federation/tasks/enqueue.test.d.mts +0 -2
  92. package/dist/federation/tasks/enqueue.test.mjs +0 -992
  93. package/dist/federation/tasks/tasks.test.d.mts +0 -2
  94. package/dist/federation/tasks/tasks.test.mjs +0 -555
  95. package/dist/mq-03vS-C9P.mjs +0 -276
  96. package/dist/testing-Dy-WhqpN.mjs +0 -77
  97. /package/dist/{accept-CgDcxvjV.mjs → accept-CPkZzmGN.mjs} +0 -0
  98. /package/dist/{activity-listener-BeTGV3wc.mjs → activity-listener-tztVvlNb.mjs} +0 -0
  99. /package/dist/{assert_equals-PBVKNMJd.mjs → assert_equals-C-ZRDbaf.mjs} +0 -0
  100. /package/dist/{circuit-breaker-hJBB6jwA.mjs → circuit-breaker-CSWsyoef.mjs} +0 -0
  101. /package/dist/{client-B_A6mfn3.mjs → client-ByXmQhYD.mjs} +0 -0
  102. /package/dist/{collection-Dp5ky45w.mjs → collection-Cc3DVAhE.mjs} +0 -0
  103. /package/dist/{keycache-CaOR6NYg.mjs → keycache-BeU0LCII.mjs} +0 -0
  104. /package/dist/{keys-CSYsOMFG.mjs → keys-DGu1NFwu.mjs} +0 -0
  105. /package/dist/{kv-CIvR3Non.mjs → kv-rV3vodCc.mjs} +0 -0
  106. /package/dist/{negotiation-m_L2nyS3.mjs → negotiation-DDstyBvc.mjs} +0 -0
  107. /package/dist/{public-audience-c9zmYKgA.mjs → public-audience-Cvbr2Gzt.mjs} +0 -0
  108. /package/dist/{retry-DI4O-zYl.mjs → retry-CXg_MBI-.mjs} +0 -0
  109. /package/dist/{types-BFowWFTT.mjs → types-J53Kw7so.mjs} +0 -0
@@ -1,2 +0,0 @@
1
- import { Temporal } from "@js-temporal/polyfill";
2
- import { URLPattern } from "urlpattern-polyfill";
@@ -1,555 +0,0 @@
1
- import { Temporal } from "@js-temporal/polyfill";
2
- import "urlpattern-polyfill";
3
- globalThis.addEventListener = () => {};
4
- import { a as numberSchema, i as makeSchema, n as baseOptions, o as stringSchema, t as MockQueue } from "../../testing-Dy-WhqpN.mjs";
5
- import { o as createFederation } from "../../middleware-iP9VRMus.mjs";
6
- import { r as createFederationBuilder } from "../../builder-Ck0Fl_a5.mjs";
7
- import { t as TaskCodec } from "../../codec-CmlPqjNX.mjs";
8
- import { t as InProcessMessageQueue } from "../../mq-03vS-C9P.mjs";
9
- import { Note } from "@fedify/vocab";
10
- import { delay } from "es-toolkit";
11
- import { mockDocumentLoader, test } from "@fedify/fixture";
12
- import { deepStrictEqual, ok, rejects, strictEqual, throws } from "node:assert/strict";
13
- //#region src/federation/tasks/tasks.test.ts
14
- const envelopeSchema = makeSchema((data) => typeof data === "object" && data != null && data.note instanceof Note && typeof data.title === "string");
15
- const makeTaskMessage = async (taskName, data, overrides = {}) => ({
16
- type: "task",
17
- id: crypto.randomUUID(),
18
- baseUrl: "https://example.com/",
19
- taskName,
20
- data: await new TaskCodec({ contextLoader: mockDocumentLoader }).serialize(data),
21
- started: Temporal.Now.instant().toString(),
22
- attempt: 0,
23
- traceContext: {},
24
- ...overrides
25
- });
26
- async function waitFor(predicate, timeoutMs) {
27
- const started = Date.now();
28
- while (!predicate()) {
29
- await delay(50);
30
- if (Date.now() - started > timeoutMs) throw new Error("Timeout");
31
- }
32
- }
33
- test("defineTask()", async (t) => {
34
- await t.step("returns a handle carrying name and schema", () => {
35
- const task = createFederation({
36
- ...baseOptions,
37
- queue: { task: new MockQueue() }
38
- }).defineTask("greet", {
39
- schema: stringSchema,
40
- handler: () => {}
41
- });
42
- strictEqual(task.name, "greet");
43
- strictEqual(task.schema, stringSchema);
44
- });
45
- await t.step("throws on a duplicate name", () => {
46
- const federation = createFederation({
47
- ...baseOptions,
48
- queue: { task: new MockQueue() }
49
- });
50
- federation.defineTask("dup", {
51
- schema: stringSchema,
52
- handler: () => {}
53
- });
54
- throws(() => federation.defineTask("dup", {
55
- schema: stringSchema,
56
- handler: () => {}
57
- }), {
58
- name: "TypeError",
59
- message: /already defined/
60
- });
61
- });
62
- await t.step("accepts names that collide with Object.prototype", () => {
63
- const federation = createFederation({
64
- ...baseOptions,
65
- queue: { task: new MockQueue() }
66
- });
67
- for (const name of [
68
- "constructor",
69
- "toString",
70
- "hasOwnProperty"
71
- ]) {
72
- strictEqual(federation.defineTask(name, {
73
- schema: stringSchema,
74
- handler: () => {}
75
- }).name, name);
76
- strictEqual(federation.taskDefinitions.get(name)?.name, name);
77
- }
78
- throws(() => federation.defineTask("toString", {
79
- schema: stringSchema,
80
- handler: () => {}
81
- }), {
82
- name: "TypeError",
83
- message: /already defined/
84
- });
85
- });
86
- await t.step("build() clones the task registry", async () => {
87
- const builder = createFederationBuilder();
88
- builder.defineTask("first", {
89
- schema: stringSchema,
90
- handler: () => {}
91
- });
92
- const f1 = await builder.build({
93
- ...baseOptions,
94
- queue: { task: new MockQueue() }
95
- });
96
- builder.defineTask("second", {
97
- schema: stringSchema,
98
- handler: () => {}
99
- });
100
- const f2 = await builder.build({
101
- ...baseOptions,
102
- queue: { task: new MockQueue() }
103
- });
104
- deepStrictEqual([...f1.taskDefinitions.keys()], ["first"]);
105
- deepStrictEqual([...f2.taskDefinitions.keys()], ["first", "second"]);
106
- f1.defineTask("third", {
107
- schema: stringSchema,
108
- handler: () => {}
109
- });
110
- deepStrictEqual([...f2.taskDefinitions.keys()], ["first", "second"]);
111
- });
112
- });
113
- test("task type-level guards", () => {});
114
- test("Context.enqueueTask() end-to-end", async (t) => {
115
- await t.step("round-trips a typed payload to the handler", async () => {
116
- const queue = new InProcessMessageQueue();
117
- const federation = createFederation({
118
- ...baseOptions,
119
- queue: { task: queue }
120
- });
121
- const received = [];
122
- const task = federation.defineTask("notify", {
123
- schema: envelopeSchema,
124
- handler: (ctx, data) => {
125
- received.push({
126
- ctx,
127
- data
128
- });
129
- }
130
- });
131
- await federation.createContext(new URL("https://example.com/"), void 0).enqueueTask(task, {
132
- note: new Note({ content: "Hello, world!" }),
133
- title: "greeting"
134
- });
135
- const controller = new AbortController();
136
- const listening = federation.startQueue(void 0, {
137
- signal: controller.signal,
138
- queue: "task"
139
- });
140
- try {
141
- await waitFor(() => received.length > 0, 15e3);
142
- } finally {
143
- controller.abort();
144
- await listening;
145
- }
146
- strictEqual(received.length, 1);
147
- const { ctx: handlerCtx, data } = received[0];
148
- ok(data.note instanceof Note);
149
- strictEqual(data.note.content?.toString(), "Hello, world!");
150
- strictEqual(data.title, "greeting");
151
- strictEqual(handlerCtx.origin, "https://example.com");
152
- });
153
- });
154
- test("task queue routing", async (t) => {
155
- await t.step("prefers the per-task queue", async () => {
156
- const taskQueue = new MockQueue();
157
- const perTaskQueue = new MockQueue();
158
- const federation = createFederation({
159
- ...baseOptions,
160
- queue: { task: taskQueue }
161
- });
162
- const task = federation.defineTask("isolated", {
163
- schema: stringSchema,
164
- handler: () => {},
165
- queue: perTaskQueue
166
- });
167
- await federation.createContext(new URL("https://example.com/"), void 0).enqueueTask(task, "data");
168
- strictEqual(perTaskQueue.enqueued.length, 1);
169
- strictEqual(taskQueue.enqueued.length, 0);
170
- });
171
- await t.step("falls back to the outbox queue by default", async () => {
172
- const outboxQueue = new MockQueue();
173
- const federation = createFederation({
174
- ...baseOptions,
175
- queue: { outbox: outboxQueue }
176
- });
177
- const task = federation.defineTask("fallback", {
178
- schema: stringSchema,
179
- handler: () => {}
180
- });
181
- await federation.createContext(new URL("https://example.com/"), void 0).enqueueTask(task, "data");
182
- strictEqual(outboxQueue.enqueued.length, 1);
183
- });
184
- await t.step("taskQueueResolution: \"strict\" throws at enqueue instead", async () => {
185
- const outboxQueue = new MockQueue();
186
- const federation = createFederation({
187
- ...baseOptions,
188
- queue: { outbox: outboxQueue },
189
- taskQueueResolution: "strict"
190
- });
191
- const task = federation.defineTask("strict", {
192
- schema: stringSchema,
193
- handler: () => {}
194
- });
195
- const ctx = federation.createContext(new URL("https://example.com/"), void 0);
196
- await rejects(() => ctx.enqueueTask(task, "data"), {
197
- name: "TypeError",
198
- message: /No message queue is configured/
199
- });
200
- strictEqual(outboxQueue.enqueued.length, 0);
201
- });
202
- await t.step("throws when no queue is configured at all", async () => {
203
- const federation = createFederation({ ...baseOptions });
204
- const task = federation.defineTask("queueless", {
205
- schema: stringSchema,
206
- handler: () => {}
207
- });
208
- const ctx = federation.createContext(new URL("https://example.com/"), void 0);
209
- await rejects(() => ctx.enqueueTask(task, "data"), {
210
- name: "TypeError",
211
- message: /No message queue is configured/
212
- });
213
- });
214
- });
215
- test("startQueue() task worker", async (t) => {
216
- await t.step("starts only the task worker for queue: \"task\"", async () => {
217
- const inbox = new MockQueue();
218
- const outbox = new MockQueue();
219
- const fanout = new MockQueue();
220
- const taskQueue = new MockQueue();
221
- const federation = createFederation({
222
- ...baseOptions,
223
- queue: {
224
- inbox,
225
- outbox,
226
- fanout,
227
- task: taskQueue
228
- }
229
- });
230
- const controller = new AbortController();
231
- const listening = federation.startQueue(void 0, {
232
- signal: controller.signal,
233
- queue: "task"
234
- });
235
- strictEqual(taskQueue.listenCount, 1);
236
- strictEqual(inbox.listenCount, 0);
237
- strictEqual(outbox.listenCount, 0);
238
- strictEqual(fanout.listenCount, 0);
239
- controller.abort();
240
- await listening;
241
- });
242
- await t.step("starts the worker for a task-only deployment", async () => {
243
- const taskQueue = new MockQueue();
244
- const federation = createFederation({
245
- ...baseOptions,
246
- queue: { task: taskQueue }
247
- });
248
- const controller = new AbortController();
249
- const listening = federation.startQueue(void 0, { signal: controller.signal });
250
- strictEqual(taskQueue.listenCount, 1);
251
- controller.abort();
252
- await listening;
253
- });
254
- await t.step("does not double-listen on a shared queue", async () => {
255
- const shared = new MockQueue();
256
- const federation = createFederation({
257
- ...baseOptions,
258
- queue: {
259
- outbox: shared,
260
- task: shared
261
- }
262
- });
263
- const controller = new AbortController();
264
- const listening = federation.startQueue(void 0, { signal: controller.signal });
265
- strictEqual(shared.listenCount, 1);
266
- controller.abort();
267
- await listening;
268
- });
269
- await t.step("starts a worker for a dedicated per-task queue", async () => {
270
- const taskQueue = new MockQueue();
271
- const dedicated = new MockQueue();
272
- const federation = createFederation({
273
- ...baseOptions,
274
- queue: { task: taskQueue }
275
- });
276
- federation.defineTask("dedicated", {
277
- schema: stringSchema,
278
- handler: () => {},
279
- queue: dedicated
280
- });
281
- const controller = new AbortController();
282
- const listening = federation.startQueue(void 0, { signal: controller.signal });
283
- strictEqual(taskQueue.listenCount, 1);
284
- strictEqual(dedicated.listenCount, 1);
285
- controller.abort();
286
- await listening;
287
- });
288
- await t.step("starts a per-task queue even without a federation queue", async () => {
289
- const dedicated = new MockQueue();
290
- const federation = createFederation({ ...baseOptions });
291
- federation.defineTask("dedicated", {
292
- schema: stringSchema,
293
- handler: () => {},
294
- queue: dedicated
295
- });
296
- const controller = new AbortController();
297
- const listening = federation.startQueue(void 0, { signal: controller.signal });
298
- strictEqual(dedicated.listenCount, 1);
299
- controller.abort();
300
- await listening;
301
- });
302
- await t.step("does not listen twice on a per-task queue shared with a standard queue", async () => {
303
- const shared = new MockQueue();
304
- const federation = createFederation({
305
- ...baseOptions,
306
- queue: { task: shared }
307
- });
308
- federation.defineTask("reuses-task-queue", {
309
- schema: stringSchema,
310
- handler: () => {},
311
- queue: shared
312
- });
313
- const controller = new AbortController();
314
- const listening = federation.startQueue(void 0, { signal: controller.signal });
315
- strictEqual(shared.listenCount, 1);
316
- controller.abort();
317
- await listening;
318
- });
319
- await t.step("routes an enqueued task on a dedicated queue to its handler", async () => {
320
- const dedicated = new MockQueue();
321
- const federation = createFederation({ ...baseOptions });
322
- let received;
323
- const task = federation.defineTask("dedicated-end-to-end", {
324
- schema: stringSchema,
325
- handler: (_ctx, data) => {
326
- received = data;
327
- },
328
- queue: dedicated
329
- });
330
- await federation.createContext(new URL("https://example.com/"), void 0).enqueueTask(task, "payload");
331
- strictEqual(dedicated.enqueued.length, 1);
332
- await federation.processQueuedTask(void 0, dedicated.enqueued[0].message);
333
- strictEqual(received, "payload");
334
- });
335
- await t.step("queue: \"task\" starts the outbox fallback when no task queue is set", async () => {
336
- const inbox = new MockQueue();
337
- const outbox = new MockQueue();
338
- const fanout = new MockQueue();
339
- const federation = createFederation({
340
- ...baseOptions,
341
- queue: {
342
- inbox,
343
- outbox,
344
- fanout
345
- }
346
- });
347
- federation.defineTask("fallback", {
348
- schema: stringSchema,
349
- handler: () => {}
350
- });
351
- const controller = new AbortController();
352
- const listening = federation.startQueue(void 0, {
353
- signal: controller.signal,
354
- queue: "task"
355
- });
356
- strictEqual(outbox.listenCount, 1);
357
- strictEqual(inbox.listenCount, 0);
358
- strictEqual(fanout.listenCount, 0);
359
- controller.abort();
360
- await listening;
361
- });
362
- await t.step("queue: \"task\" starts a task queue shared with the outbox once", async () => {
363
- const inbox = new MockQueue();
364
- const shared = new MockQueue();
365
- const fanout = new MockQueue();
366
- const federation = createFederation({
367
- ...baseOptions,
368
- queue: {
369
- inbox,
370
- outbox: shared,
371
- fanout,
372
- task: shared
373
- }
374
- });
375
- const controller = new AbortController();
376
- const listening = federation.startQueue(void 0, {
377
- signal: controller.signal,
378
- queue: "task"
379
- });
380
- strictEqual(shared.listenCount, 1);
381
- strictEqual(inbox.listenCount, 0);
382
- strictEqual(fanout.listenCount, 0);
383
- controller.abort();
384
- await listening;
385
- });
386
- });
387
- test("MockQueue.listen() resolves on a pre-aborted signal", async () => {
388
- const queue = new MockQueue();
389
- const controller = new AbortController();
390
- controller.abort();
391
- let timer;
392
- const settled = await Promise.race([queue.listen(() => {}, { signal: controller.signal }).then(() => "resolved"), new Promise((resolve) => {
393
- timer = setTimeout(() => resolve("pending"), 50);
394
- })]);
395
- clearTimeout(timer);
396
- strictEqual(settled, "resolved");
397
- });
398
- test("processQueuedTask() task dispatch", async (t) => {
399
- await t.step("drops an unknown task with a warning", async () => {
400
- const queue = new MockQueue();
401
- const federation = createFederation({
402
- ...baseOptions,
403
- queue: { task: queue }
404
- });
405
- const message = await makeTaskMessage("never-defined", "data");
406
- await federation.processQueuedTask(void 0, message);
407
- strictEqual(queue.enqueued.length, 0);
408
- });
409
- await t.step("drops an undecodable payload without retry", async () => {
410
- const queue = new MockQueue();
411
- const federation = createFederation({
412
- ...baseOptions,
413
- queue: { task: queue }
414
- });
415
- let called = 0;
416
- federation.defineTask("broken-wire", {
417
- schema: stringSchema,
418
- handler: () => {
419
- called++;
420
- }
421
- });
422
- const message = await makeTaskMessage("broken-wire", "data");
423
- await federation.processQueuedTask(void 0, {
424
- ...message,
425
- data: "garbage that is not devalue"
426
- });
427
- strictEqual(called, 0);
428
- strictEqual(queue.enqueued.length, 0);
429
- });
430
- await t.step("drops a drifted payload without retry", async () => {
431
- const queue = new MockQueue();
432
- const federation = createFederation({
433
- ...baseOptions,
434
- queue: { task: queue }
435
- });
436
- let called = 0;
437
- federation.defineTask("drifted", {
438
- schema: numberSchema,
439
- handler: () => {
440
- called++;
441
- }
442
- });
443
- const message = await makeTaskMessage("drifted", "stringly-typed");
444
- await federation.processQueuedTask(void 0, message);
445
- strictEqual(called, 0);
446
- strictEqual(queue.enqueued.length, 0);
447
- });
448
- await t.step("re-enqueues with attempt + 1 when the handler throws", async () => {
449
- const queue = new MockQueue();
450
- const federation = createFederation({
451
- ...baseOptions,
452
- queue: { task: queue }
453
- });
454
- const errors = [];
455
- federation.defineTask("flaky", {
456
- schema: stringSchema,
457
- handler: () => {
458
- throw new Error("boom");
459
- },
460
- retryPolicy: () => Temporal.Duration.from({ milliseconds: 1 }),
461
- onError: (_ctx, error, data) => {
462
- errors.push([error, data]);
463
- }
464
- });
465
- const message = await makeTaskMessage("flaky", "data", { orderingKey: "k" });
466
- await federation.processQueuedTask(void 0, message);
467
- strictEqual(queue.enqueued.length, 1);
468
- const retry = queue.enqueued[0];
469
- strictEqual(retry.message.attempt, 1);
470
- strictEqual(retry.message.taskName, "flaky");
471
- strictEqual(retry.message.orderingKey, "k");
472
- strictEqual(retry.options?.orderingKey, "k");
473
- ok(retry.options?.delay instanceof Temporal.Duration);
474
- strictEqual(errors.length, 1);
475
- deepStrictEqual(errors[0], [/* @__PURE__ */ new Error("boom"), "data"]);
476
- });
477
- await t.step("gives up when the retry policy returns null", async () => {
478
- const queue = new MockQueue();
479
- const federation = createFederation({
480
- ...baseOptions,
481
- queue: { task: queue }
482
- });
483
- federation.defineTask("hopeless", {
484
- schema: stringSchema,
485
- handler: () => {
486
- throw new Error("boom");
487
- },
488
- retryPolicy: () => null
489
- });
490
- const message = await makeTaskMessage("hopeless", "data");
491
- await federation.processQueuedTask(void 0, message);
492
- strictEqual(queue.enqueued.length, 0);
493
- });
494
- await t.step("per-task retryPolicy overrides the federation default", async () => {
495
- const queue = new MockQueue();
496
- const federation = createFederation({
497
- ...baseOptions,
498
- queue: { task: queue },
499
- taskRetryPolicy: () => null
500
- });
501
- federation.defineTask("override", {
502
- schema: stringSchema,
503
- handler: () => {
504
- throw new Error("boom");
505
- },
506
- retryPolicy: () => Temporal.Duration.from({ milliseconds: 1 })
507
- });
508
- federation.defineTask("default", {
509
- schema: stringSchema,
510
- handler: () => {
511
- throw new Error("boom");
512
- }
513
- });
514
- await federation.processQueuedTask(void 0, await makeTaskMessage("override", "data"));
515
- strictEqual(queue.enqueued.length, 1);
516
- await federation.processQueuedTask(void 0, await makeTaskMessage("default", "data"));
517
- strictEqual(queue.enqueued.length, 1);
518
- });
519
- await t.step("still retries when message.started is malformed", async () => {
520
- const queue = new MockQueue();
521
- const federation = createFederation({
522
- ...baseOptions,
523
- queue: { task: queue }
524
- });
525
- federation.defineTask("bad-started", {
526
- schema: stringSchema,
527
- handler: () => {
528
- throw new Error("boom");
529
- },
530
- retryPolicy: () => Temporal.Duration.from({ milliseconds: 1 })
531
- });
532
- const message = await makeTaskMessage("bad-started", "data", { started: "not-an-instant" });
533
- await federation.processQueuedTask(void 0, message);
534
- strictEqual(queue.enqueued.length, 1);
535
- strictEqual(queue.enqueued[0].message.attempt, 1);
536
- });
537
- await t.step("rethrows on a nativeRetrial queue", async () => {
538
- const queue = new MockQueue({ nativeRetrial: true });
539
- const federation = createFederation({
540
- ...baseOptions,
541
- queue: { task: queue }
542
- });
543
- federation.defineTask("native", {
544
- schema: stringSchema,
545
- handler: () => {
546
- throw new Error("boom");
547
- }
548
- });
549
- const message = await makeTaskMessage("native", "data");
550
- await rejects(() => federation.processQueuedTask(void 0, message), { message: /boom/ });
551
- strictEqual(queue.enqueued.length, 0);
552
- });
553
- });
554
- //#endregion
555
- export {};