@openfn/ws-worker 1.20.0 → 1.20.2

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,22 @@
1
1
  # ws-worker
2
2
 
3
+ ## 1.20.2
4
+
5
+ ### Patch Changes
6
+
7
+ - Add internal fallback timeout to events. Also adjust error handling to try and catch an uncaught error
8
+ - q
9
+
10
+ ## 1.20.1
11
+
12
+ ### Patch Changes
13
+
14
+ - Updated dependencies [a1bfdc1]
15
+ - Updated dependencies [c70369b]
16
+ - @openfn/runtime@1.7.7
17
+ - @openfn/logger@1.1.1
18
+ - @openfn/engine-multi@1.9.1
19
+
3
20
  ## 1.20.0
4
21
 
5
22
  ### Minor Changes
package/dist/index.d.ts CHANGED
@@ -56,6 +56,7 @@ type WorkerRunOptions = ExecuteOptions & {
56
56
  batchLogs?: boolean;
57
57
  batchInterval?: number;
58
58
  batchLimit?: number;
59
+ eventTimeoutSeconds?: number;
59
60
  };
60
61
 
61
62
  type Context = {
package/dist/index.js CHANGED
@@ -936,21 +936,37 @@ function eventProcessor(engine, context, callbacks, options = {}) {
936
936
  const { id: planId, logger } = context;
937
937
  const {
938
938
  batchLimit: limit = DEFAULT_BATCH_LIMIT,
939
- batchInterval: interval = DEFAULT_BATCH_INTERVAL
939
+ batchInterval: interval = DEFAULT_BATCH_INTERVAL,
940
+ timeout_ms
940
941
  } = options;
941
942
  const queue = [];
943
+ let activeBatch = null;
944
+ let batch = [];
945
+ let batchTimeout;
946
+ let didFinish = false;
947
+ let timeoutHandle;
942
948
  const next = async () => {
943
949
  const evt = queue[0];
944
950
  if (evt) {
951
+ didFinish = false;
952
+ const finish = () => {
953
+ clearTimeout(timeoutHandle);
954
+ if (!didFinish) {
955
+ didFinish = true;
956
+ queue.shift();
957
+ setImmediate(next);
958
+ }
959
+ };
960
+ if (timeout_ms) {
961
+ timeoutHandle = setTimeout(() => {
962
+ logger.error(`${planId} :: ${evt.name} :: timeout (fallback)`);
963
+ finish();
964
+ }, timeout_ms);
965
+ }
945
966
  await process2(evt.name, evt.event);
946
- queue.shift();
947
- next();
967
+ finish();
948
968
  }
949
969
  };
950
- let activeBatch = null;
951
- let batch = [];
952
- let start = -1;
953
- let batchTimeout;
954
970
  const sendBatch = async (name) => {
955
971
  clearTimeout(batchTimeout);
956
972
  activeBatch = null;
@@ -958,16 +974,24 @@ function eventProcessor(engine, context, callbacks, options = {}) {
958
974
  batch = [];
959
975
  };
960
976
  const send = async (name, payload, batchSize) => {
961
- const lightningEvent = eventMap[name] ?? name;
962
- await callbacks[name](context, payload);
963
- if (batchSize) {
964
- logger.info(
965
- `${planId} :: sent ${lightningEvent} (${batchSize}):: OK :: ${Date.now() - start}ms`
966
- );
967
- } else {
968
- logger.info(
969
- `${planId} :: sent ${lightningEvent} :: OK :: ${Date.now() - start}ms`
970
- );
977
+ try {
978
+ const start = Date.now();
979
+ const lightningEvent = eventMap[name] ?? name;
980
+ await callbacks[name](context, payload);
981
+ if (batchSize) {
982
+ logger.info(
983
+ `${planId} :: sent ${lightningEvent} (${batchSize}):: OK :: ${Date.now() - start}ms`
984
+ );
985
+ } else {
986
+ logger.info(
987
+ `${planId} :: sent ${lightningEvent} :: OK :: ${Date.now() - start}ms`
988
+ );
989
+ }
990
+ } catch (e2) {
991
+ if (!e2.reportedToSentry) {
992
+ Sentry3.captureException(e2);
993
+ logger.error(e2);
994
+ }
971
995
  }
972
996
  };
973
997
  const process2 = async (name, event) => {
@@ -988,32 +1012,24 @@ function eventProcessor(engine, context, callbacks, options = {}) {
988
1012
  await sendBatch(activeBatch);
989
1013
  }
990
1014
  if (name in callbacks) {
991
- try {
992
- start = Date.now();
993
- if (options?.batch?.[name]) {
994
- activeBatch = name;
995
- batch.push(event);
996
- while (queue.length > 1 && queue[1].name === name) {
997
- const [nextBatchItem] = queue.splice(1, 1);
998
- batch.push(nextBatchItem.event);
999
- if (batch.length >= limit) {
1000
- return sendBatch(name);
1001
- }
1015
+ if (options?.batch?.[name]) {
1016
+ activeBatch = name;
1017
+ batch.push(event);
1018
+ while (queue.length > 1 && queue[1].name === name) {
1019
+ const [nextBatchItem] = queue.splice(1, 1);
1020
+ batch.push(nextBatchItem.event);
1021
+ if (batch.length >= limit) {
1022
+ return sendBatch(name);
1002
1023
  }
1003
- if (!batchTimeout) {
1004
- const batchName = activeBatch;
1005
- batchTimeout = setTimeout(async () => {
1006
- sendBatch(batchName);
1007
- }, interval);
1008
- }
1009
- return;
1010
1024
  }
1011
- await send(name, event);
1012
- } catch (e2) {
1013
- if (!e2.reportedToSentry) {
1014
- Sentry3.captureException(e2);
1015
- logger.error(e2);
1025
+ if (!batchTimeout) {
1026
+ const batchName = activeBatch;
1027
+ batchTimeout = setTimeout(async () => {
1028
+ sendBatch(batchName);
1029
+ }, interval);
1016
1030
  }
1031
+ } else {
1032
+ await send(name, event);
1017
1033
  }
1018
1034
  } else {
1019
1035
  logger.warn("no event bound for", name);
@@ -1056,6 +1072,10 @@ function execute(channel, engine, logger, plan, input, options = {}, onFinish =
1056
1072
  runId: plan.id
1057
1073
  }
1058
1074
  });
1075
+ const batch = {};
1076
+ if (options.batchLogs) {
1077
+ batch[WORKFLOW_LOG2] = true;
1078
+ }
1059
1079
  eventProcessor(
1060
1080
  engine,
1061
1081
  context,
@@ -1069,11 +1089,10 @@ function execute(channel, engine, logger, plan, input, options = {}, onFinish =
1069
1089
  [WORKFLOW_ERROR2]: onRunError
1070
1090
  },
1071
1091
  {
1072
- batch: options.batchLogs ? {
1073
- [WORKFLOW_LOG2]: true
1074
- } : {},
1092
+ batch,
1075
1093
  batchInterval: options.batchInterval,
1076
- batchLimit: options.batchLimit
1094
+ batchLimit: options.batchLimit,
1095
+ timeout_ms: (options.eventTimeoutSeconds ?? 0) * 1e3 * 1.1
1077
1096
  }
1078
1097
  );
1079
1098
  const resolvers = {
@@ -1468,6 +1487,7 @@ function createServer(engine, options = {}) {
1468
1487
  }
1469
1488
  options2.timeoutRetryCount = app.options.timeoutRetryCount;
1470
1489
  options2.timeoutRetryDelay = app.options.timeoutRetryDelayMs ?? app.options.socketTimeoutSeconds;
1490
+ options2.eventTimeoutSeconds = app.options.messageTimeoutSeconds;
1471
1491
  options2.batchLogs = app.options.batchLogs;
1472
1492
  options2.batchInterval = app.options.batchInterval;
1473
1493
  options2.batchLimit = app.options.batchLimit;
package/dist/start.js CHANGED
@@ -1085,21 +1085,37 @@ function eventProcessor(engine, context, callbacks, options = {}) {
1085
1085
  const { id: planId, logger: logger2 } = context;
1086
1086
  const {
1087
1087
  batchLimit: limit = DEFAULT_BATCH_LIMIT,
1088
- batchInterval: interval = DEFAULT_BATCH_INTERVAL
1088
+ batchInterval: interval = DEFAULT_BATCH_INTERVAL,
1089
+ timeout_ms
1089
1090
  } = options;
1090
1091
  const queue = [];
1092
+ let activeBatch = null;
1093
+ let batch = [];
1094
+ let batchTimeout;
1095
+ let didFinish = false;
1096
+ let timeoutHandle;
1091
1097
  const next = async () => {
1092
1098
  const evt = queue[0];
1093
1099
  if (evt) {
1100
+ didFinish = false;
1101
+ const finish = () => {
1102
+ clearTimeout(timeoutHandle);
1103
+ if (!didFinish) {
1104
+ didFinish = true;
1105
+ queue.shift();
1106
+ setImmediate(next);
1107
+ }
1108
+ };
1109
+ if (timeout_ms) {
1110
+ timeoutHandle = setTimeout(() => {
1111
+ logger2.error(`${planId} :: ${evt.name} :: timeout (fallback)`);
1112
+ finish();
1113
+ }, timeout_ms);
1114
+ }
1094
1115
  await process2(evt.name, evt.event);
1095
- queue.shift();
1096
- next();
1116
+ finish();
1097
1117
  }
1098
1118
  };
1099
- let activeBatch = null;
1100
- let batch = [];
1101
- let start = -1;
1102
- let batchTimeout;
1103
1119
  const sendBatch = async (name) => {
1104
1120
  clearTimeout(batchTimeout);
1105
1121
  activeBatch = null;
@@ -1107,16 +1123,24 @@ function eventProcessor(engine, context, callbacks, options = {}) {
1107
1123
  batch = [];
1108
1124
  };
1109
1125
  const send = async (name, payload, batchSize) => {
1110
- const lightningEvent = eventMap[name] ?? name;
1111
- await callbacks[name](context, payload);
1112
- if (batchSize) {
1113
- logger2.info(
1114
- `${planId} :: sent ${lightningEvent} (${batchSize}):: OK :: ${Date.now() - start}ms`
1115
- );
1116
- } else {
1117
- logger2.info(
1118
- `${planId} :: sent ${lightningEvent} :: OK :: ${Date.now() - start}ms`
1119
- );
1126
+ try {
1127
+ const start = Date.now();
1128
+ const lightningEvent = eventMap[name] ?? name;
1129
+ await callbacks[name](context, payload);
1130
+ if (batchSize) {
1131
+ logger2.info(
1132
+ `${planId} :: sent ${lightningEvent} (${batchSize}):: OK :: ${Date.now() - start}ms`
1133
+ );
1134
+ } else {
1135
+ logger2.info(
1136
+ `${planId} :: sent ${lightningEvent} :: OK :: ${Date.now() - start}ms`
1137
+ );
1138
+ }
1139
+ } catch (e2) {
1140
+ if (!e2.reportedToSentry) {
1141
+ Sentry3.captureException(e2);
1142
+ logger2.error(e2);
1143
+ }
1120
1144
  }
1121
1145
  };
1122
1146
  const process2 = async (name, event) => {
@@ -1137,32 +1161,24 @@ function eventProcessor(engine, context, callbacks, options = {}) {
1137
1161
  await sendBatch(activeBatch);
1138
1162
  }
1139
1163
  if (name in callbacks) {
1140
- try {
1141
- start = Date.now();
1142
- if (options?.batch?.[name]) {
1143
- activeBatch = name;
1144
- batch.push(event);
1145
- while (queue.length > 1 && queue[1].name === name) {
1146
- const [nextBatchItem] = queue.splice(1, 1);
1147
- batch.push(nextBatchItem.event);
1148
- if (batch.length >= limit) {
1149
- return sendBatch(name);
1150
- }
1151
- }
1152
- if (!batchTimeout) {
1153
- const batchName = activeBatch;
1154
- batchTimeout = setTimeout(async () => {
1155
- sendBatch(batchName);
1156
- }, interval);
1164
+ if (options?.batch?.[name]) {
1165
+ activeBatch = name;
1166
+ batch.push(event);
1167
+ while (queue.length > 1 && queue[1].name === name) {
1168
+ const [nextBatchItem] = queue.splice(1, 1);
1169
+ batch.push(nextBatchItem.event);
1170
+ if (batch.length >= limit) {
1171
+ return sendBatch(name);
1157
1172
  }
1158
- return;
1159
1173
  }
1160
- await send(name, event);
1161
- } catch (e2) {
1162
- if (!e2.reportedToSentry) {
1163
- Sentry3.captureException(e2);
1164
- logger2.error(e2);
1174
+ if (!batchTimeout) {
1175
+ const batchName = activeBatch;
1176
+ batchTimeout = setTimeout(async () => {
1177
+ sendBatch(batchName);
1178
+ }, interval);
1165
1179
  }
1180
+ } else {
1181
+ await send(name, event);
1166
1182
  }
1167
1183
  } else {
1168
1184
  logger2.warn("no event bound for", name);
@@ -1205,6 +1221,10 @@ function execute(channel, engine, logger2, plan, input, options = {}, onFinish =
1205
1221
  runId: plan.id
1206
1222
  }
1207
1223
  });
1224
+ const batch = {};
1225
+ if (options.batchLogs) {
1226
+ batch[WORKFLOW_LOG2] = true;
1227
+ }
1208
1228
  eventProcessor(
1209
1229
  engine,
1210
1230
  context,
@@ -1218,11 +1238,10 @@ function execute(channel, engine, logger2, plan, input, options = {}, onFinish =
1218
1238
  [WORKFLOW_ERROR2]: onRunError
1219
1239
  },
1220
1240
  {
1221
- batch: options.batchLogs ? {
1222
- [WORKFLOW_LOG2]: true
1223
- } : {},
1241
+ batch,
1224
1242
  batchInterval: options.batchInterval,
1225
- batchLimit: options.batchLimit
1243
+ batchLimit: options.batchLimit,
1244
+ timeout_ms: (options.eventTimeoutSeconds ?? 0) * 1e3 * 1.1
1226
1245
  }
1227
1246
  );
1228
1247
  const resolvers = {
@@ -1617,6 +1636,7 @@ function createServer(engine, options = {}) {
1617
1636
  }
1618
1637
  options2.timeoutRetryCount = app.options.timeoutRetryCount;
1619
1638
  options2.timeoutRetryDelay = app.options.timeoutRetryDelayMs ?? app.options.socketTimeoutSeconds;
1639
+ options2.eventTimeoutSeconds = app.options.messageTimeoutSeconds;
1620
1640
  options2.batchLogs = app.options.batchLogs;
1621
1641
  options2.batchInterval = app.options.batchInterval;
1622
1642
  options2.batchLimit = app.options.batchLimit;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openfn/ws-worker",
3
- "version": "1.20.0",
3
+ "version": "1.20.2",
4
4
  "description": "A Websocket Worker to connect Lightning to a Runtime Engine",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -23,9 +23,9 @@
23
23
  "koa-logger": "^3.2.1",
24
24
  "phoenix": "1.7.10",
25
25
  "ws": "^8.18.3",
26
- "@openfn/engine-multi": "1.9.0",
27
- "@openfn/logger": "1.1.0",
28
- "@openfn/runtime": "1.7.6",
26
+ "@openfn/engine-multi": "1.9.1",
27
+ "@openfn/logger": "1.1.1",
28
+ "@openfn/runtime": "1.7.7",
29
29
  "@openfn/lexicon": "^1.3.0"
30
30
  },
31
31
  "devDependencies": {
@@ -43,7 +43,7 @@
43
43
  "tsup": "^6.7.0",
44
44
  "typescript": "^4.9.5",
45
45
  "yargs": "^17.7.2",
46
- "@openfn/lightning-mock": "2.3.9"
46
+ "@openfn/lightning-mock": "2.3.10"
47
47
  },
48
48
  "files": [
49
49
  "dist",