@optimizely/ocp-local-env 1.0.0-beta.5 → 1.0.0-beta.7
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/package.json +3 -2
- package/dist/public/bundle.7a5338c67e783e9b42f7.js +3 -0
- package/dist/public/{bundle.932ab47a0dbf0319bc8b.js.LICENSE.txt → bundle.7a5338c67e783e9b42f7.js.LICENSE.txt} +33 -0
- package/dist/public/bundle.7a5338c67e783e9b42f7.js.map +1 -0
- package/dist/public/index.html +1 -1
- package/dist/src/executor/DestinationExecutor.js +10 -7
- package/dist/src/executor/DestinationExecutor.js.map +1 -1
- package/dist/src/executor/FunctionExecutor.js +1 -1
- package/dist/src/executor/FunctionExecutor.js.map +1 -1
- package/dist/src/executor/JobExecutor.js +1 -1
- package/dist/src/executor/JobExecutor.js.map +1 -1
- package/dist/src/executor/LifecycleExecutor.js +1 -1
- package/dist/src/executor/LifecycleExecutor.js.map +1 -1
- package/dist/src/executor/SourceExecutor.d.ts +32 -0
- package/dist/src/executor/SourceExecutor.js +161 -0
- package/dist/src/executor/SourceExecutor.js.map +1 -0
- package/dist/src/local_engine/LocalJobApi.d.ts +38 -0
- package/dist/src/local_engine/LocalJobApi.js +180 -0
- package/dist/src/local_engine/LocalJobApi.js.map +1 -0
- package/dist/src/local_engine/local-engine-child-base.d.ts +16 -0
- package/dist/src/local_engine/local-engine-child-base.js +201 -14
- package/dist/src/local_engine/local-engine-child-base.js.map +1 -1
- package/dist/src/local_engine/local-engine-client.d.ts +70 -1
- package/dist/src/local_engine/local-engine-client.js +545 -26
- package/dist/src/local_engine/local-engine-client.js.map +1 -1
- package/dist/src/local_engine/local-engine-types.d.ts +98 -2
- package/dist/src/local_engine/local-engine-unified.d.ts +18 -0
- package/dist/src/local_engine/local-engine-unified.js +227 -1
- package/dist/src/local_engine/local-engine-unified.js.map +1 -1
- package/dist/src/local_engine/local-engine-utils.js +34 -7
- package/dist/src/local_engine/local-engine-utils.js.map +1 -1
- package/dist/src/local_engine/localSDKConfig.js +237 -39
- package/dist/src/local_engine/localSDKConfig.js.map +1 -1
- package/dist/src/local_engine/storage/LocalConfigStore.d.ts +18 -0
- package/dist/src/local_engine/storage/LocalConfigStore.js +52 -3
- package/dist/src/local_engine/storage/LocalConfigStore.js.map +1 -1
- package/dist/src/local_engine/storage/LocalJobStore.d.ts +1 -0
- package/dist/src/local_engine/storage/LocalJobStore.js +12 -2
- package/dist/src/local_engine/storage/LocalJobStore.js.map +1 -1
- package/dist/src/local_engine/storage/LocalKVStore.d.ts +1 -0
- package/dist/src/local_engine/storage/LocalKVStore.js +134 -75
- package/dist/src/local_engine/storage/LocalKVStore.js.map +1 -1
- package/dist/src/local_engine/storage/LocalNotificationStore.d.ts +1 -0
- package/dist/src/local_engine/storage/LocalNotificationStore.js +17 -3
- package/dist/src/local_engine/storage/LocalNotificationStore.js.map +1 -1
- package/dist/src/local_engine/storage/LocalSecretsStore.d.ts +1 -0
- package/dist/src/local_engine/storage/LocalSecretsStore.js +37 -6
- package/dist/src/local_engine/storage/LocalSecretsStore.js.map +1 -1
- package/dist/src/local_engine/storage/LocalSettingsStore.d.ts +1 -0
- package/dist/src/local_engine/storage/LocalSettingsStore.js +61 -11
- package/dist/src/local_engine/storage/LocalSettingsStore.js.map +1 -1
- package/dist/src/local_engine/storage/SourceDataStore.d.ts +23 -0
- package/dist/src/local_engine/storage/SourceDataStore.js +83 -0
- package/dist/src/local_engine/storage/SourceDataStore.js.map +1 -0
- package/dist/src/local_engine/storage/SourceJobExecutionStore.d.ts +25 -0
- package/dist/src/local_engine/storage/SourceJobExecutionStore.js +61 -0
- package/dist/src/local_engine/storage/SourceJobExecutionStore.js.map +1 -0
- package/dist/src/local_engine/utils.js +20 -4
- package/dist/src/local_engine/utils.js.map +1 -1
- package/dist/src/logging/LogManager.d.ts +191 -34
- package/dist/src/logging/LogManager.js +209 -103
- package/dist/src/logging/LogManager.js.map +1 -1
- package/dist/src/server/api/destinations.js +30 -6
- package/dist/src/server/api/destinations.js.map +1 -1
- package/dist/src/server/api/jobs.js +3 -0
- package/dist/src/server/api/jobs.js.map +1 -1
- package/dist/src/server/api/sources.d.ts +7 -0
- package/dist/src/server/api/sources.js +380 -0
- package/dist/src/server/api/sources.js.map +1 -0
- package/dist/src/server/api.js +64 -3
- package/dist/src/server/api.js.map +1 -1
- package/dist/src/server.js +203 -19
- package/dist/src/server.js.map +1 -1
- package/dist/src/ui/components/App.js +165 -21
- package/dist/src/ui/components/App.js.map +1 -1
- package/dist/src/ui/components/DestinationsView.d.ts +8 -0
- package/dist/src/ui/components/DestinationsView.js +30 -9
- package/dist/src/ui/components/DestinationsView.js.map +1 -1
- package/dist/src/ui/components/FunctionsView.d.ts +7 -0
- package/dist/src/ui/components/FunctionsView.js +69 -9
- package/dist/src/ui/components/FunctionsView.js.map +1 -1
- package/dist/src/ui/components/JobsView.d.ts +7 -0
- package/dist/src/ui/components/JobsView.js +55 -15
- package/dist/src/ui/components/JobsView.js.map +1 -1
- package/dist/src/ui/components/SourceDataViewer.d.ts +8 -0
- package/dist/src/ui/components/SourceDataViewer.js +84 -0
- package/dist/src/ui/components/SourceDataViewer.js.map +1 -0
- package/dist/src/ui/components/SourceJobsSection.d.ts +8 -0
- package/dist/src/ui/components/SourceJobsSection.js +99 -0
- package/dist/src/ui/components/SourceJobsSection.js.map +1 -0
- package/dist/src/ui/components/SourceLifecycleSection.d.ts +7 -0
- package/dist/src/ui/components/SourceLifecycleSection.js +58 -0
- package/dist/src/ui/components/SourceLifecycleSection.js.map +1 -0
- package/dist/src/ui/components/SourceSchemaViewer.d.ts +7 -0
- package/dist/src/ui/components/SourceSchemaViewer.js +65 -0
- package/dist/src/ui/components/SourceSchemaViewer.js.map +1 -0
- package/dist/src/ui/components/SourceWebhookEditor.d.ts +8 -0
- package/dist/src/ui/components/SourceWebhookEditor.js +168 -0
- package/dist/src/ui/components/SourceWebhookEditor.js.map +1 -0
- package/dist/src/ui/components/SourcesView.d.ts +14 -0
- package/dist/src/ui/components/SourcesView.js +74 -0
- package/dist/src/ui/components/SourcesView.js.map +1 -0
- package/dist/src/ui/components/TabbedConsole.d.ts +3 -1
- package/dist/src/ui/components/TabbedConsole.js +81 -11
- package/dist/src/ui/components/TabbedConsole.js.map +1 -1
- package/dist/src/ui/hooks/useEntityNavigation.d.ts +72 -0
- package/dist/src/ui/hooks/useEntityNavigation.js +150 -0
- package/dist/src/ui/hooks/useEntityNavigation.js.map +1 -0
- package/dist/src/ui/hooks/useQueryParams.d.ts +6 -0
- package/dist/src/ui/hooks/useQueryParams.js +39 -0
- package/dist/src/ui/hooks/useQueryParams.js.map +1 -0
- package/dist/src/ui/index.js +3 -2
- package/dist/src/ui/index.js.map +1 -1
- package/package.json +3 -2
- package/dist/public/bundle.932ab47a0dbf0319bc8b.js +0 -3
- package/dist/public/bundle.932ab47a0dbf0319bc8b.js.map +0 -1
- package/dist/src/server/api/lifecycle.d.ts +0 -6
- package/dist/src/server/api/lifecycle.js +0 -72
- package/dist/src/server/api/lifecycle.js.map +0 -1
|
@@ -10,9 +10,96 @@ exports.LocalEngineClient = void 0;
|
|
|
10
10
|
const child_process_1 = require("child_process");
|
|
11
11
|
const path_1 = __importDefault(require("path"));
|
|
12
12
|
const local_engine_utils_1 = require("./local-engine-utils");
|
|
13
|
+
const LogManager_1 = require("../logging/LogManager");
|
|
14
|
+
function getLogCategoryFromMessageType(context) {
|
|
15
|
+
switch (context.type) {
|
|
16
|
+
case 'function':
|
|
17
|
+
return LogManager_1.LogCategory.Function;
|
|
18
|
+
case 'lifecycle':
|
|
19
|
+
return LogManager_1.LogCategory.Lifecycle;
|
|
20
|
+
case 'destination':
|
|
21
|
+
return LogManager_1.LogCategory.Destination;
|
|
22
|
+
case 'source':
|
|
23
|
+
return LogManager_1.LogCategory.Source;
|
|
24
|
+
case 'jobs':
|
|
25
|
+
return LogManager_1.LogCategory.Jobs;
|
|
26
|
+
default:
|
|
27
|
+
return LogManager_1.LogCategory.AppRunner;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Process buffered output and log complete lines
|
|
32
|
+
*/
|
|
33
|
+
function processBufferedOutput(buffer, newData, isError, context) {
|
|
34
|
+
const logManager = LogManager_1.LogManager.getInstance();
|
|
35
|
+
const combined = buffer + newData;
|
|
36
|
+
const lines = combined.split('\n');
|
|
37
|
+
// Keep the last incomplete line in the buffer
|
|
38
|
+
const remainingBuffer = lines.pop() || '';
|
|
39
|
+
// Log only valid JSON lines (filters out pretty-printed output)
|
|
40
|
+
lines.forEach(line => {
|
|
41
|
+
const trimmed = line.trim();
|
|
42
|
+
if (trimmed) {
|
|
43
|
+
try {
|
|
44
|
+
// Try to parse as JSON
|
|
45
|
+
const parsed = JSON.parse(trimmed);
|
|
46
|
+
// Only log if it's a valid JSON object (structured log)
|
|
47
|
+
if (typeof parsed === 'object' && parsed !== null) {
|
|
48
|
+
// Log with execution context
|
|
49
|
+
if (context) {
|
|
50
|
+
// Map execution context type to log category enum
|
|
51
|
+
let category = getLogCategoryFromMessageType(context);
|
|
52
|
+
logManager.log({
|
|
53
|
+
source: LogManager_1.LogSource.App,
|
|
54
|
+
category,
|
|
55
|
+
level: isError ? 'error' : 'info',
|
|
56
|
+
message: trimmed,
|
|
57
|
+
context: { id: context.id }
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
// Fallback for app output without context
|
|
62
|
+
logManager.log({
|
|
63
|
+
source: LogManager_1.LogSource.App,
|
|
64
|
+
category: LogManager_1.LogCategory.AppRunner,
|
|
65
|
+
level: isError ? 'error' : 'info',
|
|
66
|
+
message: trimmed,
|
|
67
|
+
context: { id: '' }
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
console.error(trimmed, context);
|
|
73
|
+
}
|
|
74
|
+
// Silently ignore non-JSON lines (pretty-printed output)
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
// Not valid JSON - silently ignore
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
return remainingBuffer;
|
|
82
|
+
}
|
|
13
83
|
class LocalEngineClient {
|
|
14
84
|
constructor() {
|
|
15
85
|
this.connections = new Map();
|
|
86
|
+
this.logManager = LogManager_1.LogManager.getInstance();
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Get the singleton instance of LocalEngineClient
|
|
90
|
+
* This ensures all IPC handlers share the same instance and JobExecutor
|
|
91
|
+
*/
|
|
92
|
+
static getInstance() {
|
|
93
|
+
if (!LocalEngineClient.instance) {
|
|
94
|
+
LocalEngineClient.instance = new LocalEngineClient();
|
|
95
|
+
}
|
|
96
|
+
return LocalEngineClient.instance;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Set the JobExecutor instance for handling job trigger requests
|
|
100
|
+
*/
|
|
101
|
+
setJobExecutor(jobExecutor) {
|
|
102
|
+
this.jobExecutor = jobExecutor;
|
|
16
103
|
}
|
|
17
104
|
/**
|
|
18
105
|
* Get or create a connection for the specified app
|
|
@@ -39,17 +126,26 @@ class LocalEngineClient {
|
|
|
39
126
|
*/
|
|
40
127
|
async createConnection(appConfig, appDir) {
|
|
41
128
|
const wrapperScript = path_1.default.join(__dirname, 'local-engine-unified.js');
|
|
42
|
-
|
|
129
|
+
this.logManager.info(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, 'Starting unified wrapper for app', {
|
|
130
|
+
id: '',
|
|
131
|
+
operation: 'spawn',
|
|
132
|
+
appId: appConfig.manifest.meta?.app_id
|
|
133
|
+
});
|
|
43
134
|
const childProcess = (0, child_process_1.spawn)('node', [wrapperScript], {
|
|
44
135
|
cwd: appDir,
|
|
45
136
|
stdio: ['pipe', 'pipe', 'pipe', 'ipc'],
|
|
46
|
-
env: {
|
|
137
|
+
env: {
|
|
138
|
+
...process.env,
|
|
139
|
+
DISABLE_LOGMANAGER_CONSOLE: 'true' // Prevent double logging from child process
|
|
140
|
+
}
|
|
47
141
|
});
|
|
48
142
|
const connection = {
|
|
49
143
|
process: childProcess,
|
|
50
144
|
ready: false,
|
|
51
145
|
pendingRequests: new Map(),
|
|
52
|
-
lastActivity: Date.now()
|
|
146
|
+
lastActivity: Date.now(),
|
|
147
|
+
stdoutBuffer: '',
|
|
148
|
+
stderrBuffer: ''
|
|
53
149
|
};
|
|
54
150
|
// Set up message handling
|
|
55
151
|
this.setupMessageHandlers(connection);
|
|
@@ -67,27 +163,31 @@ class LocalEngineClient {
|
|
|
67
163
|
try {
|
|
68
164
|
(0, local_engine_utils_1.logIPCMessage)('RECV', message, '[IPC Client]');
|
|
69
165
|
if (!(0, local_engine_utils_1.validateMessage)(message)) {
|
|
70
|
-
|
|
166
|
+
this.logManager.error(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, 'Received invalid message', {
|
|
167
|
+
id: connection.process.pid.toString(),
|
|
168
|
+
messageType: message?.type
|
|
169
|
+
});
|
|
71
170
|
return;
|
|
72
171
|
}
|
|
73
172
|
this.handleChildMessage(connection, message);
|
|
74
173
|
}
|
|
75
174
|
catch (error) {
|
|
76
|
-
|
|
175
|
+
this.logManager.error(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, 'Error handling child message', {
|
|
176
|
+
id: 'unknown',
|
|
177
|
+
error
|
|
178
|
+
});
|
|
77
179
|
}
|
|
78
180
|
});
|
|
79
|
-
// Handle stdout/stderr
|
|
181
|
+
// Handle stdout/stderr - processBufferedOutput logs to LogManager
|
|
80
182
|
connection.process.stdout?.on('data', (data) => {
|
|
81
|
-
const output = data.toString()
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
183
|
+
const output = data.toString();
|
|
184
|
+
connection.stdoutBuffer = processBufferedOutput(connection.stdoutBuffer || '', output, false, connection.currentContext // Pass execution context
|
|
185
|
+
);
|
|
85
186
|
});
|
|
86
187
|
connection.process.stderr?.on('data', (data) => {
|
|
87
|
-
const error = data.toString()
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
188
|
+
const error = data.toString();
|
|
189
|
+
connection.stderrBuffer = processBufferedOutput(connection.stderrBuffer || '', error, true, connection.currentContext // Pass execution context
|
|
190
|
+
);
|
|
91
191
|
});
|
|
92
192
|
}
|
|
93
193
|
/**
|
|
@@ -95,15 +195,27 @@ class LocalEngineClient {
|
|
|
95
195
|
*/
|
|
96
196
|
setupErrorHandlers(connection) {
|
|
97
197
|
connection.process.on('error', (error) => {
|
|
98
|
-
|
|
198
|
+
this.logManager.error(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, 'Child process error', {
|
|
199
|
+
id: connection.process.pid?.toString() || 'unknown',
|
|
200
|
+
operation: 'error',
|
|
201
|
+
error
|
|
202
|
+
});
|
|
99
203
|
this.handleConnectionError(connection, error);
|
|
100
204
|
});
|
|
101
205
|
connection.process.on('exit', (code, signal) => {
|
|
102
|
-
|
|
206
|
+
this.logManager.info(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, 'Child process exited', {
|
|
207
|
+
id: connection.process.pid?.toString() || 'unknown',
|
|
208
|
+
operation: 'exit',
|
|
209
|
+
exitCode: code ?? undefined,
|
|
210
|
+
signal: signal ?? undefined
|
|
211
|
+
});
|
|
103
212
|
this.handleConnectionExit(connection, code, signal);
|
|
104
213
|
});
|
|
105
214
|
connection.process.on('close', () => {
|
|
106
|
-
|
|
215
|
+
this.logManager.info(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, 'Child process closed', {
|
|
216
|
+
id: connection.process.pid?.toString() || 'unknown',
|
|
217
|
+
operation: 'close'
|
|
218
|
+
});
|
|
107
219
|
connection.ready = false;
|
|
108
220
|
});
|
|
109
221
|
}
|
|
@@ -128,15 +240,29 @@ class LocalEngineClient {
|
|
|
128
240
|
case 'error':
|
|
129
241
|
this.handleErrorMessage(connection, message);
|
|
130
242
|
break;
|
|
243
|
+
case 'trigger_job':
|
|
244
|
+
this.handleTriggerJobMessage(connection, message);
|
|
245
|
+
break;
|
|
246
|
+
case 'get_job_detail':
|
|
247
|
+
this.handleGetJobDetailMessage(connection, message);
|
|
248
|
+
break;
|
|
249
|
+
case 'get_job_status':
|
|
250
|
+
this.handleGetJobStatusMessage(connection, message);
|
|
251
|
+
break;
|
|
131
252
|
default:
|
|
132
|
-
|
|
253
|
+
this.logManager.warn(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, 'Unknown message type', {
|
|
254
|
+
id: 'unknown',
|
|
255
|
+
messageType: message.type
|
|
256
|
+
});
|
|
133
257
|
}
|
|
134
258
|
}
|
|
135
259
|
/**
|
|
136
260
|
* Handle ready message from child
|
|
137
261
|
*/
|
|
138
262
|
handleReadyMessage(connection) {
|
|
139
|
-
|
|
263
|
+
this.logManager.info(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, 'Child process is ready', {
|
|
264
|
+
id: connection.process.pid?.toString() || 'unknown'
|
|
265
|
+
});
|
|
140
266
|
connection.ready = true;
|
|
141
267
|
}
|
|
142
268
|
/**
|
|
@@ -144,15 +270,20 @@ class LocalEngineClient {
|
|
|
144
270
|
*/
|
|
145
271
|
handleProgressMessage(connection, message) {
|
|
146
272
|
const { requestId, message: progressMsg, progress } = message.data;
|
|
147
|
-
|
|
273
|
+
this.logManager.debug(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, `Progress: ${progressMsg}`, {
|
|
274
|
+
id: requestId || 'unknown',
|
|
275
|
+
messageType: 'progress'
|
|
276
|
+
});
|
|
148
277
|
}
|
|
149
278
|
/**
|
|
150
279
|
* Handle log message from child
|
|
151
280
|
*/
|
|
152
281
|
handleLogMessage(connection, message) {
|
|
153
282
|
const { level, message: logMsg, requestId } = message.data;
|
|
154
|
-
|
|
155
|
-
|
|
283
|
+
this.logManager.debug(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, logMsg, {
|
|
284
|
+
id: requestId || connection.process.pid.toString() || 'unknown',
|
|
285
|
+
messageType: 'log'
|
|
286
|
+
});
|
|
156
287
|
}
|
|
157
288
|
/**
|
|
158
289
|
* Handle success message from child
|
|
@@ -164,9 +295,16 @@ class LocalEngineClient {
|
|
|
164
295
|
(0, local_engine_utils_1.cleanupPendingRequest)(pendingRequest);
|
|
165
296
|
connection.pendingRequests.delete(requestId);
|
|
166
297
|
pendingRequest.resolve(result);
|
|
298
|
+
// Clear execution context
|
|
299
|
+
if (connection.currentContext?.requestId === requestId) {
|
|
300
|
+
connection.currentContext = undefined;
|
|
301
|
+
}
|
|
167
302
|
}
|
|
168
303
|
else {
|
|
169
|
-
|
|
304
|
+
this.logManager.warn(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, 'Received success for unknown request', {
|
|
305
|
+
id: requestId || 'unknown',
|
|
306
|
+
messageType: 'success'
|
|
307
|
+
});
|
|
170
308
|
}
|
|
171
309
|
}
|
|
172
310
|
/**
|
|
@@ -180,16 +318,196 @@ class LocalEngineClient {
|
|
|
180
318
|
connection.pendingRequests.delete(requestId);
|
|
181
319
|
const error = (0, local_engine_utils_1.deserializeError)({ message: errorMsg, stack });
|
|
182
320
|
pendingRequest.reject(error);
|
|
321
|
+
// Clear execution context
|
|
322
|
+
if (connection.currentContext?.requestId === requestId) {
|
|
323
|
+
connection.currentContext = undefined;
|
|
324
|
+
}
|
|
183
325
|
}
|
|
184
326
|
else {
|
|
185
|
-
|
|
327
|
+
this.logManager.warn(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, 'Received error for unknown request', {
|
|
328
|
+
id: requestId || 'unknown',
|
|
329
|
+
messageType: 'error',
|
|
330
|
+
errorMessage: errorMsg
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Handle job trigger request from child
|
|
336
|
+
*/
|
|
337
|
+
async handleTriggerJobMessage(connection, message) {
|
|
338
|
+
const { jobName, parameters } = message.data;
|
|
339
|
+
const requestId = message.id;
|
|
340
|
+
if (!this.jobExecutor) {
|
|
341
|
+
this.logManager.error(LogManager_1.LogSource.System, LogManager_1.LogCategory.Jobs, 'JobExecutor not available', {
|
|
342
|
+
id: requestId,
|
|
343
|
+
jobName
|
|
344
|
+
});
|
|
345
|
+
// Send error response
|
|
346
|
+
const errorResponse = {
|
|
347
|
+
...(0, local_engine_utils_1.createBaseMessage)('error'),
|
|
348
|
+
type: 'error',
|
|
349
|
+
data: {
|
|
350
|
+
requestId,
|
|
351
|
+
error: 'JobExecutor not initialized',
|
|
352
|
+
executionTime: 0
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
(0, local_engine_utils_1.sendIPCMessage)(connection.process, errorResponse);
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
this.logManager.info(LogManager_1.LogSource.System, LogManager_1.LogCategory.Jobs, 'Processing job trigger request from child', {
|
|
359
|
+
id: requestId,
|
|
360
|
+
jobName
|
|
361
|
+
});
|
|
362
|
+
// Execute the job - this returns a response object with success/error info
|
|
363
|
+
const response = await this.jobExecutor.executeJob({
|
|
364
|
+
jobId: jobName,
|
|
365
|
+
parameters: parameters || {}
|
|
366
|
+
});
|
|
367
|
+
// Check if execution failed
|
|
368
|
+
if (!response.success) {
|
|
369
|
+
this.logManager.error(LogManager_1.LogSource.System, LogManager_1.LogCategory.Jobs, 'Job trigger request failed', {
|
|
370
|
+
id: requestId,
|
|
371
|
+
jobName,
|
|
372
|
+
error: response.error
|
|
373
|
+
});
|
|
374
|
+
// Send error response back to child
|
|
375
|
+
const errorResponse = {
|
|
376
|
+
...(0, local_engine_utils_1.createBaseMessage)('error'),
|
|
377
|
+
type: 'error',
|
|
378
|
+
data: {
|
|
379
|
+
requestId,
|
|
380
|
+
error: response.error || 'Failed to trigger job',
|
|
381
|
+
executionTime: 0
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
(0, local_engine_utils_1.sendIPCMessage)(connection.process, errorResponse);
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
// Get the execution details
|
|
388
|
+
const execution = this.jobExecutor.getExecution(response.executionId);
|
|
389
|
+
if (!execution) {
|
|
390
|
+
this.logManager.error(LogManager_1.LogSource.System, LogManager_1.LogCategory.Jobs, 'Execution not found after trigger', {
|
|
391
|
+
id: requestId,
|
|
392
|
+
jobName,
|
|
393
|
+
executionId: response.executionId
|
|
394
|
+
});
|
|
395
|
+
const errorResponse = {
|
|
396
|
+
...(0, local_engine_utils_1.createBaseMessage)('error'),
|
|
397
|
+
type: 'error',
|
|
398
|
+
data: {
|
|
399
|
+
requestId,
|
|
400
|
+
error: `Execution not found after trigger: ${response.executionId}`,
|
|
401
|
+
executionTime: 0
|
|
402
|
+
}
|
|
403
|
+
};
|
|
404
|
+
(0, local_engine_utils_1.sendIPCMessage)(connection.process, errorResponse);
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
this.logManager.info(LogManager_1.LogSource.System, LogManager_1.LogCategory.Jobs, 'Job triggered successfully from child', {
|
|
408
|
+
id: requestId,
|
|
409
|
+
jobName,
|
|
410
|
+
executionId: response.executionId
|
|
411
|
+
});
|
|
412
|
+
// Send success response with execution details
|
|
413
|
+
const successResponse = {
|
|
414
|
+
...(0, local_engine_utils_1.createBaseMessage)('success'),
|
|
415
|
+
type: 'success',
|
|
416
|
+
data: {
|
|
417
|
+
requestId,
|
|
418
|
+
result: {
|
|
419
|
+
jobId: execution.id,
|
|
420
|
+
jobName: execution.jobId,
|
|
421
|
+
status: execution.status,
|
|
422
|
+
parameters: execution.parameters,
|
|
423
|
+
startedAt: execution.startedAt,
|
|
424
|
+
completedAt: execution.completedAt
|
|
425
|
+
},
|
|
426
|
+
executionTime: 0
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
(0, local_engine_utils_1.sendIPCMessage)(connection.process, successResponse);
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Handle job detail request from child
|
|
433
|
+
*/
|
|
434
|
+
async handleGetJobDetailMessage(connection, message) {
|
|
435
|
+
const { requestId, executionId } = message.data;
|
|
436
|
+
const execution = this.jobExecutor?.getExecution(executionId);
|
|
437
|
+
if (!execution) {
|
|
438
|
+
const errorResponse = {
|
|
439
|
+
...(0, local_engine_utils_1.createBaseMessage)('error'),
|
|
440
|
+
type: 'error',
|
|
441
|
+
data: {
|
|
442
|
+
requestId,
|
|
443
|
+
error: `Execution ${executionId} not found`,
|
|
444
|
+
executionTime: 0
|
|
445
|
+
}
|
|
446
|
+
};
|
|
447
|
+
(0, local_engine_utils_1.sendIPCMessage)(connection.process, errorResponse);
|
|
448
|
+
return;
|
|
186
449
|
}
|
|
450
|
+
// Send success response with execution details
|
|
451
|
+
const successResponse = {
|
|
452
|
+
...(0, local_engine_utils_1.createBaseMessage)('success'),
|
|
453
|
+
type: 'success',
|
|
454
|
+
data: {
|
|
455
|
+
requestId,
|
|
456
|
+
result: {
|
|
457
|
+
jobId: execution.id,
|
|
458
|
+
jobName: execution.jobId,
|
|
459
|
+
status: execution.status,
|
|
460
|
+
parameters: execution.parameters,
|
|
461
|
+
startedAt: execution.startedAt,
|
|
462
|
+
completedAt: execution.completedAt
|
|
463
|
+
},
|
|
464
|
+
executionTime: 0
|
|
465
|
+
}
|
|
466
|
+
};
|
|
467
|
+
(0, local_engine_utils_1.sendIPCMessage)(connection.process, successResponse);
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Handle job status request from child
|
|
471
|
+
*/
|
|
472
|
+
async handleGetJobStatusMessage(connection, message) {
|
|
473
|
+
const { requestId, executionId } = message.data;
|
|
474
|
+
const execution = this.jobExecutor?.getExecution(executionId);
|
|
475
|
+
if (!execution) {
|
|
476
|
+
const errorResponse = {
|
|
477
|
+
...(0, local_engine_utils_1.createBaseMessage)('error'),
|
|
478
|
+
type: 'error',
|
|
479
|
+
data: {
|
|
480
|
+
requestId,
|
|
481
|
+
error: `Execution ${executionId} not found`,
|
|
482
|
+
executionTime: 0
|
|
483
|
+
}
|
|
484
|
+
};
|
|
485
|
+
(0, local_engine_utils_1.sendIPCMessage)(connection.process, errorResponse);
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
// Send success response with just the status
|
|
489
|
+
const successResponse = {
|
|
490
|
+
...(0, local_engine_utils_1.createBaseMessage)('success'),
|
|
491
|
+
type: 'success',
|
|
492
|
+
data: {
|
|
493
|
+
requestId,
|
|
494
|
+
result: {
|
|
495
|
+
status: execution.status
|
|
496
|
+
},
|
|
497
|
+
executionTime: 0
|
|
498
|
+
}
|
|
499
|
+
};
|
|
500
|
+
(0, local_engine_utils_1.sendIPCMessage)(connection.process, successResponse);
|
|
187
501
|
}
|
|
188
502
|
/**
|
|
189
503
|
* Handle connection errors
|
|
190
504
|
*/
|
|
191
505
|
handleConnectionError(connection, error) {
|
|
192
|
-
|
|
506
|
+
this.logManager.error(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, 'Connection error', {
|
|
507
|
+
id: connection.process.pid?.toString() || 'unknown',
|
|
508
|
+
operation: 'error',
|
|
509
|
+
error
|
|
510
|
+
});
|
|
193
511
|
// Reject all pending requests
|
|
194
512
|
for (const [requestId, pendingRequest] of connection.pendingRequests) {
|
|
195
513
|
(0, local_engine_utils_1.cleanupPendingRequest)(pendingRequest);
|
|
@@ -198,10 +516,58 @@ class LocalEngineClient {
|
|
|
198
516
|
connection.pendingRequests.clear();
|
|
199
517
|
connection.ready = false;
|
|
200
518
|
}
|
|
519
|
+
/**
|
|
520
|
+
* Flush remaining buffered output before connection closes
|
|
521
|
+
*/
|
|
522
|
+
flushRemainingBuffers(connection) {
|
|
523
|
+
const logManager = LogManager_1.LogManager.getInstance();
|
|
524
|
+
// Flush stdout buffer if it has content
|
|
525
|
+
if (connection.stdoutBuffer?.trim()) {
|
|
526
|
+
try {
|
|
527
|
+
logManager.log({
|
|
528
|
+
source: LogManager_1.LogSource.App,
|
|
529
|
+
category: LogManager_1.LogCategory.AppRunner,
|
|
530
|
+
level: 'info',
|
|
531
|
+
message: connection.stdoutBuffer.trim(),
|
|
532
|
+
context: { id: 'unknown' }
|
|
533
|
+
});
|
|
534
|
+
connection.stdoutBuffer = '';
|
|
535
|
+
}
|
|
536
|
+
catch (error) {
|
|
537
|
+
this.logManager.error(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, 'Error flushing stdout buffer', {
|
|
538
|
+
id: 'buffer',
|
|
539
|
+
operation: 'flush',
|
|
540
|
+
error
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
// Flush stderr buffer if it has content
|
|
545
|
+
if (connection.stderrBuffer?.trim()) {
|
|
546
|
+
try {
|
|
547
|
+
logManager.log({
|
|
548
|
+
source: LogManager_1.LogSource.App,
|
|
549
|
+
category: LogManager_1.LogCategory.AppRunner,
|
|
550
|
+
level: 'error',
|
|
551
|
+
message: connection.stderrBuffer.trim(),
|
|
552
|
+
context: { id: 'unknown' }
|
|
553
|
+
});
|
|
554
|
+
connection.stderrBuffer = '';
|
|
555
|
+
}
|
|
556
|
+
catch (error) {
|
|
557
|
+
this.logManager.error(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, 'Error flushing stderr buffer', {
|
|
558
|
+
id: 'buffer',
|
|
559
|
+
operation: 'flush',
|
|
560
|
+
error
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}
|
|
201
565
|
/**
|
|
202
566
|
* Handle connection exit
|
|
203
567
|
*/
|
|
204
568
|
handleConnectionExit(connection, code, signal) {
|
|
569
|
+
// Flush any remaining buffered output before handling exit
|
|
570
|
+
this.flushRemainingBuffers(connection);
|
|
205
571
|
// Reject all pending requests
|
|
206
572
|
for (const [requestId, pendingRequest] of connection.pendingRequests) {
|
|
207
573
|
(0, local_engine_utils_1.cleanupPendingRequest)(pendingRequest);
|
|
@@ -238,6 +604,50 @@ class LocalEngineClient {
|
|
|
238
604
|
checkReady();
|
|
239
605
|
});
|
|
240
606
|
}
|
|
607
|
+
/**
|
|
608
|
+
* Get execution type from message type
|
|
609
|
+
*/
|
|
610
|
+
getExecutionType(messageType) {
|
|
611
|
+
if (messageType === 'execute_function')
|
|
612
|
+
return 'function';
|
|
613
|
+
if (messageType === 'execute_lifecycle')
|
|
614
|
+
return 'lifecycle';
|
|
615
|
+
if (messageType.startsWith('execute_destination_'))
|
|
616
|
+
return 'destination';
|
|
617
|
+
if (messageType.startsWith('execute_source_'))
|
|
618
|
+
return 'source';
|
|
619
|
+
if (messageType === 'execute_job')
|
|
620
|
+
return 'jobs';
|
|
621
|
+
return 'function'; // fallback
|
|
622
|
+
}
|
|
623
|
+
/**
|
|
624
|
+
* Get execution ID from message
|
|
625
|
+
*/
|
|
626
|
+
getExecutionId(message) {
|
|
627
|
+
switch (message.type) {
|
|
628
|
+
case 'execute_function':
|
|
629
|
+
return message.data.functionId;
|
|
630
|
+
case 'execute_lifecycle':
|
|
631
|
+
return message.data.method;
|
|
632
|
+
case 'execute_destination_ready':
|
|
633
|
+
case 'execute_destination_deliver':
|
|
634
|
+
case 'execute_destination_schema':
|
|
635
|
+
return message.data.destinationId;
|
|
636
|
+
case 'execute_source_webhook':
|
|
637
|
+
case 'execute_source_create':
|
|
638
|
+
case 'execute_source_update':
|
|
639
|
+
case 'execute_source_delete':
|
|
640
|
+
case 'execute_source_enable':
|
|
641
|
+
case 'execute_source_pause':
|
|
642
|
+
case 'execute_source_job':
|
|
643
|
+
case 'execute_source_schema':
|
|
644
|
+
return message.data.sourceId;
|
|
645
|
+
case 'execute_job':
|
|
646
|
+
return message.data.jobId;
|
|
647
|
+
default:
|
|
648
|
+
return 'unknown';
|
|
649
|
+
}
|
|
650
|
+
}
|
|
241
651
|
/**
|
|
242
652
|
* Send a request and wait for response
|
|
243
653
|
*/
|
|
@@ -246,6 +656,13 @@ class LocalEngineClient {
|
|
|
246
656
|
const pendingRequest = (0, local_engine_utils_1.createPendingRequest)(message.id, message.type === 'execute_function' ? 'function' : 'lifecycle', resolve, reject, timeoutMs);
|
|
247
657
|
// Set up timeout
|
|
248
658
|
pendingRequest.timeout = (0, local_engine_utils_1.createRequestTimeout)(message.id, timeoutMs, reject, () => connection.pendingRequests.delete(message.id));
|
|
659
|
+
// Set execution context for stdout/stderr capture
|
|
660
|
+
connection.currentContext = {
|
|
661
|
+
type: this.getExecutionType(message.type),
|
|
662
|
+
id: this.getExecutionId(message),
|
|
663
|
+
requestId: message.id,
|
|
664
|
+
startTime: Date.now()
|
|
665
|
+
};
|
|
249
666
|
// Track the request
|
|
250
667
|
connection.pendingRequests.set(message.id, pendingRequest);
|
|
251
668
|
// Send the message
|
|
@@ -329,6 +746,102 @@ class LocalEngineClient {
|
|
|
329
746
|
};
|
|
330
747
|
return this.sendRequest(connection, message);
|
|
331
748
|
}
|
|
749
|
+
/**
|
|
750
|
+
* Execute source webhook
|
|
751
|
+
*/
|
|
752
|
+
async executeSourceWebhook(request, appConfig) {
|
|
753
|
+
const connection = await this.getConnection(appConfig, appConfig.path);
|
|
754
|
+
const message = {
|
|
755
|
+
...(0, local_engine_utils_1.createBaseMessage)('execute_source_webhook'),
|
|
756
|
+
type: 'execute_source_webhook',
|
|
757
|
+
data: request
|
|
758
|
+
};
|
|
759
|
+
return this.sendRequest(connection, message);
|
|
760
|
+
}
|
|
761
|
+
/**
|
|
762
|
+
* Execute source create lifecycle
|
|
763
|
+
*/
|
|
764
|
+
async executeSourceCreate(sourceId, guid, appConfig) {
|
|
765
|
+
const connection = await this.getConnection(appConfig, appConfig.path);
|
|
766
|
+
const message = {
|
|
767
|
+
...(0, local_engine_utils_1.createBaseMessage)('execute_source_create'),
|
|
768
|
+
type: 'execute_source_create',
|
|
769
|
+
data: { sourceId, guid, action: 'create' }
|
|
770
|
+
};
|
|
771
|
+
return this.sendRequest(connection, message);
|
|
772
|
+
}
|
|
773
|
+
/**
|
|
774
|
+
* Execute source update lifecycle
|
|
775
|
+
*/
|
|
776
|
+
async executeSourceUpdate(sourceId, guid, appConfig) {
|
|
777
|
+
const connection = await this.getConnection(appConfig, appConfig.path);
|
|
778
|
+
const message = {
|
|
779
|
+
...(0, local_engine_utils_1.createBaseMessage)('execute_source_update'),
|
|
780
|
+
type: 'execute_source_update',
|
|
781
|
+
data: { sourceId, guid, action: 'update' }
|
|
782
|
+
};
|
|
783
|
+
return this.sendRequest(connection, message);
|
|
784
|
+
}
|
|
785
|
+
/**
|
|
786
|
+
* Execute source delete lifecycle
|
|
787
|
+
*/
|
|
788
|
+
async executeSourceDelete(sourceId, guid, appConfig) {
|
|
789
|
+
const connection = await this.getConnection(appConfig, appConfig.path);
|
|
790
|
+
const message = {
|
|
791
|
+
...(0, local_engine_utils_1.createBaseMessage)('execute_source_delete'),
|
|
792
|
+
type: 'execute_source_delete',
|
|
793
|
+
data: { sourceId, guid, action: 'delete' }
|
|
794
|
+
};
|
|
795
|
+
return this.sendRequest(connection, message);
|
|
796
|
+
}
|
|
797
|
+
/**
|
|
798
|
+
* Execute source enable lifecycle
|
|
799
|
+
*/
|
|
800
|
+
async executeSourceEnable(sourceId, guid, appConfig) {
|
|
801
|
+
const connection = await this.getConnection(appConfig, appConfig.path);
|
|
802
|
+
const message = {
|
|
803
|
+
...(0, local_engine_utils_1.createBaseMessage)('execute_source_enable'),
|
|
804
|
+
type: 'execute_source_enable',
|
|
805
|
+
data: { sourceId, guid, action: 'enable' }
|
|
806
|
+
};
|
|
807
|
+
return this.sendRequest(connection, message);
|
|
808
|
+
}
|
|
809
|
+
/**
|
|
810
|
+
* Execute source pause lifecycle
|
|
811
|
+
*/
|
|
812
|
+
async executeSourcePause(sourceId, guid, appConfig) {
|
|
813
|
+
const connection = await this.getConnection(appConfig, appConfig.path);
|
|
814
|
+
const message = {
|
|
815
|
+
...(0, local_engine_utils_1.createBaseMessage)('execute_source_pause'),
|
|
816
|
+
type: 'execute_source_pause',
|
|
817
|
+
data: { sourceId, guid, action: 'pause' }
|
|
818
|
+
};
|
|
819
|
+
return this.sendRequest(connection, message);
|
|
820
|
+
}
|
|
821
|
+
/**
|
|
822
|
+
* Execute source job
|
|
823
|
+
*/
|
|
824
|
+
async executeSourceJob(request, appConfig) {
|
|
825
|
+
const connection = await this.getConnection(appConfig, appConfig.path);
|
|
826
|
+
const message = {
|
|
827
|
+
...(0, local_engine_utils_1.createBaseMessage)('execute_source_job'),
|
|
828
|
+
type: 'execute_source_job',
|
|
829
|
+
data: request
|
|
830
|
+
};
|
|
831
|
+
return this.sendRequest(connection, message);
|
|
832
|
+
}
|
|
833
|
+
/**
|
|
834
|
+
* Execute source schema
|
|
835
|
+
*/
|
|
836
|
+
async executeSourceSchema(sourceId, appConfig) {
|
|
837
|
+
const connection = await this.getConnection(appConfig, appConfig.path);
|
|
838
|
+
const message = {
|
|
839
|
+
...(0, local_engine_utils_1.createBaseMessage)('execute_source_schema'),
|
|
840
|
+
type: 'execute_source_schema',
|
|
841
|
+
data: { sourceId }
|
|
842
|
+
};
|
|
843
|
+
return this.sendRequest(connection, message);
|
|
844
|
+
}
|
|
332
845
|
/**
|
|
333
846
|
* Close a specific connection
|
|
334
847
|
*/
|
|
@@ -337,6 +850,8 @@ class LocalEngineClient {
|
|
|
337
850
|
if (!connection)
|
|
338
851
|
return;
|
|
339
852
|
try {
|
|
853
|
+
// Flush any remaining buffered output before shutdown
|
|
854
|
+
this.flushRemainingBuffers(connection);
|
|
340
855
|
// Send shutdown message
|
|
341
856
|
const shutdownMessage = {
|
|
342
857
|
...(0, local_engine_utils_1.createBaseMessage)('shutdown'),
|
|
@@ -351,7 +866,11 @@ class LocalEngineClient {
|
|
|
351
866
|
}
|
|
352
867
|
}
|
|
353
868
|
catch (error) {
|
|
354
|
-
|
|
869
|
+
this.logManager.warn(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, 'Error during connection shutdown', {
|
|
870
|
+
id: connection.process.pid?.toString() || 'unknown',
|
|
871
|
+
operation: 'shutdown',
|
|
872
|
+
error
|
|
873
|
+
});
|
|
355
874
|
}
|
|
356
875
|
finally {
|
|
357
876
|
this.connections.delete(connectionKey);
|