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

Sign up to get free protection for your applications and to get access to all the features.
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": [