@5minds/node-red-contrib-processcube 1.5.5 → 1.5.6-feature-60b2c2-m3pneelx

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
+ console.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
+ console.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
+ console.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.5",
3
+ "version": "1.5.6-feature-60b2c2-m3pneelx",
4
4
  "license": "MIT",
5
5
  "description": "Node-RED nodes for ProcessCube",
6
6
  "scripts": {
@@ -57,7 +57,7 @@
57
57
  "examples": "examples"
58
58
  },
59
59
  "dependencies": {
60
- "@5minds/processcube_engine_client": "^5.1.0",
60
+ "@5minds/processcube_engine_client": "5.1.0-hotfix-a73235-m346kg1n",
61
61
  "jwt-decode": "^4.0.0",
62
62
  "openid-client": "^5.5.0"
63
63
  },
@@ -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
+ console.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,20 +1,23 @@
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');
4
5
 
5
- const DELAY_FACTOR = 0.85;
6
-
7
6
  module.exports = function (RED) {
8
7
  function ProcessCubeEngineNode(n) {
9
8
  RED.nodes.createNode(this, n);
10
9
  const node = this;
11
10
  const identityChangedCallbacks = [];
12
- this.url = RED.util.evaluateNodeProperty(n.url, n.urlType, node);
13
11
  this.identity = null;
14
12
 
15
13
  this.credentials.clientId = RED.util.evaluateNodeProperty(n.clientId, n.clientIdType, node);
16
14
  this.credentials.clientSecret = RED.util.evaluateNodeProperty(n.clientSecret, n.clientSecretType, node);
17
15
 
16
+ node.eventEmitter = new EventEmitter();
17
+
18
+ // set the engine url
19
+ const stopRefreshing = periodicallyRefreshEngineClient(this, n, 10000);
20
+
18
21
  this.registerOnIdentityChanged = function (callback) {
19
22
  identityChangedCallbacks.push(callback);
20
23
  };
@@ -36,123 +39,99 @@ module.exports = function (RED) {
36
39
  }
37
40
  };
38
41
 
39
- node.on('close', async () => {
40
- if (this.engineClient) {
41
- this.engineClient.dispose();
42
- this.engineClient = null;
42
+ function periodicallyRefreshEngineClient(node, n, intervalMs) {
43
+ function refreshUrl() {
44
+ const newUrl = RED.util.evaluateNodeProperty(n.url, n.urlType, node);
45
+
46
+ if (node.url === newUrl) {
47
+ return;
48
+ }
49
+
50
+ node.url = newUrl;
51
+ if (node.credentials.clientId && node.credentials.clientSecret) {
52
+ if (this.engineClient) {
53
+ this.engineClient.dispose();
54
+ }
55
+ node.engineClient = new engine_client.EngineClient(node.url, () =>
56
+ getFreshIdentity(node.url, node)
57
+ );
58
+
59
+ node.eventEmitter.emit('engine-client-changed');
60
+ } else {
61
+ if (this.engineClient) {
62
+ this.engineClient.dispose();
63
+ }
64
+ node.engineClient = new engine_client.EngineClient(node.url);
65
+
66
+ node.eventEmitter.emit('engine-client-changed');
67
+ }
43
68
  }
44
- });
45
69
 
46
- if (this.credentials.clientId && this.credentials.clientSecret) {
47
- this.engineClient = new engine_client.EngineClient(this.url);
48
-
49
- this.engineClient.applicationInfo
50
- .getAuthorityAddress()
51
- .then((authorityUrl) => {
52
- startRefreshingIdentityCycle(
53
- this.credentials.clientId,
54
- this.credentials.clientSecret,
55
- authorityUrl,
56
- node
57
- ).catch((reason) => {
58
- console.error(reason);
59
- node.error(reason);
60
- });
61
- })
62
- .catch((reason) => {
63
- console.error(reason);
64
- node.error(reason);
65
- });
66
- } else {
67
- this.engineClient = new engine_client.EngineClient(this.url);
68
- }
69
- }
70
- RED.nodes.registerType('processcube-engine-config', ProcessCubeEngineNode, {
71
- credentials: {
72
- clientId: { type: 'text' },
73
- clientSecret: { type: 'password' },
74
- },
75
- });
76
- };
70
+ refreshUrl();
71
+ const intervalId = setInterval(refreshUrl, intervalMs);
77
72
 
78
- async function getFreshTokenSet(clientId, clientSecret, authorityUrl) {
79
- const issuer = await oidc.Issuer.discover(authorityUrl);
73
+ return () => clearInterval(intervalId);
74
+ }
80
75
 
81
- const client = new issuer.Client({
82
- client_id: clientId,
83
- client_secret: clientSecret,
84
- });
76
+ async function getFreshIdentity(url, node) {
77
+ try {
78
+ if (
79
+ !RED.util.evaluateNodeProperty(n.clientId, n.clientIdType, node) ||
80
+ !RED.util.evaluateNodeProperty(n.clientSecret, n.clientSecretType, node)
81
+ ) {
82
+ return null;
83
+ }
84
+
85
+ const res = await fetch(url + '/atlas_engine/api/v1/authority', {
86
+ method: 'GET',
87
+ headers: {
88
+ Authorization: `Bearer ZHVtbXlfdG9rZW4=`,
89
+ 'Content-Type': 'application/json',
90
+ },
91
+ });
85
92
 
86
- const tokenSet = await client.grant({
87
- grant_type: 'client_credentials',
88
- scope: 'engine_etw engine_read engine_write',
89
- });
93
+ const body = await res.json();
90
94
 
91
- return tokenSet;
92
- }
95
+ const issuer = await oidc.Issuer.discover(body);
93
96
 
94
- function getIdentityForExternalTaskWorkers(tokenSet) {
95
- const accessToken = tokenSet.access_token;
96
- const decodedToken = jwt.jwtDecode(accessToken);
97
+ const client = new issuer.Client({
98
+ client_id: RED.util.evaluateNodeProperty(n.clientId, n.clientIdType, node),
99
+ client_secret: RED.util.evaluateNodeProperty(n.clientSecret, n.clientSecretType, node),
100
+ });
97
101
 
98
- return {
99
- token: tokenSet.access_token,
100
- userId: decodedToken.sub,
101
- };
102
- }
102
+ const tokenSet = await client.grant({
103
+ grant_type: 'client_credentials',
104
+ scope: 'engine_etw engine_read engine_write',
105
+ });
103
106
 
104
- async function getExpiresInForExternalTaskWorkers(tokenSet) {
105
- let expiresIn = tokenSet.expires_in;
107
+ const accessToken = tokenSet.access_token;
108
+ const decodedToken = jwt.jwtDecode(accessToken);
106
109
 
107
- if (!expiresIn && tokenSet.expires_at) {
108
- expiresIn = Math.floor(tokenSet.expires_at - Date.now() / 1000);
109
- }
110
+ const freshIdentity = {
111
+ token: tokenSet.access_token,
112
+ userId: decodedToken.sub,
113
+ };
110
114
 
111
- if (expiresIn === undefined) {
112
- throw new Error('Could not determine the time until the access token for external task workers expires');
113
- }
115
+ node.setIdentity(freshIdentity);
114
116
 
115
- return expiresIn;
116
- }
117
-
118
- /**
119
- * Start refreshing the identity in regular intervals.
120
- * @param {TokenSet | null} tokenSet The token set to refresh the identity for
121
- * @returns {Promise<void>} A promise that resolves when the timer for refreshing the identity is initialized
122
- * */
123
- async function startRefreshingIdentityCycle(clientId, clientSecret, authorityUrl, configNode) {
124
- let retries = 5;
125
-
126
- const refresh = async () => {
127
- try {
128
- const newTokenSet = await getFreshTokenSet(clientId, clientSecret, authorityUrl);
129
- const expiresIn = await getExpiresInForExternalTaskWorkers(newTokenSet);
130
- const delay = expiresIn * DELAY_FACTOR * 1000;
131
-
132
- freshIdentity = getIdentityForExternalTaskWorkers(newTokenSet);
133
-
134
- configNode.setIdentity(freshIdentity);
135
-
136
- retries = 5;
137
- setTimeout(refresh, delay);
138
- } catch (error) {
139
- if (retries === 0) {
140
- console.error(
141
- 'Could not refresh identity for external task worker processes. Stopping all external task workers.',
142
- { error }
143
- );
144
- return;
117
+ return freshIdentity;
118
+ } catch (e) {
119
+ node.error(`Could not get fresh identity: ${e}`);
145
120
  }
146
- console.error('Could not refresh identity for external task worker processes.', {
147
- error,
148
- retryCount: retries,
149
- });
150
- retries--;
151
-
152
- const delay = 2 * 1000;
153
- setTimeout(refresh, delay);
154
121
  }
155
- };
156
122
 
157
- await refresh();
158
- }
123
+ node.on('close', async () => {
124
+ if (this.engineClient) {
125
+ stopRefreshing();
126
+ this.engineClient.dispose();
127
+ this.engineClient = null;
128
+ }
129
+ });
130
+ }
131
+ RED.nodes.registerType('processcube-engine-config', ProcessCubeEngineNode, {
132
+ credentials: {
133
+ clientId: { type: 'text' },
134
+ clientSecret: { type: 'password' },
135
+ },
136
+ });
137
+ };
@@ -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
+ console.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
+ };