@requence/service 0.8.2-edge.1156 → 0.8.2-edge.1157

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.js CHANGED
@@ -178,13 +178,27 @@ function isClaimCheckObject(data) {
178
178
 
179
179
  // ../helpers/src/utils/requenceCallback.ts
180
180
  import { z as z5 } from "zod/v4";
181
- var callbackObjectSchema = z5.object({
182
- sourceId: z5.string(),
183
- outputName: z5.string().nullable(),
184
- propertyPath: z5.array(z5.union([z5.string(), z5.int()])),
185
- callbackId: z5.uuid(),
186
- __REQUENCE_type: z5.literal("RequenceCallback")
187
- });
181
+ var REQUENCE_CALLBACK_TAG = "RequenceCallback";
182
+ var callbackPathSchema = z5.array(z5.union([z5.string(), z5.int()]));
183
+ var callbackObjectSchema = z5.discriminatedUnion("lifetime", [
184
+ z5.object({
185
+ __REQUENCE_type: z5.literal(REQUENCE_CALLBACK_TAG),
186
+ lifetime: z5.literal("connection"),
187
+ outputName: z5.string().nullable(),
188
+ propertyPath: callbackPathSchema,
189
+ sourceId: z5.string(),
190
+ callbackId: z5.uuid()
191
+ }),
192
+ z5.object({
193
+ __REQUENCE_type: z5.literal(REQUENCE_CALLBACK_TAG),
194
+ lifetime: z5.literal("durable"),
195
+ outputName: z5.string().nullable(),
196
+ propertyPath: callbackPathSchema,
197
+ name: z5.string(),
198
+ nodeId: z5.string(),
199
+ bound: z5.unknown().optional()
200
+ })
201
+ ]);
188
202
  function isCallbackObject(data) {
189
203
  return callbackObjectSchema.safeParse(data).success;
190
204
  }
@@ -200,6 +214,43 @@ function createCallback(callback) {
200
214
  }
201
215
  });
202
216
  }
217
+ var DURABLE_CALLBACK_BINDING = Symbol.for("requence.durableCallbackBinding");
218
+ function createDurableCallbackReference(binding) {
219
+ const reference = () => {
220
+ throw new Error(`durable callback "${binding.name}" was called in the service that emitted it — a durable callback reference is a value to emit, and it runs only when the graph invokes it`);
221
+ };
222
+ Object.defineProperty(reference, "name", {
223
+ value: binding.name,
224
+ configurable: true
225
+ });
226
+ return Object.defineProperty(reference, DURABLE_CALLBACK_BINDING, {
227
+ value: binding,
228
+ enumerable: false
229
+ });
230
+ }
231
+ function readDurableCallbackBinding(value) {
232
+ if (typeof value !== "function") {
233
+ return;
234
+ }
235
+ const binding = value[DURABLE_CALLBACK_BINDING];
236
+ return typeof binding === "object" && binding !== null && typeof binding.name === "string" ? binding : undefined;
237
+ }
238
+ function serviceCallbackQueueName(dispatchQueue) {
239
+ return `${dispatchQueue}-callbacks`;
240
+ }
241
+ var DURABLE_CALLBACK_INVOCATION_TTL_MS = 60000;
242
+ var DURABLE_CALLBACK_QUEUE_ARGUMENTS = {
243
+ messageTtl: DURABLE_CALLBACK_INVOCATION_TTL_MS,
244
+ deadLetterExchange: "error"
245
+ };
246
+ var durableCallbackInvocationSchema = z5.object({
247
+ taskId: z5.uuid(),
248
+ nodeId: z5.string(),
249
+ name: z5.string(),
250
+ bound: z5.unknown().optional(),
251
+ arg: z5.unknown().optional(),
252
+ configuration: z5.unknown().optional()
253
+ });
203
254
 
204
255
  // ../helpers/src/utils/serviceRender.ts
205
256
  import { z as z6 } from "zod/v4";
