@5minds/node-red-contrib-processcube 1.5.5-feature-22f94f-m3eulbpf → 1.5.6-develop-51b402-m3iul3hf

Sign up to get free protection for your applications and to get access to all the features.
@@ -24,33 +24,38 @@ module.exports = function (RED) {
24
24
  async (processNotification) => {
25
25
  if (
26
26
  config.processmodel != '' &&
27
- config.processmodel != processNotification.processModelId
28
- )
27
+ config.processmodel != processNotification.processModelId) {
29
28
  return;
29
+ }
30
+
30
31
  const newQuery = {
31
32
  processInstanceId: processNotification.processInstanceId,
32
33
  ...query,
33
34
  };
34
35
 
35
- const matchingInstances = await client.processInstances.query(newQuery, {
36
- identity: currentIdentity,
37
- });
38
-
39
- if (
40
- matchingInstances.processInstances &&
41
- matchingInstances.processInstances.length == 1
42
- ) {
43
- const processInstance = matchingInstances.processInstances[0];
44
-
45
- node.send({
46
- payload: {
47
- processInstanceId: processNotification.processInstanceId,
48
- processModelId: processNotification.processModelId,
49
- processInstance: processInstance,
50
- action: 'starting',
51
- type: 'processInstance',
52
- },
36
+ try {
37
+ const matchingInstances = await client.processInstances.query(newQuery, {
38
+ identity: currentIdentity,
53
39
  });
40
+
41
+ if (
42
+ matchingInstances.processInstances &&
43
+ matchingInstances.processInstances.length == 1
44
+ ) {
45
+ const processInstance = matchingInstances.processInstances[0];
46
+
47
+ node.send({
48
+ payload: {
49
+ processInstanceId: processNotification.processInstanceId,
50
+ processModelId: processNotification.processModelId,
51
+ processInstance: processInstance,
52
+ action: 'starting',
53
+ type: 'processInstance',
54
+ },
55
+ });
56
+ }
57
+ } catch (error) {
58
+ node.error(error);
54
59
  }
55
60
  },
56
61
  { identity: currentIdentity }
@@ -60,34 +65,39 @@ module.exports = function (RED) {
60
65
  async (processNotification) => {
61
66
  if (
62
67
  config.processmodel != '' &&
63
- config.processmodel != processNotification.processModelId
64
- )
68
+ config.processmodel != processNotification.processModelId) {
65
69
  return;
70
+ }
71
+
66
72
  const newQuery = {
67
73
  processInstanceId: processNotification.processInstanceId,
68
74
  ...query,
69
75
  };
70
76
 
71
- const matchingInstances = await client.processInstances.query(newQuery, {
72
- identity: currentIdentity,
73
- });
74
-
75
- if (
76
- matchingInstances.processInstances &&
77
- matchingInstances.processInstances.length == 1
78
- ) {
79
- const processInstance = matchingInstances.processInstances[0];
80
- node.send({
81
- payload: {
82
- processInstanceId: processNotification.processInstanceId,
83
- processModelId: processNotification.processModelId,
84
- flowNodeId: processNotification.flowNodeId,
85
- token: processNotification.currentToken,
86
- processInstance: processInstance,
87
- action: 'started',
88
- type: 'processInstance',
89
- },
77
+ try {
78
+ const matchingInstances = await client.processInstances.query(newQuery, {
79
+ identity: currentIdentity,
90
80
  });
81
+
82
+ if (
83
+ matchingInstances.processInstances &&
84
+ matchingInstances.processInstances.length == 1
85
+ ) {
86
+ const processInstance = matchingInstances.processInstances[0];
87
+ node.send({
88
+ payload: {
89
+ processInstanceId: processNotification.processInstanceId,
90
+ processModelId: processNotification.processModelId,
91
+ flowNodeId: processNotification.flowNodeId,
92
+ token: processNotification.currentToken,
93
+ processInstance: processInstance,
94
+ action: 'started',
95
+ type: 'processInstance',
96
+ },
97
+ });
98
+ }
99
+ } catch (error) {
100
+ node.error(error);
91
101
  }
92
102
  },
93
103
  { identity: currentIdentity }
@@ -106,25 +116,29 @@ module.exports = function (RED) {
106
116
  ...query,
107
117
  };
108
118
 
109
- const matchingInstances = await client.processInstances.query(newQuery, {
110
- identity: currentIdentity,
111
- });
112
-
113
- if (
114
- matchingInstances.processInstances &&
115
- matchingInstances.processInstances.length == 1
116
- ) {
117
- const processInstance = matchingInstances.processInstances[0];
118
- node.send({
119
- payload: {
120
- processInstanceId: processNotification.processInstanceId,
121
- processModelId: processNotification.processModelId,
122
- token: processNotification.currentToken,
123
- processInstance: processInstance,
124
- action: 'resumed',
125
- type: 'processInstance',
126
- },
119
+ try {
120
+ const matchingInstances = await client.processInstances.query(newQuery, {
121
+ identity: currentIdentity,
127
122
  });
123
+
124
+ if (
125
+ matchingInstances.processInstances &&
126
+ matchingInstances.processInstances.length == 1
127
+ ) {
128
+ const processInstance = matchingInstances.processInstances[0];
129
+ node.send({
130
+ payload: {
131
+ processInstanceId: processNotification.processInstanceId,
132
+ processModelId: processNotification.processModelId,
133
+ token: processNotification.currentToken,
134
+ processInstance: processInstance,
135
+ action: 'resumed',
136
+ type: 'processInstance',
137
+ },
138
+ });
139
+ }
140
+ } catch (error) {
141
+ node.error(error);
128
142
  }
129
143
  },
130
144
  { identity: currentIdentity }
@@ -143,26 +157,30 @@ module.exports = function (RED) {
143
157
  ...query,
144
158
  };
145
159
 
146
- const matchingInstances = await client.processInstances.query(newQuery, {
147
- identity: currentIdentity,
148
- });
149
-
150
- if (
151
- matchingInstances.processInstances &&
152
- matchingInstances.processInstances.length == 1
153
- ) {
154
- const processInstance = matchingInstances.processInstances[0];
155
- node.send({
156
- payload: {
157
- processInstanceId: processNotification.processInstanceId,
158
- processModelId: processNotification.processModelId,
159
- flowNodeId: processNotification.flowNodeId,
160
- token: processNotification.currentToken,
161
- processInstance: processInstance,
162
- action: 'finished',
163
- type: 'processInstance',
164
- },
160
+ try {
161
+ const matchingInstances = await client.processInstances.query(newQuery, {
162
+ identity: currentIdentity,
165
163
  });
164
+
165
+ if (
166
+ matchingInstances.processInstances &&
167
+ matchingInstances.processInstances.length == 1
168
+ ) {
169
+ const processInstance = matchingInstances.processInstances[0];
170
+ node.send({
171
+ payload: {
172
+ processInstanceId: processNotification.processInstanceId,
173
+ processModelId: processNotification.processModelId,
174
+ flowNodeId: processNotification.flowNodeId,
175
+ token: processNotification.currentToken,
176
+ processInstance: processInstance,
177
+ action: 'finished',
178
+ type: 'processInstance',
179
+ },
180
+ });
181
+ }
182
+ } catch (error) {
183
+ node.error(error);
166
184
  }
167
185
  },
168
186
  { identity: currentIdentity }
@@ -181,25 +199,28 @@ module.exports = function (RED) {
181
199
  ...query,
182
200
  };
183
201
 
184
- const matchingInstances = await client.processInstances.query(newQuery, {
185
- identity: currentIdentity,
186
- });
187
-
188
- if (
189
- matchingInstances.processInstances &&
190
- matchingInstances.processInstances.length == 1
191
- ) {
192
- const processInstance = matchingInstances.processInstances[0];
193
- node.send({
194
- payload: {
195
- processInstanceId: processNotification.processInstanceId,
196
- processModelId: processNotification.processModelId,
197
- token: processNotification.currentToken,
198
- processInstance: processInstance,
199
- action: 'terminated',
200
- type: 'processInstance',
201
- },
202
+ try {
203
+ const matchingInstances = await client.processInstances.query(newQuery, {
204
+ identity: currentIdentity,
202
205
  });
206
+ if (
207
+ matchingInstances.processInstances &&
208
+ matchingInstances.processInstances.length == 1
209
+ ) {
210
+ const processInstance = matchingInstances.processInstances[0];
211
+ node.send({
212
+ payload: {
213
+ processInstanceId: processNotification.processInstanceId,
214
+ processModelId: processNotification.processModelId,
215
+ token: processNotification.currentToken,
216
+ processInstance: processInstance,
217
+ action: 'terminated',
218
+ type: 'processInstance',
219
+ },
220
+ });
221
+ }
222
+ } catch (error) {
223
+ node.error(error);
203
224
  }
204
225
  },
205
226
  { identity: currentIdentity }
@@ -218,25 +239,29 @@ module.exports = function (RED) {
218
239
  ...query,
219
240
  };
220
241
 
221
- const matchingInstances = await client.processInstances.query(newQuery, {
222
- identity: currentIdentity,
223
- });
224
-
225
- if (
226
- matchingInstances.processInstances &&
227
- matchingInstances.processInstances.length == 1
228
- ) {
229
- const processInstance = matchingInstances.processInstances[0];
230
- node.send({
231
- payload: {
232
- processInstanceId: processNotification.processInstanceId,
233
- processModelId: processNotification.processModelId,
234
- token: processNotification.currentToken,
235
- processInstance: processInstance,
236
- action: 'error',
237
- type: 'processInstance',
238
- },
242
+ try {
243
+ const matchingInstances = await client.processInstances.query(newQuery, {
244
+ identity: currentIdentity,
239
245
  });
246
+
247
+ if (
248
+ matchingInstances.processInstances &&
249
+ matchingInstances.processInstances.length == 1
250
+ ) {
251
+ const processInstance = matchingInstances.processInstances[0];
252
+ node.send({
253
+ payload: {
254
+ processInstanceId: processNotification.processInstanceId,
255
+ processModelId: processNotification.processModelId,
256
+ token: processNotification.currentToken,
257
+ processInstance: processInstance,
258
+ action: 'error',
259
+ type: 'processInstance',
260
+ },
261
+ });
262
+ }
263
+ } catch (error) {
264
+ node.error(error);
240
265
  }
241
266
  },
242
267
  { identity: currentIdentity }
@@ -255,24 +280,28 @@ module.exports = function (RED) {
255
280
  ...query,
256
281
  };
257
282
 
258
- const matchingInstances = await client.processInstances.query(newQuery, {
259
- identity: currentIdentity,
260
- });
261
-
262
- if (
263
- matchingInstances.processInstances &&
264
- matchingInstances.processInstances.length == 1
265
- ) {
266
- const processInstance = matchingInstances.processInstances[0];
267
- node.send({
268
- payload: {
269
- processInstanceId: processNotification.processInstanceId,
270
- processModelId: processNotification.processModelId,
271
- processInstance: processInstance,
272
- action: 'owner-changed',
273
- type: 'processInstance',
274
- },
283
+ try {
284
+ const matchingInstances = await client.processInstances.query(newQuery, {
285
+ identity: currentIdentity,
275
286
  });
287
+
288
+ if (
289
+ matchingInstances.processInstances &&
290
+ matchingInstances.processInstances.length == 1
291
+ ) {
292
+ const processInstance = matchingInstances.processInstances[0];
293
+ node.send({
294
+ payload: {
295
+ processInstanceId: processNotification.processInstanceId,
296
+ processModelId: processNotification.processModelId,
297
+ processInstance: processInstance,
298
+ action: 'owner-changed',
299
+ type: 'processInstance',
300
+ },
301
+ });
302
+ }
303
+ } catch (error) {
304
+ node.error(error);
276
305
  }
277
306
  },
278
307
  { identity: currentIdentity }
@@ -291,24 +320,28 @@ module.exports = function (RED) {
291
320
  ...query,
292
321
  };
293
322
 
294
- const matchingInstances = await client.processInstances.query(newQuery, {
295
- identity: currentIdentity,
296
- });
297
-
298
- if (
299
- matchingInstances.processInstances &&
300
- matchingInstances.processInstances.length == 1
301
- ) {
302
- const processInstance = matchingInstances.processInstances[0];
303
- node.send({
304
- payload: {
305
- processInstanceId: processNotification.processInstanceId,
306
- processModelId: processNotification.processModelId,
307
- processInstance: processInstance,
308
- action: 'instances-deleted',
309
- type: 'processInstance',
310
- },
323
+ try {
324
+ const matchingInstances = await client.processInstances.query(newQuery, {
325
+ identity: currentIdentity,
311
326
  });
327
+
328
+ if (
329
+ matchingInstances.processInstances &&
330
+ matchingInstances.processInstances.length == 1
331
+ ) {
332
+ const processInstance = matchingInstances.processInstances[0];
333
+ node.send({
334
+ payload: {
335
+ processInstanceId: processNotification.processInstanceId,
336
+ processModelId: processNotification.processModelId,
337
+ processInstance: processInstance,
338
+ action: 'instances-deleted',
339
+ type: 'processInstance',
340
+ },
341
+ });
342
+ }
343
+ } catch (error) {
344
+ node.error(error);
312
345
  }
313
346
  },
314
347
  { identity: currentIdentity }
@@ -400,6 +433,7 @@ module.exports = function (RED) {
400
433
  },
401
434
  { identity: currentIdentity }
402
435
  );
436
+
403
437
  });
404
438
 
405
439
  node.on('close', () => {
@@ -29,10 +29,9 @@
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
- ## Configs
32
+ ## Inputs
33
33
 
34
- : name (string): name of the node
35
- : engine (string): the engine to connect to
34
+ : payload (string): The id of the processinstance that is going to be terminated.
36
35
 
37
36
  ## Outputs
38
37
 
@@ -2,19 +2,20 @@ const engine_client = require('@5minds/processcube_engine_client');
2
2
  const jwt = require('jwt-decode');
3
3
  const oidc = require('openid-client');
4
4
 
5
- const DELAY_FACTOR = 0.85;
6
-
7
5
  module.exports = function (RED) {
8
6
  function ProcessCubeEngineNode(n) {
9
7
  RED.nodes.createNode(this, n);
10
8
  const node = this;
11
9
  const identityChangedCallbacks = [];
12
- this.url = RED.util.evaluateNodeProperty(n.url, n.urlType, node);
13
10
  this.identity = null;
14
11
 
15
12
  this.credentials.clientId = RED.util.evaluateNodeProperty(n.clientId, n.clientIdType, node);
16
13
  this.credentials.clientSecret = RED.util.evaluateNodeProperty(n.clientSecret, n.clientSecretType, node);
17
14
 
15
+ // known issue: kann bei falschem timing zu laufzeitfehlern führen (absprache MM)
16
+ // set the engine url
17
+ const stopRefreshing = periodicallyRefreshEngineClient(this, n, 10000);
18
+
18
19
  this.registerOnIdentityChanged = function (callback) {
19
20
  identityChangedCallbacks.push(callback);
20
21
  };
@@ -36,123 +37,95 @@ module.exports = function (RED) {
36
37
  }
37
38
  };
38
39
 
39
- node.on('close', async () => {
40
- if (this.engineClient) {
41
- this.engineClient.dispose();
42
- this.engineClient = null;
40
+ function periodicallyRefreshEngineClient(node, n, intervalMs) {
41
+ function refreshUrl() {
42
+ const newUrl = RED.util.evaluateNodeProperty(n.url, n.urlType, node);
43
+
44
+ if (node.url == newUrl) {
45
+ return;
46
+ }
47
+
48
+ node.url = newUrl;
49
+ if (node.credentials.clientId && node.credentials.clientSecret) {
50
+ if (this.engineClient) {
51
+ this.engineClient.dispose();
52
+ }
53
+ node.engineClient = new engine_client.EngineClient(node.url, () =>
54
+ getFreshIdentity(node.url, node)
55
+ );
56
+ } else {
57
+ if (this.engineClient) {
58
+ this.engineClient.dispose();
59
+ }
60
+ node.engineClient = new engine_client.EngineClient(node.url);
61
+ }
43
62
  }
44
- });
45
63
 
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);
64
+ refreshUrl();
65
+ const intervalId = setInterval(refreshUrl, intervalMs);
66
+
67
+ return () => clearInterval(intervalId);
68
68
  }
69
- }
70
- RED.nodes.registerType('processcube-engine-config', ProcessCubeEngineNode, {
71
- credentials: {
72
- clientId: { type: 'text' },
73
- clientSecret: { type: 'password' },
74
- },
75
- });
76
- };
77
69
 
78
- async function getFreshTokenSet(clientId, clientSecret, authorityUrl) {
79
- const issuer = await oidc.Issuer.discover(authorityUrl);
70
+ async function getFreshIdentity(url, node) {
71
+ try {
72
+ if (
73
+ !RED.util.evaluateNodeProperty(n.clientId, n.clientIdType, node) ||
74
+ !RED.util.evaluateNodeProperty(n.clientSecret, n.clientSecretType, node)
75
+ ) {
76
+ return null;
77
+ }
78
+
79
+ const res = await fetch(url + '/atlas_engine/api/v1/authority', {
80
+ method: 'GET',
81
+ headers: {
82
+ Authorization: `Bearer ZHVtbXlfdG9rZW4=`,
83
+ 'Content-Type': 'application/json',
84
+ },
85
+ });
80
86
 
81
- const client = new issuer.Client({
82
- client_id: clientId,
83
- client_secret: clientSecret,
84
- });
87
+ const body = await res.json();
85
88
 
86
- const tokenSet = await client.grant({
87
- grant_type: 'client_credentials',
88
- scope: 'engine_etw engine_read engine_write',
89
- });
89
+ const issuer = await oidc.Issuer.discover(body);
90
90
 
91
- return tokenSet;
92
- }
91
+ const client = new issuer.Client({
92
+ client_id: RED.util.evaluateNodeProperty(n.clientId, n.clientIdType, node),
93
+ client_secret: RED.util.evaluateNodeProperty(n.clientSecret, n.clientSecretType, node),
94
+ });
93
95
 
94
- function getIdentityForExternalTaskWorkers(tokenSet) {
95
- const accessToken = tokenSet.access_token;
96
- const decodedToken = jwt.jwtDecode(accessToken);
96
+ const tokenSet = await client.grant({
97
+ grant_type: 'client_credentials',
98
+ scope: 'engine_etw engine_read engine_write',
99
+ });
97
100
 
98
- return {
99
- token: tokenSet.access_token,
100
- userId: decodedToken.sub,
101
- };
102
- }
101
+ const accessToken = tokenSet.access_token;
102
+ const decodedToken = jwt.jwtDecode(accessToken);
103
103
 
104
- async function getExpiresInForExternalTaskWorkers(tokenSet) {
105
- let expiresIn = tokenSet.expires_in;
104
+ const freshIdentity = {
105
+ token: tokenSet.access_token,
106
+ userId: decodedToken.sub,
107
+ };
106
108
 
107
- if (!expiresIn && tokenSet.expires_at) {
108
- expiresIn = Math.floor(tokenSet.expires_at - Date.now() / 1000);
109
- }
110
-
111
- if (expiresIn === undefined) {
112
- throw new Error('Could not determine the time until the access token for external task workers expires');
113
- }
109
+ node.setIdentity(freshIdentity);
114
110
 
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;
111
+ return freshIdentity;
112
+ } catch (e) {
113
+ node.error(`Could not get fresh identity: ${e}`);
145
114
  }
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
115
  }
155
- };
156
116
 
157
- await refresh();
158
- }
117
+ node.on('close', async () => {
118
+ if (this.engineClient) {
119
+ stopRefreshing();
120
+ this.engineClient.dispose();
121
+ this.engineClient = null;
122
+ }
123
+ });
124
+ }
125
+ RED.nodes.registerType('processcube-engine-config', ProcessCubeEngineNode, {
126
+ credentials: {
127
+ clientId: { type: 'text' },
128
+ clientSecret: { type: 'password' },
129
+ },
130
+ });
131
+ };