@5minds/node-red-contrib-processcube 0.14.0-feature-7fe136-lyw00gz5 → 0.14.0-feature-612fd3-lywvsveq

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.
@@ -11,6 +11,7 @@ services:
11
11
  - FLOWS=/nodered/node-red-contrib-processcube-flows.json
12
12
  volumes:
13
13
  - ./nodered/:/nodered/
14
+ - ./examples/:/examples/
14
15
 
15
16
  engine:
16
17
  image: 5minds/processcube_engine:2024-1
@@ -19,6 +20,7 @@ services:
19
20
  volumes:
20
21
  - ./processes:/processes:ro
21
22
  environment:
23
+ application__name: Engine for Node-RED contrib
22
24
  iam__baseUrl: http://authority:11560
23
25
  iam__allowAnonymousRootAccess: true
24
26
  command: --seed-dir=/processes --port 8000
@@ -25,7 +25,7 @@ module.exports = function(RED) {
25
25
  }
26
26
  };
27
27
 
28
- eventEmitter.emit(`error-${externalTaskId}`, msg.payload);
28
+ eventEmitter.emit(`handle-${externalTaskId}`, msg, true);
29
29
 
30
30
  node.send(msg);
31
31
  });
@@ -11,24 +11,16 @@ function showStatus(node, msgCounter) {
11
11
  }
12
12
  }
13
13
 
14
- function decrCounter(msgCounter) {
15
- msgCounter--;
16
-
17
- if (msgCounter < 0) {
18
- msgCounter = 0;
19
- }
20
-
21
- return msgCounter;
22
- }
14
+ const started_external_tasks = {};
23
15
 
