@5minds/node-red-contrib-processcube 0.14.0-feature-7cec87-lyytfjz9 → 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
 
@@ -5,17 +5,12 @@ services:
5
5
  context: .
6
6
  ports:
7
7
  - "1880:1880"
8
- - "9229:9229"
9
8
  environment:
10
9
  - TZ=Europe/Berlin
11
10
  - ENGINE_URL=http://engine:8000
12
11
  - FLOWS=/nodered/node-red-contrib-processcube-flows.json
13
12
  volumes:
14
13
  - ./nodered/:/nodered/
15
- - ./examples/:/examples/
16
- depends_on:
17
- - engine
18
- - authority
19
14
 
20
15
  engine:
21
16
  image: 5minds/processcube_engine:2024-1
@@ -24,16 +19,9 @@ services:
24
19
  volumes:
25
20
  - ./processes:/processes:ro
26
21
  environment:
27
- application__name: Engine for Node-RED contrib
28
22
  iam__baseUrl: http://authority:11560
29
23
  iam__allowAnonymousRootAccess: true
30
24
  command: --seed-dir=/processes --port 8000
31
- depends_on:
32
- - authority
33
- healthcheck:
34
- test: bash -c "[ -f /tmp/healthy ]"
35
- timeout: 1s
36
- retries: 20
37
25
 
38
26
  authority:
39
27
  image: 5minds/processcube_authority:3.0.4
@@ -26,20 +26,6 @@
26
26
  </div>
27
27
  </script>
28
28
 
29
- <script type="text/markdown" data-help-name="externaltask-error">
30
- Used for reporting errors in the processing of external tasks. The error
31
- code `Error` in the configuration is forwarded to the ProcessCube engine for
32
- handling within *Error-Boundary-Events*.
33
-
34
- ## Inputs
35
-
36
- : msg (Object) : Passed as `ErrorDetails` to the engine
37
- : Error (string) : From the configuration
38
- : Message (string) : The caught exception message
39
- : StackTrace (string) : The stack trace of the exception
40
-
41
- ### References
42
-
43
- - [The ProcessCube Developer Network](https://processcube.io) - All documentation for the ProcessCube&copy; platform
44
- - [Node-RED Integration in ProcessCube&copy;](https://processcube.io/docs/node-red) - Node-RED integration in ProcessCube&copy;
29
+ <script type="text/html" data-help-name="externaltask-error">
30
+ <p>A node which error response to an External Task of https://processcube.io</p>
45
31
  </script>
@@ -8,22 +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
- const error = new Error(msgError.message);
20
- error.errorCode = config.error;
21
- error.errorDetails = RED.util.encodeObject(msg);
20
+ msg.payload = {
21
+ "error": {
22
+ errorCode: config.error,
23
+ errorMessage: error.message,
24
+ errorDetails: error.source
25
+ }
26
+ };
22
27
 
23
- msg.errorCode = config.error;
24
- msg.errorMessage = msgError.message;
25
-
26
- eventEmitter.emit(`handle-${flowNodeInstanceId}`, error, true);
28
+ eventEmitter.emit(`error-${externalTaskId}`, msg.payload);
27
29
 
28
30
  node.send(msg);
29
31
  });
@@ -31,23 +31,6 @@
31
31
  </div>
32
32
  </script>
33
33
 
34
- <script type="text/markdown" data-help-name="externaltask-input">
35
- Waiting for external tasks that correspond to the `Topic` configured in
36
- the connected ProcessCube Engine for processing.
37
-
38
- ## Outputs
39
-
40
- : payload (string) : Defines the input of the external task token
41
- : task (object) : The external task object
42
- : flowNodeInstanceId : The Id of the external task, which is needed to complete the task
43
-
44
- ### Details
45
-
46
- - To finish the external task the `externaltask-output` node is required.
47
- - For handling a error while executing a flow as external task the `externaltask-error` node is required.
48
-
49
- ### References
50
-
51
- - [The ProcessCube Developer Network](https://processcube.io) - All documentation for the ProcessCube&copy; Plattform
52
- - [Node-RED Integration in ProcessCube&copy;](https://processcube.io/docs/node-red) - Node-RED Integration in ProcessCube&copy;
34
+ <script type="text/html" data-help-name="externaltask-input">
35
+ <p>A node which subscribes to an External Task Topic of https://processcube.io</p>
53
36
  </script>
@@ -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
- };
74
+ showStatus(node, msgCounter);
98
75
 
99
- node.log(`Received *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}' with *msg._msgid* '${msg._msgid}'`);
100
-
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,45 +83,17 @@ 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
- if (externalTask) {
121
- delete started_external_tasks[externalTask.flowNodeInstanceId];
122
- }
123
-
124
- showStatus(node, Object.keys(started_external_tasks).length);
125
- break;
126
- default:
127
- node.error(`Worker error ${errorType}: ${error.message}`);
128
- break;
129
- }
130
- });
131
-
132
- try {
133
- externalTaskWorker.start();
134
- } catch (error) {
135
- node.error(`Worker start 'externalTaskWorker.start' failed: ${error.message}`);
136
- }
137
-
138
- node.on("close", () => {
88
+ node.on("close", async () => {
139
89
  try {
140
90
  externalTaskWorker.stop();
141
91
  } catch {
142
- node.error('Client close failed');
92
+ console.warn('Client close failed');
143
93
  }
144
94
  });
145
95
  }
146
- ).catch((error) => {
147
- node.error(`Error in subscribeToExternalTaskTopic: ${error.message}`);
148
- });
96
+ );
149
97
  }
150
-
151
98
  RED.nodes.registerType("externaltask-input", ExternalTaskInput);
152
99
  }
@@ -21,16 +21,6 @@
21
21
  </div>
22
22
  </script>
23
23
 
24
- <script type="text/markdown" data-help-name="externaltask-output">
25
- Used to complete the external task. The `msg.payload` is returned to the ProcessCube
26
- engine as the result of the external task.
27
-
28
- ## Inputs
29
-
30
- : payload (Object) : Returned to the ProcessCube engine as the result of the external task
31
-
32
- ### References
33
-
34
- - [The ProcessCube Developer Network](https://processcube.io) - All documentation for the ProcessCube&copy; platform
35
- - [Node-RED Integration in ProcessCube&copy;](https://processcube.io/docs/node-red) - Node-RED integration in ProcessCube&copy;
24
+ <script type="text/html" data-help-name="externaltask-output">
25
+ <p>A node which response to an External Task of https://processcube.io</p>
36
26
  </script>
@@ -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);