@hatchet-dev/typescript-sdk 1.31.0 → 1.32.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.
Files changed (46) hide show
  1. package/README.md +46 -0
  2. package/clients/dispatcher/action-listener.d.ts +3 -8
  3. package/clients/dispatcher/action-listener.js +7 -25
  4. package/clients/dispatcher/action.d.ts +19 -0
  5. package/clients/dispatcher/action.js +35 -0
  6. package/clients/dispatcher/dispatcher-client.d.ts +2 -2
  7. package/clients/dispatcher/heartbeat/heartbeat-controller.d.ts +1 -1
  8. package/clients/listeners/durable-listener/durable-events.d.ts +56 -0
  9. package/clients/listeners/durable-listener/durable-events.js +2 -0
  10. package/clients/listeners/durable-listener/durable-listener-client.d.ts +3 -52
  11. package/clients/listeners/durable-listener/durable-listener-client.js +3 -2
  12. package/clients/listeners/durable-listener/pooled-durable-listener-client.js +2 -1
  13. package/clients/listeners/run-listener/pooled-child-listener-client.js +2 -1
  14. package/clients/rest/generated/Api.d.ts +1 -62
  15. package/clients/rest/generated/Api.js +0 -50
  16. package/clients/rest/generated/data-contracts.d.ts +0 -52
  17. package/dist/check-edge-entry.mjs +84 -0
  18. package/edge/declarations.d.ts +49 -0
  19. package/edge/declarations.js +21 -0
  20. package/edge/index.d.ts +49 -0
  21. package/edge/index.js +115 -0
  22. package/package.json +21 -16
  23. package/scripts/check-edge-entry.mjs +84 -0
  24. package/util/abort-error.d.ts +0 -10
  25. package/util/abort-error.js +0 -15
  26. package/util/abort-signal.d.ts +12 -0
  27. package/util/abort-signal.js +19 -0
  28. package/util/logger/logger.d.ts +1 -1
  29. package/v1/client/worker/context.d.ts +58 -12
  30. package/v1/client/worker/context.js +79 -51
  31. package/v1/client/worker/deprecated/pre-eviction.d.ts +5 -2
  32. package/v1/client/worker/deprecated/pre-eviction.js +5 -0
  33. package/v1/client/worker/runtime.d.ts +118 -0
  34. package/v1/client/worker/runtime.js +9 -0
  35. package/v1/client/worker/worker-internal.d.ts +3 -39
  36. package/v1/client/worker/worker-internal.js +22 -393
  37. package/v1/client/worker/worker-runtime.d.ts +8 -0
  38. package/v1/client/worker/worker-runtime.js +67 -0
  39. package/v1/client/worker/workflow-proto.d.ts +76 -0
  40. package/v1/client/worker/workflow-proto.js +482 -0
  41. package/v1/parent-run-context-storage.d.ts +11 -0
  42. package/v1/parent-run-context-storage.js +28 -0
  43. package/v1/parent-run-context-vars.d.ts +15 -1
  44. package/v1/parent-run-context-vars.js +13 -4
  45. package/version.d.ts +1 -1
  46. package/version.js +1 -1
@@ -1,17 +1,15 @@
1
- import { Action, ActionKey, ActionListener } from '../../../clients/dispatcher/action-listener';
1
+ import { ActionListener } from '../../../clients/dispatcher/action-listener';
2
+ import { Action, ActionKey } from '../../../clients/dispatcher/action';
2
3
  import { StepActionEvent, StepActionEventType, GroupKeyActionEvent, GroupKeyActionEventType, BatchActionEvent } from '../../../protoc/dispatcher';
3
4
  import HatchetPromise from '../../../util/hatchet-promise/hatchet-promise';
4
- import { CreateStepRateLimit } from '../../../protoc/workflows';
5
5
  import { Logger } from '../../../util/logger';
6
6
  import { BaseWorkflowDeclaration, WorkflowDefinition, HatchetClient } from '../..';
7
- import { TaskBatchConfig } from '../../../protoc/v1/workflows';
8
- import { Concurrency, CreateWorkflowTaskOpts } from '../../task';
9
7
  import { WorkerLabels } from '../../../clients/dispatcher/dispatcher-client';
10
- import { Duration } from '../duration';
11
8
  import { Context } from './context';
12
9
  import { SlotConfig } from '../../slot-types';
13
10
  import { DurableEvictionManager } from './eviction/eviction-manager';
14
11
  import { EvictionPolicy } from './eviction/eviction-policy';
12
+ export { assertValidConcurrencyArr, mapBatchConfigPb, mapConcurrencyPb, mapRateLimitPb, mapSlotRequestsPb, resolveExecutionTimeout, resolveScheduleTimeout, taskConcurrencyArr, } from './workflow-proto';
15
13
  export type ActionRegistry = Record<Action['actionId'], Function>;
