@5minds/node-red-contrib-processcube 1.5.6-develop-51b402-m3iul3hf → 1.5.6-feature-aa14a2-m3pntyi8

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,6 +4,13 @@ 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
+
7
14
  const register = async () => {
8
15
  const client = node.engine.engineClient;
9
16
 
@@ -11,7 +18,7 @@ module.exports = function (RED) {
11
18
  node.error('No engine configured.');
12
19
  return;
13
20
  }
14
-
21
+
15
22
  let currentIdentity = node.engine.identity;
16
23
 
17
24
  let subscription = null;
@@ -23,24 +30,23 @@ module.exports = function (RED) {
23
30
  payload: endEventFinished,
24
31
  });
25
32
  },
26
- { identity: currentIdentity },
33
+ { identity: currentIdentity }
27
34
  );
28
35
 
29
36
  node.engine.registerOnIdentityChanged(async (identity) => {
30
37
  client.events.removeSubscription(subscription, currentIdentity);
31
-
38
+
32
39
  currentIdentity = identity;
33
40
 
34
41
  subscription = await client.events.onEndEventFinished(
35
42
  (endEventFinished) => {
36
43
  node.send({
37
- payload: endEventFinished
44
+ payload: endEventFinished,
38
45
  });
39
46
  },
40
- { identity: currentIdentity },
47
+ { identity: currentIdentity }
41
48
  );
42
49
  });
43
-
44
50
  } catch (error) {
45
51
  node.error(error);
46
52
  }
@@ -4,6 +4,13 @@ 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
+
7
14
  const register = async () => {
8
15
  let currentIdentity = node.engine.identity;
9
16
 
@@ -32,132 +32,149 @@ module.exports = function (RED) {
32
32
  eventEmitter = flowContext.get('emitter');
33
33
  }
34
34
 
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
- };
43
-
44
- return await new Promise((resolve, reject) => {
45
- const handleFinishTask = (msg) => {
46
- let result = RED.util.encodeObject(msg.payload);
35
+ const engineEventEmitter = node.engine.eventEmitter;
47
36
 
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
- );
37
+ engineEventEmitter.on('engine-client-changed', () => {
38
+ node.log('new engineClient received');
39
+ register();
40
+ });
51
41
 
52
- if (externalTask.flowNodeInstanceId) {
53
- delete started_external_tasks[externalTask.flowNodeInstanceId];
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}`);
54
49
  }
50
+ };
55
51
 
56
- showStatus(node, Object.keys(started_external_tasks).length);
52
+ return await new Promise((resolve, reject) => {
53
+ const handleFinishTask = (msg) => {
54
+ let result = RED.util.encodeObject(msg.payload);
57
55
 
58
- //resolve(result);
59
- saveHandleCallback(result, resolve);
60
- };
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
+ );
61
59
 
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
- );
60
+ if (externalTask.flowNodeInstanceId) {
61
+ delete started_external_tasks[externalTask.flowNodeInstanceId];
62
+ }
66
63
 
67
- if (externalTask.flowNodeInstanceId) {
68
- delete started_external_tasks[externalTask.flowNodeInstanceId];
69
- }
64
+ showStatus(node, Object.keys(started_external_tasks).length);
70
65
 
71
- showStatus(node, Object.keys(started_external_tasks).length);
66
+ //resolve(result);
67
+ saveHandleCallback(result, resolve);
68
+ };
72
69
 
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
- };
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
+ );
79
74
 
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
- );
75
+ if (externalTask.flowNodeInstanceId) {
76
+ delete started_external_tasks[externalTask.flowNodeInstanceId];
77
+ }
84
78
 
85
- if (isError) {
86
- handleErrorTask(msg);
87
- } else {
88
- handleFinishTask(msg);
89
- }
90
- });
79
+ showStatus(node, Object.keys(started_external_tasks).length);
91
80
 
92
- started_external_tasks[externalTask.flowNodeInstanceId] = externalTask;
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
+ };
93
87
 
94
- showStatus(node, Object.keys(started_external_tasks).length);
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
+ );
95
92
 
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
- };
93
+ if (isError) {
94
+ handleErrorTask(msg);
95
+ } else {
96
+ handleFinishTask(msg);
97
+ }
98
+ });
103
99
 
104
- node.log(
105
- `Received *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}' with *msg._msgid* '${msg._msgid}'`
106
- );
100
+ started_external_tasks[externalTask.flowNodeInstanceId] = externalTask;
107
101
 
