@workflow/world-testing 5.0.0-beta.46 → 5.0.0-beta.47

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.
@@ -2804,6 +2804,7 @@ var RegisteredStepsKey, globalSymbols, registeredSteps, BUILTIN_RESPONSE_STEP_NA
2804
2804
  var init_private = __esm({
2805
2805
  "../core/dist/private.js"() {
2806
2806
  "use strict";
2807
+ init_dist2();
2807
2808
  init_global();
2808
2809
  RegisteredStepsKey = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps");
2809
2810
  globalSymbols = globalThis;
@@ -19509,8 +19510,9 @@ var init_queue = __esm({
19509
19510
  /** Epoch ms immediately before the queue publish was requested. */
19510
19511
  queuePublishRequestedAtMs: external_exports.number(),
19511
19512
  /**
19512
- * Which `resumeHook()` dispatch path ran: `lazy` or `sequential` (`parallel`
19513
- * from producers predating lazy-only resume).
19513
+ * Which `resumeHook()` dispatch path ran. Current producers always report
19514
+ * `sequential` (durable write, then wake); older producers may report
19515
+ * `lazy` or `parallel`.
19514
19516
  */
19515
19517
  strategy: external_exports.string().optional(),
19516
19518
  /** Epoch ms the final consumer's queue handler was entered. */
@@ -19582,9 +19584,9 @@ var init_queue = __esm({
19582
19584
  /** Run creation data, only present on the first queue delivery from start() */
19583
19585
  runInput: RunInputSchema.optional(),
19584
19586
  /**
19585
- * Lazy hook resume data, only present when `resumeHook()` takes the parallel
19586
- * fast path. A consumer that understands this field idempotently ensures the
19587
- * `hook_received` event exists (keyed by `resumeId`) before replaying.
19587
+ * Legacy lazy hook resume data. A consumer that understands this field
19588
+ * idempotently ensures the `hook_received` event exists (keyed by `resumeId`)
19589
+ * before replaying.
19588
19590
  */
19589
19591
  hookInput: HookResumeInputSchema.optional(),
19590
19592
  /**
@@ -19596,7 +19598,7 @@ var init_queue = __esm({
19596
19598
  stepInput: StepDispatchInputSchema.optional(),
19597
19599
  /**
19598
19600
  * Hook-resume TTR timing. Present on both `resumeHook()` dispatch paths
19599
- * (unlike `hookInput`, which only rides the lazy path), and
19601
+ * (unlike legacy `hookInput`), and
19600
19602
  * forwarded onto a dispatched step message when the resuming invocation
19601
19603
  * hands the next durable step to another invocation. Purely observational.
19602
19604
  * See {@link HookResumeTimingSchema}.
@@ -19654,12 +19656,14 @@ var init_hooks = __esm({
19654
19656
  encryptionPublicKey: external_exports.string().optional(),
19655
19657
  // Feature marker: the version of the lazy-hook-resume consumer protocol the
19656
19658
  // run's creating deployment supports. Present (>= 1) means that deployment's
19657
- // `@workflow/core` re-ensures the `hook_received` event from the queue
19658
- // message's `hookInput` on replay, so `resumeHook()`'s lazy path is safe to
19659
- // use. Because a run is pinned to its creating deployment, this
19660
- // marker is a reliable per-run attestation, unlike inferring support from a
19661
- // version compare against a predicted release cutoff. Absent on runs created
19662
- // before the marker existed (fall back to the sequential path).
19659
+ // `@workflow/core` re-ensures the `hook_received` event from a queue
19660
+ // message's `hookInput` on replay. Current producers no longer send
19661
+ // `hookInput` (the durable write happens before the wake is published), so
19662
+ // they never read this marker; it remains stamped so OLDER producers, which
19663
+ // still gate their lazy path on it, keep working against new runs. Because a
19664
+ // run is pinned to its creating deployment, this marker is a reliable
19665
+ // per-run attestation, unlike inferring support from a version compare
19666
+ // against a predicted release cutoff.
19663
19667
  hookResumeInputVersion: external_exports.number().optional()
19664
19668
  });
19665
19669
  HOOK_RESUME_INPUT_VERSION = 1;
@@ -21227,7 +21231,7 @@ function SemanticConvention(...names) {
21227
21231
  value
21228
21232
  ]));
21229
21233
  }
21230
- var WorkflowName, WorkflowOperation, WorkflowRunId, WorkflowRunStatus, WorkflowStartedAt, WorkflowEventsCount, WorkflowExecutionMode, WorkflowParkedEventsCount, WorkflowParkedEventId, WorkflowParkedEventType, WorkflowArgumentsCount, WorkflowResultType, WorkflowTracePropagated, WorkflowVm, QuickJSOutcome, QuickJSEventsPreloaded, QuickJSEventsFetchedCount, QuickJSEventsFetchedPages, QuickJSPendingOpsCount, QuickJSInlineSteps, WorkflowTraceMode, WorkflowTurbo, WorkflowErrorName, WorkflowErrorMessage, WorkflowErrorCode, WorkflowStepsCreated, WorkflowHooksCreated, WorkflowWaitsCreated, WorkflowStepsFailedSerialization, WorkflowOwnedRecoverySteps, WorkflowBackstopWakesArmed, WorkflowRouteType, WorkflowRouteHandlerCached, WorkflowRouteInvocationCount, WorkflowRouteEntrypointAgeMs, WorkflowRouteModuleBodyInitMs, FaasInstance, StepName, StepId, StepAttempt, StepStatus, StepMaxRetries, StepTracePropagated, StepTtfsMs, StepStsoMs, StepRsfsMs, StepFinalSchedulingReplayMs, StepLatencyOptimizations, StepSkipped, StepSkipReason, StepArgumentsCount, StepResultType, StepErrorName, StepErrorMessage, StepFatalError, StepRetryExhausted, StepRetryTimeoutSeconds, StepRetryWillRetry, MessagingSystem, MessagingDestinationName, MessagingMessageId, MessagingOperationType, QueueOverheadMs, DeploymentId, WorkflowRunPinnedDeploymentId, WorkflowDeploymentMismatchRetryCount, WorkflowDeploymentMismatchRecovered, HookToken, HookId, HookFound, HookResilientResume, HookResilientResumeMaterialized, HookResumeSetupSource, StepResilientDispatchRecovered, StepResilientDispatchMaterialized, ResumeTotalMs, ResumeProducerPrepMs, ResumeQueueDeliveryMs, ResumeSetupMs, ResumeReplayMs, ResumeStepDispatchMs, ResumeStepClaimMs, ResumeStepPrepareMs, ResumeTrigger, ResumeStrategy, ResumeSetupSource, ResumeStepExecution, WebhookHandlersTriggered, WorkflowSuspensionState, WorkflowSuspensionHookCount, WorkflowSuspensionStepCount, WorkflowSuspensionWaitCount, HttpRequestMethod, HttpRoute, UrlFull, ServerAddress, ServerPort, HttpResponseStatusCode, ErrorType, WorldParseFormat, WorkflowEventsPagesLoaded, QueueDeserializeTimeMs, QueueExecutionTimeMs, QueueSerializeTimeMs, SerializationOperation, SerializationCompressed, SerializationCodec, SerializationUncompressedBytes, SerializationStoredBytes, SerializationCompressionRatio, SerializationGuestCodeExecutions, SerializationGuestCodeDetails, PeerService, RpcSystem, RpcService, RpcMethod, ErrorRetryable, ErrorCategory;
21234
+ var WorkflowName, WorkflowOperation, WorkflowRunId, WorkflowRunStatus, WorkflowStartedAt, WorkflowEventsCount, WorkflowExecutionMode, WorkflowBundleCompileCacheHit, WorkflowReplayLoadSource, WorkflowParkedEventsCount, WorkflowParkedEventId, WorkflowParkedEventType, WorkflowArgumentsCount, WorkflowResultType, WorkflowTracePropagated, WorkflowVm, QuickJSOutcome, QuickJSEventsPreloaded, QuickJSEventsFetchedCount, QuickJSEventsFetchedPages, QuickJSPendingOpsCount, QuickJSInlineSteps, WorkflowTraceMode, WorkflowTurbo, WorkflowErrorName, WorkflowErrorMessage, WorkflowErrorCode, WorkflowStepsCreated, WorkflowHooksCreated, WorkflowWaitsCreated, WorkflowStepsFailedSerialization, WorkflowOwnedRecoverySteps, WorkflowBackstopWakesArmed, WorkflowRouteType, WorkflowRouteHandlerCached, WorkflowRouteInvocationCount, WorkflowRouteEntrypointAgeMs, WorkflowRouteModuleBodyInitMs, FaasInstance, StepName, StepId, StepAttempt, StepStatus, StepMaxRetries, StepTracePropagated, StepTtfsMs, StepStsoMs, StepRsfsMs, StepFinalSchedulingReplayMs, StepLatencyOptimizations, StepSkipped, StepSkipReason, StepArgumentsCount, StepResultType, StepErrorName, StepErrorMessage, StepFatalError, StepRetryExhausted, StepRetryTimeoutSeconds, StepRetryWillRetry, MessagingSystem, MessagingDestinationName, MessagingMessageId, MessagingOperationType, QueueOverheadMs, DeploymentId, WorkflowRunPinnedDeploymentId, WorkflowDeploymentMismatchRetryCount, WorkflowDeploymentMismatchRecovered, HookToken, HookId, HookFound, HookResilientResume, HookResumeCommitted, HookWakePublished, HookResilientResumeMaterialized, HookResumeSetupSource, StepResilientDispatchRecovered, StepResilientDispatchMaterialized, ResumeTotalMs, ResumeProducerPrepMs, ResumeQueueDeliveryMs, ResumeSetupMs, ResumeReplayMs, ResumeStepDispatchMs, ResumeStepClaimMs, ResumeStepPrepareMs, ResumeTrigger, ResumeStrategy, ResumeSetupSource, ResumeStepExecution, WebhookHandlersTriggered, WorkflowSuspensionState, WorkflowSuspensionHookCount, WorkflowSuspensionStepCount, WorkflowSuspensionWaitCount, HttpRequestMethod, HttpRoute, UrlFull, ServerAddress, ServerPort, HttpResponseStatusCode, ErrorType, WorldParseFormat, WorkflowEventsPagesLoaded, QueueDeserializeTimeMs, QueueExecutionTimeMs, QueueSerializeTimeMs, SerializationOperation, SerializationCompressed, SerializationCodec, SerializationUncompressedBytes, SerializationStoredBytes, SerializationCompressionRatio, SerializationGuestCodeExecutions, SerializationGuestCodeDetails, PeerService, RpcSystem, RpcService, RpcMethod, ErrorRetryable, ErrorCategory;
21231
21235
  var init_semantic_conventions = __esm({
21232
21236
  "../core/dist/telemetry/semantic-conventions.js"() {
21233
21237
  "use strict";
@@ -21239,6 +21243,8 @@ var init_semantic_conventions = __esm({
21239
21243
  WorkflowStartedAt = SemanticConvention("workflow.started_at");
21240
21244
  WorkflowEventsCount = SemanticConvention("workflow.events.count");
21241
21245
  WorkflowExecutionMode = SemanticConvention("workflow.execution.mode");
21246
+ WorkflowBundleCompileCacheHit = SemanticConvention("workflow.bundle.compile.cache_hit");
21247
+ WorkflowReplayLoadSource = SemanticConvention("workflow.replay.load.source");
21242
21248
  WorkflowParkedEventsCount = SemanticConvention("workflow.events.parked.count");
21243
21249
  WorkflowParkedEventId = SemanticConvention("workflow.events.parked.event_id");
21244
21250
  WorkflowParkedEventType = SemanticConvention("workflow.events.parked.event_type");
@@ -21303,6 +21309,8 @@ var init_semantic_conventions = __esm({
21303
21309
  HookId = SemanticConvention("workflow.hook.id");
21304
21310
  HookFound = SemanticConvention("workflow.hook.found");
21305
21311
  HookResilientResume = SemanticConvention("workflow.hook.resilient_resume");
21312
+ HookResumeCommitted = SemanticConvention("workflow.hook.resume_committed");
21313
+ HookWakePublished = SemanticConvention("workflow.hook.wake_published");
21306
21314
  HookResilientResumeMaterialized = SemanticConvention("workflow.hook.resilient_resume_materialized");
21307
21315
  HookResumeSetupSource = SemanticConvention("workflow.resume_setup_source");
21308
21316
  StepResilientDispatchRecovered = SemanticConvention("workflow.step.resilient_dispatch_recovered");
@@ -23405,6 +23413,16 @@ async function deserializeTraceCarrier(traceCarrier) {
23405
23413
  if (!otel) return;
23406
23414
  return otel.propagation.extract(otel.context.active(), traceCarrier);
23407
23415
  }
23416
+ function describeThrownValue(value) {
23417
+ try {
23418
+ if (typeof value === "object" && value !== null && "message" in value && typeof value.message === "string") {
23419
+ return value.message;
23420
+ }
23421
+ return String(value);
23422
+ } catch {
23423
+ return "Unknown error";
23424
+ }
23425
+ }
23408
23426
  function logOtelDiagnosticOnce(otel, tracer) {
23409
23427
  const debugEnabled = typeof process !== "undefined" && typeof process.env.DEBUG === "string" && (process.env.DEBUG.includes("workflow:") || process.env.DEBUG === "*");
23410
23428
  if (otelDiagLogged || !debugEnabled) return;
@@ -23459,7 +23477,7 @@ async function trace(spanName, ...args) {
23459
23477
  } else {
23460
23478
  span.setStatus({
23461
23479
  code: otel.SpanStatusCode.ERROR,
23462
- message: e.message
23480
+ message: describeThrownValue(e)
23463
23481
  });
23464
23482
  }
23465
23483
  throw e;
@@ -23552,6 +23570,7 @@ var init_telemetry = __esm({
23552
23570
  });
23553
23571
  });
23554
23572
  otelDiagLogged = false;
23573
+ __name(describeThrownValue, "describeThrownValue");
23555
23574
  __name(logOtelDiagnosticOnce, "logOtelDiagnosticOnce");
23556
23575
  __name(trace, "trace");
23557
23576
  __name(recordElapsedSpan, "recordElapsedSpan");
@@ -25963,7 +25982,7 @@ var version2;
25963
25982
  var init_version = __esm({
25964
25983
  "../core/dist/version.js"() {
25965
25984
  "use strict";
25966
- version2 = "5.0.0-beta.46";
25985
+ version2 = "5.0.0-beta.47";
25967
25986
  }
25968
25987
  });
25969
25988
 
@@ -31094,7 +31113,6 @@ var resume_hook_exports = {};
31094
31113
  __export(resume_hook_exports, {
31095
31114
  getHookByToken: () => getHookByToken,
31096
31115
  resumeHook: () => resumeHook,
31097
- resumeHookDurable: () => resumeHookDurable,
31098
31116
  resumeWebhook: () => resumeWebhook
31099
31117
  });
31100
31118
  async function computeResumePayloadDigest(bytes) {
@@ -31106,6 +31124,38 @@ async function computeResumePayloadDigest(bytes) {
31106
31124
  }
31107
31125
  return hex3;
31108
31126
  }
31127
+ function isRetryableWakeError(error48, isDeploymentUnavailableError) {
31128
+ if (isDeploymentUnavailableError?.(error48)) return false;
31129
+ const status = error48 ?? {};
31130
+ const code2 = status.status ?? status.statusCode;
31131
+ if (typeof code2 === "number") {
31132
+ return code2 >= 500 || code2 === 408 || code2 === 429;
31133
+ }
31134
+ const name = error48?.name;
31135
+ return name !== "BadRequestError" && name !== "UnauthorizedError" && name !== "ForbiddenError";
31136
+ }
31137
+ async function publishHookWakeWithRetry(publish, isDeploymentUnavailableError) {
31138
+ let lastError;
31139
+ for (let attempt = 0; attempt <= HOOK_WAKE_RETRY_DELAYS_MS.length; attempt++) {
31140
+ try {
31141
+ await publish();
31142
+ return;
31143
+ } catch (error48) {
31144
+ lastError = error48;
31145
+ if (!isRetryableWakeError(error48, isDeploymentUnavailableError)) break;
31146
+ const delayMs = HOOK_WAKE_RETRY_DELAYS_MS[attempt];
31147
+ if (delayMs !== void 0) {
31148
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
31149
+ }
31150
+ }
31151
+ }
31152
+ if (HookNotFoundError.is(lastError)) {
31153
+ throw new WorkflowRuntimeError("The hook resume was committed, but its workflow wake could not be published", {
31154
+ cause: lastError
31155
+ });
31156
+ }
31157
+ throw lastError;
31158
+ }
31109
31159
  function resumeContextFromRun(run2) {
31110
31160
  const coreVersion = run2.executionContext?.workflowCoreVersion;
31111
31161
  const traceCarrier = run2.executionContext?.traceCarrier;
@@ -31163,12 +31213,9 @@ async function getHookByToken(token) {
31163
31213
  return hook;
31164
31214
  }
31165
31215
  async function resumeHook(tokenOrHook, payload, encryptionKeyOverride) {
31166
- return resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, false, Date.now(), false);
31167
- }
31168
- async function resumeHookDurable(tokenOrHook, payload, encryptionKeyOverride) {
31169
- return resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, false, Date.now(), true);
31216
+ return resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, false, Date.now());
31170
31217
  }
31171
- async function resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, hookFreshlyLookedUp, resumeRequestedAtMs, requireDurableWrite) {
31218
+ async function resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, hookFreshlyLookedUp, resumeRequestedAtMs) {
31172
31219
  return await waitedUntil(() => {
31173
31220
  return trace("hook.resume", async (span) => {
31174
31221
  const world = await getWorldLazy();
@@ -31205,11 +31252,15 @@ async function resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, hookF
31205
31252
  }
31206
31253
  const compression = (resumeContext.runSpecVersion ?? 0) >= SPEC_VERSION_SUPPORTS_COMPRESSION && capabilities.supportedFormats.has(SerializationFormat.GZIP);
31207
31254
  const ops = [];
31255
+ const readbackOps = [];
31208
31256
  const v1Compat = isLegacySpecVersion(hook.specVersion);
31209
- const dehydratedPayload = await dehydrateStepReturnValue(payload, hook.runId, payloadKey, ops, globalThis, v1Compat, capabilities.framedByteStreams, compression);
31210
- safeWaitUntil(Promise.all(ops), (err) => {
31257
+ const dehydratedPayload = await dehydrateStepReturnValue(payload, hook.runId, payloadKey, ops, globalThis, v1Compat, capabilities.framedByteStreams, compression, void 0, readbackOps);
31258
+ await Promise.all(ops.map((op) => op.catch((error48) => {
31259
+ if (error48 !== void 0) throw error48;
31260
+ })));
31261
+ safeWaitUntil(Promise.all(readbackOps), (err) => {
31211
31262
  if (err === void 0) return;
31212
- runtimeLogger.warn("Background flush of hook payload ops failed", {
31263
+ runtimeLogger.warn("Background readback of hook payload failed", {
31213
31264
  workflowRunId: hook.runId,
31214
31265
  hookId: hook.hookId,
31215
31266
  error: err instanceof Error ? err.message : String(err)
@@ -31227,81 +31278,66 @@ async function resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, hookF
31227
31278
  deploymentId: resumeContext.deploymentId,
31228
31279
  specVersion: resumeContext.runSpecVersion ?? SPEC_VERSION_LEGACY
31229
31280
  };
31230
- const lazyResumeDisabled = process.env.WORKFLOW_DISABLE_LAZY_HOOK_RESUME === "1";
31231
31281
  const backendDedupSupported = (hookResumeCapabilitiesAreFresh ? hook.resumeCapabilities?.hookResumeDedupVersion ?? 0 : 0) >= HOOK_RESUME_DEDUP_VERSION || world.capabilities?.hookResumeDedup === true;
31232
- const fallbackReason = requireDurableWrite ? (
31233
- // resolves (an ordering barrier), which only the eager write
31234
- // provides. Checked first so the span names the real reason
31235
- // rather than whichever gate happens to fail alongside it.
31236
- "durable_required"
31237
- ) : lazyResumeDisabled ? "disabled" : !backendDedupSupported ? "backend_unsupported" : (resumeContext.hookResumeInputVersion ?? 0) < HOOK_RESUME_INPUT_VERSION ? "consumer_unsupported" : v1Compat ? "legacy" : (resumeContext.runSpecVersion ?? 0) < SPEC_VERSION_SUPPORTS_CBOR_QUEUE_TRANSPORT ? "non_cbor_transport" : !(dehydratedPayload instanceof Uint8Array) ? "non_bytes" : dehydratedPayload.byteLength > MAX_INLINE_RESUME_PAYLOAD_BYTES ? "oversized" : null;
31238
- const useLazyResume = fallbackReason === null;
31282
+ const canClaimResume = backendDedupSupported && !v1Compat && dehydratedPayload instanceof Uint8Array;
31239
31283
  span?.setAttributes({
31240
- "workflow.hook.resume_strategy": useLazyResume ? "lazy" : "sequential",
31241
- ...fallbackReason ? {
31242
- "workflow.hook.resume_fallback_reason": fallbackReason
31243
- } : {}
31284
+ "workflow.hook.resume_strategy": "sequential"
31244
31285
  });
31245
- if (!useLazyResume) {
31246
- const isHookGoneError = /* @__PURE__ */ __name((err) => HookNotFoundError.is(err) || EntityConflictError.is(err) || RunExpiredError.is(err), "isHookGoneError");
31247
- try {
31248
- await world.events.create(hook.runId, {
31249
- eventType: "hook_received",
31250
- specVersion: SPEC_VERSION_CURRENT,
31251
- correlationId: hook.hookId,
31252
- eventData: {
31253
- ...v1Compat ? {} : {
31254
- token: hook.token
31255
- },
31256
- payload: dehydratedPayload
31257
- }
31258
- }, {
31259
- v1Compat
31260
- });
31261
- } catch (err) {
31262
- if (isHookGoneError(err)) {
31263
- throw new HookNotFoundError(hook.token);
31264
- }
31265
- throw err;
31266
- }
31267
- const queuePublishRequestedAtMs2 = Date.now();
31268
- await world.queue(queueName, {
31269
- runId: hook.runId,
31270
- traceCarrier: resumeContext.traceCarrier ?? void 0,
31271
- hookResumeTiming: {
31272
- resumeRequestedAtMs,
31273
- queuePublishRequestedAtMs: queuePublishRequestedAtMs2,
31274
- strategy: "sequential"
31286
+ const resumeId = canClaimResume ? generateResumeId() : void 0;
31287
+ const payloadDigest = canClaimResume ? await computeResumePayloadDigest(dehydratedPayload) : void 0;
31288
+ if (resumeId) {
31289
+ span?.setAttributes({
31290
+ "workflow.hook.resume_id": resumeId
31291
+ });
31292
+ }
31293
+ const isHookGoneError = /* @__PURE__ */ __name((err) => HookNotFoundError.is(err) || RunExpiredError.is(err), "isHookGoneError");
31294
+ try {
31295
+ await world.events.create(hook.runId, {
31296
+ eventType: "hook_received",
31297
+ specVersion: SPEC_VERSION_CURRENT,
31298
+ correlationId: hook.hookId,
31299
+ eventData: {
31300
+ ...v1Compat ? {} : {
31301
+ token: hook.token
31302
+ },
31303
+ payload: dehydratedPayload
31275
31304
  }
31276
- }, queueOptions);
31277
- return hook;
31305
+ }, {
31306
+ v1Compat,
31307
+ ...resumeId && payloadDigest ? {
31308
+ resumeId,
31309
+ resumePayloadDigest: payloadDigest
31310
+ } : {}
31311
+ });
31312
+ } catch (err) {
31313
+ if (isHookGoneError(err)) {
31314
+ throw new HookNotFoundError(hook.token);
31315
+ }
31316
+ throw err;
31278
31317
  }
31279
- const resumeId = generateResumeId();
31280
- const payloadDigest = await computeResumePayloadDigest(dehydratedPayload);
31281
- span?.setAttributes({
31282
- "workflow.hook.resume_id": resumeId
31283
- });
31318
+ span?.setAttributes(HookResumeCommitted(true));
31284
31319
  const queuePublishRequestedAtMs = Date.now();
31285
- await world.queue(queueName, {
31320
+ await publishHookWakeWithRetry(() => world.queue(queueName, {
31286
31321
  runId: hook.runId,
31287
31322
  traceCarrier: resumeContext.traceCarrier ?? void 0,
31288
- hookInput: {
31289
- resumeId,
31290
- hookId: hook.hookId,
31291
- token: hook.token,
31292
- payload: dehydratedPayload,
31293
- payloadDigest,
31294
- // Deployment affinity for the consumer's cheap pre-write
31295
- // check: lets a misrouted delivery re-route before its
31296
- // hoisted hook_received write instead of after.
31297
- deploymentId: resumeContext.deploymentId
31298
- },
31299
31323
  hookResumeTiming: {
31300
31324
  resumeRequestedAtMs,
31301
31325
  queuePublishRequestedAtMs,
31302
- strategy: "lazy"
31326
+ strategy: "sequential"
31303
31327
  }
31304
- }, queueOptions);
31328
+ }, {
31329
+ ...queueOptions,
31330
+ // Dedup retried publishes whose response was lost: a
31331
+ // duplicate wake is harmless for correctness (deterministic
31332
+ // replay) but costs a full replay of the run, and the queue
31333
+ // accepts a repeated idempotency key by delivering only one
31334
+ // of the messages. Claim-less writes have no resumeId and
31335
+ // keep the previous behavior.
31336
+ ...resumeId ? {
31337
+ idempotencyKey: `hook-${resumeId}`
31338
+ } : {}
31339
+ }), world.isDeploymentUnavailableError?.bind(world));
31340
+ span?.setAttributes(HookWakePublished(true));
31305
31341
  return hook;
31306
31342
  } catch (err) {
31307
31343
  span?.setAttributes({
@@ -31338,7 +31374,7 @@ async function resumeWebhook(token, request) {
31338
31374
  status: 202
31339
31375
  });
31340
31376
  }
31341
- await resumeHookImpl(hook, request, encryptionKey, true, resumeRequestedAtMs, false);
31377
+ await resumeHookImpl(hook, request, encryptionKey, true, resumeRequestedAtMs);
31342
31378
  if (responseReadable) {
31343
31379
  const reader = responseReadable.getReader();
31344
31380
  const chunk = await reader.read();
@@ -31354,7 +31390,7 @@ async function resumeWebhook(token, request) {
31354
31390
  }
31355
31391
  return response;
31356
31392
  }
31357
- var generateResumeId, MAX_INLINE_RESUME_PAYLOAD_BYTES;
31393
+ var generateResumeId, HOOK_WAKE_RETRY_DELAYS_MS;
31358
31394
  var init_resume_hook = __esm({
31359
31395
  "../core/dist/runtime/resume-hook.js"() {
31360
31396
  "use strict";
@@ -31374,15 +31410,19 @@ var init_resume_hook = __esm({
31374
31410
  init_helpers();
31375
31411
  init_wait_until();
31376
31412
  generateResumeId = monotonicFactory();
31377
- MAX_INLINE_RESUME_PAYLOAD_BYTES = 128 * 1024;
31378
31413
  __name(computeResumePayloadDigest, "computeResumePayloadDigest");
31414
+ HOOK_WAKE_RETRY_DELAYS_MS = [
31415
+ 25,
31416
+ 100
31417
+ ];
31418
+ __name(isRetryableWakeError, "isRetryableWakeError");
31419
+ __name(publishHookWakeWithRetry, "publishHookWakeWithRetry");
31379
31420
  __name(resumeContextFromRun, "resumeContextFromRun");
31380
31421
  __name(resolveHookResumeInfo, "resolveHookResumeInfo");
31381
31422
  __name(resolveHookEncryptionKey, "resolveHookEncryptionKey");
31382
31423
  __name(getHookByTokenWithKey, "getHookByTokenWithKey");
31383
31424
  __name(getHookByToken, "getHookByToken");
31384
31425
  __name(resumeHook, "resumeHook");
31385
- __name(resumeHookDurable, "resumeHookDurable");
31386
31426
  __name(resumeHookImpl, "resumeHookImpl");
31387
31427
  __name(resumeWebhook, "resumeWebhook");
31388
31428
  }
@@ -31945,7 +31985,7 @@ function attachAbortListenerOnce(signal, streamName, runId, cryptoKey, ops) {
31945
31985
  once: true
31946
31986
  });
31947
31987
  }
31948
- function getExternalReducers(global2 = globalThis, ops, runId, cryptoKey, framedByteStreams = false, runReadyBarrier) {
31988
+ function getExternalReducers(global2 = globalThis, ops, runId, cryptoKey, framedByteStreams = false, runReadyBarrier, readbackOps = ops) {
31949
31989
  return {
31950
31990
  ...getAllBaseReducers(global2),
31951
31991
  ReadableStream: /* @__PURE__ */ __name((value) => {
@@ -31966,7 +32006,7 @@ function getExternalReducers(global2 = globalThis, ops, runId, cryptoKey, framed
31966
32006
  ops.push(value.pipeTo(writable));
31967
32007
  }
31968
32008
  } else {
31969
- ops.push(value.pipeThrough(getSerializeStream(getExternalReducers(global2, ops, runId, cryptoKey, framedByteStreams, runReadyBarrier), cryptoKey)).pipeTo(writable));
32009
+ ops.push(value.pipeThrough(getSerializeStream(getExternalReducers(global2, ops, runId, cryptoKey, framedByteStreams, runReadyBarrier, readbackOps), cryptoKey)).pipeTo(writable));
31970
32010
  }
31971
32011
  const s = {
31972
32012
  name
@@ -31997,7 +32037,7 @@ function getExternalReducers(global2 = globalThis, ops, runId, cryptoKey, framed
31997
32037
  const streamId = (global2[STABLE_ULID] || defaultUlid)();
31998
32038
  const name = `strm_${streamId}`;
31999
32039
  const readable = new WorkflowServerReadableStream(runId, name);
32000
- ops.push(readable.pipeTo(value));
32040
+ readbackOps.push(readable.pipeTo(value));
32001
32041
  return {
32002
32042
  name
32003
32043
  };
@@ -32096,7 +32136,7 @@ function getWorkflowReducers(global2 = globalThis) {
32096
32136
  }, "AbortSignal")
32097
32137
  };
32098
32138
  }
32099
- function getStepReducers(global2 = globalThis, ops, runId, cryptoKey, framedByteStreams = false, runReadyBarrier) {
32139
+ function getStepReducers(global2 = globalThis, ops, runId, cryptoKey, framedByteStreams = false, runReadyBarrier, readbackOps = ops) {
32100
32140
  return {
32101
32141
  ...getAllBaseReducers(global2),
32102
32142
  ReadableStream: /* @__PURE__ */ __name((value) => {
@@ -32122,7 +32162,7 @@ function getStepReducers(global2 = globalThis, ops, runId, cryptoKey, framedByte
32122
32162
  ops.push(value.pipeTo(writable));
32123
32163
  }
32124
32164
  } else {
32125
- ops.push(value.pipeThrough(getSerializeStream(getStepReducers(global2, ops, runId, cryptoKey, framedByteStreams, runReadyBarrier), cryptoKey)).pipeTo(writable));
32165
+ ops.push(value.pipeThrough(getSerializeStream(getStepReducers(global2, ops, runId, cryptoKey, framedByteStreams, runReadyBarrier, readbackOps), cryptoKey)).pipeTo(writable));
32126
32166
  }
32127
32167
  }
32128
32168
  const s = {
@@ -32139,7 +32179,7 @@ function getStepReducers(global2 = globalThis, ops, runId, cryptoKey, framedByte
32139
32179
  if (!name) {
32140
32180
  const streamId = (global2[STABLE_ULID] || defaultUlid)();
32141
32181
  name = `strm_${streamId}`;
32142
- ops.push(new WorkflowServerReadableStream(runId, name).pipeThrough(getDeserializeStream(getStepRevivers(global2, ops, runId, cryptoKey), cryptoKey)).pipeTo(value));
32182
+ readbackOps.push(new WorkflowServerReadableStream(runId, name).pipeThrough(getDeserializeStream(getStepRevivers(global2, readbackOps, runId, cryptoKey), cryptoKey)).pipeTo(value));
32143
32183
  }
32144
32184
  const s = {
32145
32185
  name
@@ -32268,8 +32308,8 @@ function reviveAbortController(value, ops, runId) {
32268
32308
  if (value.hookToken) {
32269
32309
  const hookResume = (async () => {
32270
32310
  try {
32271
- const { resumeHookDurable: resumeHookDurable2 } = await Promise.resolve().then(() => (init_resume_hook(), resume_hook_exports));
32272
- await resumeHookDurable2(value.hookToken, {
32311
+ const { resumeHook: resumeHook2 } = await Promise.resolve().then(() => (init_resume_hook(), resume_hook_exports));
32312
+ await resumeHook2(value.hookToken, {
32273
32313
  aborted: true,
32274
32314
  reason
32275
32315
  });
@@ -32581,16 +32621,16 @@ function getStepRevivers(global2 = globalThis, ops, runId, cryptoKey, deployment
32581
32621
  AbortSignal: /* @__PURE__ */ __name((value) => reviveAbortSignal(value, ops, runId), "AbortSignal")
32582
32622
  };
32583
32623
  }
32584
- async function dehydrateWorkflowArguments(value, runId, key, ops = [], global2 = globalThis, v1Compat = false, framedByteStreams = false, compression = false) {
32624
+ async function dehydrateWorkflowArguments(value, runId, key, ops = [], global2 = globalThis, v1Compat = false, framedByteStreams = false, compression = false, readbackOps = ops) {
32585
32625
  if (v1Compat) {
32586
- const str = stringify(value, getExternalReducers(global2, ops, runId, key, framedByteStreams));
32626
+ const str = stringify(value, getExternalReducers(global2, ops, runId, key, framedByteStreams, void 0, readbackOps));
32587
32627
  return revive(str);
32588
32628
  }
32589
32629
  try {
32590
32630
  const compressionStats = {};
32591
32631
  const result = await serialize(value, key, {
32592
32632
  global: global2,
32593
- extraReducers: getStreamAndRequestReducers(getExternalReducers(global2, ops, runId, key, framedByteStreams)),
32633
+ extraReducers: getStreamAndRequestReducers(getExternalReducers(global2, ops, runId, key, framedByteStreams, void 0, readbackOps)),
32594
32634
  compression,
32595
32635
  compressionStats
32596
32636
  });
@@ -32660,16 +32700,16 @@ async function hydrateStepArguments(value, runId, key, ops = [], global2 = globa
32660
32700
  await recordCompression(compressionStats, "deserialize");
32661
32701
  return result;
32662
32702
  }
32663
- async function dehydrateStepReturnValue(value, runId, key, ops = [], global2 = globalThis, v1Compat = false, framedByteStreams = false, compression = false, runReadyBarrier) {
32703
+ async function dehydrateStepReturnValue(value, runId, key, ops = [], global2 = globalThis, v1Compat = false, framedByteStreams = false, compression = false, runReadyBarrier, readbackOps = ops) {
32664
32704
  if (v1Compat) {
32665
- const str = stringify(value, getStepReducers(global2, ops, runId, key, framedByteStreams, runReadyBarrier));
32705
+ const str = stringify(value, getStepReducers(global2, ops, runId, key, framedByteStreams, runReadyBarrier, readbackOps));
32666
32706
  return revive(str);
32667
32707
  }
32668
32708
  try {
32669
32709
  const compressionStats = {};
32670
32710
  const result = await serialize2(value, key, {
32671
32711
  global: global2,
32672
- extraReducers: getStreamAndRequestReducers(getStepReducers(global2, ops, runId, key, framedByteStreams, runReadyBarrier)),
32712
+ extraReducers: getStreamAndRequestReducers(getStepReducers(global2, ops, runId, key, framedByteStreams, runReadyBarrier, readbackOps)),
32673
32713
  compression,
32674
32714
  compressionStats
32675
32715
  });
@@ -33460,9 +33500,9 @@ async function start(workflow, argsOrOptions, options) {
33460
33500
  },
33461
33501
  // Attest that the *consumer* deployment's runtime re-ensures a
33462
33502
  // `hook_received` event from a queue message's `hookInput` on replay.
33463
- // A resume of this run reads the marker (mirrored onto the hook's
33464
- // resumeContext by the server) to decide whether the parallel fast
33465
- // path is safe. For a cross-deployment start the consumer is the
33503
+ // An OLDER producer resuming this run reads the marker (mirrored onto
33504
+ // the hook's resumeContext by the server) to decide whether its lazy
33505
+ // fast path is safe. For a cross-deployment start the consumer is the
33466
33506
  // target deployment, so we stamp the *target's* value carried back on
33467
33507
  // the health-check probe, never the caller's. Omitted when we could
33468
33508
  // not attest the target (older target, timeout, or no probe channel),
@@ -33573,7 +33613,7 @@ __name(start, "start");
33573
33613
  value: "start",
33574
33614
  configurable: true
33575
33615
  });
33576
- })(start, "step//@workflow/core/runtime/start@5.0.0-beta.46//start");
33616
+ })(start, "step//@workflow/core/runtime/start@5.0.0-beta.47//start");
33577
33617
 
33578
33618
  // ../core/dist/runtime/runs.js
33579
33619
  async function wakeUpRun(world, runId, options) {
@@ -33972,7 +34012,7 @@ var Run = class _Run {
33972
34012
  value: "wakeUp",
33973
34013
  configurable: true
33974
34014
  });
33975
- })(Run.prototype["wakeUp"], "step//@workflow/core/runtime/run@5.0.0-beta.46//Run#wakeUp");
34015
+ })(Run.prototype["wakeUp"], "step//@workflow/core/runtime/run@5.0.0-beta.47//Run#wakeUp");
33976
34016
  (function(__wf_fn, __wf_id) {
33977
34017
  var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
33978
34018
  __wf_reg.set(__wf_id, __wf_fn);
@@ -33981,7 +34021,7 @@ var Run = class _Run {
33981
34021
  value: "cancel",
33982
34022
  configurable: true
33983
34023
  });
33984
- })(Run.prototype["cancel"], "step//@workflow/core/runtime/run@5.0.0-beta.46//Run#cancel");
34024
+ })(Run.prototype["cancel"], "step//@workflow/core/runtime/run@5.0.0-beta.47//Run#cancel");
33985
34025
  (function(__wf_fn, __wf_id) {
33986
34026
  var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
33987
34027
  __wf_reg.set(__wf_id, __wf_fn);
@@ -33990,7 +34030,7 @@ var Run = class _Run {
33990
34030
  value: "getReadable",
33991
34031
  configurable: true
33992
34032
  });
33993
- })(Run.prototype["getReadable"], "step//@workflow/core/runtime/run@5.0.0-beta.46//Run#getReadable");
34033
+ })(Run.prototype["getReadable"], "step//@workflow/core/runtime/run@5.0.0-beta.47//Run#getReadable");
33994
34034
  (function(__wf_fn, __wf_id) {
33995
34035
  var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
33996
34036
  __wf_reg.set(__wf_id, __wf_fn);
@@ -33999,7 +34039,7 @@ var Run = class _Run {
33999
34039
  value: "exists",
34000
34040
  configurable: true
34001
34041
  });
34002
- })(Object.getOwnPropertyDescriptor(Run.prototype, "exists").get, "step//@workflow/core/runtime/run@5.0.0-beta.46//Run#exists");
34042
+ })(Object.getOwnPropertyDescriptor(Run.prototype, "exists").get, "step//@workflow/core/runtime/run@5.0.0-beta.47//Run#exists");
34003
34043
  (function(__wf_fn, __wf_id) {
34004
34044
  var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
34005
34045
  __wf_reg.set(__wf_id, __wf_fn);
@@ -34008,7 +34048,7 @@ var Run = class _Run {
34008
34048
  value: "status",
34009
34049
  configurable: true
34010
34050
  });
34011
- })(Object.getOwnPropertyDescriptor(Run.prototype, "status").get, "step//@workflow/core/runtime/run@5.0.0-beta.46//Run#status");
34051
+ })(Object.getOwnPropertyDescriptor(Run.prototype, "status").get, "step//@workflow/core/runtime/run@5.0.0-beta.47//Run#status");
34012
34052
  (function(__wf_fn, __wf_id) {
34013
34053
  var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
34014
34054
  __wf_reg.set(__wf_id, __wf_fn);
@@ -34017,7 +34057,7 @@ var Run = class _Run {
34017
34057
  value: "returnValue",
34018
34058
  configurable: true
34019
34059
  });
34020
- })(Object.getOwnPropertyDescriptor(Run.prototype, "returnValue").get, "step//@workflow/core/runtime/run@5.0.0-beta.46//Run#returnValue");
34060
+ })(Object.getOwnPropertyDescriptor(Run.prototype, "returnValue").get, "step//@workflow/core/runtime/run@5.0.0-beta.47//Run#returnValue");
34021
34061
  (function(__wf_fn, __wf_id) {
34022
34062
  var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
34023
34063
  __wf_reg.set(__wf_id, __wf_fn);
@@ -34026,7 +34066,7 @@ var Run = class _Run {
34026
34066
  value: "workflowName",
34027
34067
  configurable: true
34028
34068
  });
34029
- })(Object.getOwnPropertyDescriptor(Run.prototype, "workflowName").get, "step//@workflow/core/runtime/run@5.0.0-beta.46//Run#workflowName");
34069
+ })(Object.getOwnPropertyDescriptor(Run.prototype, "workflowName").get, "step//@workflow/core/runtime/run@5.0.0-beta.47//Run#workflowName");
34030
34070
  (function(__wf_fn, __wf_id) {
34031
34071
  var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
34032
34072
  __wf_reg.set(__wf_id, __wf_fn);
@@ -34035,7 +34075,7 @@ var Run = class _Run {
34035
34075
  value: "createdAt",
34036
34076
  configurable: true
34037
34077
  });
34038
- })(Object.getOwnPropertyDescriptor(Run.prototype, "createdAt").get, "step//@workflow/core/runtime/run@5.0.0-beta.46//Run#createdAt");
34078
+ })(Object.getOwnPropertyDescriptor(Run.prototype, "createdAt").get, "step//@workflow/core/runtime/run@5.0.0-beta.47//Run#createdAt");
34039
34079
  (function(__wf_fn, __wf_id) {
34040
34080
  var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
34041
34081
  __wf_reg.set(__wf_id, __wf_fn);
@@ -34044,7 +34084,7 @@ var Run = class _Run {
34044
34084
  value: "startedAt",
34045
34085
  configurable: true
34046
34086
  });
34047
- })(Object.getOwnPropertyDescriptor(Run.prototype, "startedAt").get, "step//@workflow/core/runtime/run@5.0.0-beta.46//Run#startedAt");
34087
+ })(Object.getOwnPropertyDescriptor(Run.prototype, "startedAt").get, "step//@workflow/core/runtime/run@5.0.0-beta.47//Run#startedAt");
34048
34088
  (function(__wf_fn, __wf_id) {
34049
34089
  var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
34050
34090
  __wf_reg.set(__wf_id, __wf_fn);
@@ -34053,7 +34093,7 @@ var Run = class _Run {
34053
34093
  value: "completedAt",
34054
34094
  configurable: true
34055
34095
  });
34056
- })(Object.getOwnPropertyDescriptor(Run.prototype, "completedAt").get, "step//@workflow/core/runtime/run@5.0.0-beta.46//Run#completedAt");
34096
+ })(Object.getOwnPropertyDescriptor(Run.prototype, "completedAt").get, "step//@workflow/core/runtime/run@5.0.0-beta.47//Run#completedAt");
34057
34097
  (function(__wf_cls, __wf_id) {
34058
34098
  var __wf_sym = /* @__PURE__ */ Symbol.for("workflow-class-registry"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
34059
34099
  __wf_reg.set(__wf_id, __wf_cls);
@@ -34063,7 +34103,7 @@ var Run = class _Run {
34063
34103
  enumerable: false,
34064
34104
  configurable: false
34065
34105
  });
34066
- })(Run, "class//@workflow/core/runtime/run@5.0.0-beta.46//Run");
34106
+ })(Run, "class//@workflow/core/runtime/run@5.0.0-beta.47//Run");
34067
34107
 
34068
34108
  // ../workflow/dist/stdlib.js
34069
34109
  async function fetch2(...args) {