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

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
+ 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
+ };