108
- node.send(msg);
109
- });
110
- };
102
+ showStatus(node, Object.keys(started_external_tasks).length);
111
103
 
112
- client.externalTasks
113
- .subscribeToExternalTaskTopic(config.topic, etwCallback, RED.util.evaluateNodeProperty(config.workerConfig, 'json', node))
114
- .then(async (externalTaskWorker) => {
115
- node.status({ fill: 'blue', shape: 'ring', text: 'subcribed' });
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
+ };
116
111
 
117
- externalTaskWorker.identity = engine.identity;
118
- engine.registerOnIdentityChanged((identity) => {
119
- externalTaskWorker.identity = identity;
120
- });
112
+ node.log(
113
+ `Received *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}' with *msg._msgid* '${msg._msgid}'`
114
+ );
121
115
 
122
- // export type WorkerErrorHandler = (errorType: 'fetchAndLock' | 'extendLock' | 'processExternalTask' | 'finishExternalTask', error: Error, externalTask?: ExternalTask<any>) => void;
123
- externalTaskWorker.onWorkerError((errorType, error, externalTask) => {
124
- switch (errorType) {
125
- case 'extendLock':
126
- case 'finishExternalTask':
127
- case 'processExternalTask':
128
- node.error(
129
- `Worker error ${errorType} for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}': ${error.message}`
130
- );
131
-
132
- if (externalTask) {
133
- delete started_external_tasks[externalTask.flowNodeInstanceId];
134
- }
135
-
136
- showStatus(node, Object.keys(started_external_tasks).length);
137
- break;
138
- default:
139
- node.error(`Worker error ${errorType}: ${error.message}`);
140
- break;
141
- }
116
+ node.send(msg);
142
117
  });
118
+ };
143
119
 
144
- try {
145
- externalTaskWorker.start();
146
- } catch (error) {
147
- node.error(`Worker start 'externalTaskWorker.start' failed: ${error.message}`);
148
- }
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
+ });
149
155
 
