@openfn/ws-worker 0.5.0 → 0.7.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 +31 -0
- package/dist/index.d.ts +22 -11
- package/dist/index.js +95 -62
- package/dist/start.js +144 -91
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# ws-worker
|
|
2
2
|
|
|
3
|
+
## 0.7.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 39af8e1: Ensure that we refer to the child of a 'run' (aka attempt) as a 'step'
|
|
8
|
+
|
|
9
|
+
## 0.6.0
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- eb10b1f: Updated start env vars and arguments
|
|
14
|
+
- 281391b: Support attemptTimeoutMs in attempt options
|
|
15
|
+
Better server logging at startup
|
|
16
|
+
Support start arguments from the environment (but prefer CLI)
|
|
17
|
+
- 2857fe6: Send the exit reason to the attempt logs
|
|
18
|
+
- Updated dependencies [281391b]
|
|
19
|
+
- @openfn/engine-multi@0.3.0
|
|
20
|
+
|
|
21
|
+
## 0.6.0
|
|
22
|
+
|
|
23
|
+
### Minor Changes
|
|
24
|
+
|
|
25
|
+
- 9b9ca0c: New worker pool engine
|
|
26
|
+
|
|
27
|
+
### Patch Changes
|
|
28
|
+
|
|
29
|
+
- Updated dependencies [0f22694]
|
|
30
|
+
- Updated dependencies [9b9ca0c]
|
|
31
|
+
- @openfn/runtime@0.2.5
|
|
32
|
+
- @openfn/engine-multi@0.3.0
|
|
33
|
+
|
|
3
34
|
## 0.5.0
|
|
4
35
|
|
|
5
36
|
### Minor Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -56,13 +56,24 @@ type Attempt = {
|
|
|
56
56
|
};
|
|
57
57
|
|
|
58
58
|
type AttemptOptions = {
|
|
59
|
+
// This is what Lightning will ssend us
|
|
60
|
+
// Note that this is the NEW terminology, so it's the timeout for the whole "attempt"
|
|
61
|
+
runTimeout?: number;
|
|
62
|
+
|
|
63
|
+
// this is the internal old terminology, which will be deprecated soon
|
|
64
|
+
attemptTimeoutMs?: number;
|
|
65
|
+
|
|
66
|
+
attemptTimeout?: number; // deprecated
|
|
67
|
+
|
|
68
|
+
// deprecated alias for timeout. Maps to "attemptTimeout" internally
|
|
59
69
|
timeout?: number;
|
|
70
|
+
|
|
60
71
|
sanitize?: SanitizePolicies;
|
|
61
72
|
};
|
|
62
73
|
|
|
63
74
|
// Internal server state for each attempt
|
|
64
75
|
type AttemptState = {
|
|
65
|
-
|
|
76
|
+
activeStep?: string;
|
|
66
77
|
activeJob?: string;
|
|
67
78
|
plan: ExecutionPlan;
|
|
68
79
|
options: AttemptOptions;
|
|
@@ -131,27 +142,27 @@ declare type AttemptLogPayload = {
|
|
|
131
142
|
level?: string;
|
|
132
143
|
source?: string;
|
|
133
144
|
job_id?: string;
|
|
134
|
-
|
|
145
|
+
step_id?: string;
|
|
135
146
|
};
|
|
136
147
|
declare type AttemptLogReply = void;
|
|
137
|
-
declare const
|
|
138
|
-
declare type
|
|
148
|
+
declare const STEP_START = "step:start";
|
|
149
|
+
declare type StepStartPayload = {
|
|
139
150
|
job_id: string;
|
|
140
|
-
|
|
151
|
+
step_id: string;
|
|
141
152
|
attempt_id?: string;
|
|
142
153
|
input_dataclip_id?: string;
|
|
143
154
|
versions: Record<string, string>;
|
|
144
155
|
};
|
|
145
|
-
declare type
|
|
146
|
-
declare const
|
|
147
|
-
declare type
|
|
156
|
+
declare type StepStartReply = void;
|
|
157
|
+
declare const STEP_COMPLETE = "step:complete";
|
|
158
|
+
declare type StepCompletePayload = ExitReason & {
|
|
148
159
|
attempt_id?: string;
|
|
149
160
|
job_id: string;
|
|
150
|
-
|
|
161
|
+
step_id: string;
|
|
151
162
|
output_dataclip?: string;
|
|
152
163
|
output_dataclip_id?: string;
|
|
153
164
|
};
|
|
154
|
-
declare type
|
|
165
|
+
declare type StepCompleteReply = void;
|
|
155
166
|
declare const INTERNAL_ATTEMPT_COMPLETE = "server:attempt-complete";
|
|
156
167
|
|
|
157
168
|
declare type Context = {
|
|
@@ -189,4 +200,4 @@ interface ServerApp extends Koa {
|
|
|
189
200
|
}
|
|
190
201
|
declare function createServer(engine: RuntimeEngine, options?: ServerOptions): ServerApp;
|
|
191
202
|
|
|
192
|
-
export { ATTEMPT_COMPLETE, ATTEMPT_LOG, ATTEMPT_START, AttemptCompletePayload, AttemptCompleteReply, AttemptLogPayload, AttemptLogReply, AttemptStartPayload, AttemptStartReply, CLAIM, ClaimAttempt, ClaimPayload, ClaimReply, GET_ATTEMPT, GET_CREDENTIAL, GET_DATACLIP, GetAttemptPayload, GetAttemptReply, GetCredentialPayload, GetCredentialReply, GetDataClipReply, GetDataclipPayload, INTERNAL_ATTEMPT_COMPLETE,
|
|
203
|
+
export { ATTEMPT_COMPLETE, ATTEMPT_LOG, ATTEMPT_START, AttemptCompletePayload, AttemptCompleteReply, AttemptLogPayload, AttemptLogReply, AttemptStartPayload, AttemptStartReply, CLAIM, ClaimAttempt, ClaimPayload, ClaimReply, GET_ATTEMPT, GET_CREDENTIAL, GET_DATACLIP, GetAttemptPayload, GetAttemptReply, GetCredentialPayload, GetCredentialReply, GetDataClipReply, GetDataclipPayload, INTERNAL_ATTEMPT_COMPLETE, STEP_COMPLETE, STEP_START, StepCompletePayload, StepCompleteReply, StepStartPayload, StepStartReply, createServer as default };
|
package/dist/index.js
CHANGED
|
@@ -15,8 +15,8 @@ var GET_DATACLIP = "fetch:dataclip";
|
|
|
15
15
|
var ATTEMPT_START = "attempt:start";
|
|
16
16
|
var ATTEMPT_COMPLETE = "attempt:complete";
|
|
17
17
|
var ATTEMPT_LOG = "attempt:log";
|
|
18
|
-
var
|
|
19
|
-
var
|
|
18
|
+
var STEP_START = "step:start";
|
|
19
|
+
var STEP_COMPLETE = "step:complete";
|
|
20
20
|
var INTERNAL_ATTEMPT_COMPLETE = "server:attempt-complete";
|
|
21
21
|
|
|
22
22
|
// src/api/destroy.ts
|
|
@@ -186,6 +186,14 @@ var mapTriggerEdgeCondition = (edge) => {
|
|
|
186
186
|
return true;
|
|
187
187
|
return condition;
|
|
188
188
|
};
|
|
189
|
+
var mapOptions = (options) => {
|
|
190
|
+
const { attemptTimeout, timeout, runTimeout, ...opts } = options;
|
|
191
|
+
const to = runTimeout || attemptTimeout || timeout;
|
|
192
|
+
if (to) {
|
|
193
|
+
opts.attemptTimeoutMs = to;
|
|
194
|
+
}
|
|
195
|
+
return opts;
|
|
196
|
+
};
|
|
189
197
|
var convert_attempt_default = (attempt) => {
|
|
190
198
|
const options = attempt.options || {};
|
|
191
199
|
const plan = {
|
|
@@ -249,7 +257,7 @@ var convert_attempt_default = (attempt) => {
|
|
|
249
257
|
plan.jobs = Object.values(nodes);
|
|
250
258
|
return {
|
|
251
259
|
plan,
|
|
252
|
-
options
|
|
260
|
+
options: mapOptions(options)
|
|
253
261
|
};
|
|
254
262
|
};
|
|
255
263
|
|
|
@@ -298,6 +306,9 @@ var create_attempt_state_default = (plan, options = {}) => {
|
|
|
298
306
|
return state;
|
|
299
307
|
};
|
|
300
308
|
|
|
309
|
+
// src/events/step-complete.ts
|
|
310
|
+
import crypto2 from "node:crypto";
|
|
311
|
+
|
|
301
312
|
// src/api/reasons.ts
|
|
302
313
|
var calculateJobExitReason = (jobId, state = { data: {} }, error) => {
|
|
303
314
|
let reason = "success";
|
|
@@ -331,18 +342,17 @@ var calculateAttemptExitReason = (state) => {
|
|
|
331
342
|
return { reason: "success", error_type: null, error_message: null };
|
|
332
343
|
};
|
|
333
344
|
|
|
334
|
-
// src/events/
|
|
335
|
-
|
|
336
|
-
function onRunComplete({ channel, state }, event, error) {
|
|
345
|
+
// src/events/step-complete.ts
|
|
346
|
+
function onStepComplete({ channel, state }, event, error) {
|
|
337
347
|
const dataclipId = crypto2.randomUUID();
|
|
338
|
-
const
|
|
348
|
+
const step_id = state.activeStep;
|
|
339
349
|
const job_id = state.activeJob;
|
|
340
350
|
if (!state.dataclips) {
|
|
341
351
|
state.dataclips = {};
|
|
342
352
|
}
|
|
343
353
|
const outputState = event.state || {};
|
|
344
354
|
state.dataclips[dataclipId] = event.state;
|
|
345
|
-
delete state.
|
|
355
|
+
delete state.activeStep;
|
|
346
356
|
delete state.activeJob;
|
|
347
357
|
state.lastDataclipId = dataclipId;
|
|
348
358
|
event.next?.forEach((nextJobId) => {
|
|
@@ -355,7 +365,7 @@ function onRunComplete({ channel, state }, event, error) {
|
|
|
355
365
|
);
|
|
356
366
|
state.reasons[job_id] = { reason, error_message, error_type };
|
|
357
367
|
const evt = {
|
|
358
|
-
|
|
368
|
+
step_id,
|
|
359
369
|
job_id,
|
|
360
370
|
output_dataclip_id: dataclipId,
|
|
361
371
|
output_dataclip: stringify_default(outputState),
|
|
@@ -366,17 +376,17 @@ function onRunComplete({ channel, state }, event, error) {
|
|
|
366
376
|
duration: event.duration,
|
|
367
377
|
thread_id: event.threadId
|
|
368
378
|
};
|
|
369
|
-
return sendEvent(channel,
|
|
379
|
+
return sendEvent(channel, STEP_COMPLETE, evt);
|
|
370
380
|
}
|
|
371
381
|
|
|
372
|
-
// src/events/
|
|
382
|
+
// src/events/step-start.ts
|
|
373
383
|
import crypto3 from "node:crypto";
|
|
374
384
|
import { timestamp } from "@openfn/logger";
|
|
375
385
|
|
|
376
386
|
// package.json
|
|
377
387
|
var package_default = {
|
|
378
388
|
name: "@openfn/ws-worker",
|
|
379
|
-
version: "0.
|
|
389
|
+
version: "0.7.0",
|
|
380
390
|
description: "A Websocket Worker to connect Lightning to a Runtime Engine",
|
|
381
391
|
main: "dist/index.js",
|
|
382
392
|
type: "module",
|
|
@@ -439,14 +449,14 @@ var package_default = {
|
|
|
439
449
|
// src/util/versions.ts
|
|
440
450
|
import { mainSymbols } from "figures";
|
|
441
451
|
var { triangleRightSmall: t } = mainSymbols;
|
|
442
|
-
var versions_default = (
|
|
452
|
+
var versions_default = (stepId, versions, adaptor) => {
|
|
443
453
|
let longest = "compiler".length;
|
|
444
454
|
for (const v in versions) {
|
|
445
455
|
longest = Math.max(v.length, longest);
|
|
446
456
|
}
|
|
447
457
|
const { node, compiler, engine, worker, runtime, ...adaptors } = versions;
|
|
448
458
|
const prefix = (str2) => ` ${t} ${str2.padEnd(longest + 4, " ")}`;
|
|
449
|
-
let str = `Versions for
|
|
459
|
+
let str = `Versions for step ${stepId}:
|
|
450
460
|
${prefix("node.js")}${versions.node || "unknown"}
|
|
451
461
|
${prefix("worker")}${versions.worker || "unknown"}
|
|
452
462
|
${prefix("engine")}${versions.engine || "unknown"}`;
|
|
@@ -460,11 +470,11 @@ ${prefix("engine")}${versions.engine || "unknown"}`;
|
|
|
460
470
|
return str;
|
|
461
471
|
};
|
|
462
472
|
|
|
463
|
-
// src/events/
|
|
464
|
-
async function
|
|
473
|
+
// src/events/step-start.ts
|
|
474
|
+
async function onStepStart(context, event) {
|
|
465
475
|
const time = (timestamp() - BigInt(1e7)).toString();
|
|
466
476
|
const { channel, state } = context;
|
|
467
|
-
state.
|
|
477
|
+
state.activeStep = crypto3.randomUUID();
|
|
468
478
|
state.activeJob = event.jobId;
|
|
469
479
|
const job = state.plan.jobs.find(({ id }) => id === event.jobId);
|
|
470
480
|
const input_dataclip_id = state.inputDataclips[event.jobId];
|
|
@@ -476,17 +486,17 @@ async function onRunStart(context, event) {
|
|
|
476
486
|
...context,
|
|
477
487
|
state: {
|
|
478
488
|
...state,
|
|
479
|
-
|
|
489
|
+
activeStep: state.activeStep
|
|
480
490
|
}
|
|
481
491
|
};
|
|
482
|
-
await sendEvent(channel,
|
|
483
|
-
|
|
492
|
+
await sendEvent(channel, STEP_START, {
|
|
493
|
+
step_id: state.activeStep,
|
|
484
494
|
job_id: state.activeJob,
|
|
485
495
|
input_dataclip_id,
|
|
486
496
|
versions
|
|
487
497
|
});
|
|
488
498
|
const versionMessage = versions_default(
|
|
489
|
-
versionLogContext.state.
|
|
499
|
+
versionLogContext.state.activeStep,
|
|
490
500
|
versions,
|
|
491
501
|
job?.adaptor
|
|
492
502
|
);
|
|
@@ -499,6 +509,57 @@ async function onRunStart(context, event) {
|
|
|
499
509
|
return;
|
|
500
510
|
}
|
|
501
511
|
|
|
512
|
+
// src/util/log-final-reason.ts
|
|
513
|
+
import { timestamp as timestamp2 } from "@openfn/logger";
|
|
514
|
+
var log_final_reason_default = async (context, reason) => {
|
|
515
|
+
const time = (timestamp2() - BigInt(1e7)).toString();
|
|
516
|
+
let message = `Run complete with status: ${reason.reason}`;
|
|
517
|
+
if (reason.reason !== "success") {
|
|
518
|
+
message += `
|
|
519
|
+
${reason.error_type}: ${reason.error_message || "unknown"}`;
|
|
520
|
+
}
|
|
521
|
+
await onJobLog(context, {
|
|
522
|
+
time,
|
|
523
|
+
message: [message],
|
|
524
|
+
level: "info",
|
|
525
|
+
name: "R/T"
|
|
526
|
+
});
|
|
527
|
+
};
|
|
528
|
+
|
|
529
|
+
// src/events/attempt-complete.ts
|
|
530
|
+
async function onWorkflowComplete(context, _event) {
|
|
531
|
+
const { state, channel, onFinish } = context;
|
|
532
|
+
const result = state.dataclips[state.lastDataclipId];
|
|
533
|
+
const reason = calculateAttemptExitReason(state);
|
|
534
|
+
await log_final_reason_default(context, reason);
|
|
535
|
+
await sendEvent(channel, ATTEMPT_COMPLETE, {
|
|
536
|
+
final_dataclip_id: state.lastDataclipId,
|
|
537
|
+
...reason
|
|
538
|
+
});
|
|
539
|
+
onFinish({ reason, state: result });
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
// src/events/attempt-error.ts
|
|
543
|
+
async function onAttemptError(context, event) {
|
|
544
|
+
const { state, channel, logger, onFinish } = context;
|
|
545
|
+
try {
|
|
546
|
+
const reason = calculateJobExitReason("", { data: {} }, event);
|
|
547
|
+
if (state.activeJob) {
|
|
548
|
+
await onJobError(context, { error: event });
|
|
549
|
+
}
|
|
550
|
+
await log_final_reason_default(context, reason);
|
|
551
|
+
await sendEvent(channel, ATTEMPT_COMPLETE, {
|
|
552
|
+
final_dataclip_id: state.lastDataclipId,
|
|
553
|
+
...reason
|
|
554
|
+
});
|
|
555
|
+
onFinish({ reason });
|
|
556
|
+
} catch (e) {
|
|
557
|
+
logger.error("ERROR in workflow-error handler:", e.message);
|
|
558
|
+
logger.error(e);
|
|
559
|
+
onFinish({});
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
502
563
|
// src/util/throttle.ts
|
|
503
564
|
var createThrottler = () => {
|
|
504
565
|
const q = [];
|
|
@@ -530,8 +591,8 @@ var throttle_default = createThrottler;
|
|
|
530
591
|
var enc = new TextDecoder("utf-8");
|
|
531
592
|
var eventMap = {
|
|
532
593
|
"workflow-start": ATTEMPT_START,
|
|
533
|
-
"job-start":
|
|
534
|
-
"job-complete":
|
|
594
|
+
"job-start": STEP_START,
|
|
595
|
+
"job-complete": STEP_COMPLETE,
|
|
535
596
|
"workflow-log": ATTEMPT_LOG,
|
|
536
597
|
"workflow-complete": ATTEMPT_COMPLETE
|
|
537
598
|
};
|
|
@@ -561,12 +622,12 @@ function execute(channel, engine, logger, plan, options = {}, onFinish = (_resul
|
|
|
561
622
|
const listeners = Object.assign(
|
|
562
623
|
{},
|
|
563
624
|
addEvent("workflow-start", throttle(onWorkflowStart)),
|
|
564
|
-
addEvent("job-start", throttle(
|
|
565
|
-
addEvent("job-complete", throttle(
|
|
625
|
+
addEvent("job-start", throttle(onStepStart)),
|
|
626
|
+
addEvent("job-complete", throttle(onStepComplete)),
|
|
566
627
|
addEvent("job-error", throttle(onJobError)),
|
|
567
628
|
addEvent("workflow-log", throttle(onJobLog)),
|
|
568
629
|
addEvent("workflow-complete", throttle(onWorkflowComplete)),
|
|
569
|
-
addEvent("workflow-error", throttle(
|
|
630
|
+
addEvent("workflow-error", throttle(onAttemptError))
|
|
570
631
|
);
|
|
571
632
|
engine.listen(plan.id, listeners);
|
|
572
633
|
const resolvers = {
|
|
@@ -584,7 +645,7 @@ function execute(channel, engine, logger, plan, options = {}, onFinish = (_resul
|
|
|
584
645
|
try {
|
|
585
646
|
engine.execute(plan, { resolvers, ...options });
|
|
586
647
|
} catch (e) {
|
|
587
|
-
|
|
648
|
+
onAttemptError(context, {
|
|
588
649
|
workflowId: plan.id,
|
|
589
650
|
message: e.message,
|
|
590
651
|
type: e.type,
|
|
@@ -602,41 +663,14 @@ var sendEvent = (channel, event, payload) => new Promise((resolve, reject) => {
|
|
|
602
663
|
function onJobError(context, event) {
|
|
603
664
|
const { state, error, jobId } = event;
|
|
604
665
|
if (state?.errors?.[jobId]?.message === error.message) {
|
|
605
|
-
return
|
|
666
|
+
return onStepComplete(context, event);
|
|
606
667
|
} else {
|
|
607
|
-
return
|
|
668
|
+
return onStepComplete(context, event, event.error);
|
|
608
669
|
}
|
|
609
670
|
}
|
|
610
671
|
function onWorkflowStart({ channel }, _event) {
|
|
611
672
|
return sendEvent(channel, ATTEMPT_START);
|
|
612
673
|
}
|
|
613
|
-
async function onWorkflowComplete({ state, channel, onFinish }, _event) {
|
|
614
|
-
const result = state.dataclips[state.lastDataclipId];
|
|
615
|
-
const reason = calculateAttemptExitReason(state);
|
|
616
|
-
await sendEvent(channel, ATTEMPT_COMPLETE, {
|
|
617
|
-
final_dataclip_id: state.lastDataclipId,
|
|
618
|
-
...reason
|
|
619
|
-
});
|
|
620
|
-
onFinish({ reason, state: result });
|
|
621
|
-
}
|
|
622
|
-
async function onWorkflowError(context, event) {
|
|
623
|
-
const { state, channel, logger, onFinish } = context;
|
|
624
|
-
try {
|
|
625
|
-
const reason = calculateJobExitReason("", { data: {} }, event);
|
|
626
|
-
if (state.activeJob) {
|
|
627
|
-
await onJobError(context, { error: event });
|
|
628
|
-
}
|
|
629
|
-
await sendEvent(channel, ATTEMPT_COMPLETE, {
|
|
630
|
-
final_dataclip_id: state.lastDataclipId,
|
|
631
|
-
...reason
|
|
632
|
-
});
|
|
633
|
-
onFinish({ reason });
|
|
634
|
-
} catch (e) {
|
|
635
|
-
logger.error("ERROR in workflow-error handler:", e.message);
|
|
636
|
-
logger.error(e);
|
|
637
|
-
onFinish({});
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
674
|
function onJobLog({ channel, state }, event) {
|
|
641
675
|
const timeInMicroseconds = BigInt(event.time) / BigInt(1e3);
|
|
642
676
|
const log = {
|
|
@@ -646,8 +680,8 @@ function onJobLog({ channel, state }, event) {
|
|
|
646
680
|
level: event.level,
|
|
647
681
|
timestamp: timeInMicroseconds.toString()
|
|
648
682
|
};
|
|
649
|
-
if (state.
|
|
650
|
-
log.
|
|
683
|
+
if (state.activeStep) {
|
|
684
|
+
log.step_id = state.activeStep;
|
|
651
685
|
}
|
|
652
686
|
return sendEvent(channel, ATTEMPT_LOG, log);
|
|
653
687
|
}
|
|
@@ -809,7 +843,6 @@ function connect(app, logger, options = {}) {
|
|
|
809
843
|
function createServer(engine, options = {}) {
|
|
810
844
|
const logger = options.logger || createMockLogger2();
|
|
811
845
|
const port = options.port || DEFAULT_PORT;
|
|
812
|
-
logger.debug("Starting server");
|
|
813
846
|
const app = new Koa();
|
|
814
847
|
app.id = humanId({ separator: "-", capitalize: false });
|
|
815
848
|
const router = new Router();
|
|
@@ -824,7 +857,7 @@ function createServer(engine, options = {}) {
|
|
|
824
857
|
app.workflows = {};
|
|
825
858
|
app.destroyed = false;
|
|
826
859
|
app.server = app.listen(port);
|
|
827
|
-
logger.success(`
|
|
860
|
+
logger.success(`Worker ${app.id} listening on ${port}`);
|
|
828
861
|
process.send?.("READY");
|
|
829
862
|
router.get("/livez", healthcheck_default);
|
|
830
863
|
router.get("/", healthcheck_default);
|
|
@@ -902,7 +935,7 @@ export {
|
|
|
902
935
|
GET_CREDENTIAL,
|
|
903
936
|
GET_DATACLIP,
|
|
904
937
|
INTERNAL_ATTEMPT_COMPLETE,
|
|
905
|
-
|
|
906
|
-
|
|
938
|
+
STEP_COMPLETE,
|
|
939
|
+
STEP_START,
|
|
907
940
|
src_default as default
|
|
908
941
|
};
|
package/dist/start.js
CHANGED
|
@@ -4890,7 +4890,10 @@ var resolvers_default = {
|
|
|
4890
4890
|
// src/mock/runtime-engine.ts
|
|
4891
4891
|
var helpers = {
|
|
4892
4892
|
fn: (f) => (s) => f(s),
|
|
4893
|
-
wait: (duration) => (s) => new Promise((resolve5) => setTimeout(() => resolve5(s), duration))
|
|
4893
|
+
wait: (duration) => (s) => new Promise((resolve5) => setTimeout(() => resolve5(s), duration)),
|
|
4894
|
+
err: () => {
|
|
4895
|
+
throw new Error("test_err");
|
|
4896
|
+
}
|
|
4894
4897
|
};
|
|
4895
4898
|
async function createMock() {
|
|
4896
4899
|
const activeWorkflows = {};
|
|
@@ -5001,8 +5004,8 @@ var GET_DATACLIP = "fetch:dataclip";
|
|
|
5001
5004
|
var ATTEMPT_START = "attempt:start";
|
|
5002
5005
|
var ATTEMPT_COMPLETE = "attempt:complete";
|
|
5003
5006
|
var ATTEMPT_LOG = "attempt:log";
|
|
5004
|
-
var
|
|
5005
|
-
var
|
|
5007
|
+
var STEP_START = "step:start";
|
|
5008
|
+
var STEP_COMPLETE = "step:complete";
|
|
5006
5009
|
var INTERNAL_ATTEMPT_COMPLETE = "server:attempt-complete";
|
|
5007
5010
|
|
|
5008
5011
|
// src/api/destroy.ts
|
|
@@ -5172,6 +5175,14 @@ var mapTriggerEdgeCondition = (edge) => {
|
|
|
5172
5175
|
return true;
|
|
5173
5176
|
return condition;
|
|
5174
5177
|
};
|
|
5178
|
+
var mapOptions = (options) => {
|
|
5179
|
+
const { attemptTimeout, timeout, runTimeout, ...opts } = options;
|
|
5180
|
+
const to = runTimeout || attemptTimeout || timeout;
|
|
5181
|
+
if (to) {
|
|
5182
|
+
opts.attemptTimeoutMs = to;
|
|
5183
|
+
}
|
|
5184
|
+
return opts;
|
|
5185
|
+
};
|
|
5175
5186
|
var convert_attempt_default = (attempt) => {
|
|
5176
5187
|
const options = attempt.options || {};
|
|
5177
5188
|
const plan = {
|
|
@@ -5235,7 +5246,7 @@ var convert_attempt_default = (attempt) => {
|
|
|
5235
5246
|
plan.jobs = Object.values(nodes);
|
|
5236
5247
|
return {
|
|
5237
5248
|
plan,
|
|
5238
|
-
options
|
|
5249
|
+
options: mapOptions(options)
|
|
5239
5250
|
};
|
|
5240
5251
|
};
|
|
5241
5252
|
|
|
@@ -5284,6 +5295,9 @@ var create_attempt_state_default = (plan, options = {}) => {
|
|
|
5284
5295
|
return state;
|
|
5285
5296
|
};
|
|
5286
5297
|
|
|
5298
|
+
// src/events/step-complete.ts
|
|
5299
|
+
import crypto3 from "node:crypto";
|
|
5300
|
+
|
|
5287
5301
|
// src/api/reasons.ts
|
|
5288
5302
|
var calculateJobExitReason = (jobId, state = { data: {} }, error) => {
|
|
5289
5303
|
let reason = "success";
|
|
@@ -5317,18 +5331,17 @@ var calculateAttemptExitReason = (state) => {
|
|
|
5317
5331
|
return { reason: "success", error_type: null, error_message: null };
|
|
5318
5332
|
};
|
|
5319
5333
|
|
|
5320
|
-
// src/events/
|
|
5321
|
-
|
|
5322
|
-
function onRunComplete({ channel, state }, event, error) {
|
|
5334
|
+
// src/events/step-complete.ts
|
|
5335
|
+
function onStepComplete({ channel, state }, event, error) {
|
|
5323
5336
|
const dataclipId = crypto3.randomUUID();
|
|
5324
|
-
const
|
|
5337
|
+
const step_id = state.activeStep;
|
|
5325
5338
|
const job_id = state.activeJob;
|
|
5326
5339
|
if (!state.dataclips) {
|
|
5327
5340
|
state.dataclips = {};
|
|
5328
5341
|
}
|
|
5329
5342
|
const outputState = event.state || {};
|
|
5330
5343
|
state.dataclips[dataclipId] = event.state;
|
|
5331
|
-
delete state.
|
|
5344
|
+
delete state.activeStep;
|
|
5332
5345
|
delete state.activeJob;
|
|
5333
5346
|
state.lastDataclipId = dataclipId;
|
|
5334
5347
|
event.next?.forEach((nextJobId) => {
|
|
@@ -5341,7 +5354,7 @@ function onRunComplete({ channel, state }, event, error) {
|
|
|
5341
5354
|
);
|
|
5342
5355
|
state.reasons[job_id] = { reason, error_message, error_type };
|
|
5343
5356
|
const evt = {
|
|
5344
|
-
|
|
5357
|
+
step_id,
|
|
5345
5358
|
job_id,
|
|
5346
5359
|
output_dataclip_id: dataclipId,
|
|
5347
5360
|
output_dataclip: stringify_default(outputState),
|
|
@@ -5352,17 +5365,17 @@ function onRunComplete({ channel, state }, event, error) {
|
|
|
5352
5365
|
duration: event.duration,
|
|
5353
5366
|
thread_id: event.threadId
|
|
5354
5367
|
};
|
|
5355
|
-
return sendEvent(channel,
|
|
5368
|
+
return sendEvent(channel, STEP_COMPLETE, evt);
|
|
5356
5369
|
}
|
|
5357
5370
|
|
|
5358
|
-
// src/events/
|
|
5371
|
+
// src/events/step-start.ts
|
|
5359
5372
|
import crypto4 from "node:crypto";
|
|
5360
5373
|
import { timestamp } from "@openfn/logger";
|
|
5361
5374
|
|
|
5362
5375
|
// package.json
|
|
5363
5376
|
var package_default = {
|
|
5364
5377
|
name: "@openfn/ws-worker",
|
|
5365
|
-
version: "0.
|
|
5378
|
+
version: "0.7.0",
|
|
5366
5379
|
description: "A Websocket Worker to connect Lightning to a Runtime Engine",
|
|
5367
5380
|
main: "dist/index.js",
|
|
5368
5381
|
type: "module",
|
|
@@ -5425,14 +5438,14 @@ var package_default = {
|
|
|
5425
5438
|
// src/util/versions.ts
|
|
5426
5439
|
import { mainSymbols } from "figures";
|
|
5427
5440
|
var { triangleRightSmall: t } = mainSymbols;
|
|
5428
|
-
var versions_default = (
|
|
5441
|
+
var versions_default = (stepId, versions, adaptor) => {
|
|
5429
5442
|
let longest = "compiler".length;
|
|
5430
5443
|
for (const v in versions) {
|
|
5431
5444
|
longest = Math.max(v.length, longest);
|
|
5432
5445
|
}
|
|
5433
5446
|
const { node, compiler, engine, worker, runtime, ...adaptors } = versions;
|
|
5434
5447
|
const prefix = (str2) => ` ${t} ${str2.padEnd(longest + 4, " ")}`;
|
|
5435
|
-
let str = `Versions for
|
|
5448
|
+
let str = `Versions for step ${stepId}:
|
|
5436
5449
|
${prefix("node.js")}${versions.node || "unknown"}
|
|
5437
5450
|
${prefix("worker")}${versions.worker || "unknown"}
|
|
5438
5451
|
${prefix("engine")}${versions.engine || "unknown"}`;
|
|
@@ -5446,11 +5459,11 @@ ${prefix("engine")}${versions.engine || "unknown"}`;
|
|
|
5446
5459
|
return str;
|
|
5447
5460
|
};
|
|
5448
5461
|
|
|
5449
|
-
// src/events/
|
|
5450
|
-
async function
|
|
5462
|
+
// src/events/step-start.ts
|
|
5463
|
+
async function onStepStart(context, event) {
|
|
5451
5464
|
const time = (timestamp() - BigInt(1e7)).toString();
|
|
5452
5465
|
const { channel, state } = context;
|
|
5453
|
-
state.
|
|
5466
|
+
state.activeStep = crypto4.randomUUID();
|
|
5454
5467
|
state.activeJob = event.jobId;
|
|
5455
5468
|
const job = state.plan.jobs.find(({ id }) => id === event.jobId);
|
|
5456
5469
|
const input_dataclip_id = state.inputDataclips[event.jobId];
|
|
@@ -5462,17 +5475,17 @@ async function onRunStart(context, event) {
|
|
|
5462
5475
|
...context,
|
|
5463
5476
|
state: {
|
|
5464
5477
|
...state,
|
|
5465
|
-
|
|
5478
|
+
activeStep: state.activeStep
|
|
5466
5479
|
}
|
|
5467
5480
|
};
|
|
5468
|
-
await sendEvent(channel,
|
|
5469
|
-
|
|
5481
|
+
await sendEvent(channel, STEP_START, {
|
|
5482
|
+
step_id: state.activeStep,
|
|
5470
5483
|
job_id: state.activeJob,
|
|
5471
5484
|
input_dataclip_id,
|
|
5472
5485
|
versions
|
|
5473
5486
|
});
|
|
5474
5487
|
const versionMessage = versions_default(
|
|
5475
|
-
versionLogContext.state.
|
|
5488
|
+
versionLogContext.state.activeStep,
|
|
5476
5489
|
versions,
|
|
5477
5490
|
job?.adaptor
|
|
5478
5491
|
);
|
|
@@ -5485,6 +5498,57 @@ async function onRunStart(context, event) {
|
|
|
5485
5498
|
return;
|
|
5486
5499
|
}
|
|
5487
5500
|
|
|
5501
|
+
// src/util/log-final-reason.ts
|
|
5502
|
+
import { timestamp as timestamp2 } from "@openfn/logger";
|
|
5503
|
+
var log_final_reason_default = async (context, reason) => {
|
|
5504
|
+
const time = (timestamp2() - BigInt(1e7)).toString();
|
|
5505
|
+
let message = `Run complete with status: ${reason.reason}`;
|
|
5506
|
+
if (reason.reason !== "success") {
|
|
5507
|
+
message += `
|
|
5508
|
+
${reason.error_type}: ${reason.error_message || "unknown"}`;
|
|
5509
|
+
}
|
|
5510
|
+
await onJobLog(context, {
|
|
5511
|
+
time,
|
|
5512
|
+
message: [message],
|
|
5513
|
+
level: "info",
|
|
5514
|
+
name: "R/T"
|
|
5515
|
+
});
|
|
5516
|
+
};
|
|
5517
|
+
|
|
5518
|
+
// src/events/attempt-complete.ts
|
|
5519
|
+
async function onWorkflowComplete(context, _event) {
|
|
5520
|
+
const { state, channel, onFinish } = context;
|
|
5521
|
+
const result = state.dataclips[state.lastDataclipId];
|
|
5522
|
+
const reason = calculateAttemptExitReason(state);
|
|
5523
|
+
await log_final_reason_default(context, reason);
|
|
5524
|
+
await sendEvent(channel, ATTEMPT_COMPLETE, {
|
|
5525
|
+
final_dataclip_id: state.lastDataclipId,
|
|
5526
|
+
...reason
|
|
5527
|
+
});
|
|
5528
|
+
onFinish({ reason, state: result });
|
|
5529
|
+
}
|
|
5530
|
+
|
|
5531
|
+
// src/events/attempt-error.ts
|
|
5532
|
+
async function onAttemptError(context, event) {
|
|
5533
|
+
const { state, channel, logger: logger2, onFinish } = context;
|
|
5534
|
+
try {
|
|
5535
|
+
const reason = calculateJobExitReason("", { data: {} }, event);
|
|
5536
|
+
if (state.activeJob) {
|
|
5537
|
+
await onJobError(context, { error: event });
|
|
5538
|
+
}
|
|
5539
|
+
await log_final_reason_default(context, reason);
|
|
5540
|
+
await sendEvent(channel, ATTEMPT_COMPLETE, {
|
|
5541
|
+
final_dataclip_id: state.lastDataclipId,
|
|
5542
|
+
...reason
|
|
5543
|
+
});
|
|
5544
|
+
onFinish({ reason });
|
|
5545
|
+
} catch (e) {
|
|
5546
|
+
logger2.error("ERROR in workflow-error handler:", e.message);
|
|
5547
|
+
logger2.error(e);
|
|
5548
|
+
onFinish({});
|
|
5549
|
+
}
|
|
5550
|
+
}
|
|
5551
|
+
|
|
5488
5552
|
// src/util/throttle.ts
|
|
5489
5553
|
var createThrottler = () => {
|
|
5490
5554
|
const q = [];
|
|
@@ -5516,8 +5580,8 @@ var throttle_default = createThrottler;
|
|
|
5516
5580
|
var enc = new TextDecoder("utf-8");
|
|
5517
5581
|
var eventMap = {
|
|
5518
5582
|
"workflow-start": ATTEMPT_START,
|
|
5519
|
-
"job-start":
|
|
5520
|
-
"job-complete":
|
|
5583
|
+
"job-start": STEP_START,
|
|
5584
|
+
"job-complete": STEP_COMPLETE,
|
|
5521
5585
|
"workflow-log": ATTEMPT_LOG,
|
|
5522
5586
|
"workflow-complete": ATTEMPT_COMPLETE
|
|
5523
5587
|
};
|
|
@@ -5547,12 +5611,12 @@ function execute(channel, engine, logger2, plan, options = {}, onFinish = (_resu
|
|
|
5547
5611
|
const listeners = Object.assign(
|
|
5548
5612
|
{},
|
|
5549
5613
|
addEvent("workflow-start", throttle(onWorkflowStart)),
|
|
5550
|
-
addEvent("job-start", throttle(
|
|
5551
|
-
addEvent("job-complete", throttle(
|
|
5614
|
+
addEvent("job-start", throttle(onStepStart)),
|
|
5615
|
+
addEvent("job-complete", throttle(onStepComplete)),
|
|
5552
5616
|
addEvent("job-error", throttle(onJobError)),
|
|
5553
5617
|
addEvent("workflow-log", throttle(onJobLog)),
|
|
5554
5618
|
addEvent("workflow-complete", throttle(onWorkflowComplete)),
|
|
5555
|
-
addEvent("workflow-error", throttle(
|
|
5619
|
+
addEvent("workflow-error", throttle(onAttemptError))
|
|
5556
5620
|
);
|
|
5557
5621
|
engine.listen(plan.id, listeners);
|
|
5558
5622
|
const resolvers = {
|
|
@@ -5570,7 +5634,7 @@ function execute(channel, engine, logger2, plan, options = {}, onFinish = (_resu
|
|
|
5570
5634
|
try {
|
|
5571
5635
|
engine.execute(plan, { resolvers, ...options });
|
|
5572
5636
|
} catch (e) {
|
|
5573
|
-
|
|
5637
|
+
onAttemptError(context, {
|
|
5574
5638
|
workflowId: plan.id,
|
|
5575
5639
|
message: e.message,
|
|
5576
5640
|
type: e.type,
|
|
@@ -5588,41 +5652,14 @@ var sendEvent = (channel, event, payload) => new Promise((resolve5, reject) => {
|
|
|
5588
5652
|
function onJobError(context, event) {
|
|
5589
5653
|
const { state, error, jobId } = event;
|
|
5590
5654
|
if (state?.errors?.[jobId]?.message === error.message) {
|
|
5591
|
-
return
|
|
5655
|
+
return onStepComplete(context, event);
|
|
5592
5656
|
} else {
|
|
5593
|
-
return
|
|
5657
|
+
return onStepComplete(context, event, event.error);
|
|
5594
5658
|
}
|
|
5595
5659
|
}
|
|
5596
5660
|
function onWorkflowStart({ channel }, _event) {
|
|
5597
5661
|
return sendEvent(channel, ATTEMPT_START);
|
|
5598
5662
|
}
|
|
5599
|
-
async function onWorkflowComplete({ state, channel, onFinish }, _event) {
|
|
5600
|
-
const result = state.dataclips[state.lastDataclipId];
|
|
5601
|
-
const reason = calculateAttemptExitReason(state);
|
|
5602
|
-
await sendEvent(channel, ATTEMPT_COMPLETE, {
|
|
5603
|
-
final_dataclip_id: state.lastDataclipId,
|
|
5604
|
-
...reason
|
|
5605
|
-
});
|
|
5606
|
-
onFinish({ reason, state: result });
|
|
5607
|
-
}
|
|
5608
|
-
async function onWorkflowError(context, event) {
|
|
5609
|
-
const { state, channel, logger: logger2, onFinish } = context;
|
|
5610
|
-
try {
|
|
5611
|
-
const reason = calculateJobExitReason("", { data: {} }, event);
|
|
5612
|
-
if (state.activeJob) {
|
|
5613
|
-
await onJobError(context, { error: event });
|
|
5614
|
-
}
|
|
5615
|
-
await sendEvent(channel, ATTEMPT_COMPLETE, {
|
|
5616
|
-
final_dataclip_id: state.lastDataclipId,
|
|
5617
|
-
...reason
|
|
5618
|
-
});
|
|
5619
|
-
onFinish({ reason });
|
|
5620
|
-
} catch (e) {
|
|
5621
|
-
logger2.error("ERROR in workflow-error handler:", e.message);
|
|
5622
|
-
logger2.error(e);
|
|
5623
|
-
onFinish({});
|
|
5624
|
-
}
|
|
5625
|
-
}
|
|
5626
5663
|
function onJobLog({ channel, state }, event) {
|
|
5627
5664
|
const timeInMicroseconds = BigInt(event.time) / BigInt(1e3);
|
|
5628
5665
|
const log = {
|
|
@@ -5632,8 +5669,8 @@ function onJobLog({ channel, state }, event) {
|
|
|
5632
5669
|
level: event.level,
|
|
5633
5670
|
timestamp: timeInMicroseconds.toString()
|
|
5634
5671
|
};
|
|
5635
|
-
if (state.
|
|
5636
|
-
log.
|
|
5672
|
+
if (state.activeStep) {
|
|
5673
|
+
log.step_id = state.activeStep;
|
|
5637
5674
|
}
|
|
5638
5675
|
return sendEvent(channel, ATTEMPT_LOG, log);
|
|
5639
5676
|
}
|
|
@@ -5795,7 +5832,6 @@ function connect(app, logger2, options = {}) {
|
|
|
5795
5832
|
function createServer(engine, options = {}) {
|
|
5796
5833
|
const logger2 = options.logger || createMockLogger2();
|
|
5797
5834
|
const port = options.port || DEFAULT_PORT;
|
|
5798
|
-
logger2.debug("Starting server");
|
|
5799
5835
|
const app = new Koa();
|
|
5800
5836
|
app.id = humanId({ separator: "-", capitalize: false });
|
|
5801
5837
|
const router = new Router();
|
|
@@ -5810,7 +5846,7 @@ function createServer(engine, options = {}) {
|
|
|
5810
5846
|
app.workflows = {};
|
|
5811
5847
|
app.destroyed = false;
|
|
5812
5848
|
app.server = app.listen(port);
|
|
5813
|
-
logger2.success(`
|
|
5849
|
+
logger2.success(`Worker ${app.id} listening on ${port}`);
|
|
5814
5850
|
process.send?.("READY");
|
|
5815
5851
|
router.get("/livez", healthcheck_default);
|
|
5816
5852
|
router.get("/", healthcheck_default);
|
|
@@ -5879,30 +5915,37 @@ var server_default = createServer;
|
|
|
5879
5915
|
|
|
5880
5916
|
// src/start.ts
|
|
5881
5917
|
var {
|
|
5918
|
+
WORKER_BACKOFF,
|
|
5919
|
+
WORKER_CAPACITY,
|
|
5920
|
+
WORKER_LIGHTNING_SERVICE_URL,
|
|
5921
|
+
WORKER_LOG_LEVEL,
|
|
5922
|
+
WORKER_MAX_RUN_DURATION_SECONDS,
|
|
5923
|
+
WORKER_MAX_RUN_MEMORY_MB,
|
|
5924
|
+
WORKER_PORT,
|
|
5882
5925
|
WORKER_REPO_DIR,
|
|
5883
5926
|
WORKER_SECRET,
|
|
5884
|
-
|
|
5885
|
-
STATE_PROPS_TO_REMOVE
|
|
5927
|
+
WORKER_STATE_PROPS_TO_REMOVE
|
|
5886
5928
|
} = process.env;
|
|
5887
5929
|
var args = yargs_default(hideBin(process.argv)).command("server", "Start a ws-worker server").option("port", {
|
|
5888
5930
|
alias: "p",
|
|
5889
|
-
description: "Port to run the server on",
|
|
5931
|
+
description: "Port to run the server on. Env: WORKER_PORT",
|
|
5890
5932
|
type: "number",
|
|
5891
|
-
default: 2222
|
|
5933
|
+
default: WORKER_PORT || 2222
|
|
5892
5934
|
}).option("lightning", {
|
|
5893
|
-
alias: "l",
|
|
5894
|
-
description: 'Base url to Lightning websocket endpoint, eg, ws://localhost:4000/worker. Set to "mock" to use the default mock server',
|
|
5895
|
-
default: "ws://localhost:4000/worker"
|
|
5935
|
+
alias: ["l", "lightning-service-url"],
|
|
5936
|
+
description: 'Base url to Lightning websocket endpoint, eg, ws://localhost:4000/worker. Set to "mock" to use the default mock server. Env: WORKER_LIGHTNING_SERVICE_URL',
|
|
5937
|
+
default: WORKER_LIGHTNING_SERVICE_URL || "ws://localhost:4000/worker"
|
|
5896
5938
|
}).option("repo-dir", {
|
|
5897
5939
|
alias: "d",
|
|
5898
|
-
description: "Path to the runtime repo (where modules will be installed)",
|
|
5940
|
+
description: "Path to the runtime repo (where modules will be installed). Env: WORKER_REPO_DIR",
|
|
5899
5941
|
default: WORKER_REPO_DIR
|
|
5900
5942
|
}).option("secret", {
|
|
5901
5943
|
alias: "s",
|
|
5902
|
-
description: "Worker secret (comes from WORKER_SECRET by default)"
|
|
5944
|
+
description: "Worker secret. (comes from WORKER_SECRET by default). Env: WORKER_SECRET",
|
|
5945
|
+
default: WORKER_SECRET
|
|
5903
5946
|
}).option("log", {
|
|
5904
|
-
description: "
|
|
5905
|
-
default: "
|
|
5947
|
+
description: "Set the log level for stdout (default to info, set to debug for verbose output). Env: WORKER_LOG_LEVEL",
|
|
5948
|
+
default: WORKER_LOG_LEVEL || "debug",
|
|
5906
5949
|
type: "string"
|
|
5907
5950
|
}).option("loop", {
|
|
5908
5951
|
description: "Disable the claims loop",
|
|
@@ -5913,20 +5956,25 @@ var args = yargs_default(hideBin(process.argv)).command("server", "Start a ws-wo
|
|
|
5913
5956
|
default: false,
|
|
5914
5957
|
type: "boolean"
|
|
5915
5958
|
}).option("backoff", {
|
|
5916
|
-
description: "Claim backoff rules: min/max (
|
|
5917
|
-
default: "1/10"
|
|
5959
|
+
description: "Claim backoff rules: min/max (in seconds). Env: WORKER_BACKOFF",
|
|
5960
|
+
default: WORKER_BACKOFF || "1/10"
|
|
5918
5961
|
}).option("capacity", {
|
|
5919
|
-
description: "max concurrent workers",
|
|
5920
|
-
default: 5,
|
|
5962
|
+
description: "max concurrent workers. Env: WORKER_CAPACITY",
|
|
5963
|
+
default: WORKER_CAPACITY ? parseInt(WORKER_CAPACITY) : 5,
|
|
5921
5964
|
type: "number"
|
|
5922
5965
|
}).option("state-props-to-remove", {
|
|
5923
|
-
description: "A list of properties to remove from the final state returned by a job",
|
|
5924
|
-
default:
|
|
5966
|
+
description: "A list of properties to remove from the final state returned by a job. Env: WORKER_STATE_PROPS_TO_REMOVE",
|
|
5967
|
+
default: WORKER_STATE_PROPS_TO_REMOVE ?? ["configuration", "response"],
|
|
5925
5968
|
type: "array"
|
|
5926
5969
|
}).option("run-memory", {
|
|
5927
|
-
description: "Maximum memory allocated to a single run, in mb",
|
|
5970
|
+
description: "Maximum memory allocated to a single run, in mb. Env: WORKER_MAX_RUN_MEMORY_MB",
|
|
5971
|
+
type: "number",
|
|
5972
|
+
default: WORKER_MAX_RUN_MEMORY_MB ? parseInt(WORKER_MAX_RUN_MEMORY_MB) : 500
|
|
5973
|
+
}).option("max-run-duration-seconds", {
|
|
5974
|
+
alias: "t",
|
|
5975
|
+
description: "Default attempt timeout for the server, in seconds. Env: WORKER_MAX_RUN_DURATION_SECONDS",
|
|
5928
5976
|
type: "number",
|
|
5929
|
-
default:
|
|
5977
|
+
default: WORKER_MAX_RUN_DURATION_SECONDS || 60 * 5
|
|
5930
5978
|
}).parse();
|
|
5931
5979
|
var logger = createLogger("SRV", { level: args.log });
|
|
5932
5980
|
if (args.lightning === "mock") {
|
|
@@ -5935,15 +5983,13 @@ if (args.lightning === "mock") {
|
|
|
5935
5983
|
args.secret = "abdefg";
|
|
5936
5984
|
}
|
|
5937
5985
|
} else if (!args.secret) {
|
|
5938
|
-
|
|
5939
|
-
|
|
5940
|
-
process.exit(1);
|
|
5941
|
-
}
|
|
5942
|
-
args.secret = WORKER_SECRET;
|
|
5986
|
+
logger.error("WORKER_SECRET is not set");
|
|
5987
|
+
process.exit(1);
|
|
5943
5988
|
}
|
|
5944
5989
|
var [minBackoff, maxBackoff] = args.backoff.split("/").map((n) => parseInt(n, 10) * 1e3);
|
|
5945
5990
|
function engineReady(engine) {
|
|
5946
|
-
|
|
5991
|
+
logger.debug("Creating worker server...");
|
|
5992
|
+
const workerOptions = {
|
|
5947
5993
|
port: args.port,
|
|
5948
5994
|
lightning: args.lightning,
|
|
5949
5995
|
logger,
|
|
@@ -5954,7 +6000,10 @@ function engineReady(engine) {
|
|
|
5954
6000
|
max: maxBackoff
|
|
5955
6001
|
},
|
|
5956
6002
|
maxWorkflows: args.capacity
|
|
5957
|
-
}
|
|
6003
|
+
};
|
|
6004
|
+
const { logger: _l, secret: _s, ...humanOptions } = workerOptions;
|
|
6005
|
+
logger.debug("Worker options:", humanOptions);
|
|
6006
|
+
server_default(engine, workerOptions);
|
|
5958
6007
|
}
|
|
5959
6008
|
if (args.mock) {
|
|
5960
6009
|
runtime_engine_default().then((engine) => {
|
|
@@ -5962,13 +6011,17 @@ if (args.mock) {
|
|
|
5962
6011
|
engineReady(engine);
|
|
5963
6012
|
});
|
|
5964
6013
|
} else {
|
|
5965
|
-
|
|
6014
|
+
const engineOptions = {
|
|
5966
6015
|
repoDir: args.repoDir,
|
|
5967
6016
|
memoryLimitMb: args.runMemory,
|
|
5968
6017
|
maxWorkers: args.capacity,
|
|
5969
|
-
statePropsToRemove: args.statePropsToRemove
|
|
5970
|
-
|
|
5971
|
-
|
|
6018
|
+
statePropsToRemove: args.statePropsToRemove,
|
|
6019
|
+
attemptTimeoutMs: args.maxRunDurationSeconds * 1e3
|
|
6020
|
+
};
|
|
6021
|
+
logger.debug("Creating runtime engine...");
|
|
6022
|
+
logger.debug("Engine options:", engineOptions);
|
|
6023
|
+
createRTE(engineOptions).then((engine) => {
|
|
6024
|
+
logger.debug("Engine created!");
|
|
5972
6025
|
engineReady(engine);
|
|
5973
6026
|
});
|
|
5974
6027
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openfn/ws-worker",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "A Websocket Worker to connect Lightning to a Runtime Engine",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -22,9 +22,9 @@
|
|
|
22
22
|
"koa-logger": "^3.2.1",
|
|
23
23
|
"phoenix": "^1.7.7",
|
|
24
24
|
"ws": "^8.14.1",
|
|
25
|
-
"@openfn/engine-multi": "0.
|
|
26
|
-
"@openfn/
|
|
27
|
-
"@openfn/
|
|
25
|
+
"@openfn/engine-multi": "0.3.0",
|
|
26
|
+
"@openfn/logger": "0.0.19",
|
|
27
|
+
"@openfn/runtime": "0.2.5"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@types/koa": "^2.13.5",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"tsup": "^6.2.3",
|
|
42
42
|
"typescript": "^4.6.4",
|
|
43
43
|
"yargs": "^17.6.2",
|
|
44
|
-
"@openfn/lightning-mock": "1.1.
|
|
44
|
+
"@openfn/lightning-mock": "1.1.11"
|
|
45
45
|
},
|
|
46
46
|
"files": [
|
|
47
47
|
"dist",
|