@loopstack/core 0.31.0 → 0.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.
- package/dist/common/dtos/client-message.dto.d.ts +1 -0
- package/dist/common/dtos/client-message.dto.d.ts.map +1 -1
- package/dist/common/dtos/client-message.dto.js.map +1 -1
- package/dist/loop-core.module.d.ts.map +1 -1
- package/dist/loop-core.module.js +40 -38
- package/dist/loop-core.module.js.map +1 -1
- package/dist/persistence/services/workflow-checkpoint.service.d.ts +0 -1
- package/dist/persistence/services/workflow-checkpoint.service.d.ts.map +1 -1
- package/dist/persistence/services/workflow-checkpoint.service.js.map +1 -1
- package/dist/persistence/services/workflow.service.d.ts +0 -6
- package/dist/persistence/services/workflow.service.d.ts.map +1 -1
- package/dist/persistence/services/workflow.service.js +1 -30
- package/dist/persistence/services/workflow.service.js.map +1 -1
- package/dist/persistence/services/workspace.service.js +1 -1
- package/dist/persistence/services/workspace.service.js.map +1 -1
- package/dist/scheduler/services/task-processor/run-workflow-task-processor.service.d.ts +3 -1
- package/dist/scheduler/services/task-processor/run-workflow-task-processor.service.d.ts.map +1 -1
- package/dist/scheduler/services/task-processor/run-workflow-task-processor.service.js +13 -10
- package/dist/scheduler/services/task-processor/run-workflow-task-processor.service.js.map +1 -1
- package/dist/scheduler/services/workflow-runner.service.d.ts +16 -6
- package/dist/scheduler/services/workflow-runner.service.d.ts.map +1 -1
- package/dist/scheduler/services/workflow-runner.service.js +62 -30
- package/dist/scheduler/services/workflow-runner.service.js.map +1 -1
- package/dist/workflow-processor/services/block-processor.service.js +1 -1
- package/dist/workflow-processor/services/block-processor.service.js.map +1 -1
- package/dist/workflow-processor/services/create-workflow.service.d.ts +2 -4
- package/dist/workflow-processor/services/create-workflow.service.d.ts.map +1 -1
- package/dist/workflow-processor/services/create-workflow.service.js +6 -19
- package/dist/workflow-processor/services/create-workflow.service.js.map +1 -1
- package/dist/workflow-processor/services/document-persistence.service.d.ts +3 -3
- package/dist/workflow-processor/services/document-persistence.service.d.ts.map +1 -1
- package/dist/workflow-processor/services/document-persistence.service.js +20 -36
- package/dist/workflow-processor/services/document-persistence.service.js.map +1 -1
- package/dist/workflow-processor/services/{document-repository.service.d.ts → document-store.service.d.ts} +5 -3
- package/dist/workflow-processor/services/document-store.service.d.ts.map +1 -0
- package/dist/workflow-processor/services/{document-repository.service.js → document-store.service.js} +28 -18
- package/dist/workflow-processor/services/document-store.service.js.map +1 -0
- package/dist/workflow-processor/services/feature-registry.service.d.ts +12 -0
- package/dist/workflow-processor/services/feature-registry.service.d.ts.map +1 -0
- package/dist/workflow-processor/services/feature-registry.service.js +46 -0
- package/dist/workflow-processor/services/feature-registry.service.js.map +1 -0
- package/dist/workflow-processor/services/index.d.ts +6 -4
- package/dist/workflow-processor/services/index.d.ts.map +1 -1
- package/dist/workflow-processor/services/index.js +6 -4
- package/dist/workflow-processor/services/index.js.map +1 -1
- package/dist/workflow-processor/services/processors/workflow-processor.service.d.ts +19 -10
- package/dist/workflow-processor/services/processors/workflow-processor.service.d.ts.map +1 -1
- package/dist/workflow-processor/services/processors/workflow-processor.service.js +192 -211
- package/dist/workflow-processor/services/processors/workflow-processor.service.js.map +1 -1
- package/dist/workflow-processor/services/root-processor.service.d.ts +6 -8
- package/dist/workflow-processor/services/root-processor.service.d.ts.map +1 -1
- package/dist/workflow-processor/services/root-processor.service.js +18 -40
- package/dist/workflow-processor/services/root-processor.service.js.map +1 -1
- package/dist/workflow-processor/services/studio-discovery.service.d.ts +52 -0
- package/dist/workflow-processor/services/studio-discovery.service.d.ts.map +1 -0
- package/dist/workflow-processor/services/studio-discovery.service.js +179 -0
- package/dist/workflow-processor/services/studio-discovery.service.js.map +1 -0
- package/dist/workflow-processor/services/tool-pipeline.service.d.ts +14 -0
- package/dist/workflow-processor/services/tool-pipeline.service.d.ts.map +1 -0
- package/dist/workflow-processor/services/{tool-execution.service.js → tool-pipeline.service.js} +28 -40
- package/dist/workflow-processor/services/tool-pipeline.service.js.map +1 -0
- package/dist/workflow-processor/services/tool-registry.service.d.ts +16 -0
- package/dist/workflow-processor/services/tool-registry.service.d.ts.map +1 -0
- package/dist/workflow-processor/services/tool-registry.service.js +60 -0
- package/dist/workflow-processor/services/tool-registry.service.js.map +1 -0
- package/dist/workflow-processor/services/transition-resolver.service.d.ts +1 -1
- package/dist/workflow-processor/services/transition-resolver.service.d.ts.map +1 -1
- package/dist/workflow-processor/services/transition-resolver.service.js +5 -5
- package/dist/workflow-processor/services/transition-resolver.service.js.map +1 -1
- package/dist/workflow-processor/services/workflow-memory-monitor.service.d.ts +4 -5
- package/dist/workflow-processor/services/workflow-memory-monitor.service.d.ts.map +1 -1
- package/dist/workflow-processor/services/workflow-memory-monitor.service.js +9 -11
- package/dist/workflow-processor/services/workflow-memory-monitor.service.js.map +1 -1
- package/dist/workflow-processor/services/workflow-orchestration.service.d.ts +5 -2
- package/dist/workflow-processor/services/workflow-orchestration.service.d.ts.map +1 -1
- package/dist/workflow-processor/services/workflow-orchestration.service.js +18 -21
- package/dist/workflow-processor/services/workflow-orchestration.service.js.map +1 -1
- package/dist/workflow-processor/services/workflow-registry.service.d.ts +19 -0
- package/dist/workflow-processor/services/workflow-registry.service.d.ts.map +1 -0
- package/dist/workflow-processor/services/workflow-registry.service.js +66 -0
- package/dist/workflow-processor/services/workflow-registry.service.js.map +1 -0
- package/dist/workflow-processor/services/workflow-state.service.d.ts +4 -3
- package/dist/workflow-processor/services/workflow-state.service.d.ts.map +1 -1
- package/dist/workflow-processor/services/workflow-state.service.js +15 -16
- package/dist/workflow-processor/services/workflow-state.service.js.map +1 -1
- package/dist/workflow-processor/utils/execution-scope.d.ts +25 -5
- package/dist/workflow-processor/utils/execution-scope.d.ts.map +1 -1
- package/dist/workflow-processor/utils/execution-scope.js +15 -5
- package/dist/workflow-processor/utils/execution-scope.js.map +1 -1
- package/dist/workflow-processor/utils/index.d.ts +0 -4
- package/dist/workflow-processor/utils/index.d.ts.map +1 -1
- package/dist/workflow-processor/utils/index.js +0 -4
- package/dist/workflow-processor/utils/index.js.map +1 -1
- package/dist/workflow-processor/utils/workflow-templates.d.ts.map +1 -1
- package/dist/workflow-processor/utils/workflow-templates.js +13 -2
- package/dist/workflow-processor/utils/workflow-templates.js.map +1 -1
- package/package.json +2 -2
- package/dist/workflow-processor/services/block-config-cache.service.d.ts +0 -50
- package/dist/workflow-processor/services/block-config-cache.service.d.ts.map +0 -1
- package/dist/workflow-processor/services/block-config-cache.service.js +0 -178
- package/dist/workflow-processor/services/block-config-cache.service.js.map +0 -1
- package/dist/workflow-processor/services/block-discovery.service.d.ts +0 -15
- package/dist/workflow-processor/services/block-discovery.service.d.ts.map +0 -1
- package/dist/workflow-processor/services/block-discovery.service.js +0 -70
- package/dist/workflow-processor/services/block-discovery.service.js.map +0 -1
- package/dist/workflow-processor/services/document-repository.service.d.ts.map +0 -1
- package/dist/workflow-processor/services/document-repository.service.js.map +0 -1
- package/dist/workflow-processor/services/tool-execution.service.d.ts +0 -16
- package/dist/workflow-processor/services/tool-execution.service.d.ts.map +0 -1
- package/dist/workflow-processor/services/tool-execution.service.js.map +0 -1
- package/dist/workflow-processor/utils/execution-context-manager.d.ts +0 -27
- package/dist/workflow-processor/utils/execution-context-manager.d.ts.map +0 -1
- package/dist/workflow-processor/utils/execution-context-manager.js +0 -78
- package/dist/workflow-processor/utils/execution-context-manager.js.map +0 -1
- package/dist/workflow-processor/utils/state/state-manager.d.ts +0 -26
- package/dist/workflow-processor/utils/state/state-manager.d.ts.map +0 -1
- package/dist/workflow-processor/utils/state/state-manager.js +0 -68
- package/dist/workflow-processor/utils/state/state-manager.js.map +0 -1
- package/dist/workflow-processor/utils/wrap-app-proxy.d.ts +0 -3
- package/dist/workflow-processor/utils/wrap-app-proxy.d.ts.map +0 -1
- package/dist/workflow-processor/utils/wrap-app-proxy.js +0 -21
- package/dist/workflow-processor/utils/wrap-app-proxy.js.map +0 -1
- package/dist/workflow-processor/utils/wrap-block-proxy.d.ts +0 -4
- package/dist/workflow-processor/utils/wrap-block-proxy.d.ts.map +0 -1
- package/dist/workflow-processor/utils/wrap-block-proxy.js +0 -38
- package/dist/workflow-processor/utils/wrap-block-proxy.js.map +0 -1
- package/dist/workflow-processor/utils/wrap-tool-proxy.d.ts +0 -3
- package/dist/workflow-processor/utils/wrap-tool-proxy.d.ts.map +0 -1
- package/dist/workflow-processor/utils/wrap-tool-proxy.js +0 -57
- package/dist/workflow-processor/utils/wrap-tool-proxy.js.map +0 -1
|
@@ -10,195 +10,218 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
10
10
|
var WorkflowProcessorService_1;
|
|
11
11
|
import { Injectable, Logger } from '@nestjs/common';
|
|
12
12
|
import { DataSource } from 'typeorm';
|
|
13
|
-
import { ErrorDocument,
|
|
13
|
+
import { ErrorDocument, getBlockArgsSchema, getGuardMetadataMap, normalizeRetryConfig, } from '@loopstack/common';
|
|
14
14
|
import { WorkflowState, WorkflowState as WorkflowStateEnum } from '@loopstack/contracts/enums';
|
|
15
15
|
import { ConfigTraceError } from '../../../common/index.js';
|
|
16
|
-
import {
|
|
17
|
-
import { StateManager } from '../../utils/state/state-manager.js';
|
|
16
|
+
import { ExecutionScope } from '../../utils/index.js';
|
|
18
17
|
import { DocumentPersistenceService } from '../document-persistence.service.js';
|
|
19
|
-
import {
|
|
18
|
+
import { resolveDocumentName } from '../document-store.service.js';
|
|
20
19
|
import { TransitionResolverService } from '../transition-resolver.service.js';
|
|
21
20
|
import { WorkflowMemoryMonitorService } from '../workflow-memory-monitor.service.js';
|
|
22
21
|
import { WorkflowStateService } from '../workflow-state.service.js';
|
|
23
|
-
function invokeWorkflowMethod(proxy, methodName, data) {
|
|
24
|
-
const method = proxy[methodName];
|
|
25
|
-
if (typeof method !== 'function') {
|
|
26
|
-
throw new Error(`Method '${methodName}' not found on workflow ${proxy.constructor.name}`);
|
|
27
|
-
}
|
|
28
|
-
return method.call(proxy, data);
|
|
29
|
-
}
|
|
30
22
|
function rejectAfter(ms, methodName) {
|
|
31
23
|
return new Promise((_, reject) => setTimeout(() => reject(new Error(`Transition '${methodName}' timed out after ${ms}ms`)), ms));
|
|
32
24
|
}
|
|
33
|
-
function invokeGuardMethod(proxy, guardMethodName) {
|
|
34
|
-
const method = proxy[guardMethodName];
|
|
35
|
-
if (typeof method !== 'function') {
|
|
36
|
-
throw new Error(`Guard method '${guardMethodName}' not found on workflow ${proxy.constructor.name}`);
|
|
37
|
-
}
|
|
38
|
-
return method.call(proxy);
|
|
39
|
-
}
|
|
40
25
|
let WorkflowProcessorService = WorkflowProcessorService_1 = class WorkflowProcessorService {
|
|
41
26
|
workflowStateService;
|
|
42
27
|
transitionResolverService;
|
|
43
28
|
executionScope;
|
|
44
29
|
memoryMonitor;
|
|
45
|
-
toolExecutionService;
|
|
46
30
|
documentPersistenceService;
|
|
47
31
|
dataSource;
|
|
48
32
|
logger = new Logger(WorkflowProcessorService_1.name);
|
|
49
|
-
constructor(workflowStateService, transitionResolverService, executionScope, memoryMonitor,
|
|
33
|
+
constructor(workflowStateService, transitionResolverService, executionScope, memoryMonitor, documentPersistenceService, dataSource) {
|
|
50
34
|
this.workflowStateService = workflowStateService;
|
|
51
35
|
this.transitionResolverService = transitionResolverService;
|
|
52
36
|
this.executionScope = executionScope;
|
|
53
37
|
this.memoryMonitor = memoryMonitor;
|
|
54
|
-
this.toolExecutionService = toolExecutionService;
|
|
55
38
|
this.documentPersistenceService = documentPersistenceService;
|
|
56
39
|
this.dataSource = dataSource;
|
|
57
40
|
}
|
|
58
|
-
createCtx(workflow, context, validArgs, workflowEntity, latestCheckpoint, validConfig) {
|
|
59
|
-
const initialWorkflowData = {
|
|
60
|
-
hasError: false,
|
|
61
|
-
stop: false,
|
|
62
|
-
status: workflowEntity?.status ?? WorkflowState.Pending,
|
|
63
|
-
availableTransitions: [],
|
|
64
|
-
persistenceState: {
|
|
65
|
-
documentsUpdated: false,
|
|
66
|
-
},
|
|
67
|
-
documents: workflowEntity?.documents ?? [],
|
|
68
|
-
place: workflowEntity?.place ?? 'start',
|
|
69
|
-
tools: {},
|
|
70
|
-
result: null,
|
|
71
|
-
retryCount: workflowEntity?.retryCount ?? 0,
|
|
72
|
-
retryTransitionId: workflowEntity?.retryTransitionId ?? undefined,
|
|
73
|
-
};
|
|
74
|
-
if (workflowEntity) {
|
|
75
|
-
delete workflowEntity.documents;
|
|
76
|
-
}
|
|
77
|
-
const checkpoint = latestCheckpoint
|
|
78
|
-
? {
|
|
79
|
-
state: latestCheckpoint.state,
|
|
80
|
-
tools: latestCheckpoint.tools,
|
|
81
|
-
version: latestCheckpoint.version,
|
|
82
|
-
}
|
|
83
|
-
: null;
|
|
84
|
-
const stateManager = new StateManager(undefined, initialWorkflowData, checkpoint);
|
|
85
|
-
return new ExecutionContextManager(workflow, context, validArgs, stateManager, validConfig);
|
|
86
|
-
}
|
|
87
41
|
async process(workflow, args, context) {
|
|
88
42
|
const schema = getBlockArgsSchema(workflow);
|
|
89
43
|
const validArgs = schema ? schema.parse(args) : args;
|
|
90
|
-
const configSchema = getBlockConfigSchema(workflow);
|
|
91
|
-
const rawConfig = context.workflowEntity?.config;
|
|
92
|
-
const validConfig = configSchema && rawConfig ? configSchema.parse(rawConfig) : (rawConfig ?? undefined);
|
|
93
44
|
const isStateless = !!context.options?.stateless;
|
|
94
45
|
let workflowEntity;
|
|
95
46
|
let pendingTransition;
|
|
96
|
-
let
|
|
47
|
+
let latestCheckpoint = null;
|
|
48
|
+
const meta = {
|
|
49
|
+
hasError: false,
|
|
50
|
+
stop: false,
|
|
51
|
+
status: WorkflowStateEnum.Pending,
|
|
52
|
+
availableTransitions: [],
|
|
53
|
+
persistenceState: { documentsUpdated: false },
|
|
54
|
+
documents: [],
|
|
55
|
+
place: 'start',
|
|
56
|
+
tools: {},
|
|
57
|
+
result: null,
|
|
58
|
+
retryCount: 0,
|
|
59
|
+
retryTransitionId: undefined,
|
|
60
|
+
version: 1,
|
|
61
|
+
};
|
|
97
62
|
if (isStateless) {
|
|
98
|
-
|
|
99
|
-
ctx.getManager().setData('status', WorkflowStateEnum.Running);
|
|
63
|
+
meta.status = WorkflowStateEnum.Running;
|
|
100
64
|
}
|
|
101
65
|
else {
|
|
102
66
|
workflowEntity = context.workflowEntity;
|
|
103
67
|
context.workflowId = workflowEntity.id;
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
68
|
+
latestCheckpoint = await this.workflowStateService.getLatestCheckpoint(workflowEntity.id);
|
|
69
|
+
meta.status = workflowEntity.status ?? WorkflowState.Pending;
|
|
70
|
+
meta.documents = workflowEntity.documents ?? [];
|
|
71
|
+
meta.place = workflowEntity.place ?? 'start';
|
|
72
|
+
meta.retryCount = workflowEntity.retryCount ?? 0;
|
|
73
|
+
meta.retryTransitionId = workflowEntity.retryTransitionId ?? undefined;
|
|
74
|
+
if (workflowEntity) {
|
|
75
|
+
delete workflowEntity.documents;
|
|
76
|
+
}
|
|
77
|
+
const isInitialRun = meta.place === 'start';
|
|
78
|
+
const payloadTransition = context.payload?.transition;
|
|
107
79
|
pendingTransition =
|
|
108
|
-
!isInitialRun &&
|
|
109
|
-
? ctx.getContext().payload?.transition
|
|
110
|
-
: undefined;
|
|
80
|
+
!isInitialRun && payloadTransition?.workflowId === context.workflowId ? payloadTransition : undefined;
|
|
111
81
|
const isRetry = !!workflowEntity.hasError;
|
|
112
82
|
if (!isInitialRun && !pendingTransition && !isRetry) {
|
|
113
83
|
this.logger.debug('Skipping processing since state is already processed.');
|
|
114
|
-
return
|
|
84
|
+
return meta;
|
|
115
85
|
}
|
|
116
|
-
|
|
86
|
+
meta.status = WorkflowStateEnum.Running;
|
|
117
87
|
}
|
|
118
|
-
|
|
88
|
+
let state = latestCheckpoint ? (latestCheckpoint.state ?? {}) : {};
|
|
89
|
+
const checkpointVersion = latestCheckpoint ? latestCheckpoint.version + 1 : 1;
|
|
90
|
+
meta.version = checkpointVersion;
|
|
91
|
+
const scopeData = {
|
|
92
|
+
userId: context.userId,
|
|
93
|
+
workspaceId: context.workspaceId,
|
|
94
|
+
workflowId: context.workflowId ?? '',
|
|
95
|
+
labels: context.labels ?? [],
|
|
96
|
+
args: validArgs ? Object.freeze({ ...validArgs }) : undefined,
|
|
97
|
+
options: context.options,
|
|
98
|
+
cache: new Map(),
|
|
99
|
+
queryRunner: null,
|
|
100
|
+
documents: meta.documents,
|
|
101
|
+
persistenceState: meta.persistenceState,
|
|
102
|
+
transition: undefined,
|
|
103
|
+
};
|
|
119
104
|
this.logger.debug(`Process state machine for workflow ${workflow.constructor.name}`);
|
|
120
105
|
this.memoryMonitor.logWorkflowStart(workflow.constructor.name);
|
|
121
106
|
try {
|
|
122
|
-
await this.processStateMachine(
|
|
107
|
+
state = await this.processStateMachine(scopeData, meta, workflow, pendingTransition, workflowEntity, state);
|
|
123
108
|
}
|
|
124
109
|
catch (e) {
|
|
125
110
|
const error = e instanceof Error ? e : new Error(String(e));
|
|
126
|
-
this.logger.error(new ConfigTraceError(error,
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
111
|
+
this.logger.error(new ConfigTraceError(error, workflow));
|
|
112
|
+
meta.errorMessage = error.message;
|
|
113
|
+
meta.hasError = true;
|
|
114
|
+
meta.place = 'error';
|
|
130
115
|
}
|
|
131
|
-
const hasRetrySignal = !!
|
|
116
|
+
const hasRetrySignal = !!meta._retrySignal;
|
|
132
117
|
if (hasRetrySignal) {
|
|
133
|
-
|
|
134
|
-
|
|
118
|
+
meta.stop = true;
|
|
119
|
+
meta.status = WorkflowState.Waiting;
|
|
135
120
|
}
|
|
136
|
-
else if (
|
|
137
|
-
|
|
138
|
-
|
|
121
|
+
else if (meta.hasError) {
|
|
122
|
+
meta.stop = true;
|
|
123
|
+
meta.status = WorkflowState.Failed;
|
|
139
124
|
}
|
|
140
|
-
else if (
|
|
141
|
-
|
|
125
|
+
else if (meta.place === 'end') {
|
|
126
|
+
meta.status = WorkflowState.Completed;
|
|
142
127
|
}
|
|
143
128
|
else {
|
|
144
|
-
|
|
145
|
-
|
|
129
|
+
meta.stop = true;
|
|
130
|
+
meta.status = WorkflowState.Waiting;
|
|
146
131
|
}
|
|
147
|
-
|
|
132
|
+
meta.documents = scopeData.documents;
|
|
133
|
+
meta.persistenceState = scopeData.persistenceState;
|
|
134
|
+
this.memoryMonitor.logWorkflowEnd(workflow.constructor.name, meta.documents, meta.version);
|
|
148
135
|
if (workflowEntity) {
|
|
149
|
-
await this.workflowStateService.saveExecutionState(workflowEntity,
|
|
136
|
+
await this.workflowStateService.saveExecutionState(workflowEntity, state, meta);
|
|
150
137
|
}
|
|
151
|
-
return
|
|
138
|
+
return meta;
|
|
139
|
+
}
|
|
140
|
+
buildWorkflowContext(scopeData, meta) {
|
|
141
|
+
return {
|
|
142
|
+
userId: scopeData.userId,
|
|
143
|
+
workspaceId: scopeData.workspaceId,
|
|
144
|
+
workflowId: scopeData.workflowId,
|
|
145
|
+
args: scopeData.args,
|
|
146
|
+
execution: {
|
|
147
|
+
place: meta.place,
|
|
148
|
+
retryCount: meta.retryCount ?? 0,
|
|
149
|
+
},
|
|
150
|
+
};
|
|
152
151
|
}
|
|
153
|
-
|
|
152
|
+
invokeTransition(workflow, methodName, workflowCtx, state, data) {
|
|
153
|
+
const method = workflow[methodName];
|
|
154
|
+
if (typeof method !== 'function') {
|
|
155
|
+
throw new Error(`Method '${methodName}' not found on workflow ${workflow.constructor.name}`);
|
|
156
|
+
}
|
|
157
|
+
if (data !== undefined) {
|
|
158
|
+
return method.call(workflow, state, data, workflowCtx);
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
return method.call(workflow, state, workflowCtx);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
invokeGuard(workflow, guardMethodName, state) {
|
|
165
|
+
const method = workflow[guardMethodName];
|
|
166
|
+
if (typeof method !== 'function') {
|
|
167
|
+
throw new Error(`Guard method '${guardMethodName}' not found on workflow ${workflow.constructor.name}`);
|
|
168
|
+
}
|
|
169
|
+
return method.call(workflow, state);
|
|
170
|
+
}
|
|
171
|
+
async executeTransition(scopeData, meta, workflow, methodName, to, data, state, workflowEntity, workflowName, transitionMeta) {
|
|
154
172
|
const defaultTimeout = parseInt(process.env.DEFAULT_TRANSITION_TIMEOUT ?? '', 10) || 300_000;
|
|
155
173
|
const timeoutMs = transitionMeta?.timeout ?? defaultTimeout;
|
|
174
|
+
const workflowCtx = this.buildWorkflowContext(scopeData, meta);
|
|
156
175
|
const invokeMethod = () => {
|
|
157
|
-
const methodPromise = this.executionScope.run(
|
|
176
|
+
const methodPromise = this.executionScope.run(scopeData, () => this.invokeTransition(workflow, methodName, workflowCtx, state, data));
|
|
158
177
|
return timeoutMs > 0 ? Promise.race([methodPromise, rejectAfter(timeoutMs, methodName)]) : methodPromise;
|
|
159
178
|
};
|
|
160
179
|
if (!workflowEntity) {
|
|
161
180
|
const returnValue = await invokeMethod();
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
181
|
+
const newState = (returnValue != null && typeof returnValue === 'object' ? returnValue : state);
|
|
182
|
+
meta.place = to;
|
|
183
|
+
meta.version++;
|
|
184
|
+
this.memoryMonitor.logTransition(workflowName, methodName, scopeData.documents, meta.version);
|
|
185
|
+
return { returnValue, newState };
|
|
166
186
|
}
|
|
167
|
-
const documentsSnapshot = structuredClone(
|
|
168
|
-
const persistenceStateSnapshot = structuredClone(
|
|
187
|
+
const documentsSnapshot = structuredClone(scopeData.documents);
|
|
188
|
+
const persistenceStateSnapshot = structuredClone(scopeData.persistenceState);
|
|
169
189
|
const queryRunner = this.dataSource.createQueryRunner();
|
|
170
190
|
await queryRunner.connect();
|
|
171
191
|
await queryRunner.startTransaction();
|
|
172
192
|
try {
|
|
173
|
-
|
|
174
|
-
this.logger.debug(`Applying transition: ${methodName} (${
|
|
193
|
+
scopeData.queryRunner = queryRunner;
|
|
194
|
+
this.logger.debug(`Applying transition: ${methodName} (${meta.place} → ${to})`);
|
|
175
195
|
const returnValue = await invokeMethod();
|
|
176
|
-
|
|
177
|
-
|
|
196
|
+
const newState = (returnValue != null && typeof returnValue === 'object' ? returnValue : state);
|
|
197
|
+
if (to === 'end' && returnValue !== undefined && returnValue !== null) {
|
|
198
|
+
meta.result = returnValue;
|
|
178
199
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
this.memoryMonitor.logTransition(workflowName, methodName,
|
|
182
|
-
|
|
200
|
+
meta.place = to;
|
|
201
|
+
meta.version++;
|
|
202
|
+
this.memoryMonitor.logTransition(workflowName, methodName, scopeData.documents, meta.version);
|
|
203
|
+
meta.documents = scopeData.documents;
|
|
204
|
+
meta.persistenceState = scopeData.persistenceState;
|
|
205
|
+
await this.workflowStateService.saveExecutionState(workflowEntity, newState, meta, queryRunner);
|
|
183
206
|
await queryRunner.commitTransaction();
|
|
184
|
-
return returnValue;
|
|
207
|
+
return { returnValue, newState };
|
|
185
208
|
}
|
|
186
209
|
catch (error) {
|
|
187
210
|
await queryRunner.rollbackTransaction();
|
|
188
|
-
|
|
189
|
-
|
|
211
|
+
scopeData.documents = documentsSnapshot;
|
|
212
|
+
scopeData.persistenceState = persistenceStateSnapshot;
|
|
190
213
|
throw error;
|
|
191
214
|
}
|
|
192
215
|
finally {
|
|
193
|
-
|
|
216
|
+
scopeData.queryRunner = null;
|
|
194
217
|
await queryRunner.release();
|
|
195
218
|
}
|
|
196
219
|
}
|
|
197
|
-
async handleTransitionError(
|
|
198
|
-
|
|
220
|
+
async handleTransitionError(scopeData, meta, error, transitionMeta) {
|
|
221
|
+
meta.version++;
|
|
199
222
|
try {
|
|
200
|
-
await this.executionScope.run(
|
|
201
|
-
await this.documentPersistenceService.create(
|
|
223
|
+
await this.executionScope.run(scopeData, async () => {
|
|
224
|
+
await this.documentPersistenceService.create(resolveDocumentName(ErrorDocument), ErrorDocument, { error: error.message }, { id: `error_${Date.now()}` });
|
|
202
225
|
});
|
|
203
226
|
}
|
|
204
227
|
catch (docError) {
|
|
@@ -206,183 +229,142 @@ let WorkflowProcessorService = WorkflowProcessorService_1 = class WorkflowProces
|
|
|
206
229
|
}
|
|
207
230
|
const retry = transitionMeta.retry ?? normalizeRetryConfig();
|
|
208
231
|
const methodName = transitionMeta.methodName;
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
if (prevRetryTransitionId !== methodName) {
|
|
232
|
+
let retryCount = meta.retryCount ?? 0;
|
|
233
|
+
if (meta.retryTransitionId !== methodName) {
|
|
212
234
|
retryCount = 0;
|
|
213
235
|
}
|
|
214
236
|
this.logger.warn(`Transition '${methodName}' failed (attempt ${retryCount + 1}): ${error.message}`);
|
|
215
237
|
if (retry.attempts > 0 && retryCount < retry.attempts) {
|
|
216
238
|
retryCount++;
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
239
|
+
meta.retryCount = retryCount;
|
|
240
|
+
meta.retryTransitionId = methodName;
|
|
241
|
+
meta.errorMessage = error.message;
|
|
242
|
+
meta.hasError = true;
|
|
221
243
|
const delayMs = retry.backoff === 'exponential'
|
|
222
244
|
? Math.min(retry.delay * Math.pow(2, retryCount - 1), retry.maxDelay)
|
|
223
245
|
: retry.delay;
|
|
224
246
|
this.logger.log(`Auto-retry ${retryCount}/${retry.attempts} for '${methodName}' in ${delayMs}ms`);
|
|
225
|
-
|
|
247
|
+
meta._retrySignal = { delayMs };
|
|
226
248
|
return;
|
|
227
249
|
}
|
|
228
250
|
if (retry.place) {
|
|
229
251
|
this.logger.log(`Retries exhausted for '${methodName}' — transitioning to custom error place '${retry.place}'`);
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
252
|
+
meta.place = retry.place;
|
|
253
|
+
meta.hasError = true;
|
|
254
|
+
meta.errorMessage = error.message;
|
|
255
|
+
meta.retryCount = 0;
|
|
256
|
+
meta.retryTransitionId = undefined;
|
|
235
257
|
return;
|
|
236
258
|
}
|
|
237
259
|
this.logger.log(`Transition '${methodName}' failed — staying at current place for manual retry`);
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
260
|
+
meta.hasError = true;
|
|
261
|
+
meta.errorMessage = error.message;
|
|
262
|
+
meta.retryCount = retryCount + 1;
|
|
263
|
+
meta.retryTransitionId = methodName;
|
|
242
264
|
}
|
|
243
|
-
clearRetryState(
|
|
244
|
-
if (
|
|
245
|
-
|
|
246
|
-
|
|
265
|
+
clearRetryState(meta) {
|
|
266
|
+
if (meta.retryTransitionId) {
|
|
267
|
+
meta.retryCount = 0;
|
|
268
|
+
meta.retryTransitionId = undefined;
|
|
247
269
|
}
|
|
248
270
|
}
|
|
249
|
-
async processStateMachine(
|
|
250
|
-
const proxy = ctx.getInstance();
|
|
251
|
-
const workflow = proxy;
|
|
271
|
+
async processStateMachine(scopeData, meta, workflow, pendingTransition, workflowEntity, state) {
|
|
252
272
|
const guards = getGuardMetadataMap(workflow);
|
|
253
273
|
const workflowName = workflow.constructor.name;
|
|
254
274
|
if (pendingTransition) {
|
|
255
|
-
const
|
|
256
|
-
const available = this.transitionResolverService.getAvailableTransitions(workflow, currentPlace);
|
|
275
|
+
const available = this.transitionResolverService.getAvailableTransitions(workflow, meta.place);
|
|
257
276
|
const waitTransition = available.find((t) => t.wait && t.methodName === pendingTransition.id);
|
|
258
277
|
if (waitTransition) {
|
|
259
|
-
|
|
278
|
+
meta.transition = {
|
|
260
279
|
id: waitTransition.methodName,
|
|
261
|
-
from:
|
|
280
|
+
from: meta.place,
|
|
262
281
|
to: waitTransition.to,
|
|
263
282
|
payload: pendingTransition.payload,
|
|
264
283
|
meta: pendingTransition.meta,
|
|
265
|
-
}
|
|
284
|
+
};
|
|
285
|
+
scopeData.transition = meta.transition;
|
|
266
286
|
const guard = guards.get(waitTransition.methodName);
|
|
267
287
|
if (guard) {
|
|
268
|
-
const passes = await this.executionScope.run(
|
|
269
|
-
return
|
|
288
|
+
const passes = await this.executionScope.run(scopeData, () => {
|
|
289
|
+
return this.invokeGuard(workflow, guard.guardMethodName, state);
|
|
270
290
|
});
|
|
271
291
|
if (!passes) {
|
|
272
292
|
this.logger.debug(`Guard '${guard.guardMethodName}' rejected pending transition '${waitTransition.methodName}'`);
|
|
273
|
-
return;
|
|
293
|
+
return state;
|
|
274
294
|
}
|
|
275
295
|
}
|
|
276
296
|
if (workflowEntity) {
|
|
277
|
-
await this.workflowStateService.saveExecutionState(workflowEntity,
|
|
297
|
+
await this.workflowStateService.saveExecutionState(workflowEntity, state, meta);
|
|
278
298
|
}
|
|
279
299
|
const waitData = waitTransition.schema
|
|
280
300
|
? waitTransition.schema.parse(pendingTransition.payload)
|
|
281
301
|
: pendingTransition.payload;
|
|
282
302
|
try {
|
|
283
|
-
await this.executeTransition(
|
|
284
|
-
|
|
303
|
+
const result = await this.executeTransition(scopeData, meta, workflow, waitTransition.methodName, waitTransition.to, waitData, state, workflowEntity, workflowName, waitTransition);
|
|
304
|
+
state = result.newState;
|
|
305
|
+
this.clearRetryState(meta);
|
|
285
306
|
}
|
|
286
307
|
catch (e) {
|
|
287
308
|
const error = e instanceof Error ? e : new Error(String(e));
|
|
288
|
-
this.logger.error(new ConfigTraceError(error,
|
|
289
|
-
await this.handleTransitionError(
|
|
290
|
-
const
|
|
291
|
-
|
|
292
|
-
ctx.getManager().setData('availableTransitions', errorAvailable.map((t) => ({
|
|
309
|
+
this.logger.error(new ConfigTraceError(error, workflow));
|
|
310
|
+
await this.handleTransitionError(scopeData, meta, error, waitTransition);
|
|
311
|
+
const errorAvailable = this.transitionResolverService.getAvailableTransitions(workflow, meta.place);
|
|
312
|
+
meta.availableTransitions = errorAvailable.map((t) => ({
|
|
293
313
|
id: t.methodName,
|
|
294
|
-
from:
|
|
314
|
+
from: meta.place,
|
|
295
315
|
to: t.to,
|
|
296
316
|
trigger: t.wait ? 'manual' : undefined,
|
|
297
|
-
}))
|
|
298
|
-
return;
|
|
317
|
+
}));
|
|
318
|
+
return state;
|
|
299
319
|
}
|
|
300
320
|
}
|
|
301
321
|
}
|
|
302
322
|
while (true) {
|
|
303
|
-
|
|
304
|
-
if (currentPlace === 'end')
|
|
323
|
+
if (meta.place === 'end')
|
|
305
324
|
break;
|
|
306
|
-
|
|
307
|
-
const available = this.transitionResolverService.getAvailableTransitions(workflow,
|
|
308
|
-
|
|
325
|
+
meta.nextPlace = undefined;
|
|
326
|
+
const available = this.transitionResolverService.getAvailableTransitions(workflow, meta.place);
|
|
327
|
+
meta.availableTransitions = available.map((t) => ({
|
|
309
328
|
id: t.methodName,
|
|
310
|
-
from:
|
|
329
|
+
from: meta.place,
|
|
311
330
|
to: t.to,
|
|
312
331
|
trigger: t.wait ? 'manual' : undefined,
|
|
313
332
|
}));
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
return this.transitionResolverService.resolveNextTransition(proxy, available, guards);
|
|
333
|
+
const next = await this.executionScope.run(scopeData, () => {
|
|
334
|
+
return this.transitionResolverService.resolveNextTransition(workflow, available, guards, state);
|
|
317
335
|
});
|
|
318
336
|
if (!next)
|
|
319
337
|
break;
|
|
320
|
-
|
|
338
|
+
meta.transition = {
|
|
321
339
|
id: next.methodName,
|
|
322
|
-
from:
|
|
340
|
+
from: meta.place,
|
|
323
341
|
to: next.to,
|
|
324
342
|
payload: null,
|
|
325
|
-
}
|
|
343
|
+
};
|
|
344
|
+
scopeData.transition = meta.transition;
|
|
326
345
|
if (workflowEntity) {
|
|
327
|
-
await this.workflowStateService.saveExecutionState(workflowEntity,
|
|
346
|
+
await this.workflowStateService.saveExecutionState(workflowEntity, state, meta);
|
|
328
347
|
}
|
|
329
|
-
const autoData = next.from === 'start' ? ctx.getArgs() : undefined;
|
|
330
348
|
try {
|
|
331
|
-
await this.executeTransition(
|
|
332
|
-
|
|
349
|
+
const result = await this.executeTransition(scopeData, meta, workflow, next.methodName, next.to, undefined, state, workflowEntity, workflowName, next);
|
|
350
|
+
state = result.newState;
|
|
351
|
+
this.clearRetryState(meta);
|
|
333
352
|
}
|
|
334
353
|
catch (e) {
|
|
335
354
|
const error = e instanceof Error ? e : new Error(String(e));
|
|
336
|
-
this.logger.error(new ConfigTraceError(error,
|
|
337
|
-
await this.handleTransitionError(
|
|
338
|
-
const
|
|
339
|
-
|
|
340
|
-
ctx.getManager().setData('availableTransitions', errorAvailable.map((t) => ({
|
|
355
|
+
this.logger.error(new ConfigTraceError(error, workflow));
|
|
356
|
+
await this.handleTransitionError(scopeData, meta, error, next);
|
|
357
|
+
const errorAvailable = this.transitionResolverService.getAvailableTransitions(workflow, meta.place);
|
|
358
|
+
meta.availableTransitions = errorAvailable.map((t) => ({
|
|
341
359
|
id: t.methodName,
|
|
342
|
-
from:
|
|
360
|
+
from: meta.place,
|
|
343
361
|
to: t.to,
|
|
344
362
|
trigger: t.wait ? 'manual' : undefined,
|
|
345
|
-
}))
|
|
363
|
+
}));
|
|
346
364
|
break;
|
|
347
365
|
}
|
|
348
366
|
}
|
|
349
|
-
|
|
350
|
-
wireFrameworkServices(workflow, app) {
|
|
351
|
-
this.wireTools(workflow);
|
|
352
|
-
this.wireWorkflows(workflow);
|
|
353
|
-
if (app) {
|
|
354
|
-
this.wireTools(app);
|
|
355
|
-
this.wireWorkflows(app);
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
wireTools(target) {
|
|
359
|
-
const toolNames = getBlockTools(target);
|
|
360
|
-
for (const name of toolNames) {
|
|
361
|
-
const tool = target[name];
|
|
362
|
-
if (!tool || tool instanceof ServerTool)
|
|
363
|
-
continue;
|
|
364
|
-
const proxy = this.toolExecutionService.wireAndProxyTool(tool, name, target);
|
|
365
|
-
target[name] = proxy;
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
wireWorkflows(target) {
|
|
369
|
-
const workflowNames = getBlockWorkflows(target);
|
|
370
|
-
for (const name of workflowNames) {
|
|
371
|
-
const workflow = target[name];
|
|
372
|
-
if (!workflow || typeof workflow !== 'object')
|
|
373
|
-
continue;
|
|
374
|
-
const defaults = getInjectWorkflowDefaults(target, name);
|
|
375
|
-
if (!defaults)
|
|
376
|
-
continue;
|
|
377
|
-
const wf = workflow;
|
|
378
|
-
if (typeof wf.run !== 'function')
|
|
379
|
-
continue;
|
|
380
|
-
const originalRun = wf.run.bind(wf);
|
|
381
|
-
wf.run = (args, options) => {
|
|
382
|
-
const runOptions = { ...options, _config: { ...defaults, ...options?._config } };
|
|
383
|
-
return originalRun(args, runOptions);
|
|
384
|
-
};
|
|
385
|
-
}
|
|
367
|
+
return state;
|
|
386
368
|
}
|
|
387
369
|
};
|
|
388
370
|
WorkflowProcessorService = WorkflowProcessorService_1 = __decorate([
|
|
@@ -391,7 +373,6 @@ WorkflowProcessorService = WorkflowProcessorService_1 = __decorate([
|
|
|
391
373
|
TransitionResolverService,
|
|
392
374
|
ExecutionScope,
|
|
393
375
|
WorkflowMemoryMonitorService,
|
|
394
|
-
ToolExecutionService,
|
|
395
376
|
DocumentPersistenceService,
|
|
396
377
|
DataSource])
|
|
397
378
|
], WorkflowProcessorService);
|