@5minds/node-red-contrib-processcube 1.8.0-feature-6eed29-m6wgknb1 → 1.8.2-develop-44f737-m79z7jh3

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.
@@ -7,14 +7,13 @@ on:
7
7
  - '*/*'
8
8
 
9
9
  env:
10
- CI_TOOLS_VERSION: '^4.2.0'
10
+ CI_TOOLS_VERSION: '^5.0.0'
11
11
  # NOTE: Um den Releasezyklus von Alpha nach Beta zu ändern, einfach die nachfolgend deklarierten Env Variablen switchen.
12
12
  CI_TOOLS_ALPHA_BRANCH: next
13
13
  CI_TOOLS_ALPHA_NPM_TAG: next
14
- CI_TOOLS_STABLE_BRANCH: main
15
14
  # CI_TOOLS_BETA_BRANCH: next
16
15
  # CI_TOOLS_BETA_NPM_TAG: next
17
- #BOX_RELEASE_TAG: 2024-1
16
+ BOX_RELEASE_TAG: 2025-1
18
17
 
19
18
  jobs:
20
19
  build_and_publish:
@@ -28,10 +27,10 @@ jobs:
28
27
  fetch-depth: 0
29
28
  token: ${{ secrets.GH_TOKEN }}
30
29
 
31
- - name: Use Node.js 20
30
+ - name: Use Node.js 22
32
31
  uses: actions/setup-node@v4
33
32
  with:
34
- node-version: '20'
33
+ node-version: '22'
35
34
  registry-url: 'https://registry.npmjs.org'
36
35
 
37
36
  - name: Install CI Tools
@@ -63,10 +62,11 @@ jobs:
63
62
  NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
64
63
  run: ci_tools publish-npm-package --create-tag-from-branch-name
65
64
 
66
- # - name: Add Box-Release Tag
67
- # if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/next'
68
- # env:
69
- # NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
70
- # run: |
71
- # VERSION="$(ci_tools get-version)"
72
- # npm dist-tag add @5minds/processcube_app_sdk@$VERSION ${{ env.BOX_RELEASE_TAG }}
65
+ - name: Add Box-Release Tag
66
+ if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/next'
67
+ env:
68
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
69
+ run: |
70
+ VERSION="$(ci_tools get-version)"
71
+ PACKAGE_NAME="$(npm pkg get name | tr -d \")"
72
+ npm dist-tag add $PACKAGE_NAME@$VERSION ${{ env.BOX_RELEASE_TAG }}
@@ -429,7 +429,7 @@
429
429
  },
430
430
  "@5minds/node-red-contrib-processcube": {
431
431
  "name": "@5minds/node-red-contrib-processcube",
432
- "version": "1.8.0",
432
+ "version": "1.8.2",
433
433
  "local": false,
434
434
  "user": false,
435
435
  "nodes": {
@@ -455,17 +455,6 @@
455
455
  "module": "@5minds/node-red-contrib-processcube",
456
456
  "file": "/usr/src/node-red/node_modules/@5minds/node-red-contrib-processcube/endevent-finished-listener.js"
457
457
  },
458
- "ExternalTaskInputInject": {
459
- "name": "ExternalTaskInputInject",
460
- "types": [
461
- "externaltask-input-inject"
462
- ],
463
- "enabled": true,
464
- "local": false,
465
- "user": false,
466
- "module": "@5minds/node-red-contrib-processcube",
467
- "file": "/usr/src/node-red/node_modules/@5minds/node-red-contrib-processcube/externaltask-input-inject.js"
468
- },
469
458
  "externaltaskInput": {
470
459
  "name": "externaltaskInput",
471
460
  "types": [
@@ -23,7 +23,7 @@
23
23
  }
24
24
  },
25
25
  "menu-menu-item-sidebar": true,
26
- "menu-menu-item-palette": true,
26
+ "menu-menu-item-palette": false,
27
27
  "do": {
28
28
  "markNodes": true
29
29
  }
@@ -111,14 +111,6 @@
111
111
  "info": "",
112
112
  "env": []
113
113
  },
114
- {
115
- "id": "17865ef049c3b83d",
116
- "type": "tab",
117
- "label": "External Task Testing",
118
- "disabled": false,
119
- "info": "",
120
- "env": []
121
- },
122
114
  {
123
115
  "id": "8eb64bb58f95989d",
124
116
  "type": "subflow",
@@ -211,9 +203,9 @@
211
203
  "1ba1e62c9935255f",
212
204
  "b49f226ba865e164"
213
205
  ],
214
- "x": 34,
206
+ "x": 14,
215
207
  "y": 379,
