@openfn/ws-worker 1.15.2 → 1.15.4
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 +5 -1
- package/dist/index.js +31 -12
- package/dist/start.js +28 -12
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# ws-worker
|
|
2
2
|
|
|
3
|
+
## 1.15.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [84bebf4]
|
|
8
|
+
- @openfn/runtime@1.7.3
|
|
9
|
+
- @openfn/engine-multi@1.6.13
|
|
10
|
+
|
|
11
|
+
## 1.15.3
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- 5688813: Allow the worker to shutdown gracefully while claims are still in-flight. Runs will be completed before the server closes
|
|
16
|
+
|
|
3
17
|
## 1.15.2
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -99,6 +99,7 @@ interface ServerApp extends Koa {
|
|
|
99
99
|
execute: ({ id, token }: ClaimRun) => Promise<void>;
|
|
100
100
|
destroy: () => void;
|
|
101
101
|
resumeWorkloop: () => void;
|
|
102
|
+
claim: () => Promise<any>;
|
|
102
103
|
}
|
|
103
104
|
declare function createServer(engine: RuntimeEngine, options?: ServerOptions): ServerApp;
|
|
104
105
|
|
|
@@ -113,6 +114,9 @@ declare const RUN_LOG = "run:log";
|
|
|
113
114
|
declare const STEP_START = "step:start";
|
|
114
115
|
declare const STEP_COMPLETE = "step:complete";
|
|
115
116
|
declare const INTERNAL_RUN_COMPLETE = "server:run-complete";
|
|
117
|
+
declare const INTERNAL_CLAIM_START = "server:claim-start";
|
|
118
|
+
declare const INTERNAL_CLAIM_COMPLETE = "server:claim-complete";
|
|
119
|
+
declare const INTERNAL_SOCKET_READY = "server:socket-ready";
|
|
116
120
|
type QueueEvents = {
|
|
117
121
|
[CLAIM]: l.ClaimPayload;
|
|
118
122
|
};
|
|
@@ -140,4 +144,4 @@ type RunReplies = {
|
|
|
140
144
|
[STEP_COMPLETE]: l.StepCompleteReply;
|
|
141
145
|
};
|
|
142
146
|
|
|
143
|
-
export { CLAIM, GET_CREDENTIAL, GET_DATACLIP, GET_PLAN, INTERNAL_RUN_COMPLETE, QueueEventReplies, QueueEvents, RUN_COMPLETE, RUN_LOG, RUN_START, RunEvents, RunReplies, STEP_COMPLETE, STEP_START, WORK_AVAILABLE, createServer as default };
|
|
147
|
+
export { CLAIM, GET_CREDENTIAL, GET_DATACLIP, GET_PLAN, INTERNAL_CLAIM_COMPLETE, INTERNAL_CLAIM_START, INTERNAL_RUN_COMPLETE, INTERNAL_SOCKET_READY, QueueEventReplies, QueueEvents, RUN_COMPLETE, RUN_LOG, RUN_START, RunEvents, RunReplies, STEP_COMPLETE, STEP_START, WORK_AVAILABLE, createServer as default };
|
package/dist/index.js
CHANGED
|
@@ -22,6 +22,9 @@ var RUN_LOG = "run:log";
|
|
|
22
22
|
var STEP_START = "step:start";
|
|
23
23
|
var STEP_COMPLETE = "step:complete";
|
|
24
24
|
var INTERNAL_RUN_COMPLETE = "server:run-complete";
|
|
25
|
+
var INTERNAL_CLAIM_START = "server:claim-start";
|
|
26
|
+
var INTERNAL_CLAIM_COMPLETE = "server:claim-complete";
|
|
27
|
+
var INTERNAL_SOCKET_READY = "server:socket-ready";
|
|
25
28
|
|
|
26
29
|
// src/api/destroy.ts
|
|
27
30
|
var destroy = async (app, logger) => {
|
|
@@ -30,13 +33,13 @@ var destroy = async (app, logger) => {
|
|
|
30
33
|
new Promise((resolve) => {
|
|
31
34
|
app.destroyed = true;
|
|
32
35
|
app.workloop?.stop("server closed");
|
|
33
|
-
app.queueChannel?.leave();
|
|
34
36
|
app.server.close(async () => {
|
|
35
37
|
resolve();
|
|
36
38
|
});
|
|
37
39
|
}),
|
|
38
40
|
new Promise(async (resolve) => {
|
|
39
|
-
await
|
|
41
|
+
await waitForRunsAndClaims(app, logger);
|
|
42
|
+
app.queueChannel?.leave();
|
|
40
43
|
await app.engine.destroy();
|
|
41
44
|
app.socket?.disconnect();
|
|
42
45
|
resolve();
|
|
@@ -44,24 +47,26 @@ var destroy = async (app, logger) => {
|
|
|
44
47
|
]);
|
|
45
48
|
logger.success("Server closed");
|
|
46
49
|
};
|
|
47
|
-
var
|
|
50
|
+
var waitForRunsAndClaims = (app, logger) => new Promise((resolve) => {
|
|
48
51
|
const log = () => {
|
|
49
52
|
logger.debug(
|
|
50
|
-
`Waiting for ${Object.keys(app.workflows).length} runs to complete...`
|
|
53
|
+
`Waiting for ${Object.keys(app.workflows).length} runs and ${Object.keys(app.openClaims).length} claims to complete...`
|
|
51
54
|
);
|
|
52
55
|
};
|
|
53
|
-
const
|
|
54
|
-
if (Object.keys(app.workflows).length === 0) {
|
|
56
|
+
const checkAllClear = () => {
|
|
57
|
+
if (Object.keys(app.workflows).length + Object.keys(app.openClaims).length === 0) {
|
|
55
58
|
logger.debug("All runs completed!");
|
|
56
|
-
app.events.off(INTERNAL_RUN_COMPLETE,
|
|
59
|
+
app.events.off(INTERNAL_RUN_COMPLETE, checkAllClear);
|
|
60
|
+
app.events.off(INTERNAL_CLAIM_COMPLETE, checkAllClear);
|
|
57
61
|
resolve();
|
|
58
62
|
} else {
|
|
59
63
|
log();
|
|
60
64
|
}
|
|
61
65
|
};
|
|
62
|
-
if (Object.keys(app.workflows).length) {
|
|
66
|
+
if (Object.keys(app.workflows).length || Object.keys(app.openClaims).length) {
|
|
63
67
|
log();
|
|
64
|
-
app.events.on(INTERNAL_RUN_COMPLETE,
|
|
68
|
+
app.events.on(INTERNAL_RUN_COMPLETE, checkAllClear);
|
|
69
|
+
app.events.on(INTERNAL_CLAIM_COMPLETE, checkAllClear);
|
|
65
70
|
} else {
|
|
66
71
|
logger.debug("No active runs detected, closing immediately");
|
|
67
72
|
resolve();
|
|
@@ -173,6 +178,7 @@ var claim = (app, logger = mockLogger, options = {}) => {
|
|
|
173
178
|
const claimId = ++claimIdGen;
|
|
174
179
|
app.openClaims[claimId] = demand;
|
|
175
180
|
logger.debug(`requesting run (capacity ${activeWorkers}/${maxWorkers})`);
|
|
181
|
+
app.events.emit(INTERNAL_CLAIM_START);
|
|
176
182
|
const start = Date.now();
|
|
177
183
|
app.queueChannel.push(CLAIM, {
|
|
178
184
|
demand,
|
|
@@ -184,6 +190,7 @@ var claim = (app, logger = mockLogger, options = {}) => {
|
|
|
184
190
|
`${podName}claimed ${runs.length} runs in ${duration}ms (${runs.length ? runs.map((r) => r.id).join(",") : "-"})`
|
|
185
191
|
);
|
|
186
192
|
if (!runs?.length) {
|
|
193
|
+
app.events.emit(INTERNAL_CLAIM_COMPLETE, { runs });
|
|
187
194
|
return reject(new Error("No runs returned"));
|
|
188
195
|
}
|
|
189
196
|
runs.forEach(async (run) => {
|
|
@@ -203,8 +210,9 @@ var claim = (app, logger = mockLogger, options = {}) => {
|
|
|
203
210
|
}
|
|
204
211
|
logger.debug(`${podName} starting run ${run.id}`);
|
|
205
212
|
app.execute(run);
|
|
206
|
-
resolve();
|
|
207
213
|
});
|
|
214
|
+
resolve();
|
|
215
|
+
app.events.emit(INTERNAL_CLAIM_COMPLETE, { runs });
|
|
208
216
|
}).receive("error", (e) => {
|
|
209
217
|
delete app.openClaims[claimId];
|
|
210
218
|
logger.error("Error on claim", e);
|
|
@@ -1180,6 +1188,7 @@ function connect(app, logger, options = {}) {
|
|
|
1180
1188
|
logger.info(` curl -X POST http://localhost:${port}/claim`);
|
|
1181
1189
|
logger.break();
|
|
1182
1190
|
}
|
|
1191
|
+
app.events.emit(INTERNAL_SOCKET_READY);
|
|
1183
1192
|
app.resumeWorkloop();
|
|
1184
1193
|
};
|
|
1185
1194
|
const onDisconnect = () => {
|
|
@@ -1205,8 +1214,10 @@ function connect(app, logger, options = {}) {
|
|
|
1205
1214
|
};
|
|
1206
1215
|
const onMessage = (event) => {
|
|
1207
1216
|
if (event === WORK_AVAILABLE) {
|
|
1208
|
-
|
|
1209
|
-
|
|
1217
|
+
if (!app.destroyed) {
|
|
1218
|
+
claim_default(app, logger, { maxWorkers: options.maxWorkflows }).catch(() => {
|
|
1219
|
+
});
|
|
1220
|
+
}
|
|
1210
1221
|
}
|
|
1211
1222
|
};
|
|
1212
1223
|
worker_queue_default(options.lightning, app.id, options.secret, logger, {
|
|
@@ -1355,6 +1366,11 @@ function createServer(engine, options = {}) {
|
|
|
1355
1366
|
ctx.status = 204;
|
|
1356
1367
|
});
|
|
1357
1368
|
});
|
|
1369
|
+
app.claim = () => {
|
|
1370
|
+
return claim_default(app, logger, {
|
|
1371
|
+
maxWorkers: options.maxWorkflows
|
|
1372
|
+
});
|
|
1373
|
+
};
|
|
1358
1374
|
app.destroy = () => destroy_default(app, logger);
|
|
1359
1375
|
app.use(router.routes());
|
|
1360
1376
|
if (options.lightning) {
|
|
@@ -1390,7 +1406,10 @@ export {
|
|
|
1390
1406
|
GET_CREDENTIAL,
|
|
1391
1407
|
GET_DATACLIP,
|
|
1392
1408
|
GET_PLAN,
|
|
1409
|
+
INTERNAL_CLAIM_COMPLETE,
|
|
1410
|
+
INTERNAL_CLAIM_START,
|
|
1393
1411
|
INTERNAL_RUN_COMPLETE,
|
|
1412
|
+
INTERNAL_SOCKET_READY,
|
|
1394
1413
|
RUN_COMPLETE,
|
|
1395
1414
|
RUN_LOG,
|
|
1396
1415
|
RUN_START,
|
package/dist/start.js
CHANGED
|
@@ -162,6 +162,9 @@ var RUN_LOG = "run:log";
|
|
|
162
162
|
var STEP_START = "step:start";
|
|
163
163
|
var STEP_COMPLETE = "step:complete";
|
|
164
164
|
var INTERNAL_RUN_COMPLETE = "server:run-complete";
|
|
165
|
+
var INTERNAL_CLAIM_START = "server:claim-start";
|
|
166
|
+
var INTERNAL_CLAIM_COMPLETE = "server:claim-complete";
|
|
167
|
+
var INTERNAL_SOCKET_READY = "server:socket-ready";
|
|
165
168
|
|
|
166
169
|
// src/api/destroy.ts
|
|
167
170
|
var destroy = async (app, logger2) => {
|
|
@@ -170,13 +173,13 @@ var destroy = async (app, logger2) => {
|
|
|
170
173
|
new Promise((resolve5) => {
|
|
171
174
|
app.destroyed = true;
|
|
172
175
|
app.workloop?.stop("server closed");
|
|
173
|
-
app.queueChannel?.leave();
|
|
174
176
|
app.server.close(async () => {
|
|
175
177
|
resolve5();
|
|
176
178
|
});
|
|
177
179
|
}),
|
|
178
180
|
new Promise(async (resolve5) => {
|
|
179
|
-
await
|
|
181
|
+
await waitForRunsAndClaims(app, logger2);
|
|
182
|
+
app.queueChannel?.leave();
|
|
180
183
|
await app.engine.destroy();
|
|
181
184
|
app.socket?.disconnect();
|
|
182
185
|
resolve5();
|
|
@@ -184,24 +187,26 @@ var destroy = async (app, logger2) => {
|
|
|
184
187
|
]);
|
|
185
188
|
logger2.success("Server closed");
|
|
186
189
|
};
|
|
187
|
-
var
|
|
190
|
+
var waitForRunsAndClaims = (app, logger2) => new Promise((resolve5) => {
|
|
188
191
|
const log = () => {
|
|
189
192
|
logger2.debug(
|
|
190
|
-
`Waiting for ${Object.keys(app.workflows).length} runs to complete...`
|
|
193
|
+
`Waiting for ${Object.keys(app.workflows).length} runs and ${Object.keys(app.openClaims).length} claims to complete...`
|
|
191
194
|
);
|
|
192
195
|
};
|
|
193
|
-
const
|
|
194
|
-
if (Object.keys(app.workflows).length === 0) {
|
|
196
|
+
const checkAllClear = () => {
|
|
197
|
+
if (Object.keys(app.workflows).length + Object.keys(app.openClaims).length === 0) {
|
|
195
198
|
logger2.debug("All runs completed!");
|
|
196
|
-
app.events.off(INTERNAL_RUN_COMPLETE,
|
|
199
|
+
app.events.off(INTERNAL_RUN_COMPLETE, checkAllClear);
|
|
200
|
+
app.events.off(INTERNAL_CLAIM_COMPLETE, checkAllClear);
|
|
197
201
|
resolve5();
|
|
198
202
|
} else {
|
|
199
203
|
log();
|
|
200
204
|
}
|
|
201
205
|
};
|
|
202
|
-
if (Object.keys(app.workflows).length) {
|
|
206
|
+
if (Object.keys(app.workflows).length || Object.keys(app.openClaims).length) {
|
|
203
207
|
log();
|
|
204
|
-
app.events.on(INTERNAL_RUN_COMPLETE,
|
|
208
|
+
app.events.on(INTERNAL_RUN_COMPLETE, checkAllClear);
|
|
209
|
+
app.events.on(INTERNAL_CLAIM_COMPLETE, checkAllClear);
|
|
205
210
|
} else {
|
|
206
211
|
logger2.debug("No active runs detected, closing immediately");
|
|
207
212
|
resolve5();
|
|
@@ -313,6 +318,7 @@ var claim = (app, logger2 = mockLogger, options = {}) => {
|
|
|
313
318
|
const claimId = ++claimIdGen;
|
|
314
319
|
app.openClaims[claimId] = demand;
|
|
315
320
|
logger2.debug(`requesting run (capacity ${activeWorkers}/${maxWorkers})`);
|
|
321
|
+
app.events.emit(INTERNAL_CLAIM_START);
|
|
316
322
|
const start = Date.now();
|
|
317
323
|
app.queueChannel.push(CLAIM, {
|
|
318
324
|
demand,
|
|
@@ -324,6 +330,7 @@ var claim = (app, logger2 = mockLogger, options = {}) => {
|
|
|
324
330
|
`${podName}claimed ${runs.length} runs in ${duration}ms (${runs.length ? runs.map((r) => r.id).join(",") : "-"})`
|
|
325
331
|
);
|
|
326
332
|
if (!runs?.length) {
|
|
333
|
+
app.events.emit(INTERNAL_CLAIM_COMPLETE, { runs });
|
|
327
334
|
return reject(new Error("No runs returned"));
|
|
328
335
|
}
|
|
329
336
|
runs.forEach(async (run2) => {
|
|
@@ -343,8 +350,9 @@ var claim = (app, logger2 = mockLogger, options = {}) => {
|
|
|
343
350
|
}
|
|
344
351
|
logger2.debug(`${podName} starting run ${run2.id}`);
|
|
345
352
|
app.execute(run2);
|
|
346
|
-
resolve5();
|
|
347
353
|
});
|
|
354
|
+
resolve5();
|
|
355
|
+
app.events.emit(INTERNAL_CLAIM_COMPLETE, { runs });
|
|
348
356
|
}).receive("error", (e) => {
|
|
349
357
|
delete app.openClaims[claimId];
|
|
350
358
|
logger2.error("Error on claim", e);
|
|
@@ -1320,6 +1328,7 @@ function connect(app, logger2, options = {}) {
|
|
|
1320
1328
|
logger2.info(` curl -X POST http://localhost:${port}/claim`);
|
|
1321
1329
|
logger2.break();
|
|
1322
1330
|
}
|
|
1331
|
+
app.events.emit(INTERNAL_SOCKET_READY);
|
|
1323
1332
|
app.resumeWorkloop();
|
|
1324
1333
|
};
|
|
1325
1334
|
const onDisconnect = () => {
|
|
@@ -1345,8 +1354,10 @@ function connect(app, logger2, options = {}) {
|
|
|
1345
1354
|
};
|
|
1346
1355
|
const onMessage = (event) => {
|
|
1347
1356
|
if (event === WORK_AVAILABLE) {
|
|
1348
|
-
|
|
1349
|
-
|
|
1357
|
+
if (!app.destroyed) {
|
|
1358
|
+
claim_default(app, logger2, { maxWorkers: options.maxWorkflows }).catch(() => {
|
|
1359
|
+
});
|
|
1360
|
+
}
|
|
1350
1361
|
}
|
|
1351
1362
|
};
|
|
1352
1363
|
worker_queue_default(options.lightning, app.id, options.secret, logger2, {
|
|
@@ -1495,6 +1506,11 @@ function createServer(engine, options = {}) {
|
|
|
1495
1506
|
ctx.status = 204;
|
|
1496
1507
|
});
|
|
1497
1508
|
});
|
|
1509
|
+
app.claim = () => {
|
|
1510
|
+
return claim_default(app, logger2, {
|
|
1511
|
+
maxWorkers: options.maxWorkflows
|
|
1512
|
+
});
|
|
1513
|
+
};
|
|
1498
1514
|
app.destroy = () => destroy_default(app, logger2);
|
|
1499
1515
|
app.use(router.routes());
|
|
1500
1516
|
if (options.lightning) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openfn/ws-worker",
|
|
3
|
-
"version": "1.15.
|
|
3
|
+
"version": "1.15.4",
|
|
4
4
|
"description": "A Websocket Worker to connect Lightning to a Runtime Engine",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -23,10 +23,10 @@
|
|
|
23
23
|
"koa-logger": "^3.2.1",
|
|
24
24
|
"phoenix": "1.7.10",
|
|
25
25
|
"ws": "^8.18.3",
|
|
26
|
-
"@openfn/engine-multi": "1.6.
|
|
26
|
+
"@openfn/engine-multi": "1.6.13",
|
|
27
27
|
"@openfn/logger": "1.0.6",
|
|
28
|
-
"@openfn/
|
|
29
|
-
"@openfn/
|
|
28
|
+
"@openfn/runtime": "1.7.3",
|
|
29
|
+
"@openfn/lexicon": "^1.2.3"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@types/koa": "^2.15.0",
|
|
@@ -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.2.
|
|
46
|
+
"@openfn/lightning-mock": "2.2.8"
|
|
47
47
|
},
|
|
48
48
|
"files": [
|
|
49
49
|
"dist",
|