@5minds/node-red-contrib-processcube 1.5.6-feature-aa14a2-m3pntyi8 → 1.5.7-develop-41d845-m3q6c4hg

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.
@@ -4,13 +4,6 @@ module.exports = function (RED) {
4
4
  var node = this;
5
5
  node.engine = RED.nodes.getNode(config.engine);
6
6
 
7
- const eventEmitter = node.engine.eventEmitter;
8
-
9
- eventEmitter.on('engine-client-changed', () => {
10
- node.log('new engineClient received');
11
- register();
12
- });
13
-
14
7
  const register = async () => {
15
8
  const client = node.engine.engineClient;
16
9
 
@@ -18,7 +11,7 @@ module.exports = function (RED) {
18
11
  node.error('No engine configured.');
19
12
  return;
20
13
  }
21
-
14
+
22
15
  let currentIdentity = node.engine.identity;
23
16
 
24
17
  let subscription = null;
@@ -30,23 +23,24 @@ module.exports = function (RED) {
30
23
  payload: endEventFinished,
31
24
  });
32
25
  },
33
- { identity: currentIdentity }
26
+ { identity: currentIdentity },
34
27
  );
35
28
 
36
29
  node.engine.registerOnIdentityChanged(async (identity) => {
37
30
  client.events.removeSubscription(subscription, currentIdentity);
38
-
31
+
39
32
  currentIdentity = identity;
40
33
 
41
34
  subscription = await client.events.onEndEventFinished(
42
35
  (endEventFinished) => {
43
36
  node.send({
44
- payload: endEventFinished,
37
+ payload: endEventFinished
45
38
  });
46
39
  },
47
- { identity: currentIdentity }
40
+ { identity: currentIdentity },
48
41
  );
49
42
  });
43
+
50
44
  } catch (error) {
51
45
  node.error(error);
52
46
  }
