@hatchet-dev/typescript-sdk 1.19.2-alpha.2 → 1.20.0

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.
@@ -30,7 +30,6 @@ const transformer_1 = require("../../conditions/transformer");
30
30
  const condition_1 = require("../../../protoc/v1/shared/condition");
31
31
  const apply_namespace_1 = require("../../../util/apply-namespace");
32
32
  const abort_error_1 = require("../../../util/abort-error");
33
- const parent_run_context_vars_1 = require("../../parent-run-context-vars");
34
33
  const crypto_1 = require("crypto");
35
34
  const duration_1 = require("../duration");
36
35
  const engine_version_1 = require("./engine-version");
@@ -75,19 +74,10 @@ class ContextWorker {
75
74
  }
76
75
  exports.ContextWorker = ContextWorker;
77
76
  class Context {
78
- nextChildIndex(n = 1) {
79
- var _a;
80
- const ctx = parent_run_context_vars_1.parentRunContextManager.getContext();
81
- const idx = (_a = ctx === null || ctx === void 0 ? void 0 : ctx.childIndex) !== null && _a !== void 0 ? _a : this.spawnIndex;
82
- parent_run_context_vars_1.parentRunContextManager.incrementChildIndex(n);
83
- this.spawnIndex = idx + n;
84
- return idx;
85
- }
86
77
  constructor(action, v1, worker) {
87
78
  // @deprecated use ctx.abortController instead
88
79
  this.controller = new AbortController();
89
80
  this.overridesData = {};
90
- /** @deprecated — kept for backward compat; prefer {@link nextChildIndex}. */
91
81
  this.spawnIndex = 0;
92
82
  this.streamIndex = 0;
93
83
  try {
@@ -389,8 +379,8 @@ class Context {
389
379
  throw new hatchet_error_1.default(`Cannot run with sticky: workflow ${workflowName} is not registered on the worker`);
390
380
  }
391
381
  const { workflowRunId, taskRunExternalId } = this.action;
392
- const childIndex = this.nextChildIndex();
393
- const finalOpts = Object.assign(Object.assign({}, opts), { parentId: workflowRunId, parentTaskRunExternalId: taskRunExternalId, childIndex, childKey: options === null || options === void 0 ? void 0 : options.key, desiredWorkerId: sticky ? this.worker.id() : undefined, _standaloneTaskName: workflow instanceof declaration_1.TaskWorkflowDeclaration ? workflow._standalone_task_name : undefined });
382
+ const finalOpts = Object.assign(Object.assign({}, opts), { parentId: workflowRunId, parentTaskRunExternalId: taskRunExternalId, childIndex: this.spawnIndex, childKey: options === null || options === void 0 ? void 0 : options.key, desiredWorkerId: sticky ? this.worker.id() : undefined, _standaloneTaskName: workflow instanceof declaration_1.TaskWorkflowDeclaration ? workflow._standalone_task_name : undefined });
383
+ this.spawnIndex += 1;
394
384
  return { workflowName, opts: finalOpts };
395
385
  }
396
386
  spawn(workflow, input, options) {
@@ -571,12 +561,12 @@ class Context {
571
561
  // `signal` must never be sent over the wire.
572
562
  const optsWithoutSignal = Object.assign({}, opts);
573
563
  delete optsWithoutSignal.signal;
574
- const childIndex = this.nextChildIndex();
575
564
  const resp = {
576
565
  workflowName: name,
577
566
  input,
578
- options: Object.assign(Object.assign({}, optsWithoutSignal), { parentId: workflowRunId, parentTaskRunExternalId: taskRunExternalId, childIndex, desiredWorkerId: sticky ? this.worker.id() : undefined }),
567
+ options: Object.assign(Object.assign({}, optsWithoutSignal), { parentId: workflowRunId, parentTaskRunExternalId: taskRunExternalId, childIndex: this.spawnIndex, desiredWorkerId: sticky ? this.worker.id() : undefined }),
579
568
  };
569
+ this.spawnIndex += 1;
580
570
  return resp;
581
571
  });
582
572
  try {
@@ -624,8 +614,8 @@ class Context {
624
614
  throw new hatchet_error_1.default(`cannot run with sticky: workflow ${name} is not registered on the worker`);
625
615
  }
626
616
  try {
627
- const childIndex = this.nextChildIndex();
628
- const resp = yield this.v1.admin.runWorkflow(name, input, Object.assign({ parentId: workflowRunId, parentTaskRunExternalId: taskRunExternalId, childIndex, desiredWorkerId: sticky ? this.worker.id() : undefined }, opts));
617
+ const resp = yield this.v1.admin.runWorkflow(name, input, Object.assign({ parentId: workflowRunId, parentTaskRunExternalId: taskRunExternalId, childIndex: this.spawnIndex, desiredWorkerId: sticky ? this.worker.id() : undefined }, opts));
618
+ this.spawnIndex += 1;
629
619
  if (workflow instanceof declaration_1.TaskWorkflowDeclaration) {
630
620
  resp._standaloneTaskName = workflow._standalone_task_name;
631
621
  }
@@ -743,9 +733,18 @@ class DurableContext extends Context {
743
733
  }));
744
734
  });
