@5minds/node-red-contrib-processcube 0.14.0-feature-ef048b-lyy1ngi6 → 0.14.0-fix-error-in-process-instance-query-433395-lyzh0xul

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/Dockerfile CHANGED
@@ -1,4 +1,4 @@
1
- FROM node:20 AS builder
1
+ FROM node:20 as builder
2
2
 
3
3
  COPY ./ /src/node-red-contrib-processcube
4
4
 
@@ -11,10 +11,6 @@ services:
11
11
  - FLOWS=/nodered/node-red-contrib-processcube-flows.json
12
12
  volumes:
13
13
  - ./nodered/:/nodered/
14
- - ./examples/:/examples/
15
- depends_on:
16
- - engine
17
- - authority
18
14
 
19
15
  engine:
20
16
  image: 5minds/processcube_engine:2024-1
@@ -23,16 +19,9 @@ services:
23
19
  volumes:
24
20
  - ./processes:/processes:ro
25
21
  environment:
26
- application__name: Engine for Node-RED contrib
27
22
  iam__baseUrl: http://authority:11560
28
23
  iam__allowAnonymousRootAccess: true
29
24
  command: --seed-dir=/processes --port 8000
30
- depends_on:
31
- - authority
32
- healthcheck:
33
- test: bash -c "[ -f /tmp/healthy ]"
34
- timeout: 1s
35
- retries: 20
36
25
 
37
26
  authority:
38
27
  image: 5minds/processcube_authority:3.0.4
