@514labs/moose-lib 0.6.376 → 0.6.378
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/dist/scripts/workflow.js
CHANGED
|
@@ -61,7 +61,9 @@ async function ScriptWorkflow(request, inputData) {
|
|
|
61
61
|
currentData = JSON.parse(mooseJsonEncode(currentData));
|
|
62
62
|
const workflow = await getWorkflowByName(workflowName);
|
|
63
63
|
const task = request.execution_mode === "start" ? workflow.config.startingTask : await getTaskForWorkflow(workflowName, request.continue_from_task);
|
|
64
|
-
const result = await handleTask(workflow, task, currentData
|
|
64
|
+
const result = await handleTask(workflow, task, currentData, {
|
|
65
|
+
originalWorkflowInput: inputData
|
|
66
|
+
});
|
|
65
67
|
results.push(...result);
|
|
66
68
|
return results;
|
|
67
69
|
} catch (error) {
|
|
@@ -69,7 +71,7 @@ async function ScriptWorkflow(request, inputData) {
|
|
|
69
71
|
throw error;
|
|
70
72
|
}
|
|
71
73
|
}
|
|
72
|
-
async function handleTask(workflow, task, inputData) {
|
|
74
|
+
async function handleTask(workflow, task, inputData, ctx = {}) {
|
|
73
75
|
const configTimeout = task.config.timeout;
|
|
74
76
|
let taskTimeout;
|
|
75
77
|
if (!configTimeout) {
|
|
@@ -97,50 +99,29 @@ async function handleTask(workflow, task, inputData) {
|
|
|
97
99
|
activityOptions.scheduleToCloseTimeout = "87600h";
|
|
98
100
|
}
|
|
99
101
|
const { executeTask } = (0, import_workflow.proxyActivities)(activityOptions);
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
continue_from_task: task.name
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
await (0, import_workflow.sleep)(100);
|
|
114
|
-
}
|
|
115
|
-
import_workflow.log.info(`Monitor task exiting because main task completed`);
|
|
116
|
-
};
|
|
117
|
-
const result = await Promise.race([
|
|
118
|
-
executeTask(workflow, task, inputData).then((taskResult) => {
|
|
119
|
-
return {
|
|
120
|
-
type: "task_completed",
|
|
121
|
-
data: taskResult
|
|
122
|
-
};
|
|
123
|
-
}).finally(() => {
|
|
124
|
-
taskCompleted = true;
|
|
125
|
-
}),
|
|
126
|
-
monitorTask().then(() => {
|
|
127
|
-
return { type: "continue_as_new", data: void 0 };
|
|
128
|
-
})
|
|
129
|
-
]);
|
|
130
|
-
if (result.type !== "task_completed") {
|
|
131
|
-
return [];
|
|
102
|
+
if ((0, import_workflow.workflowInfo)().continueAsNewSuggested) {
|
|
103
|
+
import_workflow.log.info(`ContinueAsNew suggested by Temporal before task ${task.name}`);
|
|
104
|
+
return await (0, import_workflow.continueAsNew)(
|
|
105
|
+
{
|
|
106
|
+
workflow_name: workflow.name,
|
|
107
|
+
execution_mode: "continue_as_new",
|
|
108
|
+
continue_from_task: task.name
|
|
109
|
+
},
|
|
110
|
+
ctx.originalWorkflowInput
|
|
111
|
+
);
|
|
132
112
|
}
|
|
133
|
-
const
|
|
113
|
+
const result = await executeTask(workflow, task, inputData);
|
|
114
|
+
const results = [result];
|
|
134
115
|
if (!task.config.onComplete?.length) {
|
|
135
116
|
return results;
|
|
136
117
|
}
|
|
137
118
|
for (const childTask of task.config.onComplete) {
|
|
138
|
-
const childResult = await handleTask(workflow, childTask, result
|
|
119
|
+
const childResult = await handleTask(workflow, childTask, result, ctx);
|
|
139
120
|
results.push(...childResult);
|
|
140
121
|
}
|
|
141
|
-
if (task.name.endsWith("_extract") && result && typeof result === "object" &&
|
|
122
|
+
if (task.name.endsWith("_extract") && result && typeof result === "object" && "hasMore" in result && result.hasMore === true) {
|
|
142
123
|
import_workflow.log.info(`Extract task ${task.name} has more data, restarting chain...`);
|
|
143
|
-
const nextBatchResults = await handleTask(workflow, task, null);
|
|
124
|
+
const nextBatchResults = await handleTask(workflow, task, null, ctx);
|
|
144
125
|
results.push(...nextBatchResults);
|
|
145
126
|
}
|
|
146
127
|
return results;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/scripts/workflow.ts","../../src/scripts/serialization.ts"],"sourcesContent":["import {\n log as logger,\n ActivityOptions,\n proxyActivities,\n workflowInfo,\n continueAsNew,\n
|
|
1
|
+
{"version":3,"sources":["../../src/scripts/workflow.ts","../../src/scripts/serialization.ts"],"sourcesContent":["import {\n log as logger,\n ActivityOptions,\n proxyActivities,\n workflowInfo,\n continueAsNew,\n} from \"@temporalio/workflow\";\nimport { Duration } from \"@temporalio/common\";\nimport { Task, Workflow } from \"../dmv2\";\n\nimport { WorkflowState } from \"./types\";\nimport { mooseJsonEncode } from \"./serialization\";\n\ninterface WorkflowRequest {\n workflow_name: string;\n execution_mode: \"start\" | \"continue_as_new\";\n continue_from_task?: string; // Only for continue_as_new\n}\n\ninterface HandleTaskContext {\n originalWorkflowInput?: any;\n}\n\nconst { getWorkflowByName, getTaskForWorkflow } = proxyActivities({\n startToCloseTimeout: \"1 minutes\",\n retry: {\n maximumAttempts: 1,\n },\n});\n\nexport async function ScriptWorkflow(\n request: WorkflowRequest,\n inputData?: any,\n): Promise<any[]> {\n const state: WorkflowState = {\n completedSteps: [],\n currentStep: null,\n failedStep: null,\n };\n\n const results: any[] = [];\n const workflowName = request.workflow_name;\n let currentData = inputData?.data || inputData || {};\n\n logger.info(\n `Starting workflow: ${workflowName} (mode: ${request.execution_mode}) with data: ${JSON.stringify(currentData)}`,\n );\n\n try {\n currentData = JSON.parse(mooseJsonEncode(currentData));\n const workflow = await getWorkflowByName(workflowName);\n const task =\n request.execution_mode === \"start\" ?\n workflow.config.startingTask\n : await getTaskForWorkflow(workflowName, request.continue_from_task!);\n const result = await handleTask(workflow, task, currentData, {\n originalWorkflowInput: inputData,\n });\n results.push(...result);\n\n return results;\n } catch (error) {\n state.failedStep = workflowName;\n throw error;\n }\n}\n\nasync function handleTask(\n workflow: Workflow,\n task: Task<any, any>,\n inputData: any,\n ctx: HandleTaskContext = {},\n): Promise<any[]> {\n // Handle timeout configuration\n const configTimeout = task.config.timeout;\n let taskTimeout: Duration | undefined;\n\n if (!configTimeout) {\n taskTimeout = \"1h\";\n } else if (configTimeout === \"never\") {\n taskTimeout = undefined;\n } else {\n taskTimeout = configTimeout as Duration;\n }\n\n const taskRetries = task.config.retries ?? 3;\n // Temporal's maximumAttempts = total attempts (initial + retries)\n // User-facing \"retries\" = number of retries after initial failure\n const maxAttempts = taskRetries + 1;\n\n const timeoutMessage =\n taskTimeout ? `with timeout ${taskTimeout}` : \"with no timeout (unlimited)\";\n logger.info(\n `Handling task ${task.name} ${timeoutMessage} and retries ${taskRetries}`,\n );\n\n const activityOptions: ActivityOptions = {\n heartbeatTimeout: \"10s\",\n retry: {\n maximumAttempts: maxAttempts,\n },\n };\n\n // Temporal requires either startToCloseTimeout OR scheduleToCloseTimeout to be set\n // For unlimited timeout (timeout = \"never\"), we use scheduleToCloseTimeout with a very large value\n // For normal timeouts, we use startToCloseTimeout for single execution timeout\n if (taskTimeout) {\n // Normal timeout - limit each individual execution attempt\n activityOptions.startToCloseTimeout = taskTimeout;\n } else {\n // Unlimited timeout - set scheduleToCloseTimeout to a very large value (10 years)\n // This satisfies Temporal's requirement while effectively allowing unlimited execution\n activityOptions.scheduleToCloseTimeout = \"87600h\"; // 10 years\n }\n\n const { executeTask } = proxyActivities(activityOptions);\n\n // Check history limits BEFORE starting the task, so continue_from_task\n // points to a task that hasn't run yet (avoids duplicate execution).\n // Pass the original raw inputData so run() doesn't double-process it.\n if (workflowInfo().continueAsNewSuggested) {\n logger.info(`ContinueAsNew suggested by Temporal before task ${task.name}`);\n return await continueAsNew(\n {\n workflow_name: workflow.name,\n execution_mode: \"continue_as_new\" as const,\n continue_from_task: task.name,\n },\n ctx.originalWorkflowInput,\n );\n }\n\n // Execute the activity directly — no polling monitor.\n // A running activity does not generate workflow history events, so the\n // history stays small even for long-running (timeout: \"never\") tasks.\n const result = await executeTask(workflow, task, inputData);\n\n const results = [result];\n\n if (!task.config.onComplete?.length) {\n return results;\n }\n\n for (const childTask of task.config.onComplete) {\n const childResult = await handleTask(workflow, childTask, result, ctx);\n results.push(...childResult);\n }\n\n // Check if this is an ETL extract task that needs to loop\n // ETL extract tasks end with \"_extract\" and return BatchResult with hasMore\n if (\n task.name.endsWith(\"_extract\") &&\n result &&\n typeof result === \"object\" &&\n \"hasMore\" in result &&\n (result as any).hasMore === true\n ) {\n logger.info(`Extract task ${task.name} has more data, restarting chain...`);\n\n // Recursively call the extract task again to get the next batch\n const nextBatchResults = await handleTask(workflow, task, null, ctx);\n results.push(...nextBatchResults);\n }\n\n return results;\n}\n","// Add serialization helpers\nexport const mooseJsonEncode = (data: any): string => {\n return JSON.stringify(data, (_, value) => {\n if (value instanceof Map) {\n return {\n __type: \"Map\",\n value: Array.from(value.entries()),\n };\n }\n return value;\n });\n};\n\nexport const mooseJsonDecode = (text: string): any => {\n return JSON.parse(text, (_, value) => {\n if (value && typeof value === \"object\" && value.__type === \"Map\") {\n return new Map(value.value);\n }\n return value;\n });\n};\n"],"mappings":"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","names":["logger"]}
|
|
@@ -3,8 +3,7 @@ import {
|
|
|
3
3
|
log as logger,
|
|
4
4
|
proxyActivities,
|
|
5
5
|
workflowInfo,
|
|
6
|
-
continueAsNew
|
|
7
|
-
sleep
|
|
6
|
+
continueAsNew
|
|
8
7
|
} from "@temporalio/workflow";
|
|
9
8
|
|
|
10
9
|
// src/scripts/serialization.ts
|
|
@@ -43,7 +42,9 @@ async function ScriptWorkflow(request, inputData) {
|
|
|
43
42
|
currentData = JSON.parse(mooseJsonEncode(currentData));
|
|
44
43
|
const workflow = await getWorkflowByName(workflowName);
|
|
45
44
|
const task = request.execution_mode === "start" ? workflow.config.startingTask : await getTaskForWorkflow(workflowName, request.continue_from_task);
|
|
46
|
-
const result = await handleTask(workflow, task, currentData
|
|
45
|
+
const result = await handleTask(workflow, task, currentData, {
|
|
46
|
+
originalWorkflowInput: inputData
|
|
47
|
+
});
|
|
47
48
|
results.push(...result);
|
|
48
49
|
return results;
|
|
49
50
|
} catch (error) {
|
|
@@ -51,7 +52,7 @@ async function ScriptWorkflow(request, inputData) {
|
|
|
51
52
|
throw error;
|
|
52
53
|
}
|
|
53
54
|
}
|
|
54
|
-
async function handleTask(workflow, task, inputData) {
|
|
55
|
+
async function handleTask(workflow, task, inputData, ctx = {}) {
|
|
55
56
|
const configTimeout = task.config.timeout;
|
|
56
57
|
let taskTimeout;
|
|
57
58
|
if (!configTimeout) {
|
|
@@ -79,50 +80,29 @@ async function handleTask(workflow, task, inputData) {
|
|
|
79
80
|
activityOptions.scheduleToCloseTimeout = "87600h";
|
|
80
81
|
}
|
|
81
82
|
const { executeTask } = proxyActivities(activityOptions);
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
continue_from_task: task.name
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
await sleep(100);
|
|
96
|
-
}
|
|
97
|
-
logger.info(`Monitor task exiting because main task completed`);
|
|
98
|
-
};
|
|
99
|
-
const result = await Promise.race([
|
|
100
|
-
executeTask(workflow, task, inputData).then((taskResult) => {
|
|
101
|
-
return {
|
|
102
|
-
type: "task_completed",
|
|
103
|
-
data: taskResult
|
|
104
|
-
};
|
|
105
|
-
}).finally(() => {
|
|
106
|
-
taskCompleted = true;
|
|
107
|
-
}),
|
|
108
|
-
monitorTask().then(() => {
|
|
109
|
-
return { type: "continue_as_new", data: void 0 };
|
|
110
|
-
})
|
|
111
|
-
]);
|
|
112
|
-
if (result.type !== "task_completed") {
|
|
113
|
-
return [];
|
|
83
|
+
if (workflowInfo().continueAsNewSuggested) {
|
|
84
|
+
logger.info(`ContinueAsNew suggested by Temporal before task ${task.name}`);
|
|
85
|
+
return await continueAsNew(
|
|
86
|
+
{
|
|
87
|
+
workflow_name: workflow.name,
|
|
88
|
+
execution_mode: "continue_as_new",
|
|
89
|
+
continue_from_task: task.name
|
|
90
|
+
},
|
|
91
|
+
ctx.originalWorkflowInput
|
|
92
|
+
);
|
|
114
93
|
}
|
|
115
|
-
const
|
|
94
|
+
const result = await executeTask(workflow, task, inputData);
|
|
95
|
+
const results = [result];
|
|
116
96
|
if (!task.config.onComplete?.length) {
|
|
117
97
|
return results;
|
|
118
98
|
}
|
|
119
99
|
for (const childTask of task.config.onComplete) {
|
|
120
|
-
const childResult = await handleTask(workflow, childTask, result
|
|
100
|
+
const childResult = await handleTask(workflow, childTask, result, ctx);
|
|
121
101
|
results.push(...childResult);
|
|
122
102
|
}
|
|
123
|
-
if (task.name.endsWith("_extract") && result && typeof result === "object" &&
|
|
103
|
+
if (task.name.endsWith("_extract") && result && typeof result === "object" && "hasMore" in result && result.hasMore === true) {
|
|
124
104
|
logger.info(`Extract task ${task.name} has more data, restarting chain...`);
|
|
125
|
-
const nextBatchResults = await handleTask(workflow, task, null);
|
|
105
|
+
const nextBatchResults = await handleTask(workflow, task, null, ctx);
|
|
126
106
|
results.push(...nextBatchResults);
|
|
127
107
|
}
|
|
128
108
|
return results;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/scripts/workflow.ts","../../src/scripts/serialization.ts"],"sourcesContent":["import {\n log as logger,\n ActivityOptions,\n proxyActivities,\n workflowInfo,\n continueAsNew,\n
|
|
1
|
+
{"version":3,"sources":["../../src/scripts/workflow.ts","../../src/scripts/serialization.ts"],"sourcesContent":["import {\n log as logger,\n ActivityOptions,\n proxyActivities,\n workflowInfo,\n continueAsNew,\n} from \"@temporalio/workflow\";\nimport { Duration } from \"@temporalio/common\";\nimport { Task, Workflow } from \"../dmv2\";\n\nimport { WorkflowState } from \"./types\";\nimport { mooseJsonEncode } from \"./serialization\";\n\ninterface WorkflowRequest {\n workflow_name: string;\n execution_mode: \"start\" | \"continue_as_new\";\n continue_from_task?: string; // Only for continue_as_new\n}\n\ninterface HandleTaskContext {\n originalWorkflowInput?: any;\n}\n\nconst { getWorkflowByName, getTaskForWorkflow } = proxyActivities({\n startToCloseTimeout: \"1 minutes\",\n retry: {\n maximumAttempts: 1,\n },\n});\n\nexport async function ScriptWorkflow(\n request: WorkflowRequest,\n inputData?: any,\n): Promise<any[]> {\n const state: WorkflowState = {\n completedSteps: [],\n currentStep: null,\n failedStep: null,\n };\n\n const results: any[] = [];\n const workflowName = request.workflow_name;\n let currentData = inputData?.data || inputData || {};\n\n logger.info(\n `Starting workflow: ${workflowName} (mode: ${request.execution_mode}) with data: ${JSON.stringify(currentData)}`,\n );\n\n try {\n currentData = JSON.parse(mooseJsonEncode(currentData));\n const workflow = await getWorkflowByName(workflowName);\n const task =\n request.execution_mode === \"start\" ?\n workflow.config.startingTask\n : await getTaskForWorkflow(workflowName, request.continue_from_task!);\n const result = await handleTask(workflow, task, currentData, {\n originalWorkflowInput: inputData,\n });\n results.push(...result);\n\n return results;\n } catch (error) {\n state.failedStep = workflowName;\n throw error;\n }\n}\n\nasync function handleTask(\n workflow: Workflow,\n task: Task<any, any>,\n inputData: any,\n ctx: HandleTaskContext = {},\n): Promise<any[]> {\n // Handle timeout configuration\n const configTimeout = task.config.timeout;\n let taskTimeout: Duration | undefined;\n\n if (!configTimeout) {\n taskTimeout = \"1h\";\n } else if (configTimeout === \"never\") {\n taskTimeout = undefined;\n } else {\n taskTimeout = configTimeout as Duration;\n }\n\n const taskRetries = task.config.retries ?? 3;\n // Temporal's maximumAttempts = total attempts (initial + retries)\n // User-facing \"retries\" = number of retries after initial failure\n const maxAttempts = taskRetries + 1;\n\n const timeoutMessage =\n taskTimeout ? `with timeout ${taskTimeout}` : \"with no timeout (unlimited)\";\n logger.info(\n `Handling task ${task.name} ${timeoutMessage} and retries ${taskRetries}`,\n );\n\n const activityOptions: ActivityOptions = {\n heartbeatTimeout: \"10s\",\n retry: {\n maximumAttempts: maxAttempts,\n },\n };\n\n // Temporal requires either startToCloseTimeout OR scheduleToCloseTimeout to be set\n // For unlimited timeout (timeout = \"never\"), we use scheduleToCloseTimeout with a very large value\n // For normal timeouts, we use startToCloseTimeout for single execution timeout\n if (taskTimeout) {\n // Normal timeout - limit each individual execution attempt\n activityOptions.startToCloseTimeout = taskTimeout;\n } else {\n // Unlimited timeout - set scheduleToCloseTimeout to a very large value (10 years)\n // This satisfies Temporal's requirement while effectively allowing unlimited execution\n activityOptions.scheduleToCloseTimeout = \"87600h\"; // 10 years\n }\n\n const { executeTask } = proxyActivities(activityOptions);\n\n // Check history limits BEFORE starting the task, so continue_from_task\n // points to a task that hasn't run yet (avoids duplicate execution).\n // Pass the original raw inputData so run() doesn't double-process it.\n if (workflowInfo().continueAsNewSuggested) {\n logger.info(`ContinueAsNew suggested by Temporal before task ${task.name}`);\n return await continueAsNew(\n {\n workflow_name: workflow.name,\n execution_mode: \"continue_as_new\" as const,\n continue_from_task: task.name,\n },\n ctx.originalWorkflowInput,\n );\n }\n\n // Execute the activity directly — no polling monitor.\n // A running activity does not generate workflow history events, so the\n // history stays small even for long-running (timeout: \"never\") tasks.\n const result = await executeTask(workflow, task, inputData);\n\n const results = [result];\n\n if (!task.config.onComplete?.length) {\n return results;\n }\n\n for (const childTask of task.config.onComplete) {\n const childResult = await handleTask(workflow, childTask, result, ctx);\n results.push(...childResult);\n }\n\n // Check if this is an ETL extract task that needs to loop\n // ETL extract tasks end with \"_extract\" and return BatchResult with hasMore\n if (\n task.name.endsWith(\"_extract\") &&\n result &&\n typeof result === \"object\" &&\n \"hasMore\" in result &&\n (result as any).hasMore === true\n ) {\n logger.info(`Extract task ${task.name} has more data, restarting chain...`);\n\n // Recursively call the extract task again to get the next batch\n const nextBatchResults = await handleTask(workflow, task, null, ctx);\n results.push(...nextBatchResults);\n }\n\n return results;\n}\n","// Add serialization helpers\nexport const mooseJsonEncode = (data: any): string => {\n return JSON.stringify(data, (_, value) => {\n if (value instanceof Map) {\n return {\n __type: \"Map\",\n value: Array.from(value.entries()),\n };\n }\n return value;\n });\n};\n\nexport const mooseJsonDecode = (text: string): any => {\n return JSON.parse(text, (_, value) => {\n if (value && typeof value === \"object\" && value.__type === \"Map\") {\n return new Map(value.value);\n }\n return value;\n });\n};\n"],"mappings":"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","names":[]}
|