745
735
  }
746
- waitForEvent(key, expression, payloadSchema) {
736
+ waitForEvent(key, expression, payloadSchema, scope, lookbackWindow) {
747
737
  return __awaiter(this, void 0, void 0, function* () {
748
- const res = yield this.waitFor({ eventKey: key, expression });
738
+ const now = yield this.now();
739
+ const considerEventsSince = lookbackWindow
740
+ ? new Date(now.getTime() - (0, duration_1.durationToMs)(lookbackWindow)).toISOString()
741
+ : undefined;
742
+ const res = yield this.waitFor({
743
+ eventKey: key,
744
+ expression,
745
+ scope,
746
+ considerEventsSince,
747
+ });
749
748
  // The engine returns an object like:
750
749
  // {"CREATE": {"signal_key_1": [{"id": ..., "data": {...}}]}}
751
750
  // Since we have a single match, the list will only have one item.
@@ -806,13 +805,12 @@ class DurableContext extends Context {
806
805
  workflowName = workflow.name;
807
806
  }
808
807
  workflowName = (0, apply_namespace_1.applyNamespace)(workflowName, this.v1.config.namespace).toLowerCase();
809
- const childIndex = this.nextChildIndex();
810
808
  const triggerOpts = {
811
809
  name: workflowName,
812
810
  input: JSON.stringify(input || {}),
813
811
  parentId: this.action.workflowRunId,
814
812
  parentTaskRunExternalId: this.action.taskRunExternalId,
815
- childIndex,
813
+ childIndex: this.spawnIndex,
816
814
  childKey: options === null || options === void 0 ? void 0 : options.key,
817
815
  additionalMetadata: (options === null || options === void 0 ? void 0 : options.additionalMetadata)
818
816
  ? JSON.stringify(options.additionalMetadata)
@@ -821,6 +819,7 @@ class DurableContext extends Context {
821
819
  priority: options === null || options === void 0 ? void 0 : options.priority,
822
820
  desiredWorkerLabels: {},
823
821
  };
822
+ this.spawnIndex += 1;
824
823
  return { workflowName, triggerOpts };
825
824
  }
826
825
  /**
@@ -50,7 +50,7 @@ function Render(action, conditions) {
50
50
  if ('eventKey' in conditionOrObj) {
51
51
  return [
52
52
  ...acc,
53
- new user_event_condition_1.UserEventCondition(conditionOrObj.eventKey, conditionOrObj.expression || '', undefined, action),
53
+ new user_event_condition_1.UserEventCondition(conditionOrObj.eventKey, conditionOrObj.expression || '', undefined, action, conditionOrObj.scope, conditionOrObj.considerEventsSince),
54
54
  ];
55
55
  }
56
56
  if ('parent' in conditionOrObj) {
@@ -29,6 +29,10 @@ function conditionsToPb(conditions, namespace) {
29
29
  userEventConditions.push({
30
30
  base: Object.assign(Object.assign({}, baseToPb(condition.base)), { expression: condition.expression || '' }),
31
31
  userEventKey: (0, apply_namespace_1.applyNamespace)(condition.eventKey, namespace),
32
+ eventScope: condition.scope,
33
+ considerEventsSince: condition.considerEventsSince
34
+ ? new Date(condition.considerEventsSince)
35
+ : undefined,
32
36
  });
33
37
  }
34
38
  else if (condition instanceof parent_condition_1.ParentCondition) {
@@ -20,6 +20,14 @@ export interface UserEvent {
20
20
  * If not specified, the eventKey will be used as the default identifier.
21
21
  */
22
22
  readableDataKey?: string;
23
+ /**
24
+ An optional scope to filter events. If provided, only events with a matching scope will be considered when looking for matches. This is required if `lookback_window` is provided (if you wish to consider events that were pushed before the wait was established as valid).
25
+ */
26
+ scope?: string;
27
+ /**
28
+ An optional ISO-formatted date string indicating how far back to look for matching events when the condition is first evaluated.
29
+ */
30
+ considerEventsSince?: string;
23
31
  }
24
32
  /**
25
33
  * Represents a condition that is triggered based on a specific user event.
@@ -46,5 +54,7 @@ export interface UserEvent {
46
54
  export declare class UserEventCondition extends Condition {
47
55
  eventKey: string;
48
56
  expression: string;
49
- constructor(eventKey: string, expression: string, readableDataKey?: string, action?: Action);
57
+ scope?: string;
58
+ considerEventsSince?: string;
59
+ constructor(eventKey: string, expression: string, readableDataKey?: string, action?: Action, scope?: string, considerEventsSince?: string);
50
60
  }
@@ -25,7 +25,7 @@ const base_1 = require("./base");
25
25
  * );
26
26
  */
27
27
  class UserEventCondition extends base_1.Condition {
28
- constructor(eventKey, expression, readableDataKey, action) {
28
+ constructor(eventKey, expression, readableDataKey, action, scope, considerEventsSince) {
29
29
  super({
30
30
  readableDataKey: readableDataKey || eventKey,
31
31
  action,
@@ -34,6 +34,8 @@ class UserEventCondition extends base_1.Condition {
34
34
  });
35
35
  this.eventKey = eventKey;
36
36
  this.expression = expression;
37
+ this.scope = scope;
38
+ this.considerEventsSince = considerEventsSince;
37
39
  }
38
40
  }
39
41
  exports.UserEventCondition = UserEventCondition;
package/v1/declaration.js CHANGED
@@ -63,7 +63,9 @@ class BaseWorkflowDeclaration {
63
63
  if (!this.client) {
64
64
  throw UNBOUND_ERR;
65
65
  }
66
+ // set the parent run context
66
67
  const parentRunContext = parent_run_context_vars_1.parentRunContextManager.getContext();
68
+ parent_run_context_vars_1.parentRunContextManager.incrementChildIndex(Array.isArray(input) ? input.length : 1);
67
69
  if (!parentRunContext && ((options === null || options === void 0 ? void 0 : options.childKey) || (options === null || options === void 0 ? void 0 : options.sticky))) {
68
70
  this.client.admin.logger.warn('ignoring childKey or sticky because run is not being spawned from a parent task');
69
71
  }
@@ -77,21 +79,20 @@ class BaseWorkflowDeclaration {
77
79
  : undefined,
78
80
  warn: (message) => this.client.admin.logger.warn(message),
79
81
  });
80
- // Snapshot childIndex before incrementing — shared with Context.spawnIndex
81
- // via parentRunContextManager so both spawning APIs produce unique indices.
82
- const baseChildIndex = parentRunContext === null || parentRunContext === void 0 ? void 0 : parentRunContext.childIndex;
83
- const inputCount = Array.isArray(input) ? input.length : 1;
84
- parent_run_context_vars_1.parentRunContextManager.incrementChildIndex(inputCount);
85
- const runOpts = Object.assign(Object.assign({}, (options !== null && options !== void 0 ? options : {})), { parentId: parentRunContext === null || parentRunContext === void 0 ? void 0 : parentRunContext.parentId, parentTaskRunExternalId: parentRunContext === null || parentRunContext === void 0 ? void 0 : parentRunContext.parentTaskRunExternalId, childIndex: baseChildIndex, sticky: (options === null || options === void 0 ? void 0 : options.sticky) ? parentRunContext === null || parentRunContext === void 0 ? void 0 : parentRunContext.desiredWorkerId : undefined, childKey: options === null || options === void 0 ? void 0 : options.childKey });
82
+ parent_run_context_vars_1.parentRunContextManager.incrementChildIndex(Array.isArray(input) ? input.length : 1);
83
+ const runOpts = Object.assign(Object.assign({}, (options !== null && options !== void 0 ? options : {})), { parentId: parentRunContext === null || parentRunContext === void 0 ? void 0 : parentRunContext.parentId, parentTaskRunExternalId: parentRunContext === null || parentRunContext === void 0 ? void 0 : parentRunContext.parentTaskRunExternalId, childIndex: parentRunContext === null || parentRunContext === void 0 ? void 0 : parentRunContext.childIndex, sticky: (options === null || options === void 0 ? void 0 : options.sticky) ? parentRunContext === null || parentRunContext === void 0 ? void 0 : parentRunContext.desiredWorkerId : undefined, childKey: options === null || options === void 0 ? void 0 : options.childKey });
86
84
  if (Array.isArray(input)) {
87
85
  let resp = [];
88
86
  for (let i = 0; i < input.length; i += 500) {
89
87
  const batch = input.slice(i, i + 500);
90
- const batchResp = yield this.client.admin.runWorkflows(batch.map((inp, batchIdx) => ({
91
- workflowName: this.definition.name,
92
- input: inp,
93
- options: Object.assign(Object.assign({}, runOpts), { childIndex: (baseChildIndex !== null && baseChildIndex !== void 0 ? baseChildIndex : 0) + i + batchIdx }),
94
- })));
88
+ const batchResp = yield this.client.admin.runWorkflows(batch.map((inp) => {
89
+ var _a;
90
+ return ({
91
+ workflowName: this.definition.name,
92
+ input: inp,
93
+ options: Object.assign(Object.assign({}, runOpts), { childIndex: ((_a = runOpts.childIndex) !== null && _a !== void 0 ? _a : 0) + i }),
94
+ });
95
+ }));
95
96
  resp = resp.concat(batchResp);
96
97
  }
97
98
  const res = [];
@@ -52,6 +52,25 @@ export declare const durableReplayReset: import("../..").TaskWorkflowDeclaration
52
52
  sleep_2_duration: number;
53
53
  sleep_3_duration: number;
54
54
  }, {}, {}, {}, {}>;
55
+ export declare const LOOKBACK_WINDOW: "1m";
56
+ export declare const waitForEventLookback: import("../..").TaskWorkflowDeclaration<{
57
+ scope: string;
58
+ }, {
59
+ elapsed: number;
60
+ event: any;
61
+ }, {}, {}, {}, {}>;
62
+ export declare const waitForOrEventLookback: import("../..").TaskWorkflowDeclaration<{
63
+ scope: string;
64
+ }, {
65
+ elapsed: number;
66
+ }, {}, {}, {}, {}>;
67
+ export declare const waitForTwoEventsSecondPushedFirst: import("../..").TaskWorkflowDeclaration<{
68
+ scope: string;
69
+ }, {
70
+ elapsed: number;
71
+ event1: any;
72
+ event2: any;
73
+ }, {}, {}, {}, {}>;
55
74
  export declare const memoNowCaching: import("../..").TaskWorkflowDeclaration<import("../..").JsonObject, {
56
75
  start_time: string;
57
76
  }, {}, {}, {}, {}>;
@@ -12,10 +12,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.durableSpawnDag = exports.dagChildWorkflow = exports.memoNowCaching = 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;
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
16
  const conditions_1 = require("../../conditions");
17
17
  const non_determinism_error_1 = require("../../../util/errors/non-determinism-error");
18
18
  const sleep_1 = __importDefault(require("../../../util/sleep"));
19
+ const duration_1 = require("../../client/duration");
19
20
  const hatchet_client_1 = require("../hatchet-client");
20
21
  exports.EVENT_KEY = 'durable-example:event';
21
22
  exports.SLEEP_TIME_SECONDS = 2;
@@ -223,6 +224,46 @@ exports.durableReplayReset = hatchet_client_1.hatchet.durableTask({
223
224
  };
224
225
  }),
225
226
  });
227
+ exports.LOOKBACK_WINDOW = '1m';
228
+ exports.waitForEventLookback = hatchet_client_1.hatchet.durableTask({
229
+ name: 'wait-for-event-lookback',
230
+ executionTimeout: '10m',
231
+ fn: (input, ctx) => __awaiter(void 0, void 0, void 0, function* () {
232
+ const start = Date.now();
233
+ const event = yield ctx.waitForEvent(exports.EVENT_KEY, undefined, undefined, input.scope, exports.LOOKBACK_WINDOW);
234
+ return {
235
+ elapsed: (Date.now() - start) / 1000,
236
+ event,
237
+ };
238
+ }),
239
+ });
240
+ exports.waitForOrEventLookback = hatchet_client_1.hatchet.durableTask({
241
+ name: 'wait-for-or-event-lookback',
242
+ executionTimeout: '10m',
243
+ fn: (input, ctx) => __awaiter(void 0, void 0, void 0, function* () {
244
+ const start = Date.now();
245
+ const now = yield ctx.now();
246
+ const considerEventsSince = new Date(now.getTime() - (0, duration_1.durationToMs)(exports.LOOKBACK_WINDOW)).toISOString();
247
+ yield ctx.waitFor((0, conditions_1.Or)(new conditions_1.SleepCondition(exports.SLEEP_TIME), new conditions_1.UserEventCondition(exports.EVENT_KEY, '', undefined, undefined, input.scope, considerEventsSince)));
248
+ return {
249
+ elapsed: (Date.now() - start) / 1000,
250
+ };
251
+ }),
252
+ });
253
+ exports.waitForTwoEventsSecondPushedFirst = hatchet_client_1.hatchet.durableTask({
254
+ name: 'wait-for-two-events-second-pushed-first',
255
+ executionTimeout: '10m',
256
+ fn: (input, ctx) => __awaiter(void 0, void 0, void 0, function* () {
257
+ const start = Date.now();
258
+ const event1 = yield ctx.waitForEvent('key1', undefined, undefined, input.scope, exports.LOOKBACK_WINDOW);
259
+ const event2 = yield ctx.waitForEvent('key2', undefined, undefined, input.scope, exports.LOOKBACK_WINDOW);
260
+ return {
261
+ elapsed: (Date.now() - start) / 1000,
262
+ event1,
263
+ event2,
264
+ };
265
+ }),
266
+ });
226
267
  exports.memoNowCaching = hatchet_client_1.hatchet.durableTask({
227
268
  name: 'memo-now-caching',
228
269
  executionTimeout: '10m',
@@ -63,6 +63,9 @@ const workflows = [
63
63
  workflow_8.durableReplayReset,
64
64
  workflow_8.dagChildWorkflow,
65
65
  workflow_8.durableSpawnDag,
66
+ workflow_8.waitForEventLookback,
67
+ workflow_8.waitForOrEventLookback,
68
+ workflow_8.waitForTwoEventsSecondPushedFirst,
66
69
  workflow_9.durableEvent,
67
70
  workflow_9.durableEventWithFilter,
68
71
  workflow_11.durableSleep,
@@ -1,4 +1,4 @@
1
- import type { DurableContext } from './client/worker/context';
1
+ import { DurableContext } from './client/worker/context';
2
2
  export interface ParentRunContext {
3
3
  parentId: string;
4
4
  /**
@@ -26,7 +26,8 @@ class ParentRunContextManager {
26
26
  var _a;
27
27
  const parentRunContext = this.getContext();
28
28
  if (parentRunContext) {
29
- this.setContext(Object.assign(Object.assign({}, parentRunContext), { childIndex: ((_a = parentRunContext.childIndex) !== null && _a !== void 0 ? _a : 0) + n }));
29
+ parentRunContext.childIndex = ((_a = parentRunContext.childIndex) !== null && _a !== void 0 ? _a : 0) + n;
30
+ this.setContext(parentRunContext);
30
31
  }
31
32
  }
32
33
  getContext() {
package/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const HATCHET_VERSION = "1.19.2-alpha.2";
1
+ export declare const HATCHET_VERSION = "1.20.0";
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.19.2-alpha.2';
4
+ exports.HATCHET_VERSION = '1.20.0';