16
14
  export interface WorkerOpts {
17
15
  name: string;
@@ -107,37 +105,3 @@ export declare class InternalWorker {
107
105
  handleAction(action: Action): Promise<void | Error>;
108
106
  upsertLabels(labels: WorkerLabels): Promise<WorkerLabels>;
109
107
  }
110
- /** Durable tasks stay on the durable pool; slotCost applies only to the default pool. */
111
- export declare function mapSlotRequestsPb(task: {
112
- slotRequests?: Record<string, number>;
113
- slotCost?: number;
114
- }, isDurable: boolean): Record<string, number>;
115
- export declare function mapRateLimitPb(limits: CreateWorkflowTaskOpts<any, any>['rateLimits']): CreateStepRateLimit[];
116
- export declare function mapConcurrencyPb(entries: Concurrency[]): {
117
- expression: string;
118
- maxRuns: number | undefined;
119
- limitStrategy: import("../..").ConcurrencyLimitStrategy | undefined;
120
- name: string | undefined;
121
- isTenantScoped: boolean | undefined;
122
- maxRunsExpression: string | undefined;
123
- }[];
124
- export declare function taskConcurrencyArr(task: {
125
- concurrency?: Concurrency | Concurrency[];
126
- }, workflow: {
127
- taskDefaults?: {
128
- concurrency?: Concurrency | Concurrency[];
129
- };
130
- }): Concurrency[];
131
- export declare function assertValidConcurrencyArr(concurrency: Concurrency[] | undefined): void;
132
- export declare function mapBatchConfigPb(batch: CreateWorkflowTaskOpts<any, any>['batch']): TaskBatchConfig | undefined;
133
- export declare function resolveExecutionTimeout(task: {
134
- executionTimeout?: Duration;
135
- timeout?: Duration;
136
- }, workflowDefaults?: {
137
- executionTimeout?: Duration;
138
- }): string;
139
- export declare function resolveScheduleTimeout(task: {
140
- scheduleTimeout?: Duration;
141
- }, workflowDefaults?: {
142
- scheduleTimeout?: Duration;
143
- }): string | undefined;
@@ -52,35 +52,37 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
52
52
  return (mod && mod.__esModule) ? mod : { "default": mod };
53
53
  };
54
54
  Object.defineProperty(exports, "__esModule", { value: true });
55
- exports.InternalWorker = void 0;
56
- exports.mapSlotRequestsPb = mapSlotRequestsPb;
57
- exports.mapRateLimitPb = mapRateLimitPb;
58
- exports.mapConcurrencyPb = mapConcurrencyPb;
59
- exports.taskConcurrencyArr = taskConcurrencyArr;
60
- exports.assertValidConcurrencyArr = assertValidConcurrencyArr;
61
- exports.mapBatchConfigPb = mapBatchConfigPb;
62
- exports.resolveExecutionTimeout = resolveExecutionTimeout;
63
- exports.resolveScheduleTimeout = resolveScheduleTimeout;
55
+ exports.InternalWorker = exports.taskConcurrencyArr = exports.resolveScheduleTimeout = exports.resolveExecutionTimeout = exports.mapSlotRequestsPb = exports.mapRateLimitPb = exports.mapConcurrencyPb = exports.mapBatchConfigPb = exports.assertValidConcurrencyArr = void 0;
64
56
  const hatchet_error_1 = __importDefault(require("../../../util/errors/hatchet-error"));
65
57
  const task_run_terminated_error_1 = require("../../../util/errors/task-run-terminated-error");
58
+ const action_1 = require("../../../clients/dispatcher/action");
66
59
  const dispatcher_1 = require("../../../protoc/dispatcher");
67
60
  const hatchet_promise_1 = __importStar(require("../../../util/hatchet-promise/hatchet-promise"));
68
- const workflows_1 = require("../../../protoc/workflows");
69
61
  const logger_1 = require("../../../util/logger");
70
- const workflows_2 = require("../../../protoc/v1/workflows");
71
62
  const task_1 = require("../../task");
72
- const transformer_1 = require("../../conditions/transformer");
73
- const z = __importStar(require("zod/v4"));
74
63
  const apply_namespace_1 = require("../../../util/apply-namespace");
75
64
  const sleep_1 = __importDefault(require("../../../util/sleep"));
76
65
  const abort_error_1 = require("../../../util/abort-error");
77
- const duration_1 = require("../duration");
78
66
  const context_1 = require("./context");
79
67
  const parent_run_context_vars_1 = require("../../parent-run-context-vars");
68
+ const parent_run_context_storage_1 = require("../../parent-run-context-storage");
69
+ const workflow_proto_1 = require("./workflow-proto");
80
70
  const health_server_1 = require("./health-server");
81
71
  const eviction_manager_1 = require("./eviction/eviction-manager");
82
72
  const eviction_policy_1 = require("./eviction/eviction-policy");
83
73
  const engine_version_1 = require("./engine-version");
