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

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ };