@openfn/ws-worker 1.6.3 → 1.6.6
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 +21 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +50 -33
- package/dist/start.js +54 -35
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# ws-worker
|
|
2
2
|
|
|
3
|
+
## 1.6.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Log claim event duration
|
|
8
|
+
|
|
9
|
+
## 1.6.5
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 5db5862: Dont log compiled job code
|
|
14
|
+
- f581c6b: log duration of runs and server capacity
|
|
15
|
+
- 3e6eba2: Trap errors coming out of the websocket
|
|
16
|
+
- @openfn/engine-multi@1.2.5
|
|
17
|
+
|
|
18
|
+
## 1.6.4
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- 0cf7198: Do not send the input_dataclip_id in step:start if the dataclip was witheld
|
|
23
|
+
|
|
3
24
|
## 1.6.3
|
|
4
25
|
|
|
5
26
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -18,6 +18,8 @@ type RunState = {
|
|
|
18
18
|
// For each run, map the input ids
|
|
19
19
|
// TODO better name maybe?
|
|
20
20
|
inputDataclips: Record<string, string>;
|
|
21
|
+
// If for any reason a dataclip was not sent to lightning, track it
|
|
22
|
+
withheldDataclips: Record<string, true>;
|
|
21
23
|
reasons: Record<string, ExitReason>;
|
|
22
24
|
|
|
23
25
|
// final dataclip id
|
package/dist/index.js
CHANGED
|
@@ -29,7 +29,7 @@ var name, version, description, main, type, scripts, bin, author, license, depen
|
|
|
29
29
|
var init_package = __esm({
|
|
30
30
|
"package.json"() {
|
|
31
31
|
name = "@openfn/ws-worker";
|
|
32
|
-
version = "1.6.
|
|
32
|
+
version = "1.6.6";
|
|
33
33
|
description = "A Websocket Worker to connect Lightning to a Runtime Engine";
|
|
34
34
|
main = "dist/index.js";
|
|
35
35
|
type = "module";
|
|
@@ -232,18 +232,21 @@ var claim = (app, logger = mockLogger, options = {}) => {
|
|
|
232
232
|
const { maxWorkers = 5 } = options;
|
|
233
233
|
const activeWorkers = Object.keys(app.workflows).length;
|
|
234
234
|
if (activeWorkers >= maxWorkers) {
|
|
235
|
-
logger.debug(
|
|
235
|
+
logger.debug(
|
|
236
|
+
`skipping claim attempt: server at capacity (${activeWorkers}/${maxWorkers})`
|
|
237
|
+
);
|
|
236
238
|
return reject(new Error("Server at capacity"));
|
|
237
239
|
}
|
|
238
240
|
if (!app.queueChannel) {
|
|
239
241
|
logger.debug("skipping claim attempt: websocket unavailable");
|
|
240
242
|
return reject(new Error("No websocket available"));
|
|
241
243
|
}
|
|
242
|
-
logger.debug(
|
|
244
|
+
logger.debug(`requesting run (capacity ${activeWorkers}/${maxWorkers})`);
|
|
245
|
+
const start = Date.now();
|
|
243
246
|
app.queueChannel.push(CLAIM, { demand: 1 }).receive("ok", ({ runs }) => {
|
|
247
|
+
const duration = Date.now() - start;
|
|
244
248
|
logger.debug(
|
|
245
|
-
`claimed ${runs.length} runs:
|
|
246
|
-
runs.map((r) => r.id).join(",")
|
|
249
|
+
`claimed ${runs.length} runs in ${duration}ms (${runs.length ? runs.map((r) => r.id).join(",") : "-"})`
|
|
247
250
|
);
|
|
248
251
|
if (!runs?.length) {
|
|
249
252
|
return reject(new Error("No runs returned"));
|
|
@@ -456,6 +459,7 @@ var create_run_state_default = (plan, input) => {
|
|
|
456
459
|
lastDataclipId: "",
|
|
457
460
|
dataclips: {},
|
|
458
461
|
inputDataclips: {},
|
|
462
|
+
withheldDataclips: {},
|
|
459
463
|
reasons: {},
|
|
460
464
|
plan,
|
|
461
465
|
input
|
|
@@ -660,6 +664,7 @@ async function onStepComplete(context, event, error) {
|
|
|
660
664
|
}
|
|
661
665
|
evt.output_dataclip_id = dataclipId;
|
|
662
666
|
} catch (e) {
|
|
667
|
+
state.withheldDataclips[dataclipId] = true;
|
|
663
668
|
evt.output_dataclip_error = "DATACLIP_TOO_LARGE";
|
|
664
669
|
const time = (timestamp2() - BigInt(1e7)).toString();
|
|
665
670
|
await onJobLog(context, {
|
|
@@ -684,12 +689,15 @@ async function onStepStart(context, event) {
|
|
|
684
689
|
state.activeStep = crypto4.randomUUID();
|
|
685
690
|
state.activeJob = event.jobId;
|
|
686
691
|
const input_dataclip_id = state.inputDataclips[event.jobId];
|
|
687
|
-
|
|
692
|
+
const evt = {
|
|
688
693
|
step_id: state.activeStep,
|
|
689
694
|
job_id: state.activeJob,
|
|
690
|
-
input_dataclip_id,
|
|
691
695
|
timestamp: timeInMicroseconds(event.time)
|
|
692
|
-
}
|
|
696
|
+
};
|
|
697
|
+
if (!state.withheldDataclips[input_dataclip_id]) {
|
|
698
|
+
evt.input_dataclip_id = input_dataclip_id;
|
|
699
|
+
}
|
|
700
|
+
await sendEvent(channel, STEP_START, evt);
|
|
693
701
|
}
|
|
694
702
|
|
|
695
703
|
// src/util/log-final-reason.ts
|
|
@@ -1083,32 +1091,41 @@ function createServer(engine, options = {}) {
|
|
|
1083
1091
|
app.options = options;
|
|
1084
1092
|
app.execute = async ({ id, token }) => {
|
|
1085
1093
|
if (app.socket) {
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1094
|
+
try {
|
|
1095
|
+
const start = Date.now();
|
|
1096
|
+
app.workflows[id] = true;
|
|
1097
|
+
const {
|
|
1098
|
+
channel: runChannel,
|
|
1099
|
+
plan,
|
|
1100
|
+
options: options2 = {},
|
|
1101
|
+
input
|
|
1102
|
+
} = await run_default(app.socket, token, id, logger);
|
|
1103
|
+
if (!("payloadLimitMb" in options2)) {
|
|
1104
|
+
options2.payloadLimitMb = app.options.payloadLimitMb;
|
|
1105
|
+
}
|
|
1106
|
+
const onFinish = () => {
|
|
1107
|
+
const duration = (Date.now() - start) / 1e3;
|
|
1108
|
+
logger.debug(
|
|
1109
|
+
`workflow ${id} complete in ${duration}s: releasing worker`
|
|
1110
|
+
);
|
|
1111
|
+
delete app.workflows[id];
|
|
1112
|
+
runChannel.leave();
|
|
1113
|
+
app.events.emit(INTERNAL_RUN_COMPLETE);
|
|
1114
|
+
};
|
|
1115
|
+
const context = execute(
|
|
1116
|
+
runChannel,
|
|
1117
|
+
engine,
|
|
1118
|
+
logger,
|
|
1119
|
+
plan,
|
|
1120
|
+
input,
|
|
1121
|
+
options2,
|
|
1122
|
+
onFinish
|
|
1123
|
+
);
|
|
1124
|
+
app.workflows[id] = context;
|
|
1125
|
+
} catch (e) {
|
|
1126
|
+
logger.error(`Unexpected error executing ${id}`);
|
|
1127
|
+
logger.error(e);
|
|
1095
1128
|
}
|
|
1096
|
-
const onFinish = () => {
|
|
1097
|
-
logger.debug(`workflow ${id} complete: releasing worker`);
|
|
1098
|
-
delete app.workflows[id];
|
|
1099
|
-
runChannel.leave();
|
|
1100
|
-
app.events.emit(INTERNAL_RUN_COMPLETE);
|
|
1101
|
-
};
|
|
1102
|
-
const context = execute(
|
|
1103
|
-
runChannel,
|
|
1104
|
-
engine,
|
|
1105
|
-
logger,
|
|
1106
|
-
plan,
|
|
1107
|
-
input,
|
|
1108
|
-
options2,
|
|
1109
|
-
onFinish
|
|
1110
|
-
);
|
|
1111
|
-
app.workflows[id] = context;
|
|
1112
1129
|
} else {
|
|
1113
1130
|
logger.error("No lightning socket established");
|
|
1114
1131
|
}
|
package/dist/start.js
CHANGED
|
@@ -37,7 +37,7 @@ var name, version, description, main, type, scripts, bin, author, license, depen
|
|
|
37
37
|
var init_package = __esm({
|
|
38
38
|
"package.json"() {
|
|
39
39
|
name = "@openfn/ws-worker";
|
|
40
|
-
version = "1.6.
|
|
40
|
+
version = "1.6.6";
|
|
41
41
|
description = "A Websocket Worker to connect Lightning to a Runtime Engine";
|
|
42
42
|
main = "dist/index.js";
|
|
43
43
|
type = "module";
|
|
@@ -371,18 +371,21 @@ var claim = (app, logger2 = mockLogger, options = {}) => {
|
|
|
371
371
|
const { maxWorkers = 5 } = options;
|
|
372
372
|
const activeWorkers = Object.keys(app.workflows).length;
|
|
373
373
|
if (activeWorkers >= maxWorkers) {
|
|
374
|
-
logger2.debug(
|
|
374
|
+
logger2.debug(
|
|
375
|
+
`skipping claim attempt: server at capacity (${activeWorkers}/${maxWorkers})`
|
|
376
|
+
);
|
|
375
377
|
return reject(new Error("Server at capacity"));
|
|
376
378
|
}
|
|
377
379
|
if (!app.queueChannel) {
|
|
378
380
|
logger2.debug("skipping claim attempt: websocket unavailable");
|
|
379
381
|
return reject(new Error("No websocket available"));
|
|
380
382
|
}
|
|
381
|
-
logger2.debug(
|
|
383
|
+
logger2.debug(`requesting run (capacity ${activeWorkers}/${maxWorkers})`);
|
|
384
|
+
const start = Date.now();
|
|
382
385
|
app.queueChannel.push(CLAIM, { demand: 1 }).receive("ok", ({ runs }) => {
|
|
386
|
+
const duration = Date.now() - start;
|
|
383
387
|
logger2.debug(
|
|
384
|
-
`claimed ${runs.length} runs:
|
|
385
|
-
runs.map((r) => r.id).join(",")
|
|
388
|
+
`claimed ${runs.length} runs in ${duration}ms (${runs.length ? runs.map((r) => r.id).join(",") : "-"})`
|
|
386
389
|
);
|
|
387
390
|
if (!runs?.length) {
|
|
388
391
|
return reject(new Error("No runs returned"));
|
|
@@ -595,6 +598,7 @@ var create_run_state_default = (plan, input) => {
|
|
|
595
598
|
lastDataclipId: "",
|
|
596
599
|
dataclips: {},
|
|
597
600
|
inputDataclips: {},
|
|
601
|
+
withheldDataclips: {},
|
|
598
602
|
reasons: {},
|
|
599
603
|
plan,
|
|
600
604
|
input
|
|
@@ -799,6 +803,7 @@ async function onStepComplete(context, event, error) {
|
|
|
799
803
|
}
|
|
800
804
|
evt.output_dataclip_id = dataclipId;
|
|
801
805
|
} catch (e) {
|
|
806
|
+
state.withheldDataclips[dataclipId] = true;
|
|
802
807
|
evt.output_dataclip_error = "DATACLIP_TOO_LARGE";
|
|
803
808
|
const time = (timestamp2() - BigInt(1e7)).toString();
|
|
804
809
|
await onJobLog(context, {
|
|
@@ -823,12 +828,15 @@ async function onStepStart(context, event) {
|
|
|
823
828
|
state.activeStep = crypto5.randomUUID();
|
|
824
829
|
state.activeJob = event.jobId;
|
|
825
830
|
const input_dataclip_id = state.inputDataclips[event.jobId];
|
|
826
|
-
|
|
831
|
+
const evt = {
|
|
827
832
|
step_id: state.activeStep,
|
|
828
833
|
job_id: state.activeJob,
|
|
829
|
-
input_dataclip_id,
|
|
830
834
|
timestamp: timeInMicroseconds(event.time)
|
|
831
|
-
}
|
|
835
|
+
};
|
|
836
|
+
if (!state.withheldDataclips[input_dataclip_id]) {
|
|
837
|
+
evt.input_dataclip_id = input_dataclip_id;
|
|
838
|
+
}
|
|
839
|
+
await sendEvent(channel, STEP_START, evt);
|
|
832
840
|
}
|
|
833
841
|
|
|
834
842
|
// src/util/log-final-reason.ts
|
|
@@ -1222,32 +1230,41 @@ function createServer(engine, options = {}) {
|
|
|
1222
1230
|
app.options = options;
|
|
1223
1231
|
app.execute = async ({ id, token }) => {
|
|
1224
1232
|
if (app.socket) {
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1233
|
+
try {
|
|
1234
|
+
const start = Date.now();
|
|
1235
|
+
app.workflows[id] = true;
|
|
1236
|
+
const {
|
|
1237
|
+
channel: runChannel,
|
|
1238
|
+
plan,
|
|
1239
|
+
options: options2 = {},
|
|
1240
|
+
input
|
|
1241
|
+
} = await run_default(app.socket, token, id, logger2);
|
|
1242
|
+
if (!("payloadLimitMb" in options2)) {
|
|
1243
|
+
options2.payloadLimitMb = app.options.payloadLimitMb;
|
|
1244
|
+
}
|
|
1245
|
+
const onFinish = () => {
|
|
1246
|
+
const duration = (Date.now() - start) / 1e3;
|
|
1247
|
+
logger2.debug(
|
|
1248
|
+
`workflow ${id} complete in ${duration}s: releasing worker`
|
|
1249
|
+
);
|
|
1250
|
+
delete app.workflows[id];
|
|
1251
|
+
runChannel.leave();
|
|
1252
|
+
app.events.emit(INTERNAL_RUN_COMPLETE);
|
|
1253
|
+
};
|
|
1254
|
+
const context = execute(
|
|
1255
|
+
runChannel,
|
|
1256
|
+
engine,
|
|
1257
|
+
logger2,
|
|
1258
|
+
plan,
|
|
1259
|
+
input,
|
|
1260
|
+
options2,
|
|
1261
|
+
onFinish
|
|
1262
|
+
);
|
|
1263
|
+
app.workflows[id] = context;
|
|
1264
|
+
} catch (e) {
|
|
1265
|
+
logger2.error(`Unexpected error executing ${id}`);
|
|
1266
|
+
logger2.error(e);
|
|
1267
|
+
}
|
|
1251
1268
|
} else {
|
|
1252
1269
|
logger2.error("No lightning socket established");
|
|
1253
1270
|
}
|
|
@@ -6259,6 +6276,7 @@ function parseArgs(argv) {
|
|
|
6259
6276
|
// src/start.ts
|
|
6260
6277
|
var args = parseArgs(process.argv);
|
|
6261
6278
|
var logger = createLogger("SRV", { level: args.log });
|
|
6279
|
+
logger.info("Starting worker server...");
|
|
6262
6280
|
if (args.lightning === "mock") {
|
|
6263
6281
|
args.lightning = "ws://localhost:8888/worker";
|
|
6264
6282
|
if (!args.secret) {
|
|
@@ -6270,7 +6288,7 @@ if (args.lightning === "mock") {
|
|
|
6270
6288
|
}
|
|
6271
6289
|
var [minBackoff, maxBackoff] = args.backoff.split("/").map((n) => parseInt(n, 10) * 1e3);
|
|
6272
6290
|
function engineReady(engine) {
|
|
6273
|
-
logger.debug("Creating worker
|
|
6291
|
+
logger.debug("Creating worker instance");
|
|
6274
6292
|
const workerOptions = {
|
|
6275
6293
|
port: args.port,
|
|
6276
6294
|
lightning: args.lightning,
|
|
@@ -6301,6 +6319,7 @@ function engineReady(engine) {
|
|
|
6301
6319
|
} = workerOptions;
|
|
6302
6320
|
logger.debug("Worker options:", humanOptions);
|
|
6303
6321
|
server_default(engine, workerOptions);
|
|
6322
|
+
logger.success("Worker started OK");
|
|
6304
6323
|
}
|
|
6305
6324
|
if (args.mock) {
|
|
6306
6325
|
runtime_engine_default().then((engine) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openfn/ws-worker",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.6",
|
|
4
4
|
"description": "A Websocket Worker to connect Lightning to a Runtime Engine",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
"koa-logger": "^3.2.1",
|
|
23
23
|
"phoenix": "1.7.10",
|
|
24
24
|
"ws": "^8.18.0",
|
|
25
|
-
"@openfn/engine-multi": "1.2.
|
|
25
|
+
"@openfn/engine-multi": "1.2.5",
|
|
26
26
|
"@openfn/lexicon": "^1.1.0",
|
|
27
|
-
"@openfn/
|
|
28
|
-
"@openfn/
|
|
27
|
+
"@openfn/runtime": "1.4.2",
|
|
28
|
+
"@openfn/logger": "1.0.2"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@types/koa": "^2.13.5",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"tsup": "^6.2.3",
|
|
43
43
|
"typescript": "^4.6.4",
|
|
44
44
|
"yargs": "^17.6.2",
|
|
45
|
-
"@openfn/lightning-mock": "2.0.
|
|
45
|
+
"@openfn/lightning-mock": "2.0.19"
|
|
46
46
|
},
|
|
47
47
|
"files": [
|
|
48
48
|
"dist",
|