74
+ var workflow_proto_2 = require("./workflow-proto");
75
+ Object.defineProperty(exports, "assertValidConcurrencyArr", { enumerable: true, get: function () { return workflow_proto_2.assertValidConcurrencyArr; } });
76
+ Object.defineProperty(exports, "mapBatchConfigPb", { enumerable: true, get: function () { return workflow_proto_2.mapBatchConfigPb; } });
77
+ Object.defineProperty(exports, "mapConcurrencyPb", { enumerable: true, get: function () { return workflow_proto_2.mapConcurrencyPb; } });
78
+ Object.defineProperty(exports, "mapRateLimitPb", { enumerable: true, get: function () { return workflow_proto_2.mapRateLimitPb; } });
79
+ Object.defineProperty(exports, "mapSlotRequestsPb", { enumerable: true, get: function () { return workflow_proto_2.mapSlotRequestsPb; } });
80
+ Object.defineProperty(exports, "resolveExecutionTimeout", { enumerable: true, get: function () { return workflow_proto_2.resolveExecutionTimeout; } });
81
+ Object.defineProperty(exports, "resolveScheduleTimeout", { enumerable: true, get: function () { return workflow_proto_2.resolveScheduleTimeout; } });
82
+ Object.defineProperty(exports, "taskConcurrencyArr", { enumerable: true, get: function () { return workflow_proto_2.taskConcurrencyArr; } });
83
+ // Tasks read the parent run context across awaits; the worker is the only place that
84
+ // enters it, so it installs the AsyncLocalStorage store before any task can run.
85
+ (0, parent_run_context_storage_1.installAsyncLocalParentRunContext)();
84
86
  class InternalWorker {
85
87
  constructor(client, options) {
86
88
  var _a, _b, _c, _d;
@@ -143,7 +145,7 @@ class InternalWorker {
143
145
  const newActions = workflow._durableTasks
144
146
  .filter((task) => !!task.fn)
145
147
  .reduce((acc, task) => {
146
- const actionId = `${(0, apply_namespace_1.applyNamespace)(workflow.name, this.client.config.namespace).toLowerCase()}:${task.name.toLowerCase()}`;
148
+ const actionId = (0, action_1.createActionId)((0, apply_namespace_1.applyNamespace)(workflow.name, this.client.config.namespace), task.name);
147
149
  acc[actionId] = (ctx) => task.fn(ctx.input, ctx);
148
150
  this.durable_action_set.add(actionId);
149
151
  this.eviction_policies.set(actionId, task.evictionPolicy !== undefined
@@ -157,7 +159,7 @@ class InternalWorker {
157
159
  const newActions = workflow._tasks
158
160
  .filter((task) => !!task.fn)
159
161
  .reduce((acc, task) => {
160
- const actionId = `${workflow.name}:${task.name.toLowerCase()}`;
162
+ const actionId = (0, action_1.createActionId)(workflow.name, task.name);
161
163
  if (task.batch) {
162
164
  acc[actionId] = (ctx) => task.fn(decodeBatchItems(ctx.action.actionPayload), ctx);
163
165
  }
@@ -173,192 +175,17 @@ class InternalWorker {
173
175
  : undefined;
174
176
  const onFailureAction = onFailureFn
175
177
  ? {
176
- [onFailureTaskName(workflow)]: (ctx) => onFailureFn(ctx.input, ctx),
178
+ [(0, workflow_proto_1.onFailureTaskName)(workflow)]: (ctx) => onFailureFn(ctx.input, ctx),
177
179
  }
178
180
  : {};
179
181
  this.action_registry = Object.assign(Object.assign(Object.assign({}, this.action_registry), newActions), onFailureAction);
180
182
  }
181
183
  registerWorkflow(initWorkflow_1) {
182
184
  return __awaiter(this, arguments, void 0, function* (initWorkflow, durable = false) {
183
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
184
- // patch the namespace
185
- const workflow = Object.assign(Object.assign({}, initWorkflow.definition), { name: (0, apply_namespace_1.applyNamespace)(initWorkflow.definition.name, this.client.config.namespace).toLowerCase() });
185
+ const { namespace } = this.client.config;
186
+ const workflow = (0, workflow_proto_1.normalizeWorkflowDefinition)(initWorkflow, { namespace, durable });
186
187
  try {
187
- const { concurrency } = workflow;
188
- let onFailureTask;
189
- if (workflow.onFailure && typeof workflow.onFailure === 'function') {
190
- onFailureTask = {
191
- readableId: 'on-failure-task',
192
- action: onFailureTaskName(workflow),
193
- timeout: '60s',
194
- inputs: '{}',
195
- parents: [],
196
- retries: 0,
197
- rateLimits: [],
198
- workerLabels: {},
199
- concurrency: [],
200
- isDurable: false,
201
- slotRequests: { default: 1 },
202
- };
203
- }
204
- if (workflow.onFailure && typeof workflow.onFailure === 'object') {
205
- const onFailure = workflow.onFailure;
206
- const scheduleTimeout = (_a = onFailure.scheduleTimeout) !== null && _a !== void 0 ? _a : (_b = workflow.taskDefaults) === null || _b === void 0 ? void 0 : _b.scheduleTimeout;
207
- onFailureTask = {
208
- readableId: 'on-failure-task',
209
- action: onFailureTaskName(workflow),
210
- timeout: (0, duration_1.durationToString)(onFailure.executionTimeout || ((_c = workflow.taskDefaults) === null || _c === void 0 ? void 0 : _c.executionTimeout) || '60s'),
211
- scheduleTimeout: scheduleTimeout ? (0, duration_1.durationToString)(scheduleTimeout) : undefined,
212
- inputs: '{}',
213
- parents: [],
214
- retries: onFailure.retries || ((_d = workflow.taskDefaults) === null || _d === void 0 ? void 0 : _d.retries) || 0,
215
- rateLimits: mapRateLimitPb(onFailure.rateLimits || ((_e = workflow.taskDefaults) === null || _e === void 0 ? void 0 : _e.rateLimits)),
216
- workerLabels: mapWorkerLabelPb(onFailure.desiredWorkerLabels || ((_f = workflow.taskDefaults) === null || _f === void 0 ? void 0 : _f.workerLabels)),
217
- concurrency: [],
218
- backoffFactor: ((_g = onFailure.backoff) === null || _g === void 0 ? void 0 : _g.factor) || ((_j = (_h = workflow.taskDefaults) === null || _h === void 0 ? void 0 : _h.backoff) === null || _j === void 0 ? void 0 : _j.factor),
219
- backoffMaxSeconds: ((_k = onFailure.backoff) === null || _k === void 0 ? void 0 : _k.maxSeconds) || ((_m = (_l = workflow.taskDefaults) === null || _l === void 0 ? void 0 : _l.backoff) === null || _m === void 0 ? void 0 : _m.maxSeconds),
220
- isDurable: false,
221
- slotRequests: mapSlotRequestsPb(onFailure, false),
222
- };
223
- }
224
- let onSuccessTask;
225
- if (!durable && workflow.onSuccess && typeof workflow.onSuccess === 'function') {
226
- const parents = getLeaves([...workflow._tasks, ...workflow._durableTasks]);
227
- onSuccessTask = {
228
- name: 'on-success-task',
229
- fn: workflow.onSuccess,
230
- executionTimeout: '60s',
231
- parents,
232
- retries: 0,
233
- rateLimits: [],
234
- desiredWorkerLabels: undefined,
235
- concurrency: [],
236
- };
237
- }
238
- if (!durable && workflow.onSuccess && typeof workflow.onSuccess === 'object') {
239
- const onSuccess = workflow.onSuccess;
240
- const parents = getLeaves([...workflow._tasks, ...workflow._durableTasks]);
241
- onSuccessTask = {
242
- name: 'on-success-task',
243
- fn: onSuccess.fn,
244
- executionTimeout: onSuccess.executionTimeout || ((_o = workflow.taskDefaults) === null || _o === void 0 ? void 0 : _o.executionTimeout) || '60s',
245
- scheduleTimeout: onSuccess.scheduleTimeout || ((_p = workflow.taskDefaults) === null || _p === void 0 ? void 0 : _p.scheduleTimeout),
246
- parents,
247
- retries: onSuccess.retries || ((_q = workflow.taskDefaults) === null || _q === void 0 ? void 0 : _q.retries) || 0,
248
- rateLimits: onSuccess.rateLimits || ((_r = workflow.taskDefaults) === null || _r === void 0 ? void 0 : _r.rateLimits),
249
- desiredWorkerLabels: onSuccess.desiredWorkerLabels || ((_s = workflow.taskDefaults) === null || _s === void 0 ? void 0 : _s.workerLabels),
250
- concurrency: onSuccess.concurrency || ((_t = workflow.taskDefaults) === null || _t === void 0 ? void 0 : _t.concurrency),
251
- backoff: onSuccess.backoff || ((_u = workflow.taskDefaults) === null || _u === void 0 ? void 0 : _u.backoff),
252
- };
253
- }
254
- if (onSuccessTask) {
255
- workflow._tasks.push(onSuccessTask);
256
- }
257
- const eventTriggers = [
258
- ...(workflow.onEvents || []).map((event) => (0, apply_namespace_1.applyNamespace)(event, this.client.config.namespace)),
259
- ...(workflow.on && 'event' in workflow.on && workflow.on.event
260
- ? Array.isArray(workflow.on.event)
261
- ? workflow.on.event.map((event) => (0, apply_namespace_1.applyNamespace)(event, this.client.config.namespace))
262
- : [(0, apply_namespace_1.applyNamespace)(workflow.on.event, this.client.config.namespace)]
263
- : []),
264
- ];
265
- const cronTriggers = [
266
- ...(workflow.onCrons || []),
267
- ...(workflow.on && 'cron' in workflow.on && workflow.on.cron
268
- ? Array.isArray(workflow.on.cron)
269
- ? workflow.on.cron
270
- : [workflow.on.cron]
271
- : []),
272
- ];
273
- const concurrencyArr = Array.isArray(concurrency) ? concurrency : [];
274
- const concurrencySolo = !Array.isArray(concurrency) ? concurrency : undefined;
275
- assertValidConcurrencyArr(concurrencyArr);
276
- assertValidConcurrencyArr(concurrencySolo ? [concurrencySolo] : undefined);
277
- // Convert Zod schema to JSON Schema if provided
278
- let inputJsonSchema;
279
- if (workflow.inputValidator) {
280
- const jsonSchema = z.toJSONSchema(workflow.inputValidator);
281
- inputJsonSchema = new TextEncoder().encode(JSON.stringify(jsonSchema));
282
- }
283
- const durableTaskSet = new Set(workflow._durableTasks);
284
- let stickyStrategy;
285
- // `workflow.sticky` is optional. When omitted, we don't set any sticky strategy.
286
- //
287
- // When provided, `workflow.sticky` is a v1 (non-protobuf) config which may also include
288
- // legacy protobuf enum values for backwards compatibility.
289
- if (workflow.sticky != null) {
290
- switch (workflow.sticky) {
291
- case 'soft':
292
- case 'SOFT':
293
- case 0:
294
- stickyStrategy = workflows_1.StickyStrategy.SOFT;
295
- break;
296
- case 'hard':
297
- case 'HARD':
298
- case 1:
299
- stickyStrategy = workflows_1.StickyStrategy.HARD;
300
- break;
301
- default:
302
- throw new hatchet_error_1.default(`Invalid sticky strategy: ${workflow.sticky}`);
303
- }
304
- }
305
- const registeredWorkflow = this.client.admin.putWorkflow({
306
- name: workflow.name,
307
- description: workflow.description || '',
308
- version: workflow.version || '',
309
- eventTriggers,
310
- cronTriggers,
311
- sticky: stickyStrategy,
312
- concurrencyArr: mapConcurrencyPb(concurrencyArr),
313
- onFailureTask,
314
- defaultPriority: workflow.defaultPriority,
315
- inputJsonSchema,
316
- tasks: [...workflow._tasks, ...workflow._durableTasks].map((task) => {
317
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
318
- return ({
319
- readableId: task.name,
320
- action: `${workflow.name}:${task.name}`,
321
- timeout: resolveExecutionTimeout(task, workflow.taskDefaults),
322
- scheduleTimeout: resolveScheduleTimeout(task, workflow.taskDefaults),
323
- inputs: '{}',
324
- parents: (_b = (_a = task.parents) === null || _a === void 0 ? void 0 : _a.map((p) => p.name)) !== null && _b !== void 0 ? _b : [],
325
- userData: '{}',
326
- // Batch tasks buffer many concurrent runs into a single execution; per-item retry
327
- // semantics don't apply, so retries is always forced to 0.
328
- retries: batchOf(task) ? 0 : task.retries || ((_c = workflow.taskDefaults) === null || _c === void 0 ? void 0 : _c.retries) || 0,
329
- rateLimits: mapRateLimitPb(task.rateLimits || ((_d = workflow.taskDefaults) === null || _d === void 0 ? void 0 : _d.rateLimits)),
330
- workerLabels: mapWorkerLabelPb(task.desiredWorkerLabels || ((_e = workflow.taskDefaults) === null || _e === void 0 ? void 0 : _e.workerLabels)),
331
- backoffFactor: ((_f = task.backoff) === null || _f === void 0 ? void 0 : _f.factor) || ((_h = (_g = workflow.taskDefaults) === null || _g === void 0 ? void 0 : _g.backoff) === null || _h === void 0 ? void 0 : _h.factor),
332
- backoffMaxSeconds: ((_j = task.backoff) === null || _j === void 0 ? void 0 : _j.maxSeconds) || ((_l = (_k = workflow.taskDefaults) === null || _k === void 0 ? void 0 : _k.backoff) === null || _l === void 0 ? void 0 : _l.maxSeconds),
333
- conditions: (0, transformer_1.taskConditionsToPb)(task, this.client.config.namespace),
334
- isDurable: durableTaskSet.has(task),
335
- slotRequests: mapSlotRequestsPb(task, durableTaskSet.has(task)),
336
- batch: mapBatchConfigPb(batchOf(task)),
337
- concurrency: (() => {
338
- const taskConcurrency = taskConcurrencyArr(task, workflow);
339
- assertValidConcurrencyArr(taskConcurrency);
340
- return mapConcurrencyPb(taskConcurrency);
341
- })(),
342
- });
343
- }),
344
- concurrency: concurrencySolo ? mapConcurrencyPb([concurrencySolo])[0] : undefined,
345
- defaultFilters: (_w = (_v = workflow.defaultFilters) === null || _v === void 0 ? void 0 : _v.map((f) => ({
346
- scope: f.scope,
347
- expression: f.expression,
348
- payload: f.payload ? new TextEncoder().encode(JSON.stringify(f.payload)) : undefined,
349
- }))) !== null && _w !== void 0 ? _w : [],
350
- idempotency: workflow.idempotency
351
- ? {
352
- expression: workflow.idempotency.expression,
353
- ttlMs: workflow.idempotency.strategy === 'status'
354
- ? workflow.idempotency.fallbackTtlMs
355
- : workflow.idempotency.ttlMs,
356
- method: workflow.idempotency.strategy === 'status'
357
- ? workflows_2.IdempotencyMethod.STATUS
358
- : workflows_2.IdempotencyMethod.TTL,
359
- }
360
- : undefined,
361
- });
188
+ const registeredWorkflow = this.client.admin.putWorkflow((0, workflow_proto_1.workflowToProto)(workflow, { namespace, durable }));
362
189
  this.registeredWorkflowPromises.push(registeredWorkflow);
363
190
  yield registeredWorkflow;
364
191
  this.workflow_registry.push(workflow);
@@ -960,125 +787,6 @@ class InternalWorker {
960
787
  }
961
788
  }
962
789
  exports.InternalWorker = InternalWorker;
963
- function mapWorkerLabelPb(in_) {
964
- if (!in_) {
965
- return {};
966
- }
967
- return Object.entries(in_).reduce((acc, [key, label]) => {
968
- if (!label) {
969
- return Object.assign(Object.assign({}, acc), { [key]: {
970
- strValue: undefined,
971
- intValue: undefined,
972
- } });
973
- }
974
- if (typeof label === 'string') {
975
- return Object.assign(Object.assign({}, acc), { [key]: {
976
- strValue: label,
977
- intValue: undefined,
978
- } });
979
- }
980
- if (typeof label === 'number') {
981
- return Object.assign(Object.assign({}, acc), { [key]: {
982
- strValue: undefined,
983
- intValue: label,
984
- } });
985
- }
986
- return Object.assign(Object.assign({}, acc), { [key]: {
987
- strValue: typeof label.value === 'string' ? label.value : undefined,
988
- intValue: typeof label.value === 'number' ? label.value : undefined,
989
- required: label.required,
990
- weight: label.weight,
991
- comparator: label.comparator,
992
- } });
993
- }, {});
994
- }
995
- function onFailureTaskName(workflow) {
996
- return `${workflow.name}:on-failure-task`;
997
- }
998
- function getLeaves(tasks) {
999
- return tasks.filter((task) => isLeafTask(task, tasks));
1000
- }
1001
- function isLeafTask(task, allTasks) {
1002
- return !allTasks.some((t) => { var _a; return (_a = t.parents) === null || _a === void 0 ? void 0 : _a.some((p) => p.name === task.name); });
1003
- }
1004
- /** Durable tasks stay on the durable pool; slotCost applies only to the default pool. */
1005
- function mapSlotRequestsPb(task, isDurable) {
1006
- if (task.slotRequests) {
1007
- return task.slotRequests;
1008
- }
1009
- if (isDurable) {
1010
- return { durable: 1 };
1011
- }
1012
- if (task.slotCost !== undefined) {
1013
- if (!Number.isInteger(task.slotCost) || task.slotCost <= 0) {
1014
- throw new Error(`slotCost must be a positive integer, got: ${task.slotCost}`);
1015
- }
1016
- return { default: task.slotCost };
1017
- }
1018
- return { default: 1 };
1019
- }
1020
- function mapRateLimitPb(limits) {
1021
- if (!limits) {
1022
- return [];
1023
- }
1024
- return limits.map((l) => {
1025
- let key = l.staticKey;
1026
- const keyExpression = l.dynamicKey;
1027
- if (l.key !== undefined) {
1028
- console.warn('key is deprecated and will be removed in a future release, please use staticKey instead');
1029
- ({ key } = l);
1030
- }
1031
- if (keyExpression !== undefined) {
1032
- if (key !== undefined) {
1033
- throw new Error('Cannot have both static key and dynamic key set');
1034
- }
1035
- key = keyExpression;
1036
- if (!validateCelExpression(keyExpression)) {
1037
- throw new Error(`Invalid CEL expression: ${keyExpression}`);
1038
- }
1039
- }
1040
- if (key === undefined) {
1041
- throw new Error(`Invalid key`);
1042
- }
1043
- let units;
1044
- let unitsExpression;
1045
- if (typeof l.units === 'number') {
1046
- ({ units } = l);
1047
- }
1048
- else {
1049
- if (!validateCelExpression(l.units)) {
1050
- throw new Error(`Invalid CEL expression: ${l.units}`);
1051
- }
1052
- unitsExpression = l.units;
1053
- }
1054
- let limitExpression;
1055
- if (l.limit !== undefined) {
1056
- if (typeof l.limit === 'number') {
1057
- limitExpression = `${l.limit}`;
1058
- }
1059
- else {
1060
- if (!validateCelExpression(l.limit)) {
1061
- throw new Error(`Invalid CEL expression: ${l.limit}`);
1062
- }
1063
- limitExpression = l.limit;
1064
- }
1065
- }
1066
- if (keyExpression !== undefined && limitExpression === undefined) {
1067
- throw new Error('CEL based keys requires limit to be set');
1068
- }
1069
- if (limitExpression === undefined) {
1070
- limitExpression = `-1`;
1071
- }
1072
- return {
1073
- key,
1074
- keyExpr: keyExpression,
1075
- units,
1076
- unitsExpr: unitsExpression,
1077
- limitValuesExpr: limitExpression,
1078
- duration: l.duration,
1079
- };
1080
- });
1081
- }
1082
790
  /**
1083
791
  * Decodes the buffered items of a batch task's START_BATCH action into a Record keyed by
1084
792
  * each buffered item's task-run external id, mapping to that item's input. The wire shape
@@ -1105,82 +813,3 @@ function parseBatchPayload(actionPayload) {
1105
813
  return {};
1106
814
  }
1107
815
  }
1108
- /** Batch tasks are only available on non-durable tasks; durable tasks never carry `batch`. */
1109
- function batchOf(task) {
1110
- return 'batch' in task ? task.batch : undefined;
1111
- }
1112
- // mapConcurrencyPb maps SDK concurrency entries onto the proto shape; entries keep their
1113
- // declared order, which is the chain order.
1114
- function mapConcurrencyPb(entries) {
1115
- return entries.map((c) => ({
1116
- expression: c.expression,
1117
- // a string maxRuns is a CEL expression; the static field then carries the default
1118
- // of 1, which only governs slots created before the expression existed
1119
- maxRuns: typeof c.maxRuns === 'string' ? 1 : c.maxRuns,
1120
- limitStrategy: c.limitStrategy,
1121
- name: c.name,
1122
- isTenantScoped: c.isTenantScoped,
1123
- maxRunsExpression: typeof c.maxRuns === 'string' ? c.maxRuns : undefined,
1124
- }));
1125
- }
1126
- function taskConcurrencyArr(task, workflow) {
1127
- var _a;
1128
- if (task.concurrency) {
1129
- return Array.isArray(task.concurrency) ? task.concurrency : [task.concurrency];
1130
- }
1131
- if ((_a = workflow.taskDefaults) === null || _a === void 0 ? void 0 : _a.concurrency) {
1132
- return Array.isArray(workflow.taskDefaults.concurrency)
1133
- ? workflow.taskDefaults.concurrency
1134
- : [workflow.taskDefaults.concurrency];
1135
- }
1136
- return [];
1137
- }
1138
- function assertValidConcurrencyArr(concurrency) {
1139
- concurrency === null || concurrency === void 0 ? void 0 : concurrency.forEach((c) => {
1140
- if (typeof c.maxRuns === 'string') {
1141
- if (!c.maxRuns.trim()) {
1142
- throw new Error('concurrency.maxRuns expression must be non-empty');
1143
- }
1144
- return;
1145
- }
1146
- if (c.maxRuns !== undefined && (!Number.isInteger(c.maxRuns) || c.maxRuns <= 0)) {
1147
- throw new Error(`concurrency.maxRuns must be a positive integer or a CEL expression, got: ${c.maxRuns}`);
1148
- }
1149
- });
1150
- }
1151
- function mapBatchConfigPb(batch) {
1152
- if (!batch) {
1153
- return undefined;
1154
- }
1155
- if (!Number.isInteger(batch.maxSize) || batch.maxSize <= 0) {
1156
- throw new Error(`batch.maxSize must be a positive integer, got: ${batch.maxSize}`);
1157
- }
1158
- const batchMaxIntervalMs = batch.maxInterval !== undefined ? (0, duration_1.durationToMs)(batch.maxInterval) : undefined;
1159
- if (batchMaxIntervalMs !== undefined && batchMaxIntervalMs <= 0) {
1160
- throw new Error('batch.maxInterval must be positive when provided');
1161
- }
1162
- if (batch.groupMaxRuns !== undefined &&
1163
- (!Number.isInteger(batch.groupMaxRuns) || batch.groupMaxRuns <= 0)) {
1164
- throw new Error(`batch.groupMaxRuns must be a positive integer when provided, got: ${batch.groupMaxRuns}`);
1165
- }
1166
- return {
1167
- batchMaxSize: batch.maxSize,
1168
- batchMaxIntervalMs,
1169
- batchGroupKey: batch.groupKey,
1170
- batchGroupMaxRuns: batch.groupMaxRuns,
1171
- broadcastOutput: batch.broadcastOutput,
1172
- };
1173
- }
1174
- // Helper function to validate CEL expressions
1175
- function validateCelExpression(_expr) {
1176
- // FIXME: this is a placeholder. In a real implementation, you'd need to use a CEL parser or validator.
1177
- // For now, we'll just return true to mimic the behavior.
1178
- return true;
1179
- }
1180
- function resolveExecutionTimeout(task, workflowDefaults) {
1181
- return (0, duration_1.durationToString)(task.executionTimeout || task.timeout || (workflowDefaults === null || workflowDefaults === void 0 ? void 0 : workflowDefaults.executionTimeout) || '60s');
1182
- }
1183
- function resolveScheduleTimeout(task, workflowDefaults) {
1184
- const value = task.scheduleTimeout || (workflowDefaults === null || workflowDefaults === void 0 ? void 0 : workflowDefaults.scheduleTimeout);
1185
- return value ? (0, duration_1.durationToString)(value) : undefined;
1186
- }
@@ -0,0 +1,8 @@
1
+ import type { HatchetClient } from '../client';
2
+ import type { InternalWorker } from './worker-internal';
3
+ import type { ContextRuntime } from './runtime';
4
+ /** A `ContextRuntime` that also exposes the client it wraps, for `ctx.v1`. */
5
+ export interface WorkerContextRuntime extends ContextRuntime {
6
+ readonly client: HatchetClient;
7
+ }
8
+ export declare function createWorkerContextRuntime(client: HatchetClient, worker: InternalWorker): WorkerContextRuntime;
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.createWorkerContextRuntime = createWorkerContextRuntime;
13
+ /**
14
+ * `ContextRuntime` for a worker process: adapts the `HatchetClient` and `InternalWorker`
15
+ * a task runs on to the seam `Context` consumes.
16
+ */
17
+ const dispatcher_1 = require("../../../protoc/dispatcher");
18
+ // The event client's LogLevel enum has the same string values as the logger's LogLevel
19
+ // union; casting keeps the event client (and its gRPC imports) out of this module's
20
+ // runtime graph.
21
+ function toEventLogLevel(level) {
22
+ if (level === undefined || level === 'OFF') {
23
+ return undefined;
24
+ }
25
+ return level;
26
+ }
27
+ function createWorkerContextRuntime(client, worker) {
28
+ return {
29
+ client,
30
+ get namespace() {
31
+ return client.config.namespace;
32
+ },
33
+ logger: (name) => client.config.logger(name, client.config.log_level),
34
+ cancelRun: (taskRunExternalId) => __awaiter(this, void 0, void 0, function* () {
35
+ yield client.runs.cancel({ ids: [taskRunExternalId] });
36
+ }),
37
+ cancelBatch: (_a) => __awaiter(this, [_a], void 0, function* ({ workerId, jobId, actionId, batchId, memberIds }) {
38
+ yield client.dispatcher.sendBatchActionEvent({
39
+ workerId,
40
+ jobId,
41
+ actionId,
42
+ batchId,
43
+ eventTimestamp: new Date(),
44
+ eventType: dispatcher_1.StepActionEventType.STEP_EVENT_TYPE_CANCELLED,
45
+ items: memberIds.map((id) => ({ taskRunExternalId: id, eventPayload: '' })),
46
+ });
47
+ }),
48
+ putLog: (taskRunExternalId, message, level, retryCount, extra) => __awaiter(this, void 0, void 0, function* () {
49
+ yield client.events.putLog(taskRunExternalId, message, toEventLogLevel(level), retryCount, extra);
50
+ }),
51
+ refreshTimeout: (taskRunExternalId, incrementBy) => __awaiter(this, void 0, void 0, function* () {
52
+ yield client.dispatcher.refreshTimeout(incrementBy, taskRunExternalId);
53
+ }),
54
+ releaseSlot: (taskRunExternalId) => __awaiter(this, void 0, void 0, function* () {
55
+ yield client.dispatcher.client.releaseSlot({ taskRunExternalId });
56
+ }),
57
+ putStream: (taskRunExternalId, data, index) => __awaiter(this, void 0, void 0, function* () {
58
+ yield client.events.putStream(taskRunExternalId, data, index);
59
+ }),
60
+ runWorkflow: (workflowName, input, options) => client.admin.runWorkflow(workflowName, input, options),
61
+ runWorkflows: (runs) => client.admin.runWorkflows(runs),
62
+ workerId: () => worker.workerId,
63
+ hasWorkflow: (workflowName) => !!worker.workflow_registry.find((workflow) => 'id' in workflow ? workflow.id === workflowName : workflow.name === workflowName),
64
+ workerLabels: () => worker.labels,
65
+ upsertWorkerLabels: (labels) => worker.upsertLabels(labels),
66
+ };
67
+ }