216
- "w": 812,
208
+ "w": 832,
217
209
  "h": 202
218
210
  },
219
211
  {
@@ -726,6 +718,7 @@
726
718
  "name": "Test",
727
719
  "engine": "42e6796dddd9d4db",
728
720
  "topic": "Test",
721
+ "topicType": "str",
729
722
  "workerConfig": "{}",
730
723
  "workerConfigType": "json",
731
724
  "x": 110,
@@ -755,9 +748,10 @@
755
748
  "name": "SampleError",
756
749
  "engine": "42e6796dddd9d4db",
757
750
  "topic": "SampleError",
751
+ "topicType": "str",
758
752
  "workerConfig": "{}",
759
753
  "workerConfigType": "json",
760
- "x": 130,
754
+ "x": 110,
761
755
  "y": 480,
762
756
  "wires": [
763
757
  [
@@ -1002,6 +996,7 @@
1002
996
  "id": "3283986789f6f865",
1003
997
  "type": "externaltask-input",
1004
998
  "z": "a23d2e782beb66f4",
999
+ "d": true,
1005
1000
  "g": "73ca179de59cdabf",
1006
1001
  "name": "TopicFromENV",
1007
1002
  "engine": "42e6796dddd9d4db",
@@ -1097,6 +1092,7 @@
1097
1092
  "id": "53a1d67f1dfa05fe",
1098
1093
  "type": "externaltask-input",
1099
1094
  "z": "a23d2e782beb66f4",
1095
+ "d": true,
1100
1096
  "g": "be22a2d8eb2e28c4",
1101
1097
  "name": "the_simple_topic",
1102
1098
  "engine": "42e6796dddd9d4db",
@@ -1291,10 +1287,12 @@
1291
1287
  "id": "d0e1fa5361aba536",
1292
1288
  "type": "externaltask-input",
1293
1289
  "z": "c9ab699769824f2f",
1290
+ "d": true,
1294
1291
  "g": "bb94db89ecb73d7b",
1295
1292
  "name": "Test_Auth",
1296
1293
  "engine": "b78932d162d8d468",
1297
1294
  "topic": "Test_Auth",
1295
+ "topicType": "str",
1298
1296
  "workerConfig": "{}",
1299
1297
  "workerConfigType": "json",
1300
1298
  "x": 120,
@@ -1356,10 +1354,12 @@
1356
1354
  "id": "7af11dd03dd0fc02",
1357
1355
  "type": "externaltask-input",
1358
1356
  "z": "c9ab699769824f2f",
1357
+ "d": true,
1359
1358
  "g": "ec665c16c4c4a6e0",
1360
1359
  "name": "SampleError_Auth",
1361
1360
  "engine": "b78932d162d8d468",
1362
1361
  "topic": "SampleError_Auth",
1362
+ "topicType": "str",
1363
1363
  "workerConfig": "{}",
1364
1364
  "workerConfigType": "json",
1365
1365
  "x": 150,
@@ -3239,132 +3239,5 @@
3239
3239
  "af52431420fa7e15"
3240
3240
  ]
3241
3241
  ]
3242
- },
3243
- {
3244
- "id": "d75f8915b26e8f52",
3245
- "type": "externaltask-input-inject",
3246
- "z": "17865ef049c3b83d",
3247
- "name": "a",
3248
- "externaltask": "476cbb99633a9539",
3249
- "x": 370,
3250
- "y": 320,
3251
- "wires": [
3252
- [
3253
- "1afda17294a69742"
3254
- ]
3255
- ]
3256
- },
3257
- {
3258
- "id": "3c50b6d63b7b81d8",
3259
- "type": "inject",
3260
- "z": "17865ef049c3b83d",
3261
- "name": "",
3262
- "props": [
3263
- {
3264
- "p": "payload"
3265
- }
3266
- ],
3267
- "repeat": "",
3268
- "crontab": "",
3269
- "once": false,
3270
- "onceDelay": 0.1,
3271
- "topic": "",
3272
- "payload": "{\"hello\":\"world\"}",
3273
- "payloadType": "json",
3274
- "x": 160,
3275
- "y": 320,
3276
- "wires": [
3277
- [
3278
- "d75f8915b26e8f52"
3279
- ]
3280
- ]
3281
- },
3282
- {
3283
- "id": "1afda17294a69742",
3284
- "type": "debug",
3285
- "z": "17865ef049c3b83d",
3286
- "name": "debug 4",
3287
- "active": true,
3288
- "tosidebar": true,
3289
- "console": false,
3290
- "tostatus": false,
3291
- "complete": "false",
3292
- "statusVal": "",
3293
- "statusType": "auto",
3294
- "x": 560,
3295
- "y": 320,
3296
- "wires": []
3297
- },
3298
- {
3299
- "id": "476cbb99633a9539",
3300
- "type": "externaltask-input",
3301
- "z": "17865ef049c3b83d",
3302
- "name": "test inject",
3303
- "engine": "b78932d162d8d468",
3304
- "topic": "test",
3305
- "topicType": "str",
3306
- "workerConfig": "{}",
3307
- "workerConfigType": "json",
3308
- "x": 220,
3309
- "y": 140,
3310
- "wires": [
3311
- [
3312
- "36c31ae7ce4b2536"
3313
- ]
3314
- ]
3315
- },
3316
- {
3317
- "id": "dd8e11733ed305c1",
3318
- "type": "externaltask-output",
3319
- "z": "17865ef049c3b83d",
3320
- "name": "",
3321
- "x": 670,
3322
- "y": 200,
3323
- "wires": []
3324
- },
3325
- {
3326
- "id": "36c31ae7ce4b2536",
3327
- "type": "delay",
3328
- "z": "17865ef049c3b83d",
3329
- "name": "",
3330
- "pauseType": "delay",
3331
- "timeout": "5",
3332
- "timeoutUnits": "seconds",
3333
- "rate": "1",
3334
- "nbRateUnits": "1",
3335
- "rateUnits": "second",
3336
- "randomFirst": "1",
3337
- "randomLast": "5",
3338
- "randomUnits": "seconds",
3339
- "drop": false,
3340
- "allowrate": false,
3341
- "outputs": 1,
3342
- "x": 400,
3343
- "y": 140,
3344
- "wires": [
3345
- [
3346
- "59f385728d7d350d"
3347
- ]
3348
- ]
3349
- },
3350
- {
3351
- "id": "59f385728d7d350d",
3352
- "type": "function",
3353
- "z": "17865ef049c3b83d",
3354
- "name": "function 1",
3355
- "func": "msg.payload.running = \"1\";\nmsg.payload.at = new Date().toISOString();\nreturn msg;",
3356
- "outputs": 1,
3357
- "timeout": 0,
3358
- "noerr": 0,
3359
- "initialize": "",
3360
- "finalize": "",
3361
- "libs": [],
3362
- "x": 580,
3363
- "y": 120,
3364
- "wires": [
3365
- [
3366
- "dd8e11733ed305c1"
3367
- ]
3368
- ]
3369
3242
  }
