@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 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.3";
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("skipping claim attempt: server at capacity");
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("requesting run...");
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
- await sendEvent(channel, STEP_START, {
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
- app.workflows[id] = true;
1087
- const {
1088
- channel: runChannel,
1089
- plan,
1090
- options: options2 = {},
1091
- input
1092
- } = await run_default(app.socket, token, id, logger);
1093
- if (!("payloadLimitMb" in options2)) {
1094
- options2.payloadLimitMb = app.options.payloadLimitMb;
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.3";
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("skipping claim attempt: server at capacity");
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("requesting run...");
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
- await sendEvent(channel, STEP_START, {
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
- app.workflows[id] = true;
1226
- const {
1227
- channel: runChannel,
1228
- plan,
1229
- options: options2 = {},
1230
- input
1231
- } = await run_default(app.socket, token, id, logger2);
1232
- if (!("payloadLimitMb" in options2)) {
1233
- options2.payloadLimitMb = app.options.payloadLimitMb;
1234
- }
1235
- const onFinish = () => {
1236
- logger2.debug(`workflow ${id} complete: releasing worker`);
1237
- delete app.workflows[id];
1238
- runChannel.leave();
1239
- app.events.emit(INTERNAL_RUN_COMPLETE);
1240
- };
1241
- const context = execute(
1242
- runChannel,
1243
- engine,
1244
- logger2,
1245
- plan,
1246
- input,
1247
- options2,
1248
- onFinish
1249
- );
1250
- app.workflows[id] = context;
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 server...");
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",
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.4",
25
+ "@openfn/engine-multi": "1.2.5",
26
26
  "@openfn/lexicon": "^1.1.0",
27
- "@openfn/logger": "1.0.2",
28
- "@openfn/runtime": "1.4.2"
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.18"
45
+ "@openfn/lightning-mock": "2.0.19"
46
46
  },
47
47
  "files": [
48
48
  "dist",