@hatchet-dev/typescript-sdk 1.21.0 → 1.21.1

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.
@@ -41,6 +41,7 @@ export interface DurableTaskEventLogEntryResult {
41
41
  export interface WaitForEvent {
42
42
  kind: 'waitFor';
43
43
  waitForConditions: DurableEventListenerConditions;
44
+ label?: string;
44
45
  }
45
46
  export interface RunChildrenEvent {
46
47
  kind: 'runChildren';
@@ -449,6 +449,7 @@ class DurableListenerClient {
449
449
  invocationCount,
450
450
  durableTaskExternalId,
451
451
  waitForConditions: event.waitForConditions,
452
+ label: event.label,
452
453
  };
453
454
  request = { waitFor: waitForReq };
454
455
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hatchet-dev/typescript-sdk",
3
- "version": "1.21.0",
3
+ "version": "1.21.1",
4
4
  "description": "Background task orchestration & visibility for developers",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [
@@ -113,6 +113,11 @@ export interface DurableTaskWaitForRequest {
113
113
  durableTaskExternalId: string;
114
114
  /** Fields for DURABLE_TASK_TRIGGER_KIND_WAIT_FOR */
115
115
  waitForConditions?: DurableEventListenerConditions | undefined;
116
+ /**
117
+ * An optional human-readable label for this wait, displayed in the dashboard.
118
+ * Example: "Waiting for payment confirmation"
119
+ */
120
+ label?: string | undefined;
116
121
  }
117
122
  export interface DurableTaskRequest {
118
123
  registerWorker?: DurableTaskRequestRegisterWorker | undefined;
@@ -1447,7 +1447,12 @@ exports.DurableTaskTriggerRunsRequest = {
1447
1447
  },
1448
1448
  };
1449
1449
  function createBaseDurableTaskWaitForRequest() {
1450
- return { invocationCount: 0, durableTaskExternalId: '', waitForConditions: undefined };
1450
+ return {
1451
+ invocationCount: 0,
1452
+ durableTaskExternalId: '',
1453
+ waitForConditions: undefined,
1454
+ label: undefined,
1455
+ };
1451
1456
  }
1452
1457
  exports.DurableTaskWaitForRequest = {
1453
1458
  encode(message, writer = new wire_1.BinaryWriter()) {
@@ -1460,6 +1465,9 @@ exports.DurableTaskWaitForRequest = {
1460
1465
  if (message.waitForConditions !== undefined) {
1461
1466
  condition_1.DurableEventListenerConditions.encode(message.waitForConditions, writer.uint32(26).fork()).join();
1462
1467
  }
1468
+ if (message.label !== undefined) {
1469
+ writer.uint32(34).string(message.label);
1470
+ }
1463
1471
  return writer;
1464
1472
  },
1465
1473
  decode(input, length) {
@@ -1490,6 +1498,13 @@ exports.DurableTaskWaitForRequest = {
1490
1498
  message.waitForConditions = condition_1.DurableEventListenerConditions.decode(reader, reader.uint32());
1491
1499
  continue;
1492
1500
  }
1501
+ case 4: {
1502
+ if (tag !== 34) {
1503
+ break;
1504
+ }
1505
+ message.label = reader.string();
1506
+ continue;
1507
+ }
1493
1508
  }
1494
1509
  if ((tag & 7) === 4 || tag === 0) {
1495
1510
  break;
@@ -1515,6 +1530,7 @@ exports.DurableTaskWaitForRequest = {
1515
1530
  : isSet(object.wait_for_conditions)
1516
1531
  ? condition_1.DurableEventListenerConditions.fromJSON(object.wait_for_conditions)
1517
1532
  : undefined,
1533
+ label: isSet(object.label) ? globalThis.String(object.label) : undefined,
1518
1534
  };
1519
1535
  },
1520
1536
  toJSON(message) {
@@ -1528,13 +1544,16 @@ exports.DurableTaskWaitForRequest = {
1528
1544
  if (message.waitForConditions !== undefined) {
1529
1545
  obj.waitForConditions = condition_1.DurableEventListenerConditions.toJSON(message.waitForConditions);
1530
1546
  }
1547
+ if (message.label !== undefined) {
1548
+ obj.label = message.label;
1549
+ }
1531
1550
  return obj;
1532
1551
  },
1533
1552
  create(base) {
1534
1553
  return exports.DurableTaskWaitForRequest.fromPartial(base !== null && base !== void 0 ? base : {});
1535
1554
  },
1536
1555
  fromPartial(object) {
1537
- var _a, _b;
1556
+ var _a, _b, _c;
1538
1557
  const message = createBaseDurableTaskWaitForRequest();
1539
1558
  message.invocationCount = (_a = object.invocationCount) !== null && _a !== void 0 ? _a : 0;
1540
1559
  message.durableTaskExternalId = (_b = object.durableTaskExternalId) !== null && _b !== void 0 ? _b : '';
@@ -1542,6 +1561,7 @@ exports.DurableTaskWaitForRequest = {
1542
1561
  object.waitForConditions !== undefined && object.waitForConditions !== null
1543
1562
  ? condition_1.DurableEventListenerConditions.fromPartial(object.waitForConditions)
1544
1563
  : undefined;
1564
+ message.label = (_c = object.label) !== null && _c !== void 0 ? _c : undefined;
1545
1565
  return message;
1546
1566
  },
1547
1567
  };
@@ -11,7 +11,7 @@ class NonDeterminismError extends hatchet_error_1.default {
11
11
  ? message
12
12
  : `Non-determinism detected in task ${taskExternalId} on invocation ${invocationCount} at node ${nodeId}`;
13
13
  super(`${detail}\n` +
14
- `Check out our documentation for more details on expectations of durable tasks: https://docs.hatchet.run/v1/patterns/mixing-patterns`);
14
+ `Check out our documentation for more details on expectations of durable tasks: https://docs.hatchet.run/v1/patterns`);
15
15
  this.name = 'NonDeterminismError';
16
16
  this.taskExternalId = taskExternalId;
17
17
  this.invocationCount = invocationCount;
@@ -31,6 +31,12 @@ export interface SleepResult {
31
31
  /** The sleep duration in milliseconds. */
32
32
  durationMs: number;
33
33
  }
34
+ export interface SleepForOptions {
35
+ /** Optional key used for condition result indexing. */
36
+ readableDataKey?: string;
37
+ /** Optional human-readable wait label shown in dashboard run details. */
38
+ label?: string;
39
+ }
34
40
  type LogExtra = {
35
41
  extra?: any;
36
42
  error?: Error;
@@ -371,16 +377,20 @@ export declare class DurableContext<T, K = {}> extends Context<T, K> {
371
377
  * Pauses execution for the specified duration.
372
378
  * Duration is "global" meaning it will wait in real time regardless of transient failures like worker restarts.
373
379
  * @param duration - The duration to sleep for.
380
+ * @param readableDataKeyOrOptions - Optional readable key string or options object containing readableDataKey and label.
381
+ * @param label - Optional wait label used when readableDataKey is passed as the second argument.
374
382
  * @returns A promise that resolves with a SleepResult when the sleep duration has elapsed.
375
383
  */
384
+ sleepFor(duration: Duration, options?: SleepForOptions): Promise<SleepResult>;
376
385
  sleepFor(duration: Duration, readableDataKey?: string): Promise<SleepResult>;
386
+ sleepFor(duration: Duration, readableDataKey?: string, label?: string): Promise<SleepResult>;
377
387
  /**
378
388
  * Pauses execution until the specified conditions are met.
379
389
  * Conditions are "global" meaning they will wait in real time regardless of transient failures like worker restarts.
380
390
  * @param conditions - The conditions to wait for.
381
391
  * @returns A promise that resolves with the event that satisfied the conditions.
382
392
  */
383
- waitFor(conditions: Conditions | Conditions[]): Promise<Record<string, any>>;
393
+ waitFor(conditions: Conditions | Conditions[], label?: string): Promise<Record<string, any>>;
384
394
  /**
385
395
  * Lightweight wrapper for waiting for a user event. Allows for shorthand usage of
386
396
  * `ctx.waitFor` when specifying a user event condition.
@@ -392,8 +402,8 @@ export declare class DurableContext<T, K = {}> extends Context<T, K> {
392
402
  * @param payloadSchema - An optional Zod schema to validate and parse the event payload.
393
403
  * @returns The event payload, validated against the schema if provided.
394
404
  */
395
- waitForEvent<T extends z.ZodTypeAny>(key: string, expression?: string, payloadSchema?: T, scope?: string, lookbackWindow?: Duration): Promise<z.infer<T>>;
396
- waitForEvent(key: string, expression?: string, payloadSchema?: undefined, scope?: string, lookbackWindow?: Duration): Promise<Record<string, any>>;
405
+ waitForEvent<T extends z.ZodTypeAny>(key: string, expression?: string, payloadSchema?: T, scope?: string, lookbackWindow?: Duration, label?: string): Promise<z.infer<T>>;
406
+ waitForEvent(key: string, expression?: string, payloadSchema?: undefined, scope?: string, lookbackWindow?: Duration, label?: string): Promise<Record<string, any>>;
397
407
  /**
398
408
  * Durably sleep until a specific timestamp.
399
409
  * Uses the memoized `now()` to compute the remaining duration, then delegates to `sleepFor`.
@@ -683,15 +683,12 @@ class DurableContext extends Context {
683
683
  }
684
684
  });
685
685
  }
686
- /**
687
- * Pauses execution for the specified duration.
688
- * Duration is "global" meaning it will wait in real time regardless of transient failures like worker restarts.
689
- * @param duration - The duration to sleep for.
690
- * @returns A promise that resolves with a SleepResult when the sleep duration has elapsed.
691
- */
692
- sleepFor(duration, readableDataKey) {
686
+ sleepFor(duration, readableDataKeyOrOptions, label) {
693
687
  return __awaiter(this, void 0, void 0, function* () {
694
- const res = yield this.waitFor({ sleepFor: duration, readableDataKey });
688
+ const opts = typeof readableDataKeyOrOptions === 'string'
689
+ ? { readableDataKey: readableDataKeyOrOptions, label }
690
+ : (readableDataKeyOrOptions !== null && readableDataKeyOrOptions !== void 0 ? readableDataKeyOrOptions : {});
691
+ const res = yield this.waitFor({ sleepFor: duration, readableDataKey: opts.readableDataKey }, opts.label);
695
692
  const matches = res['CREATE'] || {};
696
693
  const [firstMatch] = Object.values(matches);
697
694
  if (!firstMatch || firstMatch.length === 0) {
@@ -718,7 +715,7 @@ class DurableContext extends Context {
718
715
  * @param conditions - The conditions to wait for.
719
716
  * @returns A promise that resolves with the event that satisfied the conditions.
720
717
  */
721
- waitFor(conditions) {
718
+ waitFor(conditions, label) {
722
719
  return __awaiter(this, void 0, void 0, function* () {
723
720
  this.throwIfCancelled();
724
721
  if (!this.supportsEviction) {
@@ -732,6 +729,7 @@ class DurableContext extends Context {
732
729
  sleepConditions: pbConditions.sleepConditions,
733
730
  userEventConditions: pbConditions.userEventConditions,
734
731
  },
732
+ label,
735
733
  });
736
734
  const resourceId = rendered
737
735
  .map((c) => c.base.readableDataKey)
@@ -743,7 +741,7 @@ class DurableContext extends Context {
743
741
  }));
744
742
  });
745
743
  }
746
- waitForEvent(key, expression, payloadSchema, scope, lookbackWindow) {
744
+ waitForEvent(key, expression, payloadSchema, scope, lookbackWindow, label) {
747
745
  return __awaiter(this, void 0, void 0, function* () {
748
746
  const now = yield this.now();
749
747
  const considerEventsSince = lookbackWindow
@@ -754,7 +752,7 @@ class DurableContext extends Context {
754
752
  expression,
755
753
  scope,
756
754
  considerEventsSince,
757
- });
755
+ }, label);
758
756
  // The engine returns an object like:
759
757
  // {"CREATE": {"signal_key_1": [{"id": ..., "data": {...}}]}}
760
758
  // Since we have a single match, the list will only have one item.
@@ -71,9 +71,14 @@ function poll(fn_1, _a) {
71
71
  return __awaiter(this, arguments, void 0, function* (fn, { timeoutMs = 30000, intervalMs = 100, shouldStop, label = 'poll', }) {
72
72
  const start = Date.now();
73
73
  while (true) {
74
- const value = yield fn();
75
- if (shouldStop(value)) {
76
- return value;
74
+ try {
75
+ const value = yield fn();
76
+ if (shouldStop(value)) {
77
+ return value;
78
+ }
79
+ }
80
+ catch (_b) {
81
+ // retry on transient errors
77
82
  }
78
83
  if (Date.now() - start > timeoutMs) {
79
84
  throw new Error(`Timed out waiting for ${label} after ${timeoutMs}ms`);
@@ -54,10 +54,13 @@ export declare const durableReplayReset: import("../..").TaskWorkflowDeclaration
54
54
  }, {}, {}, {}, {}>;
55
55
  export declare const LOOKBACK_WINDOW: "1m";
56
56
  export declare const waitForEventLookback: import("../..").TaskWorkflowDeclaration<{
57
- scope: string;
57
+ userId: number;
58
58
  }, {
59
59
  elapsed: number;
60
- event: any;
60
+ event: {
61
+ order: string;
62
+ user_id: number;
63
+ };
61
64
  }, {}, {}, {}, {}>;
62
65
  export declare const waitForOrEventLookback: import("../..").TaskWorkflowDeclaration<{
63
66
  scope: string;
@@ -13,6 +13,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.durableSpawnDag = exports.dagChildWorkflow = exports.memoNowCaching = exports.waitForTwoEventsSecondPushedFirst = exports.waitForOrEventLookback = exports.waitForEventLookback = exports.LOOKBACK_WINDOW = exports.durableReplayReset = exports.REPLAY_RESET_MEMOIZED_MAX_SECONDS = exports.REPLAY_RESET_SLEEP_SECONDS = exports.durableNonDeterminism = exports.durableWithExplicitSpawn = exports.durableSleepEventSpawn = exports.durableWithBulkSpawn = exports.durableWithSpawn = exports.spawnChildTask = exports.waitForSleepTwice = exports.durableWorkflow = exports.SLEEP_TIME = exports.SLEEP_TIME_SECONDS = exports.EVENT_KEY = void 0;
16
+ const zod_1 = require("zod");
16
17
  const conditions_1 = require("../../conditions");
17
18
  const non_determinism_error_1 = require("../../../util/errors/non-determinism-error");
18
19
  const sleep_1 = __importDefault(require("../../../util/sleep"));
@@ -37,7 +38,7 @@ exports.durableWorkflow.durableTask({
37
38
  executionTimeout: '10m',
38
39
  fn: (_input, ctx) => __awaiter(void 0, void 0, void 0, function* () {
39
40
  console.log('Waiting for sleep');
40
- const sleepResult = yield ctx.sleepFor(exports.SLEEP_TIME);
41
+ const sleepResult = yield ctx.sleepFor(exports.SLEEP_TIME, { label: 'waiting for sleep' });
41
42
  console.log('Sleep finished');
42
43
  console.log('Waiting for event');
43
44
  const event = yield ctx.waitForEvent(exports.EVENT_KEY, 'true');
@@ -225,12 +226,18 @@ exports.durableReplayReset = hatchet_client_1.hatchet.durableTask({
225
226
  }),
226
227
  });
227
228
  exports.LOOKBACK_WINDOW = '1m';
229
+ const lookbackEventPayloadSchema = zod_1.z.object({
230
+ order: zod_1.z.string(),
231
+ user_id: zod_1.z.number(),
232
+ });
228
233
  exports.waitForEventLookback = hatchet_client_1.hatchet.durableTask({
229
234
  name: 'wait-for-event-lookback',
230
235
  executionTimeout: '10m',
231
236
  fn: (input, ctx) => __awaiter(void 0, void 0, void 0, function* () {
232
237
  const start = Date.now();
233
- const event = yield ctx.waitForEvent(exports.EVENT_KEY, undefined, undefined, input.scope, exports.LOOKBACK_WINDOW);
238
+ // > Wait for event with lookback
239
+ const event = yield ctx.waitForEvent('user:create', `input.user_id == ${input.userId}`, lookbackEventPayloadSchema, `user_id:${input.userId}`, '1m');
240
+ // !!
234
241
  return {
235
242
  elapsed: (Date.now() - start) / 1000,
236
243
  event,
@@ -1,7 +1,11 @@
1
1
  export declare const EVENT_KEY = "user:update";
2
+ export declare const SCOPE = "user-1234";
2
3
  export declare const durableEvent: import("../..").TaskWorkflowDeclaration<import("../..").JsonObject, {
3
4
  Value: string;
4
5
  }, {}, {}, {}, {}>;
5
6
  export declare const durableEventWithFilter: import("../..").TaskWorkflowDeclaration<import("../..").JsonObject, {
6
7
  Value: string;
7
8
  }, {}, {}, {}, {}>;
9
+ export declare const durableEventWithLookback: import("../..").TaskWorkflowDeclaration<import("../..").JsonObject, {
10
+ Value: string;
11
+ }, {}, {}, {}, {}>;
@@ -9,9 +9,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.durableEventWithFilter = exports.durableEvent = exports.EVENT_KEY = void 0;
12
+ exports.durableEventWithLookback = exports.durableEventWithFilter = exports.durableEvent = exports.SCOPE = exports.EVENT_KEY = void 0;
13
13
  const hatchet_client_1 = require("../hatchet-client");
14
14
  exports.EVENT_KEY = 'user:update';
15
+ exports.SCOPE = 'user-1234';
15
16
  // > Durable Event
16
17
  exports.durableEvent = hatchet_client_1.hatchet.durableTask({
17
18
  name: 'durable-event',
@@ -39,3 +40,16 @@ exports.durableEventWithFilter = hatchet_client_1.hatchet.durableTask({
39
40
  }),
40
41
  });
41
42
  // !!
43
+ // > Durable Event With Lookback
44
+ exports.durableEventWithLookback = hatchet_client_1.hatchet.durableTask({
45
+ name: 'durable-event-with-lookback',
46
+ executionTimeout: '10m',
47
+ fn: (_, ctx) => __awaiter(void 0, void 0, void 0, function* () {
48
+ const res = yield ctx.waitForEvent(exports.EVENT_KEY, undefined, undefined, exports.SCOPE, '1m');
49
+ console.log('res', res);
50
+ return {
51
+ Value: 'done',
52
+ };
53
+ }),
54
+ });
55
+ // !!
@@ -1,3 +1,10 @@
1
- export declare const affinityExampleTask: import("../..").TaskWorkflowDeclaration<import("../..").UnknownInputType, {
2
- worker_id: string | undefined;
3
- }, {}, {}, {}, {}>;
1
+ type AffinityOutput = {
2
+ affinity_t1: {
3
+ worker_id: string | undefined;
4
+ };
5
+ affinity_t2: {
6
+ worker_id: string | undefined;
7
+ };
8
+ };
9
+ export declare const affinityExampleTask: import("../..").WorkflowDeclaration<{}, AffinityOutput, {}>;
10
+ export {};
@@ -11,8 +11,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.affinityExampleTask = void 0;
13
13
  const hatchet_client_1 = require("../hatchet-client");
14
- exports.affinityExampleTask = hatchet_client_1.hatchet.task({
15
- name: 'affinity-example-task',
14
+ exports.affinityExampleTask = hatchet_client_1.hatchet.workflow({
15
+ name: 'runtime_affinity_workflow',
16
+ });
17
+ const affinityT1 = exports.affinityExampleTask.task({
18
+ name: 'affinity_t1',
19
+ fn: (input, ctx) => __awaiter(void 0, void 0, void 0, function* () {
20
+ return { worker_id: ctx.worker.id() };
21
+ }),
22
+ });
23
+ exports.affinityExampleTask.task({
24
+ name: 'affinity_t2',
25
+ parents: [affinityT1],
16
26
  fn: (input, ctx) => __awaiter(void 0, void 0, void 0, function* () {
17
27
  return { worker_id: ctx.worker.id() };
18
28
  }),
package/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const HATCHET_VERSION = "1.21.0";
1
+ export declare const HATCHET_VERSION = "1.21.1";
package/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.HATCHET_VERSION = void 0;
4
- exports.HATCHET_VERSION = '1.21.0';
4
+ exports.HATCHET_VERSION = '1.21.1';