@@ -8,25 +8,24 @@ module.exports = function(RED) {
8
8
 
9
9
  node.on('input', function(msg) {
10
10
 
11
- const flowNodeInstanceId = msg.flowNodeInstanceId;
11
+ const externalTaskId = msg.externalTaskId;
12
12
 
13
- let msgError = msg.error;
13
+ let error = msg.error;
14
14
 
15
- if (msgError === undefined) {
16
- msgError.message = "An error occurred";
15
+ if (error === undefined) {
16
+ error.message = "An error occurred";
17
+ error.source = msg.payload;
17
18
  }
18
19
 
19
- msg.errorCode = config.error;
20
- msg.errorMessage = msgError.message;
21
- //msg.errorDetails = RED.util.encodeObject(msg); // circular structure
20
+ msg.payload = {
21
+ "error": {
22
+ errorCode: config.error,
23
+ errorMessage: error.message,
24
+ errorDetails: error.source
25
+ }
26
+ };
22
27
 
23
- const error = new Error(msg.errorMessage);
24
- error.errorCode = config.error;
25
-
26
- // TODO: hack cause https://github.com/5minds/ProcessCube.Engine.Client.ts/blob/develop/src/ExternalTaskWorker.ts#L180
27
- error.stack = RED.util.encodeObject(msg);
28
-
29
- eventEmitter.emit(`handle-${flowNodeInstanceId}`, error, true);
28
+ eventEmitter.emit(`error-${externalTaskId}`, msg.payload);
30
29
 
31
30
  node.send(msg);
32
31
  });
@@ -1,24 +1,44 @@
1
+ const process = require('process');
1
2
  const EventEmitter = require('node:events');
2
3
 
4
+ const engine_client = require('@5minds/processcube_engine_client');
5
+
3
6
  function showStatus(node, msgCounter) {
4
7
  if (msgCounter >= 1) {
5
- node.status({fill: "blue", shape: "dot", text: `handling tasks ${msgCounter}.`});
8
+ node.status({fill: "blue", shape: "dot", text: `handling tasks ${msgCounter}`});
6
9
  } else {
7
- node.status({fill: "blue", shape: "ring", text: `subcribed.`});
10
+ node.status({fill: "blue", shape: "ring", text: `subcribed ${msgCounter}`});
8
11
  }
9
12
  }
10
13
 
11
- const started_external_tasks = {};
14
+ function decrCounter(msgCounter) {
15
+ msgCounter--;
16
+
17
+ if (msgCounter < 0) {
18
+ msgCounter = 0;
19
+ }
20
+
21
+ return msgCounter;
22
+ }
12
23
 
13
24
  module.exports = function(RED) {
14
25
  function ExternalTaskInput(config) {
15
26
  RED.nodes.createNode(this,config);
16
27
  var node = this;
28
+ var msgCounter = 0;
17
29
  var flowContext = node.context().flow;
18
-
30
+ var nodeContext = node.context();
31
+
19
32
  this.engine = this.server = RED.nodes.getNode(config.engine);
20
33
 
21
- const client = this.engine.getEngineClient();
34
+ const engineUrl = this.engine?.url || process.env.ENGINE_URL || 'http://engine:8000';
35
+
36
+ var client = nodeContext.get('client');
37
+
38
+ if (!client) {
39
+ nodeContext.set('client', new engine_client.EngineClient(engineUrl));
40
+ client = nodeContext.get('client');
41
+ }
22
42
 
23
43
  var eventEmitter = flowContext.get('emitter');
24
44
 
@@ -30,75 +50,30 @@ module.exports = function(RED) {
30
50
  client.externalTasks.subscribeToExternalTaskTopic(
31
51
  config.topic,
32
52
  async (payload, externalTask) => {
53
+ msgCounter++;
33
54
 
34
- const saveHandleCallback = (data, callback) => {
35
- try {
36
- callback(data);
37
- } catch (error) {
38
- node.error(`Error in callback 'saveHandleCallback': ${error.message}`);
39
- }
40
- };
41
-
42
55
  return await new Promise((resolve, reject) => {
56
+
57
+ // TODO: once ist 2x gebunden
58
+ eventEmitter.once(`finish-${externalTask.flowNodeInstanceId}`, (result) => {
59
+ msgCounter = decrCounter(msgCounter);
43
60
 
44
- const handleFinishTask = (msg) => {
45
- let result = RED.util.encodeObject(msg.payload);
46
-
47
- node.log(`handle event for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* ${externalTask.processInstanceId} with result ${result} on msg._msgid ${msg._msgid}.`);
48
-
49
- if (externalTask.flowNodeInstanceId) {
50
- delete started_external_tasks[externalTask.flowNodeInstanceId];
51
- }
52
-
53
- showStatus(node, Object.keys(started_external_tasks).length);
54
-
55
-
56
- //resolve(result);
57
- saveHandleCallback(result, resolve)
58
- };
59
-
60
- const handleErrorTask = (msg) => {
61
-
62
- node.log(`handle error event for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}' on *msg._msgid* '${msg._msgid}'.`);
63
-
64
- if (externalTask.flowNodeInstanceId) {
65
- delete started_external_tasks[externalTask.flowNodeInstanceId];
66
- }
67
-
68
- showStatus(node, Object.keys(started_external_tasks).length);
69
-
61
+ showStatus(node, msgCounter);
62
+ resolve(result);
63
+ });
70
64
 
71
- // TODO: with reject, the default error handling is proceed
72
- // SEE: https://github.com/5minds/ProcessCube.Engine.Client.ts/blob/develop/src/ExternalTaskWorker.ts#L180
73
- // reject(result);
74
- //resolve(msg);
75
- saveHandleCallback(msg, resolve);
76
- };
65
+ eventEmitter.once(`error-${externalTask.flowNodeInstanceId}`, (msg) => {
66
+ msgCounter = decrCounter(msgCounter);
67
+ showStatus(node, msgCounter);
77
68
 
78
- eventEmitter.once(`handle-${externalTask.flowNodeInstanceId}`, (msg, isError = false) => {
79
- node.log(`handle event for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}' with *msg._msgid* '${msg._msgid}' and *isError* '${isError}'`);
69
+ var result = msg.payload ? msg.payload : msg;
80
70
 
81
- if (isError) {
82
- handleErrorTask(msg);
83
- } else {
84
- handleFinishTask(msg);
85
- }
71
+ reject(result);
86
72
  });
87
73
 
88
- started_external_tasks[externalTask.flowNodeInstanceId] = externalTask;
89
-
90
- showStatus(node, Object.keys(started_external_tasks).length);
91
-
92
- let msg = {
93
- _msgid: RED.util.generateId(),
94
- task: RED.util.encodeObject(externalTask),
95
- payload: payload,
96
- flowNodeInstanceId: externalTask.flowNodeInstanceId
97
- };
98
-
99
- node.log(`Received *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}' with *msg._msgid* '${msg._msgid}'`);
74
+ showStatus(node, msgCounter);
100
75
 
101
- node.send(msg);
76
+ node.send({topic: externalTask.topic, payload: payload, externalTaskId: externalTask.flowNodeInstanceId});
102
77
  });
103
78
  },
104
79
  ).then(async externalTaskWorker => {
@@ -108,36 +83,9 @@ module.exports = function(RED) {
108
83
  node.server.registerOnIdentityChanged((identity) => {
109
84
  externalTaskWorker.identity = identity;
110
85
  });
86
+ await externalTaskWorker.start();
111
87
 
112
- // export type WorkerErrorHandler = (errorType: 'fetchAndLock' | 'extendLock' | 'processExternalTask' | 'finishExternalTask', error: Error, externalTask?: ExternalTask<any>) => void;
113
- externalTaskWorker.onWorkerError((errorType, error, externalTask) => {
114
- switch (errorType) {
115
- case 'extendLock':
116
- case 'finishExternalTask':
117
- case 'processExternalTask':
118
- node.error(`Worker error ${errorType} for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}': ${error.message}`);
119
-
120
- externalTaskWorker.stop();
121
-
122
- if (externalTask) {
123
- delete started_external_tasks[externalTask.flowNodeInstanceId];
124
- }
125
-
126
- showStatus(node, Object.keys(started_external_tasks).length);
127
- break;
128
- default:
129
- node.error(`Worker error ${errorType}: ${error.message}`);
130
- break;
131
- }
132
- });
133
-
134
- try {
135
- externalTaskWorker.start();
136
- } catch (error) {
137
- node.error(`Worker start 'externalTaskWorker.start' failed: ${error.message}`);
138
- }
139
-
140
- node.on("close", () => {
88
+ node.on("close", async () => {
141
89
  try {
142
90
  externalTaskWorker.stop();
143
91
  } catch {
@@ -145,10 +93,7 @@ module.exports = function(RED) {
145
93
  }
146
94
  });
147
95
  }
148
- ).error((error) => {
149
- node.error(`Error in subscribeToExternalTaskTopic: ${error.message}`);
150
- });
96
+ );
151
97
  }
152
-
153
98
  RED.nodes.registerType("externaltask-input", ExternalTaskInput);
154
99
  }
@@ -8,13 +8,13 @@ module.exports = function(RED) {
8
8
 
9
9
  node.on('input', function(msg) {
10
10
 
11
- const flowNodeInstanceId = msg.flowNodeInstanceId;
11
+ const externalTaskId = msg.externalTaskId;
12
12
 
13
- if (!flowNodeInstanceId) {
13
+ if (!externalTaskId) {
14
14
  node.error('Error: The message did not contain the required external task id.', msg);
15
15
  }
16
16
 
17
- eventEmitter.emit(`handle-${flowNodeInstanceId}`, msg, false);
17
+ eventEmitter.emit(`finish-${externalTaskId}`, msg.payload);
18
18
  });
19
19
  }
20
20
  RED.nodes.registerType("externaltask-output", ExternalTaskOutput);
@@ -2,7 +2,7 @@
2
2
  {
3
3
  "id": "a23d2e782beb66f4",
4
4
  "type": "tab",
5
- "label": "External Task Sample",
5
+ "label": "ExternalTasks",
6
6
  "disabled": false,
7
7
  "info": "",
8
8
  "env": []
@@ -79,57 +79,6 @@
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
- "15a5f64b9e2e05fc"
100
- ],
101
- "x": 34,
102
- "y": 79,
103
- "w": 512,
104
- "h": 142
105
- },
106
- {
107
- "id": "31cb6729aac0ba46",
108
- "type": "group",
109
- "z": "a23d2e782beb66f4",
110
- "style": {
111
- "stroke": "#999999",
112
- "stroke-opacity": "1",
113
- "fill": "none",
114
- "fill-opacity": "1",
115
- "label": true,
116
- "label-position": "nw",
117
- "color": "#a4a4a4"
118
- },
119
- "nodes": [
120
- "18e05d562d48f32d",
121
- "49aee03a7885fae8",
122
- "e4555d9019cd3f47",
123
- "bd68c4bdc53b8f80",
124
- "fb87f79852b22e4a",
125
- "1ba1e62c9935255f",
126
- "b49f226ba865e164"
127
- ],
128
- "x": 34,
129
- "y": 259,
130
- "w": 812,
131
- "h": 202
132
- },
133
82
  {
134
83
  "id": "42e6796dddd9d4db",
135
84
  "type": "processcube-engine-config",
@@ -139,15 +88,15 @@
139
88
  "id": "2991a5e6df2b87d2",
140
89
  "type": "externaltask-input",
141
90
  "z": "a23d2e782beb66f4",
142
- "g": "70d7a70e375b162a",
143
91
  "name": "Test",
144
92
  "engine": "42e6796dddd9d4db",
145
93
  "topic": "Test",
146
- "x": 110,
147
- "y": 180,
94
+ "x": 90,
95
+ "y": 400,
148
96
  "wires": [
149
97
  [
150
- "d56bb7cd73fd220c"
98
+ "d56bb7cd73fd220c",
99
+ "75c7bb5cc34e354a"
151
100
  ]
152
101
  ]
153
102
  },
@@ -155,17 +104,15 @@
155
104
  "id": "911fde53bcbb7e3f",
156
105
  "type": "externaltask-output",
157
106
  "z": "a23d2e782beb66f4",
158
- "g": "70d7a70e375b162a",
159
107
  "name": "Test Ende",
160
- "x": 460,
161
- "y": 180,
108
+ "x": 500,
109
+ "y": 400,
162
110
  "wires": []
163
111
  },
164
112
  {
165
113
  "id": "d56bb7cd73fd220c",
166
114
  "type": "delay",
167
115
  "z": "a23d2e782beb66f4",
168
- "g": "70d7a70e375b162a",
169
116
  "name": "",
170
117
  "pauseType": "delay",
171
118
  "timeout": "1",
@@ -180,23 +127,56 @@
180
127
  "allowrate": false,
181
128
  "outputs": 1,
182
129
  "x": 280,
183
- "y": 180,
130
+ "y": 400,
184
131
  "wires": [
185
132
  [
186
- "911fde53bcbb7e3f"
133
+ "911fde53bcbb7e3f",
134
+ "69aec57d8bb00292"
187
135
  ]
188
136
  ]
189
137
  },
138
+ {
139
+ "id": "75c7bb5cc34e354a",
140
+ "type": "debug",
141
+ "z": "a23d2e782beb66f4",
142
+ "name": "debug 1",
143
+ "active": true,
144
+ "tosidebar": true,
145
+ "console": false,
146
+ "tostatus": false,
147
+ "complete": "false",
148
+ "statusVal": "",
149
+ "statusType": "auto",
150
+ "x": 260,
151
+ "y": 480,
152
+ "wires": []
153
+ },
154
+ {
155
+ "id": "69aec57d8bb00292",
156
+ "type": "debug",
157
+ "z": "a23d2e782beb66f4",
158
+ "name": "debug 6",
159
+ "active": true,
160
+ "tosidebar": true,
161
+ "console": false,
162
+ "tostatus": false,
163
+ "complete": "externalTaskId",
164
+ "targetType": "msg",
165
+ "statusVal": "",
166
+ "statusType": "auto",
167
+ "x": 480,
168
+ "y": 480,
169
+ "wires": []
170
+ },
190
171
  {
191
172
  "id": "18e05d562d48f32d",
192
173
  "type": "externaltask-input",
193
174
  "z": "a23d2e782beb66f4",
194
- "g": "31cb6729aac0ba46",
195
175
  "name": "SampleError",
196
176
  "engine": "42e6796dddd9d4db",
197
177
  "topic": "SampleError",
198
- "x": 130,
199
- "y": 360,
178
+ "x": 110,
179
+ "y": 640,
200
180
  "wires": [
201
181
  [
202
182
  "49aee03a7885fae8"
@@ -207,10 +187,9 @@
207
187
  "id": "49aee03a7885fae8",
208
188
  "type": "delay",
209
189
  "z": "a23d2e782beb66f4",
210
- "g": "31cb6729aac0ba46",
211
190
  "name": "",
212
191
  "pauseType": "delay",
213
- "timeout": "15",
192
+ "timeout": "5",
214
193
  "timeoutUnits": "seconds",
215
194
  "rate": "1",
216
195
  "nbRateUnits": "1",
@@ -221,8 +200,8 @@
221
200
  "drop": false,
222
201
  "allowrate": false,
223
202
  "outputs": 1,
224
- "x": 330,
225
- "y": 360,
203
+ "x": 350,
204
+ "y": 640,
226
205
  "wires": [
227
206
  [
228
207
  "bd68c4bdc53b8f80"
@@ -233,14 +212,15 @@
233
212
  "id": "e4555d9019cd3f47",
234
213
  "type": "catch",
235
214
  "z": "a23d2e782beb66f4",
236
- "g": "31cb6729aac0ba46",
237
215
  "name": "",
238
- "scope": "group",
216
+ "scope": null,
239
217
  "uncaught": false,
240
- "x": 510,
241
- "y": 420,
218
+ "x": 360,
219
+ "y": 760,
242
220
  "wires": [
243
221
  [
222
+ "fa1c26d470c38efd",
223
+ "019797b5a0882e7b",
244
224
  "fb87f79852b22e4a"
245
225
  ]
246
226
  ]
@@ -249,8 +229,7 @@
249
229
  "id": "bd68c4bdc53b8f80",
250
230
  "type": "function",
251
231
  "z": "a23d2e782beb66f4",
252
- "g": "31cb6729aac0ba46",
253
- "name": "raise Error",
232
+ "name": "function 1",
254
233
  "func": "throw Error(\"hello error\");\n\nreturn msg;",
255
234
  "outputs": 1,
256
235
  "timeout": 0,
@@ -258,23 +237,55 @@
258
237
  "initialize": "",
259
238
  "finalize": "",
260
239
  "libs": [],
261
- "x": 510,
262
- "y": 360,
240
+ "x": 560,
241
+ "y": 640,
263
242
  "wires": [
264
243
  [
265
244
  "1ba1e62c9935255f"
266
245
  ]
267
246
  ]
268
247
  },
248
+ {
249
+ "id": "fa1c26d470c38efd",
250
+ "type": "debug",
251
+ "z": "a23d2e782beb66f4",
252
+ "name": "debug 8",
253
+ "active": true,
254
+ "tosidebar": true,
255
+ "console": false,
256
+ "tostatus": false,
257
+ "complete": "false",
258
+ "statusVal": "",
259
+ "statusType": "auto",
260
+ "x": 620,
261
+ "y": 760,
262
+ "wires": []
263
+ },
264
+ {
265
+ "id": "019797b5a0882e7b",
266
+ "type": "debug",
267
+ "z": "a23d2e782beb66f4",
268
+ "name": "debug 9",
269
+ "active": true,
270
+ "tosidebar": true,
271
+ "console": false,
272
+ "tostatus": false,
273
+ "complete": "externalTaskId",
274
+ "targetType": "msg",
275
+ "statusVal": "",
276
+ "statusType": "auto",
277
+ "x": 620,
278
+ "y": 820,
279
+ "wires": []
280
+ },
269
281
  {
270
282
  "id": "fb87f79852b22e4a",
271
283
  "type": "externaltask-error",
272
284
  "z": "a23d2e782beb66f4",
273
- "g": "31cb6729aac0ba46",
274
- "name": "Send Error to Engine",
285
+ "name": "Fehler",
275
286
  "error": "MyErrorCode",
276
- "x": 720,
277
- "y": 420,
287
+ "x": 570,
288
+ "y": 900,
278
289
  "wires": [
279
290
  []
280
291
  ]
@@ -283,42 +294,56 @@
283
294
  "id": "1ba1e62c9935255f",
284
295
  "type": "externaltask-output",
285
296
  "z": "a23d2e782beb66f4",
286
- "g": "31cb6729aac0ba46",
287
297
  "name": "",
288
- "x": 710,
289
- "y": 360,
298
+ "x": 770,
299
+ "y": 640,
290
300
  "wires": []
291
301
  },
292
302
  {
293
- "id": "15a5f64b9e2e05fc",
294
- "type": "comment",
295
- "z": "a23d2e782beb66f4",
296
- "g": "70d7a70e375b162a",
297
- "name": "Simple External Task handling",
298
- "info": "",
299
- "x": 180,
300
- "y": 120,
301
- "wires": []
302
- },
303
- {
304
- "id": "b49f226ba865e164",
305
- "type": "comment",
303
+ "id": "c18723294975e975",
304
+ "type": "inject",
306
305
  "z": "a23d2e782beb66f4",
307
- "g": "31cb6729aac0ba46",
308
- "name": "Error handling with external tasks",
309
- "info": "",
306
+ "name": "",
307
+ "props": [
308
+ {
309
+ "p": "payload"
310
+ },
311
+ {
312
+ "p": "eventName",
313
+ "v": "sampleEvent",
314
+ "vt": "str"
315
+ }
316
+ ],
317
+ "repeat": "",
318
+ "crontab": "",
319
+ "once": false,
320
+ "onceDelay": 0.1,
321
+ "topic": "",
322
+ "payload": "{\t \t}",
323
+ "payloadType": "jsonata",
310
324
  "x": 190,
311
- "y": 300,
312
- "wires": []
325
+ "y": 1200,
326
+ "wires": [
327
+ [
328
+ "ddcde0ab7abfb8af"
329
+ ]
330
+ ]
313
331
  },
314
332
  {
315
- "id": "799125e21de02f13",
316
- "type": "comment",
333
+ "id": "ddcde0ab7abfb8af",
334
+ "type": "debug",
317
335
  "z": "a23d2e782beb66f4",
318
- "name": "For Testing, deploy \"External-Task-Sample.bpmn\" and start the process.",
319
- "info": "",
320
- "x": 300,
321
- "y": 40,
336
+ "name": "debug 18",
337
+ "active": true,
338
+ "tosidebar": true,
339
+ "console": false,
340
+ "tostatus": false,
341
+ "complete": "true",
342
+ "targetType": "full",
343
+ "statusVal": "",
344
+ "statusType": "auto",
345
+ "x": 480,
346
+ "y": 1200,
322
347
  "wires": []
323
348
  },
324
349
  {
@@ -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-ef048b-lyy1ngi6",
3
+ "version": "0.14.0-fix-error-in-process-instance-query-433395-lyzh0xul",
4
4
  "license": "MIT",
5
5
  "description": "Node-RED nodes for ProcessCube",
6
6
  "authors": [