@@ -4,13 +4,6 @@ module.exports = function (RED) {
4
4
  var node = this;
5
5
  node.engine = RED.nodes.getNode(config.engine);
6
6
 
7
- const eventEmitter = node.engine.eventEmitter;
8
-
9
- eventEmitter.on('engine-client-changed', () => {
10
- node.log('new engineClient received');
11
- register();
12
- });
13
-
14
7
  const register = async () => {
15
8
  let currentIdentity = node.engine.identity;
16
9
 
@@ -58,11 +58,26 @@
58
58
  Waiting for external tasks that correspond to the `Topic` configured in
59
59
  the connected ProcessCube Engine for processing.
60
60
 
61
+ ## Configs
62
+
63
+ : name (string) : The name of the node
64
+ : engine (string) : The ProcessCube Engine to connect to
65
+ : topic (string) : The topic of the external task
66
+ : workerConfig (object) : The configuration for the worker
67
+
68
+ ### workerConfig
69
+
70
+ - workerId (string): The id of the worker
71
+ - lockDuration (number): The duration in milliseconds the external task is locked for execution
72
+ - maxTasks (number): The maximum number of tasks that can be fetched at once
73
+ - longpollingTimeout (number): The duration in milliseconds the external task is locked for execution
74
+ - payloadFilter (Req-Expression): The filter for the payload of the external task
75
+
61
76
  ## Outputs
62
77
 
63
78
  : payload (string) : The payload the external task was started with.
64
79
  : task (object) : The external task object
65
- : flowNodeInstanceId : The unique identifier of the external task, which is needed to complete the task
80
+ : flowNodeInstanceId (string) : The unique identifier of the external task, which is needed to complete the task
66
81
 
67
82
  ### Details
68
83
 
@@ -32,149 +32,135 @@ module.exports = function (RED) {
32
32
  eventEmitter = flowContext.get('emitter');
33
33
  }
34
34
 
35
- const engineEventEmitter = node.engine.eventEmitter;
35
+ const etwCallback = async (payload, externalTask) => {
36
+ const saveHandleCallback = (data, callback) => {
37
+ try {
38
+ callback(data);
39
+ } catch (error) {
40
+ node.error(`Error in callback 'saveHandleCallback': ${error.message}`);
41
+ }
42
+ };
36
43
 
37
- engineEventEmitter.on('engine-client-changed', () => {
38
- node.log('new engineClient received');
39
- register();
40
- });
44
+ return await new Promise((resolve, reject) => {
45
+ const handleFinishTask = (msg) => {
46
+ let result = RED.util.encodeObject(msg.payload);
41
47
 
42
- const register = async () => {
43
- const etwCallback = async (payload, externalTask) => {
44
- const saveHandleCallback = (data, callback) => {
45
- try {
46
- callback(data);
47
- } catch (error) {
48
- node.error(`Error in callback 'saveHandleCallback': ${error.message}`);
48
+ node.log(
49
+ `handle event for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* ${externalTask.processInstanceId} with result ${result} on msg._msgid ${msg._msgid}.`
50
+ );
51
+
52
+ if (externalTask.flowNodeInstanceId) {
53
+ delete started_external_tasks[externalTask.flowNodeInstanceId];
49
54
  }
50
- };
51
55
 
52
- return await new Promise((resolve, reject) => {
53
- const handleFinishTask = (msg) => {
54
- let result = RED.util.encodeObject(msg.payload);
56
+ showStatus(node, Object.keys(started_external_tasks).length);
55
57
 
56
- node.log(
57
- `handle event for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* ${externalTask.processInstanceId} with result ${result} on msg._msgid ${msg._msgid}.`
58
- );
58
+ //resolve(result);
59
+ saveHandleCallback(result, resolve);
60
+ };
59
61
 
60
- if (externalTask.flowNodeInstanceId) {
61
- delete started_external_tasks[externalTask.flowNodeInstanceId];
62
- }
62
+ const handleErrorTask = (msg) => {
63
+ node.log(
64
+ `handle error event for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}' on *msg._msgid* '${msg._msgid}'.`
65
+ );
63
66
 
64
- showStatus(node, Object.keys(started_external_tasks).length);
67
+ if (externalTask.flowNodeInstanceId) {
68
+ delete started_external_tasks[externalTask.flowNodeInstanceId];
69
+ }
65
70
 
66
- //resolve(result);
67
- saveHandleCallback(result, resolve);
68
- };
71
+ showStatus(node, Object.keys(started_external_tasks).length);
69
72
 
70
- const handleErrorTask = (msg) => {
71
- node.log(
72
- `handle error event for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}' on *msg._msgid* '${msg._msgid}'.`
73
- );
73
+ // TODO: with reject, the default error handling is proceed
74
+ // SEE: https://github.com/5minds/ProcessCube.Engine.Client.ts/blob/develop/src/ExternalTaskWorker.ts#L180
75
+ // reject(result);
76
+ //resolve(msg);
77
+ saveHandleCallback(msg, resolve);
78
+ };
79
+
80
+ eventEmitter.once(`handle-${externalTask.flowNodeInstanceId}`, (msg, isError = false) => {
81
+ node.log(
82
+ `handle event for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}' with *msg._msgid* '${msg._msgid}' and *isError* '${isError}'`
83
+ );
74
84
 
75
- if (externalTask.flowNodeInstanceId) {
76
- delete started_external_tasks[externalTask.flowNodeInstanceId];
77
- }
85
+ if (isError) {
86
+ handleErrorTask(msg);
87
+ } else {
88
+ handleFinishTask(msg);
89
+ }
90
+ });
78
91
 
79
- showStatus(node, Object.keys(started_external_tasks).length);
92
+ started_external_tasks[externalTask.flowNodeInstanceId] = externalTask;
80
93
 
81
- // TODO: with reject, the default error handling is proceed
82
- // SEE: https://github.com/5minds/ProcessCube.Engine.Client.ts/blob/develop/src/ExternalTaskWorker.ts#L180
83
- // reject(result);
84
- //resolve(msg);
85
- saveHandleCallback(msg, resolve);
86
- };
94
+ showStatus(node, Object.keys(started_external_tasks).length);
87
95
 
88
- eventEmitter.once(`handle-${externalTask.flowNodeInstanceId}`, (msg, isError = false) => {
89
- node.log(
90
- `handle event for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}' with *msg._msgid* '${msg._msgid}' and *isError* '${isError}'`
91
- );
96
+ let msg = {
97
+ _msgid: RED.util.generateId(),
98
+ task: RED.util.encodeObject(externalTask),
99
+ payload: payload,
100
+ flowNodeInstanceId: externalTask.flowNodeInstanceId,
101
+ processInstanceId: externalTask.processInstanceId,
102
+ };
92
103
 
93
- if (isError) {
94
- handleErrorTask(msg);
95
- } else {
96
- handleFinishTask(msg);
97
- }
98
- });
104
+ node.log(
105
+ `Received *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}' with *msg._msgid* '${msg._msgid}'`
106
+ );
99
107
 
100
- started_external_tasks[externalTask.flowNodeInstanceId] = externalTask;
108
+ node.send(msg);
109
+ });
110
+ };
101
111
 
102
- showStatus(node, Object.keys(started_external_tasks).length);
112
+ let options = RED.util.evaluateNodeProperty(config.workerConfig, 'json', node);
103
113
 
104
- let msg = {
105
- _msgid: RED.util.generateId(),
106
- task: RED.util.encodeObject(externalTask),
107
- payload: payload,
108
- flowNodeInstanceId: externalTask.flowNodeInstanceId,
109
- processInstanceId: externalTask.processInstanceId,
110
- };
114
+ client.externalTasks
115
+ .subscribeToExternalTaskTopic(config.topic, etwCallback, options)
116
+ .then(async (externalTaskWorker) => {
117
+ node.status({ fill: 'blue', shape: 'ring', text: 'subcribed' });
111
118
 
112
- node.log(
113
- `Received *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}' with *msg._msgid* '${msg._msgid}'`
114
- );
119
+ externalTaskWorker.identity = engine.identity;
120
+ engine.registerOnIdentityChanged((identity) => {
121
+ externalTaskWorker.identity = identity;
122
+ });
115
123
 
116
- node.send(msg);
124
+ // export type WorkerErrorHandler = (errorType: 'fetchAndLock' | 'extendLock' | 'processExternalTask' | 'finishExternalTask', error: Error, externalTask?: ExternalTask<any>) => void;
125
+ externalTaskWorker.onWorkerError((errorType, error, externalTask) => {
126
+ switch (errorType) {
127
+ case 'extendLock':
128
+ case 'finishExternalTask':
129
+ case 'processExternalTask':
130
+ node.error(
131
+ `Worker error ${errorType} for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}': ${error.message}`
132
+ );
133
+
134
+ if (externalTask) {
135
+ delete started_external_tasks[externalTask.flowNodeInstanceId];
136
+ }
137
+
138
+ showStatus(node, Object.keys(started_external_tasks).length);
139
+ break;
140
+ default:
141
+ // reduce noise error logs
142
+ // node.error(`Worker error ${errorType}: ${error.message}`);
143
+ break;
144
+ }
117
145
  });
118
- };
119
146
 
120
- client.externalTasks
121
- .subscribeToExternalTaskTopic(
122
- config.topic,
123
- etwCallback,
124
- RED.util.evaluateNodeProperty(config.workerConfig, 'json', node)
125
- )
126
- .then(async (externalTaskWorker) => {
127
- node.status({ fill: 'blue', shape: 'ring', text: 'subcribed' });
128
-
129
- externalTaskWorker.identity = engine.identity;
130
- engine.registerOnIdentityChanged((identity) => {
131
- externalTaskWorker.identity = identity;
132
- });
133
-
134
- // export type WorkerErrorHandler = (errorType: 'fetchAndLock' | 'extendLock' | 'processExternalTask' | 'finishExternalTask', error: Error, externalTask?: ExternalTask<any>) => void;
135
- externalTaskWorker.onWorkerError((errorType, error, externalTask) => {
136
- switch (errorType) {
137
- case 'extendLock':
138
- case 'finishExternalTask':
139
- case 'processExternalTask':
140
- node.error(
141
- `Worker error ${errorType} for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}': ${error.message}`
142
- );
143
-
144
- if (externalTask) {
145
- delete started_external_tasks[externalTask.flowNodeInstanceId];
146
- }
147
-
148
- showStatus(node, Object.keys(started_external_tasks).length);
149
- break;
150
- default:
151
- node.error(`Worker error ${errorType}: ${error.message}`);
152
- break;
153
- }
154
- });
147
+ try {
148
+ externalTaskWorker.start();
149
+ } catch (error) {
150
+ node.error(`Worker start 'externalTaskWorker.start' failed: ${error.message}`);
151
+ }
155
152
 
153
+ node.on('close', () => {
156
154
  try {
157
- externalTaskWorker.start();
158
- } catch (error) {
159
- node.error(`Worker start 'externalTaskWorker.start' failed: ${error.message}`);
155
+ externalTaskWorker.stop();
156
+ } catch {
157
+ node.error('Client close failed');
160
158
  }
161
-
162
- node.on('close', () => {
163
- try {
164
- externalTaskWorker.stop();
165
- } catch {
166
- node.error('Client close failed');
167
- }
168
- });
169
- })
170
- .catch((error) => {
171
- node.error(`Error in subscribeToExternalTaskTopic: ${error.message}`);
172
159
  });
173
- };
174
-
175
- if (node.engine) {
176
- register();
177
- }
160
+ })
161
+ .catch((error) => {
162
+ node.error(`Error in subscribeToExternalTaskTopic: ${error.message}`);
163
+ });
178
164
  }
179
165
 
180
166
  RED.nodes.registerType('externaltask-input', ExternalTaskInput);
@@ -71,6 +71,22 @@
71
71
  "info": "",
72
72
  "env": []
73
73
  },
74
+ {
75
+ "id": "76c047e0d8770a20",
76
+ "type": "tab",
77
+ "label": "Other Events",
78
+ "disabled": false,
79
+ "info": "",
80
+ "env": []
81
+ },
82
+ {
83
+ "id": "2766c40d84283368",
84
+ "type": "tab",
85
+ "label": "Placeholder",
86
+ "disabled": false,
87
+ "info": "",
88
+ "env": []
89
+ },
74
90
  {
75
91
  "id": "4c59118134081e05",
76
92
  "type": "group",
@@ -481,6 +497,7 @@
481
497
  "color": "#a4a4a4"
482
498
  },
483
499
  "nodes": [
500
+
484
501
  "2fadb4c4667ecaf2",
485
502
  "93331783b7ef3fc5",
486
503
  "bc26f9821540f097",
@@ -1485,7 +1502,7 @@
1485
1502
  "g": "a71a168415778e2c",
1486
1503
  "name": "",
1487
1504
  "engine": "42e6796dddd9d4db",
1488
- "query": "{\"includeXml\":false}",
1505
+ "query": "{\"includeXml\":false,\"processDefinitionId\":\"External-Task-Sample_Definition\"}",
1489
1506
  "query_type": "json",
1490
1507
  "x": 320,
1491
1508
  "y": 140,
@@ -2094,5 +2111,95 @@
2094
2111
  "x": 760,
2095
2112
  "y": 60,
2096
2113
  "wires": []
2114
+ },
2115
+ {
2116
+ "id": "930624edc6169c55",
2117
+ "type": "process-event-listener",
2118
+ "z": "76c047e0d8770a20",
2119
+ "g": "865723b71ced9418",
2120
+ "name": "",
2121
+ "engine": "42e6796dddd9d4db",
2122
+ "processmodel": "External-Task-Sample_Process",
2123
+ "eventtype": "starting",
2124
+ "query": "{}",
2125
+ "query_type": "json",
2126
+ "x": 160,
2127
+ "y": 140,
2128
+ "wires": [
2129
+ [
2130
+ "2f2ec1cc0213eab5"
2131
+ ]
2132
+ ]
2133
+ },
2134
+ {
2135
+ "id": "2f2ec1cc0213eab5",
2136
+ "type": "debug",
2137
+ "z": "76c047e0d8770a20",
2138
+ "g": "865723b71ced9418",
2139
+ "name": "debug 34",
2140
+ "active": true,
2141
+ "tosidebar": true,
2142
+ "console": false,
2143
+ "tostatus": false,
2144
+ "complete": "false",
2145
+ "statusVal": "",
2146
+ "statusType": "auto",
2147
+ "x": 430,
2148
+ "y": 140,
2149
+ "wires": []
2150
+ },
2151
+ {
2152
+ "id": "bde205e77cd20558",
2153
+ "type": "comment",
2154
+ "z": "76c047e0d8770a20",
2155
+ "g": "865723b71ced9418",
2156
+ "name": "Hört auf die Events der Processe",
2157
+ "info": "",
2158
+ "x": 190,
2159
+ "y": 80,
2160
+ "wires": []
2161
+ },
2162
+ {
2163
+ "id": "03ac7bc273197c45",
2164
+ "type": "process-terminate",
2165
+ "z": "2766c40d84283368",
2166
+ "g": "9081b057a931f0cf",
2167
+ "name": "",
2168
+ "engine": "42e6796dddd9d4db",
2169
+ "x": 170,
2170
+ "y": 140,
2171
+ "wires": [
2172
+ [
2173
+ "bb734a85d4b37728"
2174
+ ]
2175
+ ]
2176
+ },
2177
+ {
2178
+ "id": "bb734a85d4b37728",
2179
+ "type": "debug",
2180
+ "z": "2766c40d84283368",
2181
+ "g": "9081b057a931f0cf",
2182
+ "name": "debug 35",
2183
+ "active": true,
2184
+ "tosidebar": true,
2185
+ "console": false,
2186
+ "tostatus": false,
2187
+ "complete": "false",
2188
+ "statusVal": "",
2189
+ "statusType": "auto",
2190
+ "x": 370,
2191
+ "y": 140,
2192
+ "wires": []
2193
+ },
2194
+ {
2195
+ "id": "3d03550f7d93bfd3",
2196
+ "type": "comment",
2197
+ "z": "2766c40d84283368",
2198
+ "g": "9081b057a931f0cf",
2199
+ "name": "Event for Terminating a Process",
2200
+ "info": "",
2201
+ "x": 210,
2202
+ "y": 80,
2203
+ "wires": []
2097
2204
  }
2098
2205
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@5minds/node-red-contrib-processcube",
3
- "version": "1.5.6-feature-aa14a2-m3pntyi8",
3
+ "version": "1.5.7-develop-41d845-m3q6c4hg",
4
4
  "license": "MIT",
5
5
  "description": "Node-RED nodes for ProcessCube",
6
6
  "scripts": {
@@ -4,13 +4,6 @@ module.exports = function (RED) {
4
4
  var node = this;
5
5
  node.engine = RED.nodes.getNode(config.engine);
6
6
 
7
- const eventEmitter = node.engine.eventEmitter;
8
-
9
- eventEmitter.on('engine-client-changed', () => {
10
- node.log('new engineClient received');
11
- register();
12
- });
13
-
14
7
  const register = async () => {
15
8
  const client = node.engine.engineClient;
16
9
 
@@ -31,8 +24,7 @@ module.exports = function (RED) {
31
24
  async (processNotification) => {
32
25
  if (
33
26
  config.processmodel != '' &&
34
- config.processmodel != processNotification.processModelId
35
- ) {
27
+ config.processmodel != processNotification.processModelId) {
36
28
  return;
37
29
  }
38
30
 
@@ -73,8 +65,7 @@ module.exports = function (RED) {
73
65
  async (processNotification) => {
74
66
  if (
75
67
  config.processmodel != '' &&
76
- config.processmodel != processNotification.processModelId
77
- ) {
68
+ config.processmodel != processNotification.processModelId) {
78
69
  return;
79
70
  }
80
71
 
@@ -442,6 +433,7 @@ module.exports = function (RED) {
442
433
  },
443
434
  { identity: currentIdentity }
444
435
  );
436
+
445
437
  });
446
438
 
447
439
  node.on('close', () => {
@@ -29,9 +29,10 @@
29
29
  <script type="text/markdown" data-help-name="process-terminate">
30
30
  Terminate an instance of a process model in the ProcessCube.
31
31
 
32
- ## Inputs
32
+ ## Configs
33
33
 
34
- : payload (string): The id of the processinstance that is going to be terminated.
34
+ : name (string): name of the node
35
+ : engine (string): the engine to connect to
35
36
 
36
37
  ## Outputs
37
38
 
@@ -1,4 +1,3 @@
1
- const EventEmitter = require('node:events');
2
1
  const engine_client = require('@5minds/processcube_engine_client');
3
2
  const jwt = require('jwt-decode');
4
3
  const oidc = require('openid-client');
@@ -13,8 +12,7 @@ module.exports = function (RED) {
13
12
  this.credentials.clientId = RED.util.evaluateNodeProperty(n.clientId, n.clientIdType, node);
14
13
  this.credentials.clientSecret = RED.util.evaluateNodeProperty(n.clientSecret, n.clientSecretType, node);
15
14
 
16
- node.eventEmitter = new EventEmitter();
17
-
15
+ // known issue: kann bei falschem timing zu laufzeitfehlern führen (absprache MM)
18
16
  // set the engine url
19
17
  const stopRefreshing = periodicallyRefreshEngineClient(this, n, 10000);
20
18
 
@@ -43,7 +41,7 @@ module.exports = function (RED) {
43
41
  function refreshUrl() {
44
42
  const newUrl = RED.util.evaluateNodeProperty(n.url, n.urlType, node);
45
43
 
46
- if (node.url === newUrl) {
44
+ if (node.url == newUrl) {
47
45
  return;
48
46
  }
49
47
 
@@ -55,15 +53,11 @@ module.exports = function (RED) {
55
53
  node.engineClient = new engine_client.EngineClient(node.url, () =>
56
54
  getFreshIdentity(node.url, node)
57
55
  );
58
-
59
- node.eventEmitter.emit('engine-client-changed');
60
56
  } else {
61
57
  if (this.engineClient) {
62
58
  this.engineClient.dispose();
63
59
  }
64
60
  node.engineClient = new engine_client.EngineClient(node.url);
65
-
66
- node.eventEmitter.emit('engine-client-changed');
67
61
  }
68
62
  }
69
63