24
16
  module.exports = function(RED) {
25
17
  function ExternalTaskInput(config) {
26
18
  RED.nodes.createNode(this,config);
27
19
  var node = this;
28
- var msgCounter = 0;
29
20
  var flowContext = node.context().flow;
30
21
  var nodeContext = node.context();
31
22
 
23
+
32
24
  this.engine = this.server = RED.nodes.getNode(config.engine);
33
25
 
34
26
  const engineUrl = this.engine?.url || process.env.ENGINE_URL || 'http://engine:8000';
@@ -50,30 +42,57 @@ module.exports = function(RED) {
50
42
  client.externalTasks.subscribeToExternalTaskTopic(
51
43
  config.topic,
52
44
  async (payload, externalTask) => {
53
- msgCounter++;
54
-
45
+
55
46
  return await new Promise((resolve, reject) => {
56
-
57
- // TODO: once ist 2x gebunden
58
- eventEmitter.once(`finish-${externalTask.flowNodeInstanceId}`, (result) => {
59
- msgCounter = decrCounter(msgCounter);
60
47
 
61
- showStatus(node, msgCounter);
48
+ const handleFinishTask = (msg) => {
49
+ if (msg.externalTaskId) {
50
+ delete started_external_tasks[msg.externalTaskId];
51
+ }
52
+
53
+ showStatus(node, Object.keys(started_external_tasks).length);
54
+
55
+ let result = RED.util.encodeObject(msg.payload);
56
+
62
57
  resolve(result);
63
- });
58
+ };
59
+
60
+ const handleErrorTask = (msg) => {
61
+ if (msg.externalTaskId) {
62
+ delete started_external_tasks[msg.externalTaskId];
63
+ }
64
64
 
65
- eventEmitter.once(`error-${externalTask.flowNodeInstanceId}`, (msg) => {
66
- msgCounter = decrCounter(msgCounter);
67
- showStatus(node, msgCounter);
65
+ showStatus(node, Object.keys(started_external_tasks).length);
68
66
 
69
- var result = msg.payload ? msg.payload : msg;
67
+ let result = RED.util.encodeObject(msg);
70
68
 
71
69
  reject(result);
70
+ };
71
+
72
+ eventEmitter.once(`handle-${externalTask.flowNodeInstanceId}`, (msg, isError = false) => {
73
+ node.log(`handle event for external task ${externalTask.flowNodeInstanceId} and process it with msg._msgid ${msg._msgid} and isError ${isError}`);
74
+
75
+ if (isError) {
76
+ handleErrorTask(msg);
77
+ } else {
78
+ handleFinishTask(msg);
79
+ }
72
80
  });
73
81
 
74
- showStatus(node, msgCounter);
82
+ started_external_tasks[externalTask.flowNodeInstanceId] = externalTask;
83
+
84
+ showStatus(node, Object.keys(started_external_tasks).length);
85
+
86
+ let msg = {
87
+ _msgid: RED.util.generateId(),
88
+ topic: externalTask.topic,
89
+ payload: payload,
90
+ externalTaskId: externalTask.flowNodeInstanceId
91
+ };
75
92
 
76
- node.send({topic: externalTask.topic, payload: payload, externalTaskId: externalTask.flowNodeInstanceId});
93
+ node.log(`Received external task ${externalTask.flowNodeInstanceId} and process it with msg._msgid ${msg._msgid}`);
94
+
95
+ node.send(msg);
77
96
  });
78
97
  },
79
98
  ).then(async externalTaskWorker => {
@@ -83,9 +102,32 @@ module.exports = function(RED) {
83
102
  node.server.registerOnIdentityChanged((identity) => {
84
103
  externalTaskWorker.identity = identity;
85
104
  });
86
- await externalTaskWorker.start();
87
105
 
88
- node.on("close", async () => {
106
+ // export type WorkerErrorHandler = (errorType: 'fetchAndLock' | 'extendLock' | 'processExternalTask' | 'finishExternalTask', error: Error, externalTask?: ExternalTask<any>) => void;
107
+ externalTaskWorker.onWorkerError((errorType, error, externalTask) => {
108
+ switch (errorType) {
109
+ case 'extendLock':
110
+ case 'finishExternalTask':
111
+ case 'processExternalTask':
112
+ node.error(`Worker error ${errorType} for external task ${externalTask.flowNodeInstanceId}: ${error.message}`);
113
+
114
+ externalTaskWorker.stop();
115
+
116
+ if (externalTask) {
117
+ delete started_external_tasks[externalTask.flowNodeInstanceId];
118
+ }
119
+
120
+ showStatus(node, Object.keys(started_external_tasks).length);
121
+ break;
122
+ default:
123
+ node.error(`Worker error ${errorType}: ${error.message}`);
124
+ break;
125
+ }
126
+ });
127
+
128
+ externalTaskWorker.start();
129
+
130
+ node.on("close", () => {
89
131
  try {
90
132
  externalTaskWorker.stop();
91
133
  } catch {
@@ -95,5 +137,6 @@ module.exports = function(RED) {
95
137
  }
96
138
  );
97
139
  }
140
+
98
141
  RED.nodes.registerType("externaltask-input", ExternalTaskInput);
99
142
  }
@@ -14,7 +14,7 @@ module.exports = function(RED) {
14
14
  node.error('Error: The message did not contain the required external task id.', msg);
15
15
  }
16
16
 
17
- eventEmitter.emit(`finish-${externalTaskId}`, msg.payload);
17
+ eventEmitter.emit(`handle-${externalTaskId}`, msg, false);
18
18
  });
19
19
  }
20
20
  RED.nodes.registerType("externaltask-output", ExternalTaskOutput);
@@ -79,6 +79,61 @@
79
79
  "w": 572,
80
80
  "h": 142
81
81
  },
82
+ {
83
+ "id": "70d7a70e375b162a",
84
+ "type": "group",
85
+ "z": "a23d2e782beb66f4",
86
+ "style": {
87
+ "stroke": "#999999",
88
+ "stroke-opacity": "1",
89
+ "fill": "none",
90
+ "fill-opacity": "1",
91
+ "label": true,
92
+ "label-position": "nw",
93
+ "color": "#a4a4a4"
94
+ },
95
+ "nodes": [
96
+ "2991a5e6df2b87d2",
97
+ "911fde53bcbb7e3f",
98
+ "d56bb7cd73fd220c",
99
+ "75c7bb5cc34e354a",
100
+ "69aec57d8bb00292",
101
+ "15a5f64b9e2e05fc"
102
+ ],
103
+ "x": 34,
104
+ "y": 19,
105
+ "w": 572,
106
+ "h": 222
107
+ },
108
+ {
109
+ "id": "31cb6729aac0ba46",
110
+ "type": "group",
111
+ "z": "a23d2e782beb66f4",
112
+ "style": {
113
+ "stroke": "#999999",
114
+ "stroke-opacity": "1",
115
+ "fill": "none",
116
+ "fill-opacity": "1",
117
+ "label": true,
118
+ "label-position": "nw",
119
+ "color": "#a4a4a4"
120
+ },
121
+ "nodes": [
122
+ "18e05d562d48f32d",
123
+ "49aee03a7885fae8",
124
+ "e4555d9019cd3f47",
125
+ "bd68c4bdc53b8f80",
126
+ "fa1c26d470c38efd",
127
+ "019797b5a0882e7b",
128
+ "fb87f79852b22e4a",
129
+ "1ba1e62c9935255f",
130
+ "b49f226ba865e164"
131
+ ],
132
+ "x": 34,
133
+ "y": 279,
134
+ "w": 872,
135
+ "h": 402
136
+ },
82
137
  {
83
138
  "id": "42e6796dddd9d4db",
84
139
  "type": "processcube-engine-config",
@@ -88,11 +143,12 @@
88
143
  "id": "2991a5e6df2b87d2",
89
144
  "type": "externaltask-input",
90
145
  "z": "a23d2e782beb66f4",
146
+ "g": "70d7a70e375b162a",
91
147
  "name": "Test",
92
148
  "engine": "42e6796dddd9d4db",
93
149
  "topic": "Test",
94
- "x": 90,
95
- "y": 400,
150
+ "x": 110,
151
+ "y": 120,
96
152
  "wires": [
97
153
  [
98
154
  "d56bb7cd73fd220c",
@@ -104,15 +160,17 @@
104
160
  "id": "911fde53bcbb7e3f",
105
161
  "type": "externaltask-output",
106
162
  "z": "a23d2e782beb66f4",
163
+ "g": "70d7a70e375b162a",
107
164
  "name": "Test Ende",
108
- "x": 500,
109
- "y": 400,
165
+ "x": 520,
166
+ "y": 120,
110
167
  "wires": []
111
168
  },
112
169
  {
113
170
  "id": "d56bb7cd73fd220c",
114
171
  "type": "delay",
115
172
  "z": "a23d2e782beb66f4",
173
+ "g": "70d7a70e375b162a",
116
174
  "name": "",
117
175
  "pauseType": "delay",
118
176
  "timeout": "1",
@@ -126,8 +184,8 @@
126
184
  "drop": false,
127
185
  "allowrate": false,
128
186
  "outputs": 1,
129
- "x": 280,
130
- "y": 400,
187
+ "x": 300,
188
+ "y": 120,
131
189
  "wires": [
132
190
  [
133
191
  "911fde53bcbb7e3f",
@@ -139,6 +197,7 @@
139
197
  "id": "75c7bb5cc34e354a",
140
198
  "type": "debug",
141
199
  "z": "a23d2e782beb66f4",
200
+ "g": "70d7a70e375b162a",
142
201
  "name": "debug 1",
143
202
  "active": true,
144
203
  "tosidebar": true,
@@ -147,14 +206,15 @@
147
206
  "complete": "false",
148
207
  "statusVal": "",
149
208
  "statusType": "auto",
150
- "x": 260,
151
- "y": 480,
209
+ "x": 280,
210
+ "y": 200,
152
211
  "wires": []
153
212
  },
154
213
  {
155
214
  "id": "69aec57d8bb00292",
156
215
  "type": "debug",
157
216
  "z": "a23d2e782beb66f4",
217
+ "g": "70d7a70e375b162a",
158
218
  "name": "debug 6",
159
219
  "active": true,
160
220
  "tosidebar": true,
@@ -164,19 +224,20 @@
164
224
  "targetType": "msg",
165
225
  "statusVal": "",
166
226
  "statusType": "auto",
167
- "x": 480,
168
- "y": 480,
227
+ "x": 500,
228
+ "y": 200,
169
229
  "wires": []
170
230
  },
171
231
  {
172
232
  "id": "18e05d562d48f32d",
173
233
  "type": "externaltask-input",
174
234
  "z": "a23d2e782beb66f4",
235
+ "g": "31cb6729aac0ba46",
175
236
  "name": "SampleError",
176
237
  "engine": "42e6796dddd9d4db",
177
238
  "topic": "SampleError",
178
- "x": 110,
179
- "y": 640,
239
+ "x": 130,
240
+ "y": 380,
180
241
  "wires": [
181
242
  [
182
243
  "49aee03a7885fae8"
@@ -187,6 +248,7 @@
187
248
  "id": "49aee03a7885fae8",
188
249
  "type": "delay",
189
250
  "z": "a23d2e782beb66f4",
251
+ "g": "31cb6729aac0ba46",
190
252
  "name": "",
191
253
  "pauseType": "delay",
192
254
  "timeout": "5",
@@ -200,8 +262,8 @@
200
262
  "drop": false,
201
263
  "allowrate": false,
202
264
  "outputs": 1,
203
- "x": 350,
204
- "y": 640,
265
+ "x": 370,
266
+ "y": 380,
205
267
  "wires": [
206
268
  [
207
269
  "bd68c4bdc53b8f80"
@@ -212,11 +274,12 @@
212
274
  "id": "e4555d9019cd3f47",
213
275
  "type": "catch",
214
276
  "z": "a23d2e782beb66f4",
277
+ "g": "31cb6729aac0ba46",
215
278
  "name": "",
216
279
  "scope": null,
217
280
  "uncaught": false,
218
- "x": 360,
219
- "y": 760,
281
+ "x": 380,
282
+ "y": 500,
220
283
  "wires": [
221
284
  [
222
285
  "fa1c26d470c38efd",
@@ -229,6 +292,7 @@
229
292
  "id": "bd68c4bdc53b8f80",
230
293
  "type": "function",
231
294
  "z": "a23d2e782beb66f4",
295
+ "g": "31cb6729aac0ba46",
232
296
  "name": "function 1",
233
297
  "func": "throw Error(\"hello error\");\n\nreturn msg;",
234
298
  "outputs": 1,
@@ -237,8 +301,8 @@
237
301
  "initialize": "",
238
302
  "finalize": "",
239
303
  "libs": [],
240
- "x": 560,
241
- "y": 640,
304
+ "x": 580,
305
+ "y": 380,
242
306
  "wires": [
243
307
  [
244
308
  "1ba1e62c9935255f"
@@ -249,6 +313,7 @@
249
313
  "id": "fa1c26d470c38efd",
250
314
  "type": "debug",
251
315
  "z": "a23d2e782beb66f4",
316
+ "g": "31cb6729aac0ba46",
252
317
  "name": "debug 8",
253
318
  "active": true,
254
319
  "tosidebar": true,
@@ -257,14 +322,15 @@
257
322
  "complete": "false",
258
323
  "statusVal": "",
259
324
  "statusType": "auto",
260
- "x": 620,
261
- "y": 760,
325
+ "x": 640,
326
+ "y": 500,
262
327
  "wires": []
263
328
  },
264
329
  {
265
330
  "id": "019797b5a0882e7b",
266
331
  "type": "debug",
267
332
  "z": "a23d2e782beb66f4",
333
+ "g": "31cb6729aac0ba46",
268
334
  "name": "debug 9",
269
335
  "active": true,
270
336
  "tosidebar": true,
@@ -274,18 +340,19 @@
274
340
  "targetType": "msg",
275
341
  "statusVal": "",
276
342
  "statusType": "auto",
277
- "x": 620,
278
- "y": 820,
343
+ "x": 640,
344
+ "y": 560,
279
345
  "wires": []
280
346
  },
281
347
  {
282
348
  "id": "fb87f79852b22e4a",
283
349
  "type": "externaltask-error",
284
350
  "z": "a23d2e782beb66f4",
351
+ "g": "31cb6729aac0ba46",
285
352
  "name": "Fehler",
286
353
  "error": "MyErrorCode",
287
- "x": 570,
288
- "y": 900,
354
+ "x": 590,
355
+ "y": 640,
289
356
  "wires": [
290
357
  []
291
358
  ]
@@ -294,9 +361,10 @@
294
361
  "id": "1ba1e62c9935255f",
295
362
  "type": "externaltask-output",
296
363
  "z": "a23d2e782beb66f4",
364
+ "g": "31cb6729aac0ba46",
297
365
  "name": "",
298
- "x": 770,
299
- "y": 640,
366
+ "x": 790,
367
+ "y": 380,
300
368
  "wires": []
301
369
  },
302
370
  {
@@ -346,6 +414,28 @@
346
414
  "y": 1200,
347
415
  "wires": []
348
416
  },
417
+ {
418
+ "id": "15a5f64b9e2e05fc",
419
+ "type": "comment",
420
+ "z": "a23d2e782beb66f4",
421
+ "g": "70d7a70e375b162a",
422
+ "name": "Simple External Task handling",
423
+ "info": "",
424
+ "x": 180,
425
+ "y": 60,
426
+ "wires": []
427
+ },
428
+ {
429
+ "id": "b49f226ba865e164",
430
+ "type": "comment",
431
+ "z": "a23d2e782beb66f4",
432
+ "g": "31cb6729aac0ba46",
433
+ "name": "Error handling with external tasks",
434
+ "info": "",
435
+ "x": 190,
436
+ "y": 320,
437
+ "wires": []
438
+ },
349
439
  {
350
440
  "id": "f7a9604a17188737",
351
441
  "type": "usertask-new-listener",
@@ -385,7 +385,7 @@ module.exports = {
385
385
  //tours: false,
386
386
 
387
387
  header: {
388
- title: "Node-RED powered by ProcessCube &copy;",
388
+ title: "Node-RED powered by ProcessCube&copy;",
389
389
  url: "https://processcube.io" // optional url to make the header text/image a link to this url
390
390
 
391
391
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@5minds/node-red-contrib-processcube",
3
- "version": "0.14.0-feature-7fe136-lyw00gz5",
3
+ "version": "0.14.0-feature-612fd3-lywvsveq",
4
4
  "license": "MIT",
5
5
  "description": "Node-RED nodes for ProcessCube",
6
6
  "authors": [