@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.
- package/.github/workflows/build-and-publish.yml +12 -12
- package/.processcube/nodered/.config.nodes.json +1 -12
- package/.processcube/nodered/.config.users.json +1 -1
- package/.processcube/nodered/flows.json +11 -138
- package/.processcube/nodered/settings.js +1 -1
- package/docker-compose.yml +1 -0
- package/externaltask-input.html +1 -1
- package/externaltask-input.js +94 -95
- package/package.json +2 -3
- package/processes/External-Task-Sample.bpmn +3 -3
- package/examples/External-Task-Inject-Sample.json +0 -143
- package/externaltask-input-inject.html +0 -100
- package/externaltask-input-inject.js +0 -38
@@ -7,14 +7,13 @@ on:
|
|
7
7
|
- '*/*'
|
8
8
|
|
9
9
|
env:
|
10
|
-
CI_TOOLS_VERSION: '^
|
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
|
-
|
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
|
30
|
+
- name: Use Node.js 22
|
32
31
|
uses: actions/setup-node@v4
|
33
32
|
with:
|
34
|
-
node-version: '
|
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
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
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.
|
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": [
|
@@ -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":
|
206
|
+
"x": 14,
|
215
207
|
"y": 379,
|
216
|
-
"w":
|
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":
|
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', '
|
396
|
+
categories: ['ProcessCube', 'ProcessCube Events', 'ProcessCube UI', 'dashboard 2'],
|
397
397
|
},
|
398
398
|
|
399
399
|
projects: {
|
package/docker-compose.yml
CHANGED
package/externaltask-input.html
CHANGED
@@ -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({
|
package/externaltask-input.js
CHANGED
@@ -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
|
-
|
26
|
-
node.
|
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
|
-
|
30
|
-
|
18
|
+
|
19
|
+
node._subscribed = true;
|
20
|
+
node._subscribed_error = null;
|
31
21
|
|
32
|
-
|
33
|
-
|
34
|
-
|
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
|
-
|
39
|
-
|
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
|
-
|
45
|
-
|
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
|
-
|
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.
|
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
|
-
|
88
|
-
|
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
|
-
|
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 (
|
118
|
-
|
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
|
-
|
131
|
-
handleErrorTask(msg);
|
132
|
-
} else {
|
133
|
-
handleFinishTask(msg);
|
134
|
-
}
|
135
|
-
|
148
|
+
handleFinishTask(msg);
|
136
149
|
}
|
137
|
-
|
138
150
|
});
|
139
151
|
|
140
|
-
node.
|
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
|
-
|
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
|
-
|
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.
|
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
|
-
|
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.
|
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.
|
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© Developer Network](https://processcube.io) - All documentation for the ProcessCube© platform
|
99
|
-
- [ProcessCube© LowCode Integration](https://processcube.io/docs/node-red) - LowCode integration in ProcessCube©
|
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
|
-
};
|