3370
3243
  ]
@@ -393,7 +393,7 @@ module.exports = {
393
393
  * If not set, the following default order is used:
394
394
  */
395
395
  //categories: ['subflows', 'common', 'function', 'network', 'sequence', 'parser', 'storage'],
396
- categories: ['ProcessCube', 'ProcessCube Events', 'ProcessCube UI', 'ProcessCube Testing', 'ProcessCube DevOps', 'dashboard 2'],
396
+ categories: ['ProcessCube', 'ProcessCube Events', 'ProcessCube UI', 'dashboard 2'],
397
397
  },
398
398
 
399
399
  projects: {
@@ -14,6 +14,7 @@ services:
14
14
  - TOPIC=TopicFromENV
15
15
  # start node-red with debugger port open
16
16
  - NODE_OPTIONS=--inspect=0.0.0.0:9229
17
+ - NODE_RED_ETW_HEARTBEAT_LOGGING=true
17
18
  volumes:
18
19
  # required for mapping the current source into the directory
19
20
  - ./.:/package_src/
@@ -14,7 +14,7 @@
14
14
  outputs: 1,
15
15
  icon: 'externaltask_input.svg',
16
16
  label: function () {
17
- return this.name || 'externaltask-input';
17
+ return this.name || (this.topic ? `topic: ${this.topic}` : 'externaltask-input');
18
18
  },
19
19
  oneditprepare: function () {
20
20
  $('#node-input-workerConfig').typedInput({
@@ -1,15 +1,5 @@
1
1
  const EventEmitter = require('node:events');
2
2
 
3
- function showStatus(node, msgCounter) {
4
- if (msgCounter >= 1) {
5
- node.status({ fill: 'green', shape: 'dot', text: `handling tasks ${msgCounter}.` });
6
- node.log(`handling tasks ${msgCounter}.`);
7
- } else {
8
- node.status({ fill: 'blue', shape: 'ring', text: `subcribed.` });
9
- node.log(`subcribed (heartbeat).`);
10
- }
11
- }
12
-
13
3
 
14
4
  module.exports = function (RED) {
15
5
  function ExternalTaskInput(config) {
@@ -22,31 +12,74 @@ module.exports = function (RED) {
22
12
 
23
13
  node.eventEmitter = new EventEmitter();
24
14
 
25
- // for external-task-inject
26
- node.injectNodeCallback = null;
27
- node.injectCall = null; // will be build in the register function
15
+ let options = RED.util.evaluateNodeProperty(config.workerConfig, config.workerConfigType, node);
16
+ let topic = node.topic = RED.util.evaluateNodeProperty(config.topic, config.topicType, node)
28
17
 
29
- const buildMessage = (msg, externalTask, payload) => {
30
- let newMsg = msg;
18
+
19
+ node._subscribed = true;
20
+ node._subscribed_error = null;
31
21
 
32
- if (!newMsg) {
33
- newMsg = {
34
- _msgid: RED.util.generateId(),
35
- };
22
+ node.setSubscribedStatus = () => {
23
+ this._subscribed = true;
24
+ this._subscribed_error = null;
25
+ this.showStatus();
26
+ };
27
+
28
+ node.setUnsubscribedStatus = (error) => {
29
+ this._subscribed = false;
30
+ this._subscribed_error = error;
31
+
32
+ this.error(`subscription failed (topic: ${node.topic}).`);
33
+ RED.log.error(`topic: ${node.topic} (${error.message}).`);
34
+
35
+ this.showStatus();
36
+ };
37
+
38
+ node.setStartHandlingTaskStatus = (externalTask) => {
39
+ this._subscribed = true;
40
+ this._subscribed_error = null;
41
+ this.started_external_tasks[externalTask.flowNodeInstanceId] = externalTask;
42
+
43
+ this.showStatus();
44
+ };
45
+
46
+ node.setFinishHandlingTaskStatus = (externalTask) => {
47
+ if (externalTask.flowNodeInstanceId) {
48
+ delete this.started_external_tasks[externalTask.flowNodeInstanceId];
36
49
  }
37
50
 
38
- newMsg.task = RED.util.encodeObject(externalTask);
39
- newMsg.payload = payload;
40
- newMsg.flowNodeInstanceId = externalTask.flowNodeInstanceId;
41
- newMsg.processInstanceId = externalTask.processInstanceId;
42
- newMsg.etw_input_node_id = node.id;
51
+ this._subscribed = true;
52
+ this._subscribed_error = null;
43
53
 
44
- if (externalTask._injectCall) {
45
- newMsg._injectCall = true;
54
+ this.showStatus();
55
+ };
56
+
57
+ node.setErrorFinishHandlingTaskStatus = (externalTask, error) => {
58
+ if (externalTask.flowNodeInstanceId) {
59
+ delete this.started_external_tasks[externalTask.flowNodeInstanceId];
46
60
  }
47
61
 
48
- return newMsg;
49
- }
62
+ this._subscribed_error = error;
63
+ this.error(`finished task failed (topic: ${node.topic}).`);
64
+ RED.log.error(`topic: ${node.topic} (${error.message}).`);
65
+
66
+ this.showStatus();
67
+ };
68
+
69
+ node.showStatus = () => {
70
+ const msgCounter = Object.keys(this.started_external_tasks).length;
71
+
72
+ if (this._subscribed === false) {
73
+ this.status({ fill: 'red', shape: 'ring', text: `subscription failed (${msgCounter}).` })
74
+ } else {
75
+ if (msgCounter >= 1) {
76
+ this.status({ fill: 'green', shape: 'dot', text: `handling tasks ${msgCounter}.` });
77
+ this.log(`handling tasks ${msgCounter}.`);
78
+ } else {
79
+ this.status({ fill: 'blue', shape: 'ring', text: `subcribed.` });
80
+ }
81
+ }
82
+ };
50
83
 
51
84
  const register = async () => {
52
85
  if (node.etw) {
@@ -57,6 +90,7 @@ module.exports = function (RED) {
57
90
  node.log(`cant close etw: ${JSON.stringify(node.etw)}`);
58
91
  }
59
92
  }
93
+
60
94
  const client = node.engine.engineClient;
61
95
 
62
96
  if (!client) {
@@ -64,11 +98,14 @@ module.exports = function (RED) {
64
98
  return;
65
99
  }
66
100
  const etwCallback = async (payload, externalTask) => {
67
- const saveHandleCallback = (data, callback) => {
101
+ const saveHandleCallback = (data, callback, msg) => {
68
102
  try {
69
103
  callback(data);
104
+ node.setFinishHandlingTaskStatus(externalTask);
70
105
  } catch (error) {
71
- node.error(`Error in callback 'saveHandleCallback': ${error.message}`, {});
106
+ node.setErrorFinishHandlingTaskStatus(externalTask, error);
107
+ msg.error = error;
108
+ node.error(`Error in callback 'saveHandleCallback': ${error.message}`, msg);
72
109
  }
73
110
  };
74
111
 
@@ -84,13 +121,8 @@ module.exports = function (RED) {
84
121
  `handle event for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* ${externalTask.processInstanceId} with result ${JSON.stringify(result)} on msg._msgid ${msg._msgid}.`
85
122
  );
86
123
 
87
- if (externalTask.flowNodeInstanceId) {
88
- delete node.started_external_tasks[externalTask.flowNodeInstanceId];
89
- }
90
-
91
- showStatus(node, Object.keys(node.started_external_tasks).length);
92
-
93
- saveHandleCallback(result, resolve);
124
+ //resolve(result);
125
+ saveHandleCallback(result, resolve, msg);
94
126
  };
95
127
 
96
128
  const handleErrorTask = (msg) => {
@@ -98,15 +130,11 @@ module.exports = function (RED) {
98
130
  `handle error event for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}' on *msg._msgid* '${msg._msgid}'.`
99
131
  );
100
132
 
101
- if (externalTask.flowNodeInstanceId) {
102
- delete node.started_external_tasks[externalTask.flowNodeInstanceId];
103
- }
104
-
105
- showStatus(node, Object.keys(node.started_external_tasks).length);
106
-
107
133
  // TODO: with reject, the default error handling is proceed
108
134
  // SEE: https://github.com/5minds/ProcessCube.Engine.Client.ts/blob/develop/src/ExternalTaskWorker.ts#L180
109
- saveHandleCallback(msg, resolve);
135
+ // reject(result);
136
+ //resolve(msg);
137
+ saveHandleCallback(msg, resolve, msg);
110
138
  };
111
139
 
112
140
  node.eventEmitter.once(`handle-${externalTask.flowNodeInstanceId}`, (msg, isError = false) => {
@@ -114,34 +142,15 @@ module.exports = function (RED) {
114
142
  `handle event for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}' with *msg._msgid* '${msg._msgid}' and *isError* '${isError}'`
115
143
  );
116
144
 
117
- if (msg._injectCall) {
118
- if (node.injectNodeCallback) {
119
- node.injectNodeCallback(msg);
120
- } else {
121
- node.error('No injectCall function defined.', {});
122
- }
123
-
124
- if (externalTask.flowNodeInstanceId) {
125
- delete node.started_external_tasks[externalTask.flowNodeInstanceId];
126
- showStatus(node, Object.keys(node.started_external_tasks).length);
127
- }
128
-
145
+ if (isError) {
146
+ handleErrorTask(msg);
129
147
  } else {
130
- if (isError) {
131
- handleErrorTask(msg);
132
- } else {
133
- handleFinishTask(msg);
134
- }
135
-
148
+ handleFinishTask(msg);
136
149
  }
137
-
138
150
  });
139
151
 
140
- node.started_external_tasks[externalTask.flowNodeInstanceId] = externalTask;
141
-
142
- showStatus(node, Object.keys(node.started_external_tasks).length);
152
+ node.setStartHandlingTaskStatus(externalTask);
143
153
 
144
- /*
145
154
  let msg = {
146
155
  _msgid: RED.util.generateId(),
147
156
  task: RED.util.encodeObject(externalTask),
@@ -150,9 +159,6 @@ module.exports = function (RED) {
150
159
  processInstanceId: externalTask.processInstanceId,
151
160
  etw_input_node_id: node.id,
152
161
  };
153
- */
154
-
155
- let msg = buildMessage(null, externalTask, payload);
156
162
 
157
163
  node.log(
158
164
  `Received *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}' with *msg._msgid* '${msg._msgid}'`
@@ -162,20 +168,6 @@ module.exports = function (RED) {
162
168
  });
163
169
  };
164
170
 
165
- let options = RED.util.evaluateNodeProperty(config.workerConfig, config.workerConfigType, node);
166
- let topic = RED.util.evaluateNodeProperty(config.topic, config.topicType, node)
167
-
168
- node.injectCall = async (msg) => {
169
- const genericTask = {
170
- task: {},
171
- flowNodeInstanceId: msg._msgid,
172
- processInstanceId: msg._msgid,
173
- _injectCall: true
174
- };
175
-
176
- await etwCallback(msg, genericTask);
177
- };
178
-
179
171
  client.externalTasks
180
172
  .subscribeToExternalTaskTopic(topic, etwCallback, options)
181
173
  .then(async (externalTaskWorker) => {
@@ -183,8 +175,16 @@ module.exports = function (RED) {
183
175
 
184
176
  node.etw = externalTaskWorker;
185
177
 
186
- externalTaskWorker.onHeartbeat(() => {
187
- showStatus(node, Object.keys(node.started_external_tasks).length);
178
+ externalTaskWorker.onHeartbeat((event, external_task_id) => {
179
+ node.setSubscribedStatus();
180
+
181
+ if (process.env.NODE_RED_ETW_HEARTBEAT_LOGGING) {
182
+ if (external_task_id) {
183
+ this.log(`subscription (heartbeat:topic ${node.topic}, ${event} for ${external_task_id}).`);
184
+ } else {
185
+ this.log(`subscription (heartbeat:topic ${node.topic}, ${event}).`);
186
+ }
187
+ }
188
188
  });
189
189
 
190
190
  externalTaskWorker.onWorkerError((errorType, error, externalTask) => {
@@ -193,19 +193,18 @@ module.exports = function (RED) {
193
193
  case 'finishExternalTask':
194
194
  case 'processExternalTask':
195
195
  node.error(
196
- `Worker error ${errorType} for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}': ${error.message}`,
197
- {}
196
+ `Worker error ${errorType} for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}': ${error.message}`
198
197
  );
199
198
 
200
- if (externalTask) {
201
- delete node.started_external_tasks[externalTask.flowNodeInstanceId];
202
- }
199
+ //if (externalTask) {
200
+ // delete node.started_external_tasks[externalTask.flowNodeInstanceId];
201
+ //}
202
+
203
+ node.setUnsubscribedStatus(error);
203
204
 
204
- showStatus(node, Object.keys(node.started_external_tasks).length);
205
205
  break;
206
206
  case 'fetchAndLock':
207
- node.status({ fill: 'red', shape: 'ring', text: `subscription failed.` });
208
- node.error('subscription failed.');
207
+ node.setUnsubscribedStatus(error);
209
208
  break;
210
209
  default:
211
210
  // reduce noise error logs
@@ -215,7 +214,7 @@ module.exports = function (RED) {
215
214
 
216
215
  try {
217
216
  externalTaskWorker.start();
218
- showStatus(node, Object.keys(node.started_external_tasks).length);
217
+ node.showStatus();
219
218
  } catch (error) {
220
219
  node.error(`Worker start 'externalTaskWorker.start' failed: ${error.message}`, {});
221
220
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@5minds/node-red-contrib-processcube",
3
- "version": "1.8.0-feature-6eed29-m6wgknb1",
3
+ "version": "1.8.2-develop-44f737-m79z7jh3",
4
4
  "license": "MIT",
5
5
  "description": "Node-RED nodes for ProcessCube",
6
6
  "scripts": {
@@ -37,7 +37,6 @@
37
37
  "nodes": {
38
38
  "checkAuthorization": "check-authorization.js",
39
39
  "EndEventFinishedListener": "endevent-finished-listener.js",
40
- "ExternalTaskInputInject": "externaltask-input-inject.js",
41
40
  "externaltaskInput": "externaltask-input.js",
42
41
  "externaltaskOutput": "externaltask-output.js",
43
42
  "externaltaskError": "externaltask-error.js",
@@ -60,7 +59,7 @@
60
59
  "examples": "examples"
61
60
  },
62
61
  "dependencies": {
63
- "@5minds/processcube_engine_client": "5.1.8",
62
+ "@5minds/processcube_engine_client": "5.1.10-hotfix-a83819-m79hiutk",
64
63
  "jwt-decode": "^4.0.0",
65
64
  "openid-client": "^5.5.0"
66
65
  },
@@ -73,12 +73,12 @@
73
73
  <bpmndi:BPMNShape id="Event_0rs3geg_di" bpmnElement="Event_0rs3geg">
74
74
  <dc:Bounds x="312" y="272" width="36" height="36" />
75
75
  </bpmndi:BPMNShape>
76
- <bpmndi:BPMNShape id="Event_134k5nt_di" bpmnElement="Event_0o7qlkd">
77
- <dc:Bounds x="392" y="192" width="36" height="36" />
78
- </bpmndi:BPMNShape>
79
76
  <bpmndi:BPMNShape id="Event_03ytp91_di" bpmnElement="Event_007u06e">
80
77
  <dc:Bounds x="222" y="192" width="36" height="36" />
81
78
  </bpmndi:BPMNShape>
79
+ <bpmndi:BPMNShape id="Event_134k5nt_di" bpmnElement="Event_0o7qlkd">
80
+ <dc:Bounds x="392" y="192" width="36" height="36" />
81
+ </bpmndi:BPMNShape>
82
82
  <bpmndi:BPMNEdge id="Flow_0qmxzxk_di" bpmnElement="Flow_0qmxzxk">
83
83
  <di:waypoint x="128" y="170" />
84
84
  <di:waypoint x="180" y="170" />
@@ -1,143 +0,0 @@
1
- [
2
- {
3
- "id": "17865ef049c3b83d",
4
- "type": "tab",
5
- "label": "External Task Testing",
6
- "disabled": false,
7
- "info": "",
8
- "env": []
9
- },
10
- {
11
- "id": "d75f8915b26e8f52",
12
- "type": "externaltask-input-inject",
13
- "z": "17865ef049c3b83d",
14
- "name": "a",
15
- "externaltask": "476cbb99633a9539",
16
- "x": 370,
17
- "y": 320,
18
- "wires": [
19
- [
20
- "1afda17294a69742"
21
- ]
22
- ]
23
- },
24
- {
25
- "id": "3c50b6d63b7b81d8",
26
- "type": "inject",
27
- "z": "17865ef049c3b83d",
28
- "name": "",
29
- "props": [
30
- {
31
- "p": "payload"
32
- }
33
- ],
34
- "repeat": "",
35
- "crontab": "",
36
- "once": false,
37
- "onceDelay": 0.1,
38
- "topic": "",
39
- "payload": "{\"hello\":\"world\"}",
40
- "payloadType": "json",
41
- "x": 160,
42
- "y": 320,
43
- "wires": [
44
- [
45
- "d75f8915b26e8f52"
46
- ]
47
- ]
48
- },
49
- {
50
- "id": "1afda17294a69742",
51
- "type": "debug",
52
- "z": "17865ef049c3b83d",
53
- "name": "debug 4",
54
- "active": true,
55
- "tosidebar": true,
56
- "console": false,
57
- "tostatus": false,
58
- "complete": "false",
59
- "statusVal": "",
60
- "statusType": "auto",
61
- "x": 560,
62
- "y": 320,
63
- "wires": []
64
- },
65
- {
66
- "id": "476cbb99633a9539",
67
- "type": "externaltask-input",
68
- "z": "17865ef049c3b83d",
69
- "name": "test inject",
70
- "engine": "b78932d162d8d468",
71
- "topic": "test",
72
- "topicType": "str",
73
- "workerConfig": "{}",
74
- "workerConfigType": "json",
75
- "x": 220,
76
- "y": 140,
77
- "wires": [
78
- [
79
- "36c31ae7ce4b2536"
80
- ]
81
- ]
82
- },
83
- {
84
- "id": "dd8e11733ed305c1",
85
- "type": "externaltask-output",
86
- "z": "17865ef049c3b83d",
87
- "name": "",
88
- "x": 670,
89
- "y": 200,
90
- "wires": []
91
- },
92
- {
93
- "id": "36c31ae7ce4b2536",
94
- "type": "delay",
95
- "z": "17865ef049c3b83d",
96
- "name": "",
97
- "pauseType": "delay",
98
- "timeout": "5",
99
- "timeoutUnits": "seconds",
100
- "rate": "1",
101
- "nbRateUnits": "1",
102
- "rateUnits": "second",
103
- "randomFirst": "1",
104
- "randomLast": "5",
105
- "randomUnits": "seconds",
106
- "drop": false,
107
- "allowrate": false,
108
- "outputs": 1,
109
- "x": 400,
110
- "y": 140,
111
- "wires": [
112
- [
113
- "59f385728d7d350d"
114
- ]
115
- ]
116
- },
117
- {
118
- "id": "59f385728d7d350d",
119
- "type": "function",
120
- "z": "17865ef049c3b83d",
121
- "name": "function 1",
122
- "func": "msg.payload.running = \"1\";\nmsg.payload.at = new Date().toISOString();\nreturn msg;",
123
- "outputs": 1,
124
- "timeout": 0,
125
- "noerr": 0,
126
- "initialize": "",
127
- "finalize": "",
128
- "libs": [],
129
- "x": 580,
130
- "y": 120,
131
- "wires": [
132
- [
133
- "dd8e11733ed305c1"
134
- ]
135
- ]
136
- },
137
- {
138
- "id": "b78932d162d8d468",
139
- "type": "processcube-engine-config",
140
- "name": "Engine Auth 8000",
141
- "url": "http://engine:8000"
142
- }
143
- ]
@@ -1,100 +0,0 @@
1
- <script type="text/javascript">
2
- RED.nodes.registerType('externaltask-input-inject', {
3
- category: 'ProcessCube Testing',
4
- color: '#02AFD6',
5
- defaults: {
6
- name: { value: '' },
7
- externaltask: { value: '' }
8
- },
9
- inputs: 1,
10
- outputs: 1,
11
- icon: 'externaltask_input.svg',
12
- label: function () {
13
- const nodes = RED.nodes.filterNodes({ type: 'externaltask-input' });
14
-
15
- if (nodes && nodes.length > 0) {
16
- let foundNode = null;
17
- nodes.forEach((node) => {
18
- if (node.id === this.externaltask) {
19
- foundNode = node;
20
- }
21
- });
22
-
23
- return foundNode ? `inject '${foundNode.name}'` : this.name || 'externaltask-input-inject';
24
- } else {
25
- return this.name || 'externaltask-input-inject';
26
- }
27
- },
28
- oneditprepare: function () {
29
-
30
- try {
31
- var dropdown = $('#node-input-externaltask');
32
- dropdown.empty();
33
- const selectedValue = this.externaltask || "";
34
-
35
-
36
- const localCallNodes = RED.nodes.filterNodes({ type: 'externaltask-input' });
37
- if (!Array.isArray(localCallNodes)) {
38
- console.error("Expected an array from RED.nodes.filterNodes but got:", localCallNodes);
39
- return;
40
- }
41
-
42
- if (localCallNodes.length === 0) {
43
- console.warn("No externaltask-input nodes found.");
44
- dropdown.append($("<option></option>").attr("value", "").text("No available tasks"));
45
- } else {
46
- localCallNodes.forEach((node) => {
47
- let option = $("<option></option>")
48
- .attr("value", node.id)
49
- .text(`${node.name || "Unnamed"} (${node.id})`);
50
-
51
- if (node.id === selectedValue) {
52
- option.attr("selected", "selected");
53
- }
54
-
55
- dropdown.append(option);
56
- });
57
- }
58
-
59
- } catch (error) {
60
- console.error(error);
61
- }
62
- },
63
- oneditsave: function () {
64
- this.externaltask = $('#node-input-externaltask').val();
65
- }
66
- });
67
- </script>
68
-
69
- <script type="text/html" data-template-name="externaltask-input-inject">
70
- <div class="form-row">
71
- <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
72
- <input type="text" id="node-input-name" placeholder="Name" />
73
- </div>
74
- <div class="form-row">
75
- <label for="node-input-externaltask"><i class="fa fa-tag"></i> External Task</label>
76
- <select id="node-input-externaltask"></select>
77
- </div>
78
- </script>
79
-
80
- <script type="text/markdown" data-help-name="externaltask-input-inject">
81
- Send the incoming message to the external task.
82
-
83
- ## Configs
84
-
85
- : name (string) : The name of the node
86
- : externaltask (external-input) : The External task to inject the message
87
-
88
- ## Input
89
-
90
- : payload (string | {}) : The payload to send to the external task.
91
-
92
- ## Outputs
93
-
94
- : payload (string | {}) : The payload the result from the external task.
95
-
96
- ### References
97
-
98
- - [The ProcessCube&copy; Developer Network](https://processcube.io) - All documentation for the ProcessCube&copy; platform
99
- - [ProcessCube&copy; LowCode Integration](https://processcube.io/docs/node-red) - LowCode integration in ProcessCube&copy;
100
- </script>
@@ -1,38 +0,0 @@
1
- module.exports = function (RED) {
2
- function ExternalTaskInputInject(config) {
3
- RED.nodes.createNode(this, config);
4
- var node = this;
5
-
6
- node.config = config;
7
-
8
-
9
- node.on('input', async function (msg, send, done) {
10
- node.externalTask = RED.nodes.getNode(node.config.externaltask);
11
-
12
- if (node.externalTask) {
13
- node.log(`Received message: ${JSON.stringify(msg)} and send to external task ${node.externalTask.id}.`);
14
-
15
- node.externalTask.injectNodeCallback = (msg) => {
16
- send(msg);
17
- done()
18
- }
19
-
20
- if (node.externalTask.injectCall) {
21
- node.externalTask.injectCall(msg).catch((error) => {
22
- node.error(`Error in inject call: ${error.message}`, {});
23
- done(`Error in inject call: ${error.message}`);
24
- });
25
- } else {
26
- node.error('No inject call found.');
27
- done('No inject call found.');
28
- }
29
- } else {
30
- node.error('No external task node found.');
31
- done('No external task node found.');
32
- }
33
- });
34
-
35
- }
36
-
37
- RED.nodes.registerType('externaltask-input-inject', ExternalTaskInputInject);
38
- };