@workflow/world-testing 4.0.1-beta.6 → 4.0.1-beta.7

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.
@@ -11,6 +11,11 @@
11
11
  "stepId": "__builtin_response_text"
12
12
  }
13
13
  },
14
+ "workflows/addition.ts": {
15
+ "add": {
16
+ "stepId": "step//workflows/addition.ts//add"
17
+ }
18
+ },
14
19
  "workflows/noop.ts": {
15
20
  "noop": {
16
21
  "stepId": "step//workflows/noop.ts//noop"
@@ -19,14 +24,6 @@
19
24
  "workflow/dist/stdlib.js": {
20
25
  "fetch": {
21
26
  "stepId": "step//workflow/dist/stdlib.js//fetch"
22
- },
23
- "sleep": {
24
- "stepId": "step//workflow/dist/stdlib.js//sleep"
25
- }
26
- },
27
- "workflows/addition.ts": {
28
- "add": {
29
- "stepId": "step//workflows/addition.ts//add"
30
27
  }
31
28
  }
32
29
  },
@@ -684,7 +684,7 @@ var require_build_client = __commonJS({
684
684
  BuildCache: /* @__PURE__ */ __name(() => BuildCache, "BuildCache")
685
685
  });
686
686
  module2.exports = __toCommonJS2(build_client_exports);
687
- var import_index2 = require_cache();
687
+ var import_index = require_cache();
688
688
  var BuildCache = class {
689
689
  static {
690
690
  __name(this, "BuildCache");
@@ -704,8 +704,8 @@ var require_build_client = __commonJS({
704
704
  return null;
705
705
  }
706
706
  if (res.status === 200) {
707
- const cacheState = res.headers.get(import_index2.HEADERS_VERCEL_CACHE_STATE);
708
- if (cacheState !== import_index2.PkgCacheState.Fresh) {
707
+ const cacheState = res.headers.get(import_index.HEADERS_VERCEL_CACHE_STATE);
708
+ if (cacheState !== import_index.PkgCacheState.Fresh) {
709
709
  res.body?.cancel?.();
710
710
  clearTimeout(timeoutId);
711
711
  return null;
@@ -738,13 +738,13 @@ var require_build_client = __commonJS({
738
738
  try {
739
739
  const optionalHeaders = {};
740
740
  if (options?.ttl) {
741
- optionalHeaders[import_index2.HEADERS_VERCEL_REVALIDATE] = options.ttl.toString();
741
+ optionalHeaders[import_index.HEADERS_VERCEL_REVALIDATE] = options.ttl.toString();
742
742
  }
743
743
  if (options?.tags && options.tags.length > 0) {
744
- optionalHeaders[import_index2.HEADERS_VERCEL_CACHE_TAGS] = options.tags.join(",");
744
+ optionalHeaders[import_index.HEADERS_VERCEL_CACHE_TAGS] = options.tags.join(",");
745
745
  }
746
746
  if (options?.name) {
747
- optionalHeaders[import_index2.HEADERS_VERCEL_CACHE_ITEM_NAME] = options.name;
747
+ optionalHeaders[import_index.HEADERS_VERCEL_CACHE_ITEM_NAME] = options.name;
748
748
  }
749
749
  const res = await fetch(`${this.endpoint}${key}`, {
750
750
  method: "POST",
@@ -5257,17 +5257,13 @@ __name(__builtin_response_text, "__builtin_response_text");
5257
5257
  registerStepFunction("__builtin_response_array_buffer", __builtin_response_array_buffer);
5258
5258
  registerStepFunction("__builtin_response_json", __builtin_response_json);
5259
5259
  registerStepFunction("__builtin_response_text", __builtin_response_text);
5260
- // workflows/noop.ts
5261
- var count = 0;
5262
- async function noop(_i) {
5263
- count++;
5264
- return count;
5265
- }
5266
- __name(noop, "noop");
5267
- registerStepFunction("step//workflows/noop.ts//noop", noop);
5268
5260
  // ../errors/dist/index.js
5269
5261
  var import_ms = __toESM(require_ms(), 1);
5270
5262
  var BASE_URL = "https://useworkflow.dev/err";
5263
+ function isError(value) {
5264
+ return typeof value === "object" && value !== null && "name" in value && "message" in value;
5265
+ }
5266
+ __name(isError, "isError");
5271
5267
  var WorkflowError = class extends Error {
5272
5268
  static {
5273
5269
  __name(this, "WorkflowError");
@@ -5286,6 +5282,9 @@ Learn more: ${BASE_URL}/${options.slug}` : message;
5286
5282
  Caused by: ${options.cause.stack}`;
5287
5283
  }
5288
5284
  }
5285
+ static is(value) {
5286
+ return isError(value) && value.name === "WorkflowError";
5287
+ }
5289
5288
  };
5290
5289
  var WorkflowAPIError = class extends WorkflowError {
5291
5290
  static {
@@ -5303,6 +5302,9 @@ var WorkflowAPIError = class extends WorkflowError {
5303
5302
  this.code = options?.code;
5304
5303
  this.url = options?.url;
5305
5304
  }
5305
+ static is(value) {
5306
+ return isError(value) && value.name === "WorkflowAPIError";
5307
+ }
5306
5308
  };
5307
5309
  var WorkflowRuntimeError = class extends WorkflowError {
5308
5310
  static {
@@ -5314,6 +5316,9 @@ var WorkflowRuntimeError = class extends WorkflowError {
5314
5316
  });
5315
5317
  this.name = "WorkflowRuntimeError";
5316
5318
  }
5319
+ static is(value) {
5320
+ return isError(value) && value.name === "WorkflowRuntimeError";
5321
+ }
5317
5322
  };
5318
5323
  var WorkflowRunNotFoundError = class extends WorkflowError {
5319
5324
  static {
@@ -5325,6 +5330,9 @@ var WorkflowRunNotFoundError = class extends WorkflowError {
5325
5330
  this.name = "WorkflowRunNotFoundError";
5326
5331
  this.runId = runId;
5327
5332
  }
5333
+ static is(value) {
5334
+ return isError(value) && value.name === "WorkflowRunNotFoundError";
5335
+ }
5328
5336
  };
5329
5337
  var FatalError = class extends Error {
5330
5338
  static {
@@ -5335,6 +5343,9 @@ var FatalError = class extends Error {
5335
5343
  super(message);
5336
5344
  this.name = "FatalError";
5337
5345
  }
5346
+ static is(value) {
5347
+ return isError(value) && value.name === "FatalError";
5348
+ }
5338
5349
  };
5339
5350
  var RetryableError = class extends Error {
5340
5351
  static {
@@ -5362,6 +5373,9 @@ var RetryableError = class extends Error {
5362
5373
  }
5363
5374
  this.retryAfter = new Date(Date.now() + retryAfterSeconds * 1e3);
5364
5375
  }
5376
+ static is(value) {
5377
+ return isError(value) && value.name === "RetryableError";
5378
+ }
5365
5379
  };
5366
5380
  // ../core/dist/runtime/resume-hook.js
5367
5381
  var import_functions = __toESM(require_functions(), 1);
@@ -19808,6 +19822,8 @@ var EventTypeSchema = external_exports.enum([
19808
19822
  "hook_created",
19809
19823
  "hook_received",
19810
19824
  "hook_disposed",
19825
+ "wait_created",
19826
+ "wait_completed",
19811
19827
  "workflow_completed",
19812
19828
  "workflow_failed",
19813
19829
  "workflow_started"
@@ -19858,6 +19874,17 @@ var HookDisposedEventSchema = BaseEventSchema.extend({
19858
19874
  eventType: external_exports.literal("hook_disposed"),
19859
19875
  correlationId: external_exports.string()
19860
19876
  });
19877
+ var WaitCreatedEventSchema = BaseEventSchema.extend({
19878
+ eventType: external_exports.literal("wait_created"),
19879
+ correlationId: external_exports.string(),
19880
+ eventData: external_exports.object({
19881
+ resumeAt: external_exports.coerce.date()
19882
+ })
19883
+ });
19884
+ var WaitCompletedEventSchema = BaseEventSchema.extend({
19885
+ eventType: external_exports.literal("wait_completed"),
19886
+ correlationId: external_exports.string()
19887
+ });
19861
19888
  var WorkflowCompletedEventSchema = BaseEventSchema.extend({
19862
19889
  eventType: external_exports.literal("workflow_completed")
19863
19890
  });
@@ -19878,6 +19905,8 @@ var CreateEventSchema = external_exports.discriminatedUnion("eventType", [
19878
19905
  HookCreatedEventSchema,
19879
19906
  HookReceivedEventSchema,
19880
19907
  HookDisposedEventSchema,
19908
+ WaitCreatedEventSchema,
19909
+ WaitCompletedEventSchema,
19881
19910
  WorkflowCompletedEventSchema,
19882
19911
  WorkflowFailedEventSchema,
19883
19912
  WorkflowStartedEventSchema
@@ -19985,7 +20014,8 @@ var StepSchema = external_exports.object({
19985
20014
  startedAt: external_exports.coerce.date().optional(),
19986
20015
  completedAt: external_exports.coerce.date().optional(),
19987
20016
  createdAt: external_exports.coerce.date(),
19988
- updatedAt: external_exports.coerce.date()
20017
+ updatedAt: external_exports.coerce.date(),
20018
+ retryAfter: external_exports.coerce.date().optional()
19989
20019
  });
19990
20020
  // ../../node_modules/.pnpm/ulid@3.0.1/node_modules/ulid/dist/node/index.js
19991
20021
  var import_node_crypto = __toESM(require("node:crypto"), 1);
@@ -20151,6 +20181,7 @@ function monotonicFactory(prng) {
20151
20181
  }
20152
20182
  __name(monotonicFactory, "monotonicFactory");
20153
20183
  // ../world-local/dist/queue.js
20184
+ var LOCAL_QUEUE_MAX_VISIBILITY = parseInt(process.env.WORKFLOW_LOCAL_QUEUE_MAX_VISIBILITY ?? "0", 10) || Infinity;
20154
20185
  function createQueue(port) {
20155
20186
  const transport = new JsonTransport();
20156
20187
  const generateId = monotonicFactory();
@@ -20204,8 +20235,8 @@ function createQueue(port) {
20204
20235
  const text = await response.text();
20205
20236
  if (response.status === 503) {
20206
20237
  try {
20207
- const retryIn = Number(JSON.parse(text).retryIn);
20208
- await (0, import_promises.setTimeout)(retryIn * 1e3);
20238
+ const timeoutSeconds = Number(JSON.parse(text).timeoutSeconds);
20239
+ await (0, import_promises.setTimeout)(timeoutSeconds * 1e3);
20209
20240
  defaultRetriesLeft++;
20210
20241
  continue;
20211
20242
  }
@@ -20257,15 +20288,18 @@ function createQueue(port) {
20257
20288
  }
20258
20289
  const body = await new JsonTransport().deserialize(req.body);
20259
20290
  try {
20260
- const response = await handler(body, {
20291
+ const result = await handler(body, {
20261
20292
  attempt,
20262
20293
  queueName,
20263
20294
  messageId
20264
20295
  });
20265
- const retryIn = typeof response === "undefined" ? null : response.timeoutSeconds;
20266
- if (retryIn) {
20296
+ let timeoutSeconds = null;
20297
+ if (typeof result?.timeoutSeconds === "number") {
20298
+ timeoutSeconds = Math.min(result.timeoutSeconds, LOCAL_QUEUE_MAX_VISIBILITY);
20299
+ }
20300
+ if (timeoutSeconds) {
20267
20301
  return Response.json({
20268
- retryIn
20302
+ timeoutSeconds
20269
20303
  }, {
20270
20304
  status: 503
20271
20305
  });
@@ -22670,6 +22704,7 @@ var MessageWrapper = object({
22670
22704
  payload: QueuePayloadSchema,
22671
22705
  queueName: ValidQueueName
22672
22706
  });
22707
+ var VERCEL_QUEUE_MAX_VISIBILITY = 82800;
22673
22708
  function createQueue2(config3) {
22674
22709
  const { baseUrl, usingProxy } = getHttpUrl(config3);
22675
22710
  const headers = getHeaders(config3);
@@ -22700,13 +22735,20 @@ function createQueue2(config3) {
22700
22735
  const createQueueHandler = /* @__PURE__ */ __name((prefix, handler) => {
22701
22736
  return handleCallback({
22702
22737
  [`${prefix}*`]: {
22703
- default: /* @__PURE__ */ __name((body, meta) => {
22738
+ default: /* @__PURE__ */ __name(async (body, meta) => {
22704
22739
  const { payload, queueName } = MessageWrapper.parse(body);
22705
- return handler(payload, {
22740
+ const result = await handler(payload, {
22706
22741
  queueName,
22707
22742
  messageId: MessageId.parse(meta.messageId),
22708
22743
  attempt: meta.deliveryCount
22709
22744
  });
22745
+ if (typeof result?.timeoutSeconds === "number") {
22746
+ const adjustedTimeoutSeconds = Math.min(result.timeoutSeconds, VERCEL_QUEUE_MAX_VISIBILITY);
22747
+ if (adjustedTimeoutSeconds !== result.timeoutSeconds) {
22748
+ result.timeoutSeconds = adjustedTimeoutSeconds;
22749
+ }
22750
+ }
22751
+ return result;
22710
22752
  }, "default")
22711
22753
  }
22712
22754
  });
@@ -23318,6 +23360,7 @@ var getWorld = /* @__PURE__ */ __name(() => {
23318
23360
  // ../core/dist/symbols.js
23319
23361
  var WORKFLOW_USE_STEP = Symbol.for("WORKFLOW_USE_STEP");
23320
23362
  var WORKFLOW_CREATE_HOOK = Symbol.for("WORKFLOW_CREATE_HOOK");
23363
+ var WORKFLOW_SLEEP = Symbol.for("WORKFLOW_SLEEP");
23321
23364
  var WORKFLOW_CONTEXT = Symbol.for("WORKFLOW_CONTEXT");
23322
23365
  var WORKFLOW_GET_STREAM_ID = Symbol.for("WORKFLOW_GET_STREAM_ID");
23323
23366
  var STREAM_NAME_SYMBOL = Symbol.for("WORKFLOW_STREAM_NAME");
@@ -23866,44 +23909,11 @@ __name(getActiveSpan, "getActiveSpan");
23866
23909
  // ../core/dist/step/context-storage.js
23867
23910
  var import_node_async_hooks = require("node:async_hooks");
23868
23911
  var contextStorage = /* @__PURE__ */ new import_node_async_hooks.AsyncLocalStorage();
23869
- // ../core/dist/step/get-step-metadata.js
23870
- function getStepMetadata() {
23871
- const ctx = contextStorage.getStore();
23872
- if (!ctx) {
23873
- throw new Error("`getStepMetadata()` can only be called inside a step function");
23874
- }
23875
- return ctx.stepMetadata;
23876
- }
23877
- __name(getStepMetadata, "getStepMetadata");
23878
23912
  // ../workflow/dist/stdlib.js
23879
- var import_ms3 = __toESM(require_ms(), 1);
23880
- var MAX_SLEEP_DURATION_SECONDS = (0, import_ms3.default)("23h") / 1e3;
23881
- async function sleep(param) {
23882
- const { stepStartedAt } = getStepMetadata();
23883
- const durationMs = typeof param === "string" ? (0, import_ms3.default)(param) : param.getTime() - Number(stepStartedAt);
23884
- if (typeof durationMs !== "number" || durationMs < 0) {
23885
- const message = param instanceof Date ? `Invalid sleep date: "${param}". Expected a future date.` : `Invalid sleep duration: "${param}". Expected a valid duration string like "1s", "1m", "1h", etc.`;
23886
- throw new Error(message);
23887
- }
23888
- const endAt = +stepStartedAt + durationMs;
23889
- const now = Date.now();
23890
- if (now < endAt) {
23891
- const remainingSeconds = (endAt - now) / 1e3;
23892
- const retryAfter = Math.min(remainingSeconds, MAX_SLEEP_DURATION_SECONDS);
23893
- throw new RetryableError(`Sleeping for ${(0, import_ms3.default)(retryAfter * 1e3, {
23894
- long: true
23895
- })}`, {
23896
- retryAfter
23897
- });
23898
- }
23899
- }
23900
- __name(sleep, "sleep");
23901
- sleep.maxRetries = Infinity;
23902
23913
  async function fetch2(...args) {
23903
23914
  return globalThis.fetch(...args);
23904
23915
  }
23905
23916
  __name(fetch2, "fetch");
23906
- registerStepFunction("step//workflow/dist/stdlib.js//sleep", sleep);
23907
23917
  registerStepFunction("step//workflow/dist/stdlib.js//fetch", fetch2);
23908
23918
  // workflows/addition.ts
23909
23919
  async function add(num, num2) {
@@ -23914,6 +23924,14 @@ async function add(num, num2) {
23914
23924
  }
23915
23925
  __name(add, "add");
23916
23926
  registerStepFunction("step//workflows/addition.ts//add", add);
23927
+ // workflows/noop.ts
23928
+ var count = 0;
23929
+ async function noop(_i) {
23930
+ count++;
23931
+ return count;
23932
+ }
23933
+ __name(noop, "noop");
23934
+ registerStepFunction("step//workflows/noop.ts//noop", noop);
23917
23935
  // ../core/dist/runtime.js
23918
23936
  var import_functions3 = __toESM(require_functions(), 1);
23919
23937
  // ../core/dist/logger.js
@@ -23963,33 +23981,6 @@ var StepInvokePayloadSchema2 = external_exports.object({
23963
23981
  });
23964
23982
  // ../core/dist/types.js
23965
23983
  var import_node_util = require("node:util");
23966
- function getConstructorName(obj) {
23967
- if (obj === null || obj === void 0) {
23968
- return null;
23969
- }
23970
- const ctor = obj.constructor;
23971
- if (!ctor || ctor.name === "Object") {
23972
- return null;
23973
- }
23974
- return ctor.name;
23975
- }
23976
- __name(getConstructorName, "getConstructorName");
23977
- function getConstructorNames(obj) {
23978
- const proto = Object.getPrototypeOf(obj);
23979
- const name = getConstructorName(proto);
23980
- if (name === null) {
23981
- return [];
23982
- }
23983
- return [
23984
- name,
23985
- ...getConstructorNames(proto)
23986
- ];
23987
- }
23988
- __name(getConstructorNames, "getConstructorNames");
23989
- function isInstanceOf(v, ctor) {
23990
- return getConstructorNames(v).includes(ctor.name);
23991
- }
23992
- __name(isInstanceOf, "isInstanceOf");
23993
23984
  function getErrorName(v) {
23994
23985
  if (import_node_util.types.isNativeError(v)) {
23995
23986
  return v.name;
@@ -24013,6 +24004,8 @@ var EventConsumerResult;
24013
24004
  })(EventConsumerResult || (EventConsumerResult = {}));
24014
24005
  // ../core/dist/vm/index.js
24015
24006
  var import_seedrandom = __toESM(require_seedrandom2(), 1);
24007
+ // ../core/dist/workflow/sleep.js
24008
+ var import_ms3 = __toESM(require_ms(), 1);
24016
24009
  // ../core/dist/runtime/start.js
24017
24010
  var import_functions2 = __toESM(require_functions(), 1);
24018
24011
  // ../core/dist/runtime.js
@@ -24051,6 +24044,22 @@ var stepEntrypoint = /* @__PURE__ */ getWorldHandlers().createQueueHandler("__wk
24051
24044
  span?.setAttributes({
24052
24045
  ...StepStatus(step.status)
24053
24046
  });
24047
+ const now = Date.now();
24048
+ if (step.retryAfter && step.retryAfter.getTime() > now) {
24049
+ const timeoutSeconds = Math.ceil((step.retryAfter.getTime() - now) / 1e3);
24050
+ span?.setAttributes({
24051
+ ...StepRetryTimeoutSeconds(timeoutSeconds)
24052
+ });
24053
+ runtimeLogger.debug("Step retryAfter timestamp not yet reached", {
24054
+ stepName,
24055
+ stepId: step.stepId,
24056
+ retryAfter: step.retryAfter,
24057
+ timeoutSeconds
24058
+ });
24059
+ return {
24060
+ timeoutSeconds
24061
+ };
24062
+ }
24054
24063
  let result;
24055
24064
  const attempt = step.attempt + 1;
24056
24065
  try {
@@ -24115,13 +24124,13 @@ var stepEntrypoint = /* @__PURE__ */ getWorldHandlers().createQueueHandler("__wk
24115
24124
  ...StepErrorName(getErrorName(err)),
24116
24125
  ...StepErrorMessage(String(err))
24117
24126
  });
24118
- if (isInstanceOf(err, WorkflowAPIError)) {
24127
+ if (WorkflowAPIError.is(err)) {
24119
24128
  if (err.status === 410) {
24120
24129
  console.warn(`Workflow run "${workflowRunId}" has already completed, skipping step "${stepId}": ${err.message}`);
24121
24130
  return;
24122
24131
  }
24123
24132
  }
24124
- if (isInstanceOf(err, FatalError)) {
24133
+ if (FatalError.is(err)) {
24125
24134
  const stackLines = getErrorStack(err).split("\n").slice(0, 4);
24126
24135
  console.error(`[Workflows] "${workflowRunId}" - Encountered \`FatalError\` while executing step "${stepName}":
24127
24136
  > ${stackLines.join("\n > ")}
@@ -24178,7 +24187,7 @@ Bubbling up error to parent workflow`);
24178
24187
  });
24179
24188
  }
24180
24189
  else {
24181
- if (isInstanceOf(err, RetryableError)) {
24190
+ if (RetryableError.is(err)) {
24182
24191
  console.warn(`[Workflows] "${workflowRunId}" - Encountered \`RetryableError\` while executing step "${stepName}" (attempt ${attempt}):
24183
24192
  > ${String(err.message)}
24184
24193
 
@@ -24200,9 +24209,12 @@ Bubbling up error to parent workflow`);
24200
24209
  }
24201
24210
  });
24202
24211
  await world.steps.update(workflowRunId, stepId, {
24203
- status: "pending"
24212
+ status: "pending",
24213
+ ...RetryableError.is(err) && {
24214
+ retryAfter: err.retryAfter
24215
+ }
24204
24216
  });
24205
- const timeoutSeconds = Math.max(1, isInstanceOf(err, RetryableError) ? Math.floor((+err.retryAfter.getTime() - Date.now()) / 1e3) : 1);
24217
+ const timeoutSeconds = Math.max(1, RetryableError.is(err) ? Math.ceil((+err.retryAfter.getTime() - Date.now()) / 1e3) : 1);
24206
24218
  span?.setAttributes({
24207
24219
  ...StepRetryTimeoutSeconds(timeoutSeconds),
24208
24220
  ...StepRetryWillRetry(true)