@@ -995,17 +1046,33 @@ function sanitizeLogData(data) {
995
1046
  // ../callbacks/src/handler.ts
996
1047
  function createRequenceCallbackHandler() {
997
1048
  return {
998
- tag: "RequenceCallback",
1049
+ tag: REQUENCE_CALLBACK_TAG,
999
1050
  canHandle: (value) => typeof value === "function",
1000
1051
  serialize(callback, ctx, path) {
1052
+ const binding = readDurableCallbackBinding(callback);
1053
+ if (binding) {
1054
+ if (!ctx.nodeId) {
1055
+ throw new Error(`durable callback "${binding.name}" cannot be emitted on this boundary (no ctx.nodeId) at path "${path.join(".")}"`);
1056
+ }
1057
+ return {
1058
+ __REQUENCE_type: REQUENCE_CALLBACK_TAG,
1059
+ lifetime: "durable",
1060
+ name: binding.name,
1061
+ nodeId: ctx.nodeId,
1062
+ bound: binding.bound,
1063
+ outputName: ctx.outputName ?? null,
1064
+ propertyPath: [...path]
1065
+ };
1066
+ }
1001
1067
  if (!ctx.onCallback) {
1002
1068
  throw new Error(`functions are not serializable on this boundary (no ctx.onCallback) at path "${path.join(".")}"`);
1003
1069
  }
1004
1070
  return {
1005
- ...ctx.onCallback(callback),
1071
+ ...ctx.onCallback(callback, path),
1072
+ lifetime: "connection",
1006
1073
  outputName: ctx.outputName ?? null,
1007
1074
  propertyPath: [...path],
1008
- __REQUENCE_type: "RequenceCallback"
1075
+ __REQUENCE_type: REQUENCE_CALLBACK_TAG
1009
1076
  };
1010
1077
  },
1011
1078
  isReference: (value) => isCallbackObject(value),
@@ -1189,6 +1256,10 @@ function createSurfaceHandlerValueHandler() {
1189
1256
  tag: SURFACE_HANDLER_TAG,
1190
1257
  canHandle: (value) => typeof value === "function",
1191
1258
  serialize(handler, ctx, path) {
1259
+ const binding = readDurableCallbackBinding(handler);
1260
+ if (binding) {
1261
+ throw new Error(`durable callback "${binding.name}" was put in a surface's props at "${path.join(".") || "<root>"}" — a callback addresses a position in the node's output schema, so it cannot be a UI prop; write the prop's handler in the UI's defaults instead`);
1262
+ }
1192
1263
  return ctx.onSurfaceHandler(handler, path);
1193
1264
  },
1194
1265
  isReference: (value) => isSurfaceHandlerObject(value),
@@ -1240,6 +1311,7 @@ function createOutboundBoundary(base) {
1240
1311
  maxFileSize: base.maxFileSize,
1241
1312
  measure,
1242
1313
  outputName: opts.outputName ?? null,
1314
+ nodeId: base.nodeId,
1243
1315
  onCallback: opts.onCallback,
1244
1316
  inlineKeys: opts.inlineKeys,
1245
1317
  ...opts.bestEffort ? {
@@ -1292,6 +1364,114 @@ function createInboundBoundary(base = {}) {
1292
1364
  };
1293
1365
  }
1294
1366
 
1367
+ // src/callbackGrowth.ts
1368
+ var DEV_OVERLAY_FIRST_WARNING = 100;
1369
+ var DEPLOYED_FIRST_WARNING = 1000;
1370
+ var TOP_PATHS = 3;
1371
+ function advance(from, count) {
1372
+ let next = from;
1373
+ while (next <= count) {
1374
+ next *= 10;
1375
+ }
1376
+ return next;
1377
+ }
1378
+ function formatWarning(params) {
1379
+ const worst = [...params.perPath.entries()].sort(([, a], [, b]) => b - a).slice(0, TOP_PATHS).map(([path, count]) => `${path} (${count})`).join(", ");
1380
+ return [
1381
+ `Requence: the functions you yield are piling up in memory and nothing frees them.`,
1382
+ ``,
1383
+ `Each one is kept for as long as the task runs, and it holds on to everything it`,
1384
+ `used from the code around it — including the whole value you were handling at`,
1385
+ `the time. On a task that runs for days, this service runs out of memory.`,
1386
+ ``,
1387
+ `If a function only needs data, and not a live connection or an open stream,`,
1388
+ `write it once at the top of your file and hand it the data each time:`,
1389
+ ``,
1390
+ ` const removeItem = createDurableCallback('removeItem', (arg, { id }) => ...)`,
1391
+ ``,
1392
+ ` yield { remove: removeItem.for({ id: item.id }) }`,
1393
+ ``,
1394
+ `Then there is one function, however many times you yield.`,
1395
+ ``,
1396
+ ` service: ${params.service}`,
1397
+ ` task: ${params.taskId}`,
1398
+ ` holding: ${params.delivery} from this task, ${params.connection} in this service`,
1399
+ ` worst: ${worst}`
1400
+ ].join(`
1401
+ `);
1402
+ }
1403
+ function createCallbackGrowthWatch({
1404
+ service,
1405
+ devOverlay,
1406
+ connectionCount,
1407
+ warn
1408
+ }) {
1409
+ const first = devOverlay ? DEV_OVERLAY_FIRST_WARNING : DEPLOYED_FIRST_WARNING;
1410
+ let nextConnection = first;
1411
+ return {
1412
+ forDelivery({ taskId }) {
1413
+ let delivery = 0;
1414
+ let nextDelivery = first;
1415
+ const perPath = new Map;
1416
+ return {
1417
+ record(path) {
1418
+ delivery += 1;
1419
+ const key = formatPath(path);
1420
+ perPath.set(key, (perPath.get(key) ?? 0) + 1);
1421
+ const connection = connectionCount();
1422
+ const crossedDelivery = delivery >= nextDelivery;
1423
+ const crossedConnection = connection >= nextConnection;
1424
+ if (!crossedDelivery && !crossedConnection) {
1425
+ return;
1426
+ }
1427
+ if (crossedDelivery) {
1428
+ nextDelivery = advance(nextDelivery, delivery);
1429
+ }
1430
+ if (crossedConnection) {
1431
+ nextConnection = advance(nextConnection, connection);
1432
+ }
1433
+ warn(formatWarning({ service, taskId, delivery, connection, perPath }));
1434
+ }
1435
+ };
1436
+ }
1437
+ };
1438
+ }
1439
+
1440
+ // src/durableCallback.ts
1441
+ var RESERVED_CONTEXT_KEY = "configuration";
1442
+ function assertBindable(name, bound) {
1443
+ if (bound === undefined || bound === null) {
1444
+ return;
1445
+ }
1446
+ if (typeof bound !== "object") {
1447
+ throw new Error(`durable callback "${name}" bound a ${typeof bound} — the bound data IS the callback's context, so it has to be an object`);
1448
+ }
1449
+ if (Object.hasOwn(bound, RESERVED_CONTEXT_KEY)) {
1450
+ throw new Error(`durable callback "${name}" bound a "${RESERVED_CONTEXT_KEY}" key — the bound data IS the callback's context, and that name is taken by the node's configuration`);
1451
+ }
1452
+ }
1453
+ var durableCallbacks = new Map;
1454
+ function createDurableCallback(name, handler) {
1455
+ if (durableCallbacks.has(name)) {
1456
+ throw new Error(`two durable callbacks share the name "${name}" — the name is the whole address of a durable callback, so pick a distinct one`);
1457
+ }
1458
+ durableCallbacks.set(name, { handler });
1459
+ const handle = createDurableCallbackReference({ name, bound: undefined });
1460
+ return Object.assign(handle, {
1461
+ for: (bound) => {
1462
+ assertBindable(name, bound);
1463
+ return createDurableCallbackReference({ name, bound });
1464
+ }
1465
+ });
1466
+ }
1467
+ function findDurableCallback(name) {
1468
+ return durableCallbacks.get(name);
1469
+ }
1470
+ function durableCallbackContext(name, bound, configuration) {
1471
+ assertBindable(name, bound);
1472
+ return { ...bound, configuration };
1473
+ }
1474
+
1295
1475
  // src/helpers.ts
1296
1476
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
1297
1477
  class RetryError extends Error {
@@ -1488,7 +1668,8 @@ var messageKeySchema = z9.string().transform((str) => deobfuscate(str)).pipe(z9.
1488
1668
  uploadUrl: arr[2] || undefined,
1489
1669
  streamUrl: arr[3] || undefined,
1490
1670
  maxPayloadSize: arr[4] && Number.isFinite(Number(arr[4])) ? Number(arr[4]) : undefined,
1491
- maxFileSize: arr[5] && Number.isFinite(Number(arr[5])) ? Number(arr[5]) : undefined
1671
+ maxFileSize: arr[5] && Number.isFinite(Number(arr[5])) ? Number(arr[5]) : undefined,
1672
+ nodeId: arr[6] || undefined
1492
1673
  }));
1493
1674
  var headerSchema = z9.object({
1494
1675
  properties: z9.object({
@@ -1509,6 +1690,7 @@ var payloadSchema = z9.object({
1509
1690
  }).transform((msg) => decodeWireBody(msg.content, msg.properties.contentType)).pipe(z9.object({
1510
1691
  input: z9.unknown().optional(),
1511
1692
  configuration: z9.unknown().optional(),
1693
+ nodeId: z9.string().optional(),
1512
1694
  options: z9.object({
1513
1695
  uploadUrl: z9.url().optional(),
1514
1696
  streamUrl: z9.url().optional(),
@@ -1581,6 +1763,15 @@ function safeAck(channel, message) {
1581
1763
  }
1582
1764
  }
1583
1765
  }
1766
+ function invocationHeaders(payload, invokingNodeId) {
1767
+ return {
1768
+ ...invokingNodeId ? { invokingNodeId } : {},
1769
+ ...payload.lifetime === "connection" ? { connectionId: payload.sourceId, callbackId: payload.callbackId } : { callbackName: payload.name, callbackNodeId: payload.nodeId }
1770
+ };
1771
+ }
1772
+ function invocationPayload(payload, arg) {
1773
+ return payload.lifetime === "connection" ? arg : { arg, bound: payload.bound };
1774
+ }
1584
1775
  function safeNack(channel, message) {
1585
1776
  try {
1586
1777
  channel.nack(message);
@@ -1615,7 +1806,7 @@ function createConnection({
1615
1806
  clientProperties: {
1616
1807
  ...connectionOptions?.clientProperties,
1617
1808
  ...buildServiceClientProperties({
1618
- libVersion: "javascript@0.8.2-edge.1156",
1809
+ libVersion: "javascript@0.8.2-edge.1157",
1619
1810
  serviceVersion: version,
1620
1811
  name,
1621
1812
  devOverlay: Boolean(devOverlay)
@@ -1670,6 +1861,12 @@ function createConnection({
1670
1861
  const sentComponents = new Set;
1671
1862
  const generatorTerminators = new Map;
1672
1863
  const callbacks = new Map;
1864
+ const callbackGrowth = createCallbackGrowthWatch({
1865
+ service: baseQueue,
1866
+ devOverlay: Boolean(devOverlay),
1867
+ connectionCount: () => callbacks.size,
1868
+ warn: (text) => simple_default.warn(text)
1869
+ });
1673
1870
  const backchannelInbound = createInboundBoundary(passthroughByteReferences ? { transformer: passthroughInboundTransformer } : {});
1674
1871
  const channelWrapper = connection.createChannel({
1675
1872
  async setup(channel) {
@@ -1824,6 +2021,43 @@ function createConnection({
1824
2021
  });
1825
2022
  }
1826
2023
  });
2024
+ async function runDurableCallbackInvocation(payload) {
2025
+ const parsed = durableCallbackInvocationSchema.safeParse(payload);
2026
+ if (!parsed.success) {
2027
+ simple_default.error("Requence: dropped a malformed durable callback invocation — it does not name a callback this build can run");
2028
+ return;
2029
+ }
2030
+ const { name: name2, bound, arg, configuration, taskId, nodeId } = parsed.data;
2031
+ const registration = findDurableCallback(name2);
2032
+ if (!registration) {
2033
+ throw new Error(`no durable callback registered as "${name2}" — a reference naming it was emitted by node ${nodeId} of task ${taskId}, and this version declares none`);
2034
+ }
2035
+ await registration.handler(arg, durableCallbackContext(name2, bound, configuration));
2036
+ }
2037
+ const callbackQueue = serviceCallbackQueueName(queue);
2038
+ const callbackChannelWrapper = connection.createChannel({
2039
+ async setup(channel) {
2040
+ await channel.assertQueue(callbackQueue, DURABLE_CALLBACK_QUEUE_ARGUMENTS);
2041
+ await channel.bindQueue(callbackQueue, "service", callbackQueue);
2042
+ await channel.prefetch(prefetch);
2043
+ await channel.consume(callbackQueue, async (message) => {
2044
+ if (!message) {
2045
+ return;
2046
+ }
2047
+ try {
2048
+ await runDurableCallbackInvocation(JSON.parse(message.content.toString()));
2049
+ } catch (error) {
2050
+ simple_default.error("Requence: durable callback threw:", error instanceof Error ? error.stack ?? error.message : error);
2051
+ }
2052
+ safeAck(channel, message);
2053
+ });
2054
+ }
2055
+ });
2056
+ callbackChannelWrapper.on("error", (err) => {
2057
+ if (!silent) {
2058
+ simple_default.error("Requence AMQP callback channel error:", err.message);
2059
+ }
2060
+ });
1827
2061
  handlerChannelWrapper.on("error", (err) => {
1828
2062
  if (!silent) {
1829
2063
  simple_default.error("Requence AMQP handler channel error:", err.message);
@@ -1917,7 +2151,7 @@ function createConnection({
1917
2151
  if (layer !== "props") {
1918
2152
  throw new Error(`a function in a render payload is only a handler under props or defaults (found at "${payloadPath.join(".")}")`);
1919
2153
  }
1920
- const { sourceId, callbackId } = deps.registerCallback(handler);
2154
+ const { sourceId, callbackId } = deps.registerCallback(handler, payloadPath);
1921
2155
  return {
1922
2156
  __REQUENCE_type: SURFACE_HANDLER_TAG,
1923
2157
  lifetime: "connection",
@@ -2001,13 +2235,15 @@ function createConnection({
2001
2235
  };
2002
2236
  const payload = payloadSchema.parse(message);
2003
2237
  const abortController = new AbortController;
2004
- const registerCallback = (callback) => {
2238
+ const growth = callbackGrowth.forDelivery({ taskId });
2239
+ const registerCallback = (callback, path2) => {
2005
2240
  const callbackId = crypto.randomUUID();
2006
2241
  registeredCallbackIds.add(callbackId);
2007
2242
  callbacks.set(callbackId, {
2008
2243
  callback,
2009
2244
  onCallbackInvoke: dispatchInvocation
2010
2245
  });
2246
+ growth.record(path2);
2011
2247
  return { sourceId: connectionId, callbackId };
2012
2248
  };
2013
2249
  const outbound = createOutboundBoundary({
@@ -2015,24 +2251,24 @@ function createConnection({
2015
2251
  streamUrl: payload.options.streamUrl,
2016
2252
  maxPayloadSize: payload.options.maxPayloadSize,
2017
2253
  maxFileSize: payload.options.maxFileSize,
2254
+ nodeId: payload.nodeId,
2018
2255
  wireCodec: dispatchCodec,
2019
2256
  signal: abortController.signal,
2020
2257
  warn: (msg, error) => simple_default.warn(`${msg} (task ${taskId})`, error instanceof Error ? error.message : error ?? "")
2021
2258
  });
2022
- const dispatchInvocation = (params) => {
2023
- outbound.track(outbound.send(params.arg, {
2024
- outputName: params.outputName,
2259
+ const dispatchInvocation = (invocation) => {
2260
+ outbound.track(outbound.send(invocation.arg, {
2261
+ outputName: invocation.outputName,
2025
2262
  onCallback: registerCallback
2026
2263
  }).then((data) => publish({
2027
2264
  index: 0,
2028
2265
  version,
2029
2266
  taskId,
2030
2267
  messageId,
2031
- data,
2032
- outputName: params.outputName,
2033
- connectionId: params.sourceId,
2034
- callbackId: params.callbackId,
2035
- propertyPath: params.propertyPath,
2268
+ data: invocationPayload(invocation, data),
2269
+ outputName: invocation.outputName,
2270
+ propertyPath: invocation.propertyPath,
2271
+ ...invocationHeaders(invocation, payload.nodeId),
2036
2272
  epoch
2037
2273
  })));
2038
2274
  };
@@ -2059,13 +2295,7 @@ function createConnection({
2059
2295
  passthroughByteReferences,
2060
2296
  sends: {
2061
2297
  ...buildSendApi(publishDeps),
2062
- invokeCallback: (ref, arg) => dispatchInvocation({
2063
- sourceId: ref.sourceId,
2064
- callbackId: ref.callbackId,
2065
- outputName: ref.outputName,
2066
- propertyPath: ref.propertyPath,
2067
- arg
2068
- }),
2298
+ invokeCallback: (ref, arg) => dispatchInvocation({ ...ref, arg }),
2069
2299
  options: payload.options
2070
2300
  },
2071
2301
  onLog(debugMethod, data) {
@@ -2090,7 +2320,7 @@ function createConnection({
2090
2320
  onDefer(reason) {
2091
2321
  deferred = true;
2092
2322
  deferredReason = reason || null;
2093
- return obfuscate(taskId, messageId, payload.options.uploadUrl ?? "", payload.options.streamUrl ?? "", payload.options.maxPayloadSize?.toString() ?? "", payload.options.maxFileSize?.toString() ?? "");
2323
+ return obfuscate(taskId, messageId, payload.options.uploadUrl ?? "", payload.options.streamUrl ?? "", payload.options.maxPayloadSize?.toString() ?? "", payload.options.maxFileSize?.toString() ?? "", payload.nodeId ?? "");
2094
2324
  },
2095
2325
  onCallback: dispatchInvocation
2096
2326
  });
@@ -2103,7 +2333,7 @@ function createConnection({
2103
2333
  begin: true,
2104
2334
  epoch,
2105
2335
  ...buildServiceIdentityHeaders({
2106
- libVersion: "javascript@0.8.2-edge.1156",
2336
+ libVersion: "javascript@0.8.2-edge.1157",
2107
2337
  name
2108
2338
  })
2109
2339
  });
@@ -2327,6 +2557,7 @@ function createConnection({
2327
2557
  const api = {
2328
2558
  close: async () => {
2329
2559
  stopUIWatch?.();
2560
+ await callbackChannelWrapper.close();
2330
2561
  await handlerChannelWrapper.close();
2331
2562
  await channelWrapper.close();
2332
2563
  await connection.close();
@@ -2346,29 +2577,30 @@ function createConnection({
2346
2577
  };
2347
2578
  const registeredCallbackIds = new Set;
2348
2579
  const outbound = createOutboundBoundary(options);
2349
- const registerCallback = (callback) => {
2580
+ const growth = callbackGrowth.forDelivery({ taskId });
2581
+ const registerCallback = (callback, path2) => {
2350
2582
  const callbackId = crypto.randomUUID();
2351
2583
  registeredCallbackIds.add(callbackId);
2352
2584
  callbacks.set(callbackId, {
2353
2585
  callback,
2354
2586
  onCallbackInvoke: dispatchInvocation
2355
2587
  });
2588
+ growth.record(path2);
2356
2589
  return { sourceId: connectionId, callbackId };
2357
2590
  };
2358
- const dispatchInvocation = (params) => {
2359
- outbound.track(outbound.send(params.arg, {
2360
- outputName: params.outputName,
2591
+ const dispatchInvocation = (invocation) => {
2592
+ outbound.track(outbound.send(invocation.arg, {
2593
+ outputName: invocation.outputName,
2361
2594
  onCallback: registerCallback
2362
2595
  }).then((data) => publish({
2363
2596
  index: 0,
2364
2597
  version,
2365
2598
  taskId,
2366
2599
  messageId,
2367
- data,
2368
- outputName: params.outputName,
2369
- connectionId: params.sourceId,
2370
- callbackId: params.callbackId,
2371
- propertyPath: params.propertyPath
2600
+ data: invocationPayload(invocation, data),
2601
+ outputName: invocation.outputName,
2602
+ propertyPath: invocation.propertyPath,
2603
+ ...invocationHeaders(invocation, options.nodeId)
2372
2604
  })));
2373
2605
  };
2374
2606
  const publishDeps = {
@@ -2517,30 +2749,36 @@ function asyncEventEmitter(initial = []) {
2517
2749
  context?.terminated.then(() => {
2518
2750
  terminated = true;
2519
2751
  });
2520
- let resolve2;
2521
- const initialValues = structuredClone(initial);
2752
+ const queue = structuredClone(initial);
2753
+ let waiting = null;
2522
2754
  return {
2523
2755
  push: (value) => {
2524
- if (resolve2) {
2756
+ if (waiting) {
2757
+ const resolve2 = waiting;
2758
+ waiting = null;
2525
2759
  resolve2(value);
2526
- } else {
2527
- initialValues.push(value);
2760
+ return;
2528
2761
  }
2762
+ queue.push(value);
2529
2763
  },
2530
2764
  [Symbol.asyncIterator]() {
2531
2765
  return {
2532
2766
  async next() {
2533
- if (initialValues.length > 0) {
2534
- return { value: initialValues.shift(), done: false };
2767
+ if (queue.length > 0) {
2768
+ return { value: queue.shift(), done: false };
2535
2769
  }
2536
2770
  const defer = Promise.withResolvers();
2537
- resolve2 = defer.resolve;
2771
+ waiting = defer.resolve;
2538
2772
  if (context) {
2539
2773
  const value = await Promise.race([
2540
2774
  defer.promise,
2541
2775
  context.terminated
2542
2776
  ]);
2543
- return terminated ? { done: true, value: undefined } : { done: false, value };
2777
+ if (terminated) {
2778
+ waiting = null;
2779
+ return { done: true, value: undefined };
2780
+ }
2781
+ return { done: false, value };
2544
2782
  }
2545
2783
  return { value: await defer.promise, done: false };
2546
2784
  }
@@ -2643,6 +2881,7 @@ export {
2643
2881
  isUnreachableStatus,
2644
2882
  createUI,
2645
2883
  createService,
2884
+ createDurableCallback,
2646
2885
  createCallback,
2647
2886
  asyncEventEmitter,
2648
2887
  assertReachable,
@@ -2655,5 +2894,5 @@ export {
2655
2894
  PayloadTooLargeError
2656
2895
  };
2657
2896
 
2658
- //# debugId=35955FCD96E8C5C764756E2164756E21
2897
+ //# debugId=B9ACB95FA979832B64756E2164756E21
2659
2898
  //# sourceMappingURL=index.js.map