@5minds/node-red-contrib-processcube 1.5.6-develop-51b402-m3iul3hf → 1.5.6-feature-60b2c2-m3pneelx
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/endevent-finished-listener.js +12 -6
- package/externaltask-event-listener.js +7 -0
- package/externaltask-input.js +118 -101
- package/package.json +1 -1
- package/process-event-listener.js +11 -3
- package/processcube-engine-config.js +8 -2
- package/usertask-event-listener.js +9 -2
- package/wait-for-usertask.js +38 -35
@@ -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
|
|
package/externaltask-input.js
CHANGED
@@ -32,132 +32,149 @@ module.exports = function (RED) {
|
|
32
32
|
eventEmitter = flowContext.get('emitter');
|
33
33
|
}
|
34
34
|
|
35
|
-
const
|
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
|
-
|
49
|
-
|
50
|
-
|
37
|
+
engineEventEmitter.on('engine-client-changed', () => {
|
38
|
+
console.log('new engineClient received');
|
39
|
+
register();
|
40
|
+
});
|
51
41
|
|
52
|
-
|
53
|
-
|
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
|
-
|
52
|
+
return await new Promise((resolve, reject) => {
|
53
|
+
const handleFinishTask = (msg) => {
|
54
|
+
let result = RED.util.encodeObject(msg.payload);
|
57
55
|
|
58
|
-
|
59
|
-
|
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
|
-
|
63
|
-
|
64
|
-
|
65
|
-
);
|
60
|
+
if (externalTask.flowNodeInstanceId) {
|
61
|
+
delete started_external_tasks[externalTask.flowNodeInstanceId];
|
62
|
+
}
|
66
63
|
|
67
|
-
|
68
|
-
delete started_external_tasks[externalTask.flowNodeInstanceId];
|
69
|
-
}
|
64
|
+
showStatus(node, Object.keys(started_external_tasks).length);
|
70
65
|
|
71
|
-
|
66
|
+
//resolve(result);
|
67
|
+
saveHandleCallback(result, resolve);
|
68
|
+
};
|
72
69
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
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
|
-
|
81
|
-
|
82
|
-
|
83
|
-
);
|
75
|
+
if (externalTask.flowNodeInstanceId) {
|
76
|
+
delete started_external_tasks[externalTask.flowNodeInstanceId];
|
77
|
+
}
|
84
78
|
|
85
|
-
|
86
|
-
handleErrorTask(msg);
|
87
|
-
} else {
|
88
|
-
handleFinishTask(msg);
|
89
|
-
}
|
90
|
-
});
|
79
|
+
showStatus(node, Object.keys(started_external_tasks).length);
|
91
80
|
|
92
|
-
|
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
|
-
|
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
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
};
|
93
|
+
if (isError) {
|
94
|
+
handleErrorTask(msg);
|
95
|
+
} else {
|
96
|
+
handleFinishTask(msg);
|
97
|
+
}
|
98
|
+
});
|
103
99
|
|
104
|
-
|
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
|
-
|
109
|
-
});
|
110
|
-
};
|
102
|
+
showStatus(node, Object.keys(started_external_tasks).length);
|
111
103
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
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
|
-
|
118
|
-
|
119
|
-
|
120
|
-
});
|
112
|
+
node.log(
|
113
|
+
`Received *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}' with *msg._msgid* '${msg._msgid}'`
|
114
|
+
);
|
121
115
|
|
122
|
-
|
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
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
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.
|
153
|
-
} catch {
|
154
|
-
node.error('
|
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
|
-
|
159
|
-
|
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
@@ -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,3 +1,4 @@
|
|
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');
|
@@ -12,7 +13,8 @@ module.exports = function (RED) {
|
|
12
13
|
this.credentials.clientId = RED.util.evaluateNodeProperty(n.clientId, n.clientIdType, node);
|
13
14
|
this.credentials.clientSecret = RED.util.evaluateNodeProperty(n.clientSecret, n.clientSecretType, node);
|
14
15
|
|
15
|
-
|
16
|
+
node.eventEmitter = new EventEmitter();
|
17
|
+
|
16
18
|
// set the engine url
|
17
19
|
const stopRefreshing = periodicallyRefreshEngineClient(this, n, 10000);
|
18
20
|
|
@@ -41,7 +43,7 @@ module.exports = function (RED) {
|
|
41
43
|
function refreshUrl() {
|
42
44
|
const newUrl = RED.util.evaluateNodeProperty(n.url, n.urlType, node);
|
43
45
|
|
44
|
-
if (node.url
|
46
|
+
if (node.url === newUrl) {
|
45
47
|
return;
|
46
48
|
}
|
47
49
|
|
@@ -53,11 +55,15 @@ module.exports = function (RED) {
|
|
53
55
|
node.engineClient = new engine_client.EngineClient(node.url, () =>
|
54
56
|
getFreshIdentity(node.url, node)
|
55
57
|
);
|
58
|
+
|
59
|
+
node.eventEmitter.emit('engine-client-changed');
|
56
60
|
} else {
|
57
61
|
if (this.engineClient) {
|
58
62
|
this.engineClient.dispose();
|
59
63
|
}
|
60
64
|
node.engineClient = new engine_client.EngineClient(node.url);
|
65
|
+
|
66
|
+
node.eventEmitter.emit('engine-client-changed');
|
61
67
|
}
|
62
68
|
}
|
63
69
|
|
@@ -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) {
|
package/wait-for-usertask.js
CHANGED
@@ -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(
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
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
|
-
}
|
45
|
-
|
46
|
-
|
48
|
+
},
|
49
|
+
{ identity: currentIdentity }
|
50
|
+
);
|
47
51
|
|
48
|
-
|
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
|
-
|
56
|
-
...query
|
57
|
+
state: 'suspended',
|
58
|
+
...query,
|
57
59
|
};
|
58
60
|
|
59
61
|
try {
|
60
|
-
const matchingFlowNodes = await client.userTasks.query(suspendedQuery, {
|
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(
|
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(
|
100
|
-
}
|
102
|
+
RED.nodes.registerType('wait-for-usertask', WaitForUsertask);
|
103
|
+
};
|