@hatchet-dev/typescript-sdk 1.31.1 → 1.33.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.
- package/README.md +46 -0
- package/clients/dispatcher/action-listener.d.ts +3 -8
- package/clients/dispatcher/action-listener.js +7 -25
- package/clients/dispatcher/action.d.ts +19 -0
- package/clients/dispatcher/action.js +35 -0
- package/clients/dispatcher/dispatcher-client.d.ts +2 -2
- package/clients/dispatcher/heartbeat/heartbeat-controller.d.ts +1 -1
- package/clients/listeners/durable-listener/durable-events.d.ts +56 -0
- package/clients/listeners/durable-listener/durable-events.js +2 -0
- package/clients/listeners/durable-listener/durable-listener-client.d.ts +3 -52
- package/clients/listeners/durable-listener/durable-listener-client.js +3 -2
- package/clients/listeners/durable-listener/pooled-durable-listener-client.js +2 -1
- package/clients/listeners/run-listener/pooled-child-listener-client.js +2 -1
- package/clients/rest/generated/Api.d.ts +1 -62
- package/clients/rest/generated/Api.js +0 -50
- package/clients/rest/generated/data-contracts.d.ts +0 -52
- package/dist/check-edge-entry.mjs +84 -0
- package/edge/declarations.d.ts +49 -0
- package/edge/declarations.js +21 -0
- package/edge/index.d.ts +49 -0
- package/edge/index.js +115 -0
- package/package.json +7 -2
- package/scripts/check-edge-entry.mjs +84 -0
- package/util/abort-error.d.ts +0 -10
- package/util/abort-error.js +0 -15
- package/util/abort-signal.d.ts +12 -0
- package/util/abort-signal.js +19 -0
- package/util/logger/logger.d.ts +1 -1
- package/v1/client/worker/context.d.ts +58 -12
- package/v1/client/worker/context.js +79 -51
- package/v1/client/worker/deprecated/pre-eviction.d.ts +5 -2
- package/v1/client/worker/deprecated/pre-eviction.js +5 -0
- package/v1/client/worker/health-server.d.ts +2 -0
- package/v1/client/worker/health-server.js +28 -0
- package/v1/client/worker/runtime.d.ts +118 -0
- package/v1/client/worker/runtime.js +9 -0
- package/v1/client/worker/worker-internal.d.ts +3 -39
- package/v1/client/worker/worker-internal.js +22 -393
- package/v1/client/worker/worker-runtime.d.ts +8 -0
- package/v1/client/worker/worker-runtime.js +67 -0
- package/v1/client/worker/workflow-proto.d.ts +76 -0
- package/v1/client/worker/workflow-proto.js +482 -0
- package/v1/parent-run-context-storage.d.ts +11 -0
- package/v1/parent-run-context-storage.js +28 -0
- package/v1/parent-run-context-vars.d.ts +15 -1
- package/v1/parent-run-context-vars.js +13 -4
- package/version.d.ts +1 -1
- package/version.js +1 -1
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The seams between a task's `Context` / `DurableContext` and whatever runs the task.
|
|
3
|
+
*
|
|
4
|
+
* A worker process implements them over its `HatchetClient` and durable listener (see
|
|
5
|
+
* `worker-runtime.ts`); a serverless handler implements them over the operator's request
|
|
6
|
+
* and durable socket. Nothing in this module imports from Node, so the interfaces are
|
|
7
|
+
* usable from the edge entry point.
|
|
8
|
+
* @module Runtime
|
|
9
|
+
*/
|
|
10
|
+
import type { Logger, LogLevel } from '../../../util/logger';
|
|
11
|
+
import type WorkflowRunRef from '../../../util/workflow-run-ref';
|
|
12
|
+
import type { WorkerLabelComparator } from '../../../protoc/v1/shared/trigger';
|
|
13
|
+
import type { Priority } from '../../declaration';
|
|
14
|
+
import type { DurableTaskEventLogEntryResult, DurableTaskEventMemoAck, DurableTaskEventRunAck, DurableTaskEventWaitForAck, MemoEvent, RunChildrenEvent, WaitForEvent } from '../../../clients/listeners/durable-listener/durable-events';
|
|
15
|
+
/** Labels a worker advertises for affinity-based assignment. */
|
|
16
|
+
export type WorkerLabels = Record<string, string | number | undefined>;
|
|
17
|
+
/** A worker label a spawned child run asks for. */
|
|
18
|
+
export type DesiredWorkerLabel = {
|
|
19
|
+
value: string | number;
|
|
20
|
+
required?: boolean;
|
|
21
|
+
weight?: number;
|
|
22
|
+
comparator?: WorkerLabelComparator;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Options a context passes when it spawns a child run. Mirrors the options accepted by
|
|
26
|
+
* `AdminClient.runWorkflow`.
|
|
27
|
+
*/
|
|
28
|
+
export type SpawnRunOptions = {
|
|
29
|
+
parentId?: string | undefined;
|
|
30
|
+
parentTaskRunExternalId?: string | undefined;
|
|
31
|
+
/** @deprecated Use `parentTaskRunExternalId` instead. */
|
|
32
|
+
parentStepRunId?: string | undefined;
|
|
33
|
+
childIndex?: number | undefined;
|
|
34
|
+
childKey?: string | undefined;
|
|
35
|
+
/** Alias of `childKey` kept for the child run APIs on `Context`. */
|
|
36
|
+
key?: string | undefined;
|
|
37
|
+
additionalMetadata?: Record<string, string> | undefined;
|
|
38
|
+
desiredWorkerId?: string | undefined;
|
|
39
|
+
priority?: Priority;
|
|
40
|
+
sticky?: boolean;
|
|
41
|
+
returnExceptions?: boolean;
|
|
42
|
+
desiredWorkerLabels?: Record<string, DesiredWorkerLabel>;
|
|
43
|
+
_standaloneTaskName?: string | undefined;
|
|
44
|
+
};
|
|
45
|
+
export type SpawnRunRequest<Q = object> = {
|
|
46
|
+
workflowName: string;
|
|
47
|
+
input: Q;
|
|
48
|
+
options?: SpawnRunOptions;
|
|
49
|
+
};
|
|
50
|
+
/** Identifies every member of a batch task run when the whole batch is cancelled. */
|
|
51
|
+
export type CancelBatchRequest = {
|
|
52
|
+
workerId: string;
|
|
53
|
+
jobId: string;
|
|
54
|
+
actionId: string;
|
|
55
|
+
batchId: string;
|
|
56
|
+
memberIds: string[];
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Everything a `Context` needs from the process running the task: a logger factory,
|
|
60
|
+
* the namespace, the engine-facing operations, and the worker facts `ctx.worker` reports.
|
|
61
|
+
*
|
|
62
|
+
* Implementations that cannot honour an operation (for example a serverless runtime
|
|
63
|
+
* without a Hatchet client) throw from it; the context does not guard against that.
|
|
64
|
+
*/
|
|
65
|
+
export interface ContextRuntime {
|
|
66
|
+
/** The namespace applied to workflow names and event keys, if any. */
|
|
67
|
+
readonly namespace?: string;
|
|
68
|
+
/** Creates a logger for the given component, at the runtime's configured level. */
|
|
69
|
+
logger(name: string): Logger;
|
|
70
|
+
/** Cancels a single task run. */
|
|
71
|
+
cancelRun(taskRunExternalId: string): Promise<void>;
|
|
72
|
+
/** Cancels every member of a batch task run. */
|
|
73
|
+
cancelBatch(request: CancelBatchRequest): Promise<void>;
|
|
74
|
+
/** Writes a log line for a task run to the engine. */
|
|
75
|
+
putLog(taskRunExternalId: string, message: string, level: LogLevel | undefined, retryCount: number, extra?: Record<string, unknown>): Promise<void>;
|
|
76
|
+
/** Extends the execution timeout of a task run by `incrementBy` (Go duration string). */
|
|
77
|
+
refreshTimeout(taskRunExternalId: string, incrementBy: string): Promise<void>;
|
|
78
|
+
/** Releases the worker slot held by a task run. */
|
|
79
|
+
releaseSlot(taskRunExternalId: string): Promise<void>;
|
|
80
|
+
/** Streams a chunk of data from a task run. */
|
|
81
|
+
putStream(taskRunExternalId: string, data: string | Uint8Array, index: number): Promise<void>;
|
|
82
|
+
/** Spawns one run. */
|
|
83
|
+
runWorkflow<Q = object, P = object>(workflowName: string, input: Q, options?: SpawnRunOptions): Promise<WorkflowRunRef<P>>;
|
|
84
|
+
/** Spawns many runs in one call. */
|
|
85
|
+
runWorkflows<Q = object, P = object>(runs: SpawnRunRequest<Q>[]): Promise<WorkflowRunRef<P>[]>;
|
|
86
|
+
/** The id the engine assigned to the worker, once registered. */
|
|
87
|
+
workerId(): string | undefined;
|
|
88
|
+
/** Whether the worker serves the given workflow (used by sticky child runs). */
|
|
89
|
+
hasWorkflow(workflowName: string): boolean;
|
|
90
|
+
/** The worker's current labels. */
|
|
91
|
+
workerLabels(): WorkerLabels;
|
|
92
|
+
/** Replaces the worker's labels. */
|
|
93
|
+
upsertWorkerLabels(labels: WorkerLabels): Promise<WorkerLabels>;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* The seam a `DurableContext` talks to for durable events: the worker implements it with
|
|
97
|
+
* `DurableListenerClient` over gRPC, a serverless handler with frames over a websocket.
|
|
98
|
+
*/
|
|
99
|
+
export interface DurableTransport {
|
|
100
|
+
sendEvent(durableTaskExternalId: string, invocationCount: number, event: RunChildrenEvent): Promise<DurableTaskEventRunAck>;
|
|
101
|
+
sendEvent(durableTaskExternalId: string, invocationCount: number, event: WaitForEvent): Promise<DurableTaskEventWaitForAck>;
|
|
102
|
+
sendEvent(durableTaskExternalId: string, invocationCount: number, event: MemoEvent): Promise<DurableTaskEventMemoAck>;
|
|
103
|
+
waitForCallback(durableTaskExternalId: string, invocationCount: number, branchId: number, nodeId: number, opts?: {
|
|
104
|
+
signal?: AbortSignal;
|
|
105
|
+
}): Promise<DurableTaskEventLogEntryResult>;
|
|
106
|
+
consumeCallbackWithoutBlocking(durableTaskExternalId: string, invocationCount: number, branchId: number, nodeId: number): void;
|
|
107
|
+
sendMemoCompletedNotification(durableTaskExternalId: string, nodeId: number, branchId: number, invocationCount: number, memoKey: Uint8Array, memoResultPayload?: Uint8Array): Promise<void>;
|
|
108
|
+
cleanupTaskState(durableTaskExternalId: string, invocationCount: number): void;
|
|
109
|
+
sendEvictInvocation(durableTaskExternalId: string, invocationCount: number, reason?: string): Promise<void>;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Options for constructing a `DurableContext` on top of a `ContextRuntime`.
|
|
113
|
+
*/
|
|
114
|
+
export interface DurableContextOptions {
|
|
115
|
+
/** The engine version the runtime is talking to; decides whether eviction is supported. */
|
|
116
|
+
engineVersion?: string;
|
|
117
|
+
}
|
|
118
|
+
export declare function isContextRuntime(value: unknown): value is ContextRuntime;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isContextRuntime = isContextRuntime;
|
|
4
|
+
function isContextRuntime(value) {
|
|
5
|
+
if (typeof value !== 'object' || value === null)
|
|
6
|
+
return false;
|
|
7
|
+
const candidate = value;
|
|
8
|
+
return typeof candidate.logger === 'function' && typeof candidate.workerId === 'function';
|
|
9
|
+
}
|
|
@@ -1,17 +1,15 @@
|
|
|
1
|
-
import {
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
184
|
-
|
|
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 {
|
|
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
|
-
}
|