150
- node.on('close', () => {
151
156
  try {
152
- externalTaskWorker.stop();
153
- } catch {
154
- node.error('Client close failed');
157
+ externalTaskWorker.start();
158
+ } catch (error) {
159
+ node.error(`Worker start 'externalTaskWorker.start' failed: ${error.message}`);
155
160
  }
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}`);
156
172
  });
157
- })
158
- .catch((error) => {
159
- node.error(`Error in subscribeToExternalTaskTopic: ${error.message}`);
160
- });
173
+ };
174
+
175
+ if (node.engine) {
176
+ register();
177
+ }
161
178
  }
162
179
 
163
180
  RED.nodes.registerType('externaltask-input', ExternalTaskInput);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@5minds/node-red-contrib-processcube",
3
- "version": "1.5.6-develop-51b402-m3iul3hf",
3
+ "version": "1.5.6-feature-aa14a2-m3pntyi8",
4
4
  "license": "MIT",
5
5
  "description": "Node-RED nodes for ProcessCube",
6
6
  "scripts": {
@@ -4,6 +4,13 @@ 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
+
7
14
  const register = async () => {
8
15
  const client = node.engine.engineClient;
9
16
 
@@ -24,7 +31,8 @@ module.exports = function (RED) {
24
31
  async (processNotification) => {
25
32
  if (
26
33
  config.processmodel != '' &&
27
- config.processmodel != processNotification.processModelId) {
34
+ config.processmodel != processNotification.processModelId
35
+ ) {
28
36
  return;
29
37
  }
30
38
 
@@ -65,7 +73,8 @@ module.exports = function (RED) {
65
73
  async (processNotification) => {
66
74
  if (
67
75
  config.processmodel != '' &&
68
- config.processmodel != processNotification.processModelId) {
76
+ config.processmodel != processNotification.processModelId
77
+ ) {
69
78
  return;
70
79
  }
71
80
 
@@ -433,7 +442,6 @@ module.exports = function (RED) {
433
442
  },
434
443
  { identity: currentIdentity }
435
444
  );
436
-
437
445
  });
438
446
 
439
447
  node.on('close', () => {
@@ -1,3 +1,4 @@
1
+ const EventEmitter = require('node:events');
1
2
  const engine_client = require('@5minds/processcube_engine_client');
2
3
  const jwt = require('jwt-decode');
3
4
  const oidc = require('openid-client');
@@ -12,7 +13,8 @@ module.exports = function (RED) {
12
13
  this.credentials.clientId = RED.util.evaluateNodeProperty(n.clientId, n.clientIdType, node);
13
14
  this.credentials.clientSecret = RED.util.evaluateNodeProperty(n.clientSecret, n.clientSecretType, node);
14
15
 
15
- // known issue: kann bei falschem timing zu laufzeitfehlern führen (absprache MM)
16
+ node.eventEmitter = new EventEmitter();
17
+
16
18
  // set the engine url
17
19
  const stopRefreshing = periodicallyRefreshEngineClient(this, n, 10000);
18
20
 
@@ -41,7 +43,7 @@ module.exports = function (RED) {
41
43
  function refreshUrl() {
42
44
  const newUrl = RED.util.evaluateNodeProperty(n.url, n.urlType, node);
43
45
 
44
- if (node.url == newUrl) {
46
+ if (node.url === newUrl) {
45
47
  return;
46
48
  }
47
49
 
@@ -53,11 +55,15 @@ module.exports = function (RED) {
53
55
  node.engineClient = new engine_client.EngineClient(node.url, () =>
54
56
  getFreshIdentity(node.url, node)
55
57
  );
58
+
59
+ node.eventEmitter.emit('engine-client-changed');
56
60
  } else {
57
61
  if (this.engineClient) {
58
62
  this.engineClient.dispose();
59
63
  }
60
64
  node.engineClient = new engine_client.EngineClient(node.url);
65
+
66
+ node.eventEmitter.emit('engine-client-changed');
61
67
  }
62
68
  }
63
69
 
@@ -4,6 +4,13 @@ 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
+
7
14
  const register = async () => {
8
15
  let currentIdentity = node.engine.identity;
9
16
 
@@ -20,7 +27,7 @@ module.exports = function (RED) {
20
27
  function userTaskCallback() {
21
28
  return async (userTaskNotification) => {
22
29
  if (config.usertask != '' && config.usertask != userTaskNotification.flowNodeId) return;
23
-
30
+
24
31
  const newQuery = {
25
32
  flowNodeInstanceId: userTaskNotification.flowNodeInstanceId,
26
33
  ...query,
@@ -84,7 +91,7 @@ module.exports = function (RED) {
84
91
  currentIdentity = identity;
85
92
 
86
93
  subscription = subscribe();
87
- })
94
+ });
88
95
 
89
96
  node.on('close', async () => {
90
97
  if (node.engine && node.engine.engineClient && client) {
@@ -5,13 +5,12 @@ module.exports = function (RED) {
5
5
 
6
6
  node.engine = RED.nodes.getNode(config.engine);
7
7
 
8
- const client = node.engine.engineClient;
9
-
10
8
  let subscription = null;
11
9
  let currentIdentity = node.engine.identity;
12
10
  let subscribe = null;
13
11
 
14
12
  node.on('input', async function (msg) {
13
+ const client = node.engine.engineClient;
15
14
  subscribe = async () => {
16
15
  if (!client) {
17
16
  node.error('No engine configured.');
@@ -20,44 +19,49 @@ module.exports = function (RED) {
20
19
 
21
20
  const query = RED.util.evaluateNodeProperty(config.query, config.query_type, node, msg);
22
21
 
23
- subscription = await client.userTasks.onUserTaskWaiting(async (userTaskWaitingNotification) => {
24
-
25
- const newQuery = {
26
- 'flowNodeInstanceId': userTaskWaitingNotification.flowNodeInstanceId,
27
- ...query
28
- };
29
-
30
- try {
31
- const matchingFlowNodes = await client.userTasks.query(newQuery, { identity: currentIdentity });
32
-
33
- if (matchingFlowNodes.userTasks && matchingFlowNodes.userTasks.length == 1) {
34
- // remove subscription
35
- client.userTasks.removeSubscription(subscription, currentIdentity);
36
-
37
- const userTask = matchingFlowNodes.userTasks[0];
38
-
39
- msg.payload = { userTask: userTask };
40
- node.send(msg);
41
- } else {
42
- // nothing todo - wait for next notification
22
+ subscription = await client.userTasks.onUserTaskWaiting(
23
+ async (userTaskWaitingNotification) => {
24
+ const newQuery = {
25
+ flowNodeInstanceId: userTaskWaitingNotification.flowNodeInstanceId,
26
+ ...query,
27
+ };
28
+
29
+ try {
30
+ const matchingFlowNodes = await client.userTasks.query(newQuery, {
31
+ identity: currentIdentity,
32
+ });
33
+
34
+ if (matchingFlowNodes.userTasks && matchingFlowNodes.userTasks.length == 1) {
35
+ // remove subscription
36
+ client.userTasks.removeSubscription(subscription, currentIdentity);
37
+
38
+ const userTask = matchingFlowNodes.userTasks[0];
39
+
40
+ msg.payload = { userTask: userTask };
41
+ node.send(msg);
42
+ } else {
43
+ // nothing todo - wait for next notification
44
+ }
45
+ } catch (error) {
46
+ node.error(error);
43
47
  }
44
- } catch (error) {
45
- node.error(error);
46
- }
48
+ },
49
+ { identity: currentIdentity }
50
+ );
47
51
 
48
- }, { identity: currentIdentity });
49
-
50
- node.log({ "Handling old userTasks config.only_for_new": config.only_for_new });
52
+ node.log({ 'Handling old userTasks config.only_for_new': config.only_for_new });
51
53
 
52
54
  if (config.only_for_new === false) {
53
55
  // only check suspended user tasks
54
56
  const suspendedQuery = {
55
- 'state': 'suspended',
56
- ...query
57
+ state: 'suspended',
58
+ ...query,
57
59
  };
58
60
 
59
61
  try {
60
- const matchingFlowNodes = await client.userTasks.query(suspendedQuery, { identity: currentIdentity });
62
+ const matchingFlowNodes = await client.userTasks.query(suspendedQuery, {
63
+ identity: currentIdentity,
64
+ });
61
65
 
62
66
  if (matchingFlowNodes.userTasks && matchingFlowNodes.userTasks.length >= 1) {
63
67
  const userTask = matchingFlowNodes.userTasks[0];
@@ -80,7 +84,6 @@ module.exports = function (RED) {
80
84
  });
81
85
 
82
86
  node.engine.registerOnIdentityChanged(async (identity) => {
83
-
84
87
  if (subscription) {
85
88
  client.userTasks.removeSubscription(subscription, currentIdentity);
86
89
  currentIdentity = identity;
@@ -90,11 +93,11 @@ module.exports = function (RED) {
90
93
  }
91
94
  });
92
95
 
93
- node.on("close", async () => {
96
+ node.on('close', async () => {
94
97
  if (client != null && subscription != null) {
95
98
  client.userTasks.removeSubscription(subscription, currentIdentity);
96
99
  }
97
100
  });
98
101
  }
99
- RED.nodes.registerType("wait-for-usertask", WaitForUsertask);
100
- }
102
+ RED.nodes.registerType('wait-for-usertask', WaitForUsertask);
103
+ };