@openfn/ws-worker 0.2.6 → 0.2.9
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 +27 -0
- package/README.md +1 -1
- package/dist/index.d.ts +94 -11
- package/dist/index.js +30 -14
- package/dist/start.js +83 -85
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# ws-worker
|
|
2
2
|
|
|
3
|
+
## 0.2.9
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 54d0017: Start ws-worker using node (not pnpm) by default
|
|
8
|
+
- 6f78b7a: Add env var for WORKER_REPO_DIR
|
|
9
|
+
- Updated dependencies [4a17048]
|
|
10
|
+
- @openfn/engine-multi@0.2.0
|
|
11
|
+
- @openfn/runtime@0.2.0
|
|
12
|
+
|
|
13
|
+
## 0.2.8
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- Tweak typings
|
|
18
|
+
|
|
19
|
+
## 0.2.7
|
|
20
|
+
|
|
21
|
+
### Patch Changes
|
|
22
|
+
|
|
23
|
+
- d542aa9: worker: leave attempt channel when finished working
|
|
24
|
+
- Updated dependencies [793d523]
|
|
25
|
+
- Updated dependencies [857c42b]
|
|
26
|
+
- Updated dependencies [f17fb4a]
|
|
27
|
+
- @openfn/engine-multi@0.1.11
|
|
28
|
+
- @openfn/runtime@0.1.4
|
|
29
|
+
|
|
3
30
|
## 0.2.6
|
|
4
31
|
|
|
5
32
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -48,7 +48,7 @@ You can start a dev server (which rebuilds on save) by running:
|
|
|
48
48
|
pnpm start:watch
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
-
This will wrap a real runtime engine into the server
|
|
51
|
+
This will wrap a real runtime engine into the server. It will rebuild when the Worker Engine code changes (although you'll have to `pnpm build:watch` in `runtime-manager`). This will use the repo at `WORKER_REPO_DIR` (or a default path in /tmp)
|
|
52
52
|
|
|
53
53
|
### Disabling auto-fetch
|
|
54
54
|
|
package/dist/index.d.ts
CHANGED
|
@@ -17,6 +17,40 @@ type ExitReason = {
|
|
|
17
17
|
error_type: string | null;
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
+
type Node = {
|
|
21
|
+
id: string;
|
|
22
|
+
body?: string;
|
|
23
|
+
adaptor?: string;
|
|
24
|
+
credential_id?: any; // TODO tighten this up, string or object
|
|
25
|
+
type?: 'webhook' | 'cron'; // trigger only
|
|
26
|
+
state?: any; // Initial state / defaults
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
interface Edge {
|
|
30
|
+
id: string;
|
|
31
|
+
source_job_id?: string;
|
|
32
|
+
source_trigger_id?: string;
|
|
33
|
+
target_job_id: string;
|
|
34
|
+
name?: string;
|
|
35
|
+
condition?: string;
|
|
36
|
+
error_path?: boolean;
|
|
37
|
+
errors?: any;
|
|
38
|
+
enabled?: boolean;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// An attempt object returned by Lightning
|
|
42
|
+
type Attempt = {
|
|
43
|
+
id: string;
|
|
44
|
+
dataclip_id: string;
|
|
45
|
+
starting_node_id: string;
|
|
46
|
+
|
|
47
|
+
triggers: Node[];
|
|
48
|
+
jobs: Node[];
|
|
49
|
+
edges: Edge[];
|
|
50
|
+
|
|
51
|
+
options?: AttemptOptions;
|
|
52
|
+
};
|
|
53
|
+
|
|
20
54
|
type AttemptOptions = {
|
|
21
55
|
timeout?: number;
|
|
22
56
|
sanitize?: SanitizePolicies;
|
|
@@ -45,13 +79,6 @@ type ReceiveHook = {
|
|
|
45
79
|
) => ReceiveHook;
|
|
46
80
|
};
|
|
47
81
|
|
|
48
|
-
// export declare class Socket extends PhxSocket {
|
|
49
|
-
// constructor(endpoint: string, options: { params: any });
|
|
50
|
-
// onOpen(callback: () => void): void;
|
|
51
|
-
// connect(): void;
|
|
52
|
-
// channel(channelName: string, params: any): Channel;
|
|
53
|
-
// }
|
|
54
|
-
|
|
55
82
|
interface Channel extends Channel$1 {
|
|
56
83
|
// on: (event: string, fn: (evt: any) => void) => void;
|
|
57
84
|
|
|
@@ -64,13 +91,69 @@ declare type Context = {
|
|
|
64
91
|
channel: Channel;
|
|
65
92
|
state: AttemptState;
|
|
66
93
|
logger: Logger;
|
|
67
|
-
|
|
94
|
+
onFinish: (result: any) => void;
|
|
68
95
|
};
|
|
69
96
|
|
|
70
|
-
declare
|
|
97
|
+
declare const CLAIM = "claim";
|
|
98
|
+
declare type ClaimPayload = {
|
|
99
|
+
demand?: number;
|
|
100
|
+
};
|
|
101
|
+
declare type ClaimReply = {
|
|
102
|
+
attempts: Array<ClaimAttempt>;
|
|
103
|
+
};
|
|
104
|
+
declare type ClaimAttempt = {
|
|
71
105
|
id: string;
|
|
72
106
|
token: string;
|
|
73
107
|
};
|
|
108
|
+
declare const GET_ATTEMPT = "fetch:attempt";
|
|
109
|
+
declare type GetAttemptPayload = void;
|
|
110
|
+
declare type GetAttemptReply = Attempt;
|
|
111
|
+
declare const GET_CREDENTIAL = "fetch:credential";
|
|
112
|
+
declare type GetCredentialPayload = {
|
|
113
|
+
id: string;
|
|
114
|
+
};
|
|
115
|
+
declare type GetCredentialReply = {};
|
|
116
|
+
declare const GET_DATACLIP = "fetch:dataclip";
|
|
117
|
+
declare type GetDataclipPayload = {
|
|
118
|
+
id: string;
|
|
119
|
+
};
|
|
120
|
+
declare type GetDataClipReply = Uint8Array;
|
|
121
|
+
declare const ATTEMPT_START = "attempt:start";
|
|
122
|
+
declare type AttemptStartPayload = void;
|
|
123
|
+
declare type AttemptStartReply = {};
|
|
124
|
+
declare const ATTEMPT_COMPLETE = "attempt:complete";
|
|
125
|
+
declare type AttemptCompletePayload = ExitReason & {
|
|
126
|
+
final_dataclip_id?: string;
|
|
127
|
+
};
|
|
128
|
+
declare type AttemptCompleteReply = undefined;
|
|
129
|
+
declare const ATTEMPT_LOG = "attempt:log";
|
|
130
|
+
declare type AttemptLogPayload = {
|
|
131
|
+
message: Array<string | object>;
|
|
132
|
+
timestamp: string;
|
|
133
|
+
attempt_id: string;
|
|
134
|
+
level?: string;
|
|
135
|
+
source?: string;
|
|
136
|
+
job_id?: string;
|
|
137
|
+
run_id?: string;
|
|
138
|
+
};
|
|
139
|
+
declare type AttemptLogReply = void;
|
|
140
|
+
declare const RUN_START = "run:start";
|
|
141
|
+
declare type RunStartPayload = {
|
|
142
|
+
job_id: string;
|
|
143
|
+
run_id: string;
|
|
144
|
+
attempt_id?: string;
|
|
145
|
+
input_dataclip_id?: string;
|
|
146
|
+
};
|
|
147
|
+
declare type RunStartReply = void;
|
|
148
|
+
declare const RUN_COMPLETE = "run:complete";
|
|
149
|
+
declare type RunCompletePayload = ExitReason & {
|
|
150
|
+
attempt_id?: string;
|
|
151
|
+
job_id: string;
|
|
152
|
+
run_id: string;
|
|
153
|
+
output_dataclip?: string;
|
|
154
|
+
output_dataclip_id?: string;
|
|
155
|
+
};
|
|
156
|
+
declare type RunCompleteReply = void;
|
|
74
157
|
|
|
75
158
|
declare type ServerOptions = {
|
|
76
159
|
maxWorkflows?: number;
|
|
@@ -89,10 +172,10 @@ interface ServerApp extends Koa {
|
|
|
89
172
|
socket: any;
|
|
90
173
|
channel: Channel;
|
|
91
174
|
workflows: Record<string, true | Context>;
|
|
92
|
-
execute: ({ id, token }:
|
|
175
|
+
execute: ({ id, token }: ClaimAttempt) => Promise<void>;
|
|
93
176
|
destroy: () => void;
|
|
94
177
|
killWorkloop?: () => void;
|
|
95
178
|
}
|
|
96
179
|
declare function createServer(engine: RuntimeEngine, options?: ServerOptions): ServerApp;
|
|
97
180
|
|
|
98
|
-
export { createServer as default };
|
|
181
|
+
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, RUN_COMPLETE, RUN_START, RunCompletePayload, RunCompleteReply, RunStartPayload, RunStartReply, createServer as default };
|
package/dist/index.js
CHANGED
|
@@ -286,11 +286,11 @@ var eventMap = {
|
|
|
286
286
|
"workflow-log": ATTEMPT_LOG,
|
|
287
287
|
"workflow-complete": ATTEMPT_COMPLETE
|
|
288
288
|
};
|
|
289
|
-
function execute(channel, engine, logger, plan, options = {},
|
|
289
|
+
function execute(channel, engine, logger, plan, options = {}, onFinish = (_result) => {
|
|
290
290
|
}) {
|
|
291
291
|
logger.info("executing ", plan.id);
|
|
292
292
|
const state = create_attempt_state_default(plan, options);
|
|
293
|
-
const context = { channel, state, logger,
|
|
293
|
+
const context = { channel, state, logger, onFinish };
|
|
294
294
|
const addEvent = (eventName, handler) => {
|
|
295
295
|
const wrappedFn = async (event) => {
|
|
296
296
|
const lightningEvent = eventMap[eventName] ?? eventName;
|
|
@@ -337,7 +337,8 @@ function execute(channel, engine, logger, plan, options = {}, onComplete = (_res
|
|
|
337
337
|
onWorkflowError(context, {
|
|
338
338
|
workflowId: plan.id,
|
|
339
339
|
message: e.message,
|
|
340
|
-
type: e.type
|
|
340
|
+
type: e.type,
|
|
341
|
+
severity: e.severity
|
|
341
342
|
});
|
|
342
343
|
}
|
|
343
344
|
});
|
|
@@ -398,22 +399,27 @@ function onJobComplete({ channel, state }, event, error) {
|
|
|
398
399
|
function onWorkflowStart({ channel }, _event) {
|
|
399
400
|
return sendEvent(channel, ATTEMPT_START);
|
|
400
401
|
}
|
|
401
|
-
async function onWorkflowComplete({ state, channel,
|
|
402
|
+
async function onWorkflowComplete({ state, channel, onFinish }, _event) {
|
|
402
403
|
const result = state.dataclips[state.lastDataclipId];
|
|
403
404
|
const reason = calculateAttemptExitReason(state);
|
|
404
405
|
await sendEvent(channel, ATTEMPT_COMPLETE, {
|
|
405
406
|
final_dataclip_id: state.lastDataclipId,
|
|
406
407
|
...reason
|
|
407
408
|
});
|
|
408
|
-
|
|
409
|
+
onFinish({ reason, state: result });
|
|
409
410
|
}
|
|
410
|
-
async function onWorkflowError({ state, channel,
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
411
|
+
async function onWorkflowError({ state, channel, logger, onFinish }, event) {
|
|
412
|
+
try {
|
|
413
|
+
const reason = calculateJobExitReason("", { data: {} }, event);
|
|
414
|
+
await sendEvent(channel, ATTEMPT_COMPLETE, {
|
|
415
|
+
final_dataclip_id: state.lastDataclipId,
|
|
416
|
+
...reason
|
|
417
|
+
});
|
|
418
|
+
onFinish({ reason });
|
|
419
|
+
} catch (e) {
|
|
420
|
+
logger.error("ERROR in workflow-error handler:", e.message);
|
|
421
|
+
logger.error(e);
|
|
422
|
+
}
|
|
417
423
|
}
|
|
418
424
|
function onJobLog({ channel, state }, event) {
|
|
419
425
|
const timeInMicroseconds = BigInt(event.time) / BigInt(1e3);
|
|
@@ -603,8 +609,9 @@ function createServer(engine, options = {}) {
|
|
|
603
609
|
plan,
|
|
604
610
|
options: options2
|
|
605
611
|
} = await attempt_default(app.socket, token, id, logger);
|
|
606
|
-
const
|
|
612
|
+
const onFinish = () => {
|
|
607
613
|
delete app.workflows[id];
|
|
614
|
+
attemptChannel.leave();
|
|
608
615
|
};
|
|
609
616
|
const context = execute(
|
|
610
617
|
attemptChannel,
|
|
@@ -612,7 +619,7 @@ function createServer(engine, options = {}) {
|
|
|
612
619
|
logger,
|
|
613
620
|
plan,
|
|
614
621
|
options2,
|
|
615
|
-
|
|
622
|
+
onFinish
|
|
616
623
|
);
|
|
617
624
|
app.workflows[id] = context;
|
|
618
625
|
} else {
|
|
@@ -654,5 +661,14 @@ var server_default = createServer;
|
|
|
654
661
|
// src/index.ts
|
|
655
662
|
var src_default = server_default;
|
|
656
663
|
export {
|
|
664
|
+
ATTEMPT_COMPLETE,
|
|
665
|
+
ATTEMPT_LOG,
|
|
666
|
+
ATTEMPT_START,
|
|
667
|
+
CLAIM,
|
|
668
|
+
GET_ATTEMPT,
|
|
669
|
+
GET_CREDENTIAL,
|
|
670
|
+
GET_DATACLIP,
|
|
671
|
+
RUN_COMPLETE,
|
|
672
|
+
RUN_START,
|
|
657
673
|
src_default as default
|
|
658
674
|
};
|
package/dist/start.js
CHANGED
|
@@ -4864,8 +4864,8 @@ import createLogger from "@openfn/logger";
|
|
|
4864
4864
|
import createRTE from "@openfn/engine-multi";
|
|
4865
4865
|
|
|
4866
4866
|
// src/mock/runtime-engine.ts
|
|
4867
|
-
import crypto from "node:crypto";
|
|
4868
4867
|
import { EventEmitter } from "node:events";
|
|
4868
|
+
import run from "@openfn/runtime";
|
|
4869
4869
|
|
|
4870
4870
|
// src/mock/resolvers.ts
|
|
4871
4871
|
var mockResolveCredential = (_credId) => new Promise(
|
|
@@ -4887,6 +4887,10 @@ var resolvers_default = {
|
|
|
4887
4887
|
};
|
|
4888
4888
|
|
|
4889
4889
|
// src/mock/runtime-engine.ts
|
|
4890
|
+
var helpers = {
|
|
4891
|
+
fn: (f) => (s) => f(s),
|
|
4892
|
+
wait: (duration) => (s) => new Promise((resolve5) => setTimeout(() => resolve5(s), duration))
|
|
4893
|
+
};
|
|
4890
4894
|
async function createMock() {
|
|
4891
4895
|
const activeWorkflows = {};
|
|
4892
4896
|
const bus = new EventEmitter();
|
|
@@ -4902,73 +4906,59 @@ async function createMock() {
|
|
|
4902
4906
|
const listen = (planId, events) => {
|
|
4903
4907
|
listeners[planId] = events;
|
|
4904
4908
|
};
|
|
4905
|
-
const
|
|
4906
|
-
const { id, expression, configuration, adaptor } = job;
|
|
4907
|
-
if (!expression && !adaptor) {
|
|
4908
|
-
return initialState;
|
|
4909
|
-
}
|
|
4910
|
-
const runId = crypto.randomUUID();
|
|
4911
|
-
const jobId = id;
|
|
4912
|
-
if (typeof configuration === "string") {
|
|
4913
|
-
await resolvers.credential?.(configuration);
|
|
4914
|
-
}
|
|
4915
|
-
const info = (...message) => {
|
|
4916
|
-
dispatch("workflow-log", {
|
|
4917
|
-
workflowId,
|
|
4918
|
-
message,
|
|
4919
|
-
level: "info",
|
|
4920
|
-
time: (BigInt(Date.now()) * BigInt(1e3)).toString(),
|
|
4921
|
-
name: "mck"
|
|
4922
|
-
});
|
|
4923
|
-
};
|
|
4924
|
-
dispatch("job-start", { workflowId, jobId, runId });
|
|
4925
|
-
info("Running job " + jobId);
|
|
4926
|
-
let nextState = initialState;
|
|
4927
|
-
if (expression?.startsWith?.("wait@")) {
|
|
4928
|
-
const [_, delay] = expression.split("@");
|
|
4929
|
-
nextState = initialState;
|
|
4930
|
-
await new Promise((resolve5) => {
|
|
4931
|
-
setTimeout(() => resolve5(), parseInt(delay));
|
|
4932
|
-
});
|
|
4933
|
-
} else {
|
|
4934
|
-
try {
|
|
4935
|
-
nextState = JSON.parse(expression);
|
|
4936
|
-
info("Parsing expression as JSON state");
|
|
4937
|
-
info(nextState);
|
|
4938
|
-
} catch (e) {
|
|
4939
|
-
nextState = initialState;
|
|
4940
|
-
}
|
|
4941
|
-
}
|
|
4942
|
-
dispatch("job-complete", {
|
|
4943
|
-
workflowId,
|
|
4944
|
-
jobId,
|
|
4945
|
-
state: nextState,
|
|
4946
|
-
runId,
|
|
4947
|
-
next: []
|
|
4948
|
-
});
|
|
4949
|
-
return nextState;
|
|
4950
|
-
};
|
|
4951
|
-
const execute2 = (xplan, options = {
|
|
4909
|
+
const execute2 = async (xplan, options = {
|
|
4952
4910
|
resolvers: resolvers_default
|
|
4953
4911
|
}) => {
|
|
4954
|
-
|
|
4955
|
-
throw new Error("test error");
|
|
4956
|
-
}
|
|
4957
|
-
const { id, jobs, initialState } = xplan;
|
|
4958
|
-
const workflowId = id;
|
|
4912
|
+
const { id, jobs } = xplan;
|
|
4959
4913
|
activeWorkflows[id] = true;
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
|
|
4914
|
+
for (const job of jobs) {
|
|
4915
|
+
if (typeof job.configuration === "string") {
|
|
4916
|
+
job.configuration = await options.resolvers?.credential?.(
|
|
4917
|
+
job.configuration
|
|
4918
|
+
);
|
|
4919
|
+
}
|
|
4920
|
+
if (typeof job.expression === "string" && !job.expression.match(/export default \[/)) {
|
|
4921
|
+
job.expression = `export default [${job.expression}];`;
|
|
4922
|
+
}
|
|
4923
|
+
}
|
|
4924
|
+
const jobLogger = {
|
|
4925
|
+
log: (...args2) => {
|
|
4926
|
+
dispatch("workflow-log", {
|
|
4927
|
+
workflowId: id,
|
|
4928
|
+
level: "info",
|
|
4929
|
+
json: true,
|
|
4930
|
+
message: args2,
|
|
4931
|
+
time: Date.now()
|
|
4932
|
+
});
|
|
4933
|
+
}
|
|
4934
|
+
};
|
|
4935
|
+
const opts = {
|
|
4936
|
+
strict: false,
|
|
4937
|
+
jobLogger,
|
|
4938
|
+
...options,
|
|
4939
|
+
globals: helpers,
|
|
4940
|
+
callbacks: {
|
|
4941
|
+
notify: (name, payload) => {
|
|
4942
|
+
dispatch(name, {
|
|
4943
|
+
workflowId: id,
|
|
4944
|
+
...payload
|
|
4945
|
+
});
|
|
4966
4946
|
}
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
4947
|
+
}
|
|
4948
|
+
};
|
|
4949
|
+
setTimeout(async () => {
|
|
4950
|
+
dispatch("workflow-start", { workflowId: id });
|
|
4951
|
+
try {
|
|
4952
|
+
await run(xplan, void 0, opts);
|
|
4953
|
+
} catch (e) {
|
|
4954
|
+
dispatch("workflow-error", {
|
|
4955
|
+
workflowId: id,
|
|
4956
|
+
type: e.name,
|
|
4957
|
+
message: e.message
|
|
4958
|
+
});
|
|
4959
|
+
}
|
|
4960
|
+
delete activeWorkflows[id];
|
|
4961
|
+
dispatch("workflow-complete", { workflowId: id });
|
|
4972
4962
|
}, 1);
|
|
4973
4963
|
};
|
|
4974
4964
|
const getStatus = () => {
|
|
@@ -5105,10 +5095,10 @@ var startWorkloop = (app, logger2, minBackoff2, maxBackoff2, maxWorkers) => {
|
|
|
5105
5095
|
var workloop_default = startWorkloop;
|
|
5106
5096
|
|
|
5107
5097
|
// src/api/execute.ts
|
|
5108
|
-
import
|
|
5098
|
+
import crypto2 from "node:crypto";
|
|
5109
5099
|
|
|
5110
5100
|
// src/util/convert-attempt.ts
|
|
5111
|
-
import
|
|
5101
|
+
import crypto from "node:crypto";
|
|
5112
5102
|
var conditions = {
|
|
5113
5103
|
on_job_success: "!state.errors",
|
|
5114
5104
|
on_job_failure: "state.errors",
|
|
@@ -5153,7 +5143,7 @@ var convert_attempt_default = (attempt) => {
|
|
|
5153
5143
|
}
|
|
5154
5144
|
if (attempt.jobs?.length) {
|
|
5155
5145
|
attempt.jobs.forEach((job) => {
|
|
5156
|
-
const id = job.id ||
|
|
5146
|
+
const id = job.id || crypto.randomUUID();
|
|
5157
5147
|
nodes[id] = {
|
|
5158
5148
|
id,
|
|
5159
5149
|
configuration: job.credential_id,
|
|
@@ -5274,11 +5264,11 @@ var eventMap = {
|
|
|
5274
5264
|
"workflow-log": ATTEMPT_LOG,
|
|
5275
5265
|
"workflow-complete": ATTEMPT_COMPLETE
|
|
5276
5266
|
};
|
|
5277
|
-
function execute(channel, engine, logger2, plan, options = {},
|
|
5267
|
+
function execute(channel, engine, logger2, plan, options = {}, onFinish = (_result) => {
|
|
5278
5268
|
}) {
|
|
5279
5269
|
logger2.info("executing ", plan.id);
|
|
5280
5270
|
const state = create_attempt_state_default(plan, options);
|
|
5281
|
-
const context = { channel, state, logger: logger2,
|
|
5271
|
+
const context = { channel, state, logger: logger2, onFinish };
|
|
5282
5272
|
const addEvent = (eventName, handler) => {
|
|
5283
5273
|
const wrappedFn = async (event) => {
|
|
5284
5274
|
const lightningEvent = eventMap[eventName] ?? eventName;
|
|
@@ -5325,7 +5315,8 @@ function execute(channel, engine, logger2, plan, options = {}, onComplete = (_re
|
|
|
5325
5315
|
onWorkflowError(context, {
|
|
5326
5316
|
workflowId: plan.id,
|
|
5327
5317
|
message: e.message,
|
|
5328
|
-
type: e.type
|
|
5318
|
+
type: e.type,
|
|
5319
|
+
severity: e.severity
|
|
5329
5320
|
});
|
|
5330
5321
|
}
|
|
5331
5322
|
});
|
|
@@ -5335,7 +5326,7 @@ var sendEvent = (channel, event, payload) => new Promise((resolve5, reject) => {
|
|
|
5335
5326
|
channel.push(event, payload).receive("error", reject).receive("timeout", () => reject(new Error("timeout"))).receive("ok", resolve5);
|
|
5336
5327
|
});
|
|
5337
5328
|
function onJobStart({ channel, state }, event) {
|
|
5338
|
-
state.activeRun =
|
|
5329
|
+
state.activeRun = crypto2.randomUUID();
|
|
5339
5330
|
state.activeJob = event.jobId;
|
|
5340
5331
|
const input_dataclip_id = state.inputDataclips[event.jobId];
|
|
5341
5332
|
return sendEvent(channel, RUN_START, {
|
|
@@ -5353,7 +5344,7 @@ function onJobError(context, event) {
|
|
|
5353
5344
|
}
|
|
5354
5345
|
}
|
|
5355
5346
|
function onJobComplete({ channel, state }, event, error) {
|
|
5356
|
-
const dataclipId =
|
|
5347
|
+
const dataclipId = crypto2.randomUUID();
|
|
5357
5348
|
const run_id = state.activeRun;
|
|
5358
5349
|
const job_id = state.activeJob;
|
|
5359
5350
|
if (!state.dataclips) {
|
|
@@ -5386,22 +5377,27 @@ function onJobComplete({ channel, state }, event, error) {
|
|
|
5386
5377
|
function onWorkflowStart({ channel }, _event) {
|
|
5387
5378
|
return sendEvent(channel, ATTEMPT_START);
|
|
5388
5379
|
}
|
|
5389
|
-
async function onWorkflowComplete({ state, channel,
|
|
5380
|
+
async function onWorkflowComplete({ state, channel, onFinish }, _event) {
|
|
5390
5381
|
const result = state.dataclips[state.lastDataclipId];
|
|
5391
5382
|
const reason = calculateAttemptExitReason(state);
|
|
5392
5383
|
await sendEvent(channel, ATTEMPT_COMPLETE, {
|
|
5393
5384
|
final_dataclip_id: state.lastDataclipId,
|
|
5394
5385
|
...reason
|
|
5395
5386
|
});
|
|
5396
|
-
|
|
5387
|
+
onFinish({ reason, state: result });
|
|
5397
5388
|
}
|
|
5398
|
-
async function onWorkflowError({ state, channel,
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
|
|
5403
|
-
|
|
5404
|
-
|
|
5389
|
+
async function onWorkflowError({ state, channel, logger: logger2, onFinish }, event) {
|
|
5390
|
+
try {
|
|
5391
|
+
const reason = calculateJobExitReason("", { data: {} }, event);
|
|
5392
|
+
await sendEvent(channel, ATTEMPT_COMPLETE, {
|
|
5393
|
+
final_dataclip_id: state.lastDataclipId,
|
|
5394
|
+
...reason
|
|
5395
|
+
});
|
|
5396
|
+
onFinish({ reason });
|
|
5397
|
+
} catch (e) {
|
|
5398
|
+
logger2.error("ERROR in workflow-error handler:", e.message);
|
|
5399
|
+
logger2.error(e);
|
|
5400
|
+
}
|
|
5405
5401
|
}
|
|
5406
5402
|
function onJobLog({ channel, state }, event) {
|
|
5407
5403
|
const timeInMicroseconds = BigInt(event.time) / BigInt(1e3);
|
|
@@ -5591,8 +5587,9 @@ function createServer(engine, options = {}) {
|
|
|
5591
5587
|
plan,
|
|
5592
5588
|
options: options2
|
|
5593
5589
|
} = await attempt_default(app.socket, token, id, logger2);
|
|
5594
|
-
const
|
|
5590
|
+
const onFinish = () => {
|
|
5595
5591
|
delete app.workflows[id];
|
|
5592
|
+
attemptChannel.leave();
|
|
5596
5593
|
};
|
|
5597
5594
|
const context = execute(
|
|
5598
5595
|
attemptChannel,
|
|
@@ -5600,7 +5597,7 @@ function createServer(engine, options = {}) {
|
|
|
5600
5597
|
logger2,
|
|
5601
5598
|
plan,
|
|
5602
5599
|
options2,
|
|
5603
|
-
|
|
5600
|
+
onFinish
|
|
5604
5601
|
);
|
|
5605
5602
|
app.workflows[id] = context;
|
|
5606
5603
|
} else {
|
|
@@ -5640,6 +5637,7 @@ function createServer(engine, options = {}) {
|
|
|
5640
5637
|
var server_default = createServer;
|
|
5641
5638
|
|
|
5642
5639
|
// src/start.ts
|
|
5640
|
+
var { WORKER_REPO_DIR, WORKER_SECRET } = process.env;
|
|
5643
5641
|
var args = yargs_default(hideBin(process.argv)).command("server", "Start a ws-worker server").option("port", {
|
|
5644
5642
|
alias: "p",
|
|
5645
5643
|
description: "Port to run the server on",
|
|
@@ -5651,7 +5649,8 @@ var args = yargs_default(hideBin(process.argv)).command("server", "Start a ws-wo
|
|
|
5651
5649
|
default: "ws://localhost:4000/worker"
|
|
5652
5650
|
}).option("repo-dir", {
|
|
5653
5651
|
alias: "d",
|
|
5654
|
-
description: "Path to the runtime repo (where modules will be installed)"
|
|
5652
|
+
description: "Path to the runtime repo (where modules will be installed)",
|
|
5653
|
+
default: WORKER_REPO_DIR
|
|
5655
5654
|
}).option("secret", {
|
|
5656
5655
|
alias: "s",
|
|
5657
5656
|
description: "Worker secret (comes from WORKER_SECRET by default)"
|
|
@@ -5682,7 +5681,6 @@ if (args.lightning === "mock") {
|
|
|
5682
5681
|
args.secret = "abdefg";
|
|
5683
5682
|
}
|
|
5684
5683
|
} else if (!args.secret) {
|
|
5685
|
-
const { WORKER_SECRET } = process.env;
|
|
5686
5684
|
if (!WORKER_SECRET) {
|
|
5687
5685
|
logger.error("WORKER_SECRET is not set");
|
|
5688
5686
|
process.exit(1);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openfn/ws-worker",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.9",
|
|
4
4
|
"description": "A Websocket Worker to connect Lightning to a Runtime Engine",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
"koa-logger": "^3.2.1",
|
|
22
22
|
"phoenix": "^1.7.7",
|
|
23
23
|
"ws": "^8.14.1",
|
|
24
|
-
"@openfn/engine-multi": "0.
|
|
24
|
+
"@openfn/engine-multi": "0.2.0",
|
|
25
25
|
"@openfn/logger": "0.0.19",
|
|
26
|
-
"@openfn/runtime": "0.
|
|
26
|
+
"@openfn/runtime": "0.2.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/koa": "^2.13.5",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"tsup": "^6.2.3",
|
|
41
41
|
"typescript": "^4.6.4",
|
|
42
42
|
"yargs": "^17.6.2",
|
|
43
|
-
"@openfn/lightning-mock": "1.
|
|
43
|
+
"@openfn/lightning-mock": "1.1.2"
|
|
44
44
|
},
|
|
45
45
|
"files": [
|
|
46
46
|
"dist",
|