@openfn/ws-worker 0.1.8 → 0.2.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/CHANGELOG.md +14 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +57 -14
- package/dist/start.js +57 -14
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# ws-worker
|
|
2
2
|
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 0e8e20c: BREAKING: Updated exit reasons to `{ reason: "success", error_type, error_message }`
|
|
8
|
+
Add exit reasons to job and attempt complete
|
|
9
|
+
|
|
10
|
+
### Patch Changes
|
|
11
|
+
|
|
12
|
+
- Updated dependencies [a540888]
|
|
13
|
+
- Updated dependencies [0e8e20c]
|
|
14
|
+
- @openfn/runtime@0.1.0
|
|
15
|
+
- @openfn/engine-multi@0.1.6
|
|
16
|
+
|
|
3
17
|
## 0.1.8
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,20 @@ import { RuntimeEngine } from '@openfn/engine-multi';
|
|
|
4
4
|
import { Channel as Channel$1 } from 'phoenix';
|
|
5
5
|
import { ExecutionPlan } from '@openfn/runtime';
|
|
6
6
|
|
|
7
|
+
type ExitReasonStrings =
|
|
8
|
+
| 'success'
|
|
9
|
+
| 'fail'
|
|
10
|
+
| 'crash'
|
|
11
|
+
| 'kill'
|
|
12
|
+
| 'cancel'
|
|
13
|
+
| 'exception';
|
|
14
|
+
|
|
15
|
+
type ExitReason = {
|
|
16
|
+
reason: ExitReasonStrings;
|
|
17
|
+
error_message: string | null;
|
|
18
|
+
error_type: string | null;
|
|
19
|
+
};
|
|
20
|
+
|
|
7
21
|
type AttemptOptions = {
|
|
8
22
|
timeout?: number;
|
|
9
23
|
sanitize?: SanitizePolicies;
|
|
@@ -37,6 +51,7 @@ declare type AttemptState = {
|
|
|
37
51
|
plan: ExecutionPlan;
|
|
38
52
|
options: AttemptOptions;
|
|
39
53
|
dataclips: Record<string, any>;
|
|
54
|
+
reasons: Record<string, ExitReason>;
|
|
40
55
|
lastDataclipId?: string;
|
|
41
56
|
};
|
|
42
57
|
declare type Context = {
|
package/dist/index.js
CHANGED
|
@@ -210,6 +210,30 @@ var stringify_default = (obj) => stringify(obj, (_key, value) => {
|
|
|
210
210
|
return value;
|
|
211
211
|
});
|
|
212
212
|
|
|
213
|
+
// src/api/reasons.ts
|
|
214
|
+
var calculateJobExitReason = (jobId, state, error) => {
|
|
215
|
+
let reason = "success";
|
|
216
|
+
let error_type = null;
|
|
217
|
+
let error_message = null;
|
|
218
|
+
if (error) {
|
|
219
|
+
reason = error.severity ?? "crash";
|
|
220
|
+
error_message = error.message;
|
|
221
|
+
error_type = error.subtype || error.type || error.name;
|
|
222
|
+
} else if (state.errors?.[jobId]) {
|
|
223
|
+
reason = "fail";
|
|
224
|
+
({ message: error_message, type: error_type } = state.errors[jobId]);
|
|
225
|
+
}
|
|
226
|
+
return { reason, error_type, error_message };
|
|
227
|
+
};
|
|
228
|
+
var calculateAttemptExitReason = (state) => {
|
|
229
|
+
if (state.reasons) {
|
|
230
|
+
const fail = Object.values(state.reasons).find(
|
|
231
|
+
({ reason }) => reason === "fail"
|
|
232
|
+
);
|
|
233
|
+
return fail || { reason: "success", error_type: null, error_message: null };
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
|
|
213
237
|
// src/api/execute.ts
|
|
214
238
|
var enc = new TextDecoder("utf-8");
|
|
215
239
|
var eventMap = {
|
|
@@ -219,15 +243,17 @@ var eventMap = {
|
|
|
219
243
|
"workflow-log": ATTEMPT_LOG,
|
|
220
244
|
"workflow-complete": ATTEMPT_COMPLETE
|
|
221
245
|
};
|
|
246
|
+
var createAttemptState = (plan, options = {}) => ({
|
|
247
|
+
plan,
|
|
248
|
+
lastDataclipId: plan.initialState,
|
|
249
|
+
dataclips: {},
|
|
250
|
+
reasons: {},
|
|
251
|
+
options
|
|
252
|
+
});
|
|
222
253
|
function execute(channel, engine, logger, plan, options = {}, onComplete = (_result) => {
|
|
223
254
|
}) {
|
|
224
255
|
logger.info("execute...");
|
|
225
|
-
const state =
|
|
226
|
-
plan,
|
|
227
|
-
lastDataclipId: plan.initialState,
|
|
228
|
-
dataclips: {},
|
|
229
|
-
options
|
|
230
|
-
};
|
|
256
|
+
const state = createAttemptState(plan, options);
|
|
231
257
|
const context = { channel, state, logger, onComplete };
|
|
232
258
|
const addEvent = (eventName, handler) => {
|
|
233
259
|
const wrappedFn = async (event) => {
|
|
@@ -251,6 +277,7 @@ function execute(channel, engine, logger, plan, options = {}, onComplete = (_res
|
|
|
251
277
|
addEvent("workflow-start", onWorkflowStart),
|
|
252
278
|
addEvent("job-start", onJobStart),
|
|
253
279
|
addEvent("job-complete", onJobComplete),
|
|
280
|
+
addEvent("job-error", onJobError),
|
|
254
281
|
addEvent("workflow-log", onJobLog),
|
|
255
282
|
addEvent("workflow-complete", onWorkflowComplete),
|
|
256
283
|
addEvent("workflow-error", onWorkflowError)
|
|
@@ -288,7 +315,15 @@ function onJobStart({ channel, state }, event) {
|
|
|
288
315
|
input_dataclip_id: state.lastDataclipId
|
|
289
316
|
});
|
|
290
317
|
}
|
|
291
|
-
function
|
|
318
|
+
function onJobError(context, event) {
|
|
319
|
+
const { state, error, jobId } = event;
|
|
320
|
+
if (state.errors?.[jobId]?.message === error.message) {
|
|
321
|
+
onJobComplete(context, event);
|
|
322
|
+
} else {
|
|
323
|
+
onJobComplete(context, event, event.error);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
function onJobComplete({ channel, state }, event, error) {
|
|
292
327
|
const dataclipId = crypto2.randomUUID();
|
|
293
328
|
const run_id = state.activeRun;
|
|
294
329
|
const job_id = state.activeJob;
|
|
@@ -299,12 +334,20 @@ function onJobComplete({ channel, state }, event) {
|
|
|
299
334
|
state.lastDataclipId = dataclipId;
|
|
300
335
|
delete state.activeRun;
|
|
301
336
|
delete state.activeJob;
|
|
337
|
+
const { reason, error_message, error_type } = calculateJobExitReason(
|
|
338
|
+
job_id,
|
|
339
|
+
event.state,
|
|
340
|
+
error
|
|
341
|
+
);
|
|
342
|
+
state.reasons[job_id] = { reason, error_message, error_type };
|
|
302
343
|
return sendEvent(channel, RUN_COMPLETE, {
|
|
303
344
|
run_id,
|
|
304
345
|
job_id,
|
|
305
346
|
output_dataclip_id: dataclipId,
|
|
306
347
|
output_dataclip: stringify_default(event.state),
|
|
307
|
-
reason
|
|
348
|
+
reason,
|
|
349
|
+
error_message,
|
|
350
|
+
error_type
|
|
308
351
|
});
|
|
309
352
|
}
|
|
310
353
|
function onWorkflowStart({ channel }, _event) {
|
|
@@ -312,20 +355,20 @@ function onWorkflowStart({ channel }, _event) {
|
|
|
312
355
|
}
|
|
313
356
|
async function onWorkflowComplete({ state, channel, onComplete }, _event) {
|
|
314
357
|
const result = state.dataclips[state.lastDataclipId];
|
|
358
|
+
const reason = calculateAttemptExitReason(state);
|
|
315
359
|
await sendEvent(channel, ATTEMPT_COMPLETE, {
|
|
316
360
|
final_dataclip_id: state.lastDataclipId,
|
|
317
|
-
|
|
318
|
-
reason: "ok"
|
|
361
|
+
...reason
|
|
319
362
|
});
|
|
320
|
-
onComplete(result);
|
|
363
|
+
onComplete({ reason, state: result });
|
|
321
364
|
}
|
|
322
365
|
async function onWorkflowError({ state, channel, onComplete }, event) {
|
|
366
|
+
const reason = calculateJobExitReason("", { data: {} }, event);
|
|
323
367
|
await sendEvent(channel, ATTEMPT_COMPLETE, {
|
|
324
|
-
reason: "fail",
|
|
325
368
|
final_dataclip_id: state.lastDataclipId,
|
|
326
|
-
|
|
369
|
+
...reason
|
|
327
370
|
});
|
|
328
|
-
onComplete({});
|
|
371
|
+
onComplete({ reason });
|
|
329
372
|
}
|
|
330
373
|
function onJobLog({ channel, state }, event) {
|
|
331
374
|
const timeInMicroseconds = BigInt(event.time) / BigInt(1e3);
|
package/dist/start.js
CHANGED
|
@@ -5192,6 +5192,30 @@ var stringify_default = (obj) => stringify(obj, (_key, value) => {
|
|
|
5192
5192
|
return value;
|
|
5193
5193
|
});
|
|
5194
5194
|
|
|
5195
|
+
// src/api/reasons.ts
|
|
5196
|
+
var calculateJobExitReason = (jobId, state, error) => {
|
|
5197
|
+
let reason = "success";
|
|
5198
|
+
let error_type = null;
|
|
5199
|
+
let error_message = null;
|
|
5200
|
+
if (error) {
|
|
5201
|
+
reason = error.severity ?? "crash";
|
|
5202
|
+
error_message = error.message;
|
|
5203
|
+
error_type = error.subtype || error.type || error.name;
|
|
5204
|
+
} else if (state.errors?.[jobId]) {
|
|
5205
|
+
reason = "fail";
|
|
5206
|
+
({ message: error_message, type: error_type } = state.errors[jobId]);
|
|
5207
|
+
}
|
|
5208
|
+
return { reason, error_type, error_message };
|
|
5209
|
+
};
|
|
5210
|
+
var calculateAttemptExitReason = (state) => {
|
|
5211
|
+
if (state.reasons) {
|
|
5212
|
+
const fail = Object.values(state.reasons).find(
|
|
5213
|
+
({ reason }) => reason === "fail"
|
|
5214
|
+
);
|
|
5215
|
+
return fail || { reason: "success", error_type: null, error_message: null };
|
|
5216
|
+
}
|
|
5217
|
+
};
|
|
5218
|
+
|
|
5195
5219
|
// src/api/execute.ts
|
|
5196
5220
|
var enc = new TextDecoder("utf-8");
|
|
5197
5221
|
var eventMap = {
|
|
@@ -5201,15 +5225,17 @@ var eventMap = {
|
|
|
5201
5225
|
"workflow-log": ATTEMPT_LOG,
|
|
5202
5226
|
"workflow-complete": ATTEMPT_COMPLETE
|
|
5203
5227
|
};
|
|
5228
|
+
var createAttemptState = (plan, options = {}) => ({
|
|
5229
|
+
plan,
|
|
5230
|
+
lastDataclipId: plan.initialState,
|
|
5231
|
+
dataclips: {},
|
|
5232
|
+
reasons: {},
|
|
5233
|
+
options
|
|
5234
|
+
});
|
|
5204
5235
|
function execute(channel, engine, logger2, plan, options = {}, onComplete = (_result) => {
|
|
5205
5236
|
}) {
|
|
5206
5237
|
logger2.info("execute...");
|
|
5207
|
-
const state =
|
|
5208
|
-
plan,
|
|
5209
|
-
lastDataclipId: plan.initialState,
|
|
5210
|
-
dataclips: {},
|
|
5211
|
-
options
|
|
5212
|
-
};
|
|
5238
|
+
const state = createAttemptState(plan, options);
|
|
5213
5239
|
const context = { channel, state, logger: logger2, onComplete };
|
|
5214
5240
|
const addEvent = (eventName, handler) => {
|
|
5215
5241
|
const wrappedFn = async (event) => {
|
|
@@ -5233,6 +5259,7 @@ function execute(channel, engine, logger2, plan, options = {}, onComplete = (_re
|
|
|
5233
5259
|
addEvent("workflow-start", onWorkflowStart),
|
|
5234
5260
|
addEvent("job-start", onJobStart),
|
|
5235
5261
|
addEvent("job-complete", onJobComplete),
|
|
5262
|
+
addEvent("job-error", onJobError),
|
|
5236
5263
|
addEvent("workflow-log", onJobLog),
|
|
5237
5264
|
addEvent("workflow-complete", onWorkflowComplete),
|
|
5238
5265
|
addEvent("workflow-error", onWorkflowError)
|
|
@@ -5270,7 +5297,15 @@ function onJobStart({ channel, state }, event) {
|
|
|
5270
5297
|
input_dataclip_id: state.lastDataclipId
|
|
5271
5298
|
});
|
|
5272
5299
|
}
|
|
5273
|
-
function
|
|
5300
|
+
function onJobError(context, event) {
|
|
5301
|
+
const { state, error, jobId } = event;
|
|
5302
|
+
if (state.errors?.[jobId]?.message === error.message) {
|
|
5303
|
+
onJobComplete(context, event);
|
|
5304
|
+
} else {
|
|
5305
|
+
onJobComplete(context, event, event.error);
|
|
5306
|
+
}
|
|
5307
|
+
}
|
|
5308
|
+
function onJobComplete({ channel, state }, event, error) {
|
|
5274
5309
|
const dataclipId = crypto3.randomUUID();
|
|
5275
5310
|
const run_id = state.activeRun;
|
|
5276
5311
|
const job_id = state.activeJob;
|
|
@@ -5281,12 +5316,20 @@ function onJobComplete({ channel, state }, event) {
|
|
|
5281
5316
|
state.lastDataclipId = dataclipId;
|
|
5282
5317
|
delete state.activeRun;
|
|
5283
5318
|
delete state.activeJob;
|
|
5319
|
+
const { reason, error_message, error_type } = calculateJobExitReason(
|
|
5320
|
+
job_id,
|
|
5321
|
+
event.state,
|
|
5322
|
+
error
|
|
5323
|
+
);
|
|
5324
|
+
state.reasons[job_id] = { reason, error_message, error_type };
|
|
5284
5325
|
return sendEvent(channel, RUN_COMPLETE, {
|
|
5285
5326
|
run_id,
|
|
5286
5327
|
job_id,
|
|
5287
5328
|
output_dataclip_id: dataclipId,
|
|
5288
5329
|
output_dataclip: stringify_default(event.state),
|
|
5289
|
-
reason
|
|
5330
|
+
reason,
|
|
5331
|
+
error_message,
|
|
5332
|
+
error_type
|
|
5290
5333
|
});
|
|
5291
5334
|
}
|
|
5292
5335
|
function onWorkflowStart({ channel }, _event) {
|
|
@@ -5294,20 +5337,20 @@ function onWorkflowStart({ channel }, _event) {
|
|
|
5294
5337
|
}
|
|
5295
5338
|
async function onWorkflowComplete({ state, channel, onComplete }, _event) {
|
|
5296
5339
|
const result = state.dataclips[state.lastDataclipId];
|
|
5340
|
+
const reason = calculateAttemptExitReason(state);
|
|
5297
5341
|
await sendEvent(channel, ATTEMPT_COMPLETE, {
|
|
5298
5342
|
final_dataclip_id: state.lastDataclipId,
|
|
5299
|
-
|
|
5300
|
-
reason: "ok"
|
|
5343
|
+
...reason
|
|
5301
5344
|
});
|
|
5302
|
-
onComplete(result);
|
|
5345
|
+
onComplete({ reason, state: result });
|
|
5303
5346
|
}
|
|
5304
5347
|
async function onWorkflowError({ state, channel, onComplete }, event) {
|
|
5348
|
+
const reason = calculateJobExitReason("", { data: {} }, event);
|
|
5305
5349
|
await sendEvent(channel, ATTEMPT_COMPLETE, {
|
|
5306
|
-
reason: "fail",
|
|
5307
5350
|
final_dataclip_id: state.lastDataclipId,
|
|
5308
|
-
|
|
5351
|
+
...reason
|
|
5309
5352
|
});
|
|
5310
|
-
onComplete({});
|
|
5353
|
+
onComplete({ reason });
|
|
5311
5354
|
}
|
|
5312
5355
|
function onJobLog({ channel, state }, event) {
|
|
5313
5356
|
const timeInMicroseconds = BigInt(event.time) / BigInt(1e3);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openfn/ws-worker",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "A Websocket Worker to connect Lightning to a Runtime Engine",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
"koa-logger": "^3.2.1",
|
|
22
22
|
"phoenix": "^1.7.7",
|
|
23
23
|
"ws": "^8.14.1",
|
|
24
|
-
"@openfn/engine-multi": "0.1.
|
|
24
|
+
"@openfn/engine-multi": "0.1.6",
|
|
25
25
|
"@openfn/logger": "0.0.19",
|
|
26
|
-
"@openfn/runtime": "0.0
|
|
26
|
+
"@openfn/runtime": "0.1.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/koa": "^2.13.5",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"tsup": "^6.2.3",
|
|
41
41
|
"typescript": "^4.6.4",
|
|
42
42
|
"yargs": "^17.6.2",
|
|
43
|
-
"@openfn/lightning-mock": "1.0.
|
|
43
|
+
"@openfn/lightning-mock": "1.0.7"
|
|
44
44
|
},
|
|
45
45
|
"files": [
|
|
46
46
|
"dist",
|