@5minds/node-red-contrib-processcube 1.5.6 → 1.5.7-develop-10cfa5-m3qdjs6o

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,6 +4,19 @@ module.exports = function (RED) {
4
4
  var node = this;
5
5
  node.engine = RED.nodes.getNode(config.engine);
6
6
 
7
+ let subscription = null;
8
+
9
+ const eventEmitter = node.engine.eventEmitter;
10
+
11
+ eventEmitter.on('engine-client-dispose', () => {
12
+ node.engine.engineClient.events.removeSubscription(subscription, node.engine.identity);
13
+ });
14
+
15
+ eventEmitter.on('engine-client-changed', () => {
16
+ node.log('new engineClient received');
17
+ register();
18
+ });
19
+
7
20
  const register = async () => {
8
21
  const client = node.engine.engineClient;
9
22
 
@@ -11,10 +24,8 @@ module.exports = function (RED) {
11
24
  node.error('No engine configured.');
12
25
  return;
13
26
  }
14
-
15
- let currentIdentity = node.engine.identity;
16
27
 
17
- let subscription = null;
28
+ let currentIdentity = node.engine.identity;
18
29
 
19
30
  try {
20
31
  subscription = await client.events.onEndEventFinished(
@@ -23,24 +34,23 @@ module.exports = function (RED) {
23
34
  payload: endEventFinished,
24
35
  });
25
36
  },
26
- { identity: currentIdentity },
37
+ { identity: currentIdentity }
27
38
  );
28
39
 
29
40
  node.engine.registerOnIdentityChanged(async (identity) => {
30
41
  client.events.removeSubscription(subscription, currentIdentity);
31
-
42
+
32
43
  currentIdentity = identity;
33
44
 
34
45
  subscription = await client.events.onEndEventFinished(
35
46
  (endEventFinished) => {
36
47
  node.send({
37
- payload: endEventFinished
48
+ payload: endEventFinished,
38
49
  });
39
50
  },
40
- { identity: currentIdentity },
51
+ { identity: currentIdentity }
41
52
  );
42
53
  });
43
-
44
54
  } catch (error) {
45
55
  node.error(error);
46
56
  }
@@ -4,6 +4,19 @@ module.exports = function (RED) {
4
4
  var node = this;
5
5
  node.engine = RED.nodes.getNode(config.engine);
6
6
 
7
+ let subscription;
8
+
9
+ const eventEmitter = node.engine.eventEmitter;
10
+
11
+ eventEmitter.on('engine-client-dispose', () => {
12
+ node.engine.engineClient.notification.removeSubscription(subscription, node.engine.identity);
13
+ });
14
+
15
+ eventEmitter.on('engine-client-changed', () => {
16
+ node.log('new engineClient received');
17
+ register();
18
+ });
19
+
7
20
  const register = async () => {
8
21
  let currentIdentity = node.engine.identity;
9
22
 
@@ -14,8 +27,6 @@ module.exports = function (RED) {
14
27
  return;
15
28
  }
16
29
 
17
- let subscription;
18
-
19
30
  function externalTaskCallback() {
20
31
  return (externalTaskNotification) => {
21
32
  if (config.externaltask != '' && config.externaltask != externalTaskNotification.flowNodeId) return;
@@ -58,11 +58,26 @@
58
58
  Waiting for external tasks that correspond to the `Topic` configured in
59
59
  the connected ProcessCube Engine for processing.
60
60
 
61
+ ## Configs
62
+
63
+ : name (string) : The name of the node
64
+ : engine (string) : The ProcessCube Engine to connect to
65
+ : topic (string) : The topic of the external task
66
+ : workerConfig (object) : The configuration for the worker
67
+
68
+ ### workerConfig
69
+
70
+ - workerId (string): The id of the worker
71
+ - lockDuration (number): The duration in milliseconds the external task is locked for execution
72
+ - maxTasks (number): The maximum number of tasks that can be fetched at once
73
+ - longpollingTimeout (number): The duration in milliseconds the external task is locked for execution
74
+ - payloadFilter (Req-Expression): The filter for the payload of the external task
75
+
61
76
  ## Outputs
62
77
 
63
78
  : payload (string) : The payload the external task was started with.
64
79
  : task (object) : The external task object
65
- : flowNodeInstanceId : The unique identifier of the external task, which is needed to complete the task
80
+ : flowNodeInstanceId (string) : The unique identifier of the external task, which is needed to complete the task
66
81
 
67
82
  ### Details
68
83
 
@@ -32,132 +32,152 @@ module.exports = function (RED) {
32
32
  eventEmitter = flowContext.get('emitter');
33
33
  }
34
34
 
35
- const etwCallback = async (payload, externalTask) => {
36
- const saveHandleCallback = (data, callback) => {
37
- try {
38
- callback(data);
39
- } catch (error) {
40
- node.error(`Error in callback 'saveHandleCallback': ${error.message}`);
41
- }
42
- };
35
+ const engineEventEmitter = node.engine.eventEmitter;
43
36
 
44
- return await new Promise((resolve, reject) => {
45
- const handleFinishTask = (msg) => {
46
- let result = RED.util.encodeObject(msg.payload);
37
+ engineEventEmitter.on('engine-client-dispose', () => {
38
+ node.engine.engineClient.externalTasks.removeSubscription(subscription, node.engine.identity);
39
+ });
47
40
 
48
- node.log(
49
- `handle event for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* ${externalTask.processInstanceId} with result ${result} on msg._msgid ${msg._msgid}.`
50
- );
41
+ engineEventEmitter.on('engine-client-changed', () => {
42
+ node.log('new engineClient received');
43
+ register();
44
+ });
51
45
 
52
- if (externalTask.flowNodeInstanceId) {
53
- delete started_external_tasks[externalTask.flowNodeInstanceId];
46
+ const register = async () => {
47
+ const etwCallback = async (payload, externalTask) => {
48
+ const saveHandleCallback = (data, callback) => {
49
+ try {
50
+ callback(data);
51
+ } catch (error) {
52
+ node.error(`Error in callback 'saveHandleCallback': ${error.message}`);
54
53
  }
54
+ };
55
55
 
56
- showStatus(node, Object.keys(started_external_tasks).length);
56
+ return await new Promise((resolve, reject) => {
57
+ const handleFinishTask = (msg) => {
58
+ let result = RED.util.encodeObject(msg.payload);
57
59
 
58
- //resolve(result);
59
- saveHandleCallback(result, resolve);
60
- };
60
+ node.log(
61
+ `handle event for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* ${externalTask.processInstanceId} with result ${result} on msg._msgid ${msg._msgid}.`
62
+ );
61
63
 
62
- const handleErrorTask = (msg) => {
63
- node.log(
64
- `handle error event for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}' on *msg._msgid* '${msg._msgid}'.`
65
- );
64
+ if (externalTask.flowNodeInstanceId) {
65
+ delete started_external_tasks[externalTask.flowNodeInstanceId];
66
+ }
66
67
 
67
- if (externalTask.flowNodeInstanceId) {
68
- delete started_external_tasks[externalTask.flowNodeInstanceId];
69
- }
68
+ showStatus(node, Object.keys(started_external_tasks).length);
70
69
 
71
- showStatus(node, Object.keys(started_external_tasks).length);
70
+ //resolve(result);
71
+ saveHandleCallback(result, resolve);
72
+ };
72
73
 
73
- // TODO: with reject, the default error handling is proceed
74
- // SEE: https://github.com/5minds/ProcessCube.Engine.Client.ts/blob/develop/src/ExternalTaskWorker.ts#L180
75
- // reject(result);
76
- //resolve(msg);
77
- saveHandleCallback(msg, resolve);
78
- };
74
+ const handleErrorTask = (msg) => {
75
+ node.log(
76
+ `handle error event for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}' on *msg._msgid* '${msg._msgid}'.`
77
+ );
79
78
 
80
- eventEmitter.once(`handle-${externalTask.flowNodeInstanceId}`, (msg, isError = false) => {
81
- node.log(
82
- `handle event for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}' with *msg._msgid* '${msg._msgid}' and *isError* '${isError}'`
83
- );
79
+ if (externalTask.flowNodeInstanceId) {
80
+ delete started_external_tasks[externalTask.flowNodeInstanceId];
81
+ }
84
82
 
85
- if (isError) {
86
- handleErrorTask(msg);
87
- } else {
88
- handleFinishTask(msg);
89
- }
90
- });
83
+ showStatus(node, Object.keys(started_external_tasks).length);
91
84
 
92
- started_external_tasks[externalTask.flowNodeInstanceId] = externalTask;
85
+ // TODO: with reject, the default error handling is proceed
86
+ // SEE: https://github.com/5minds/ProcessCube.Engine.Client.ts/blob/develop/src/ExternalTaskWorker.ts#L180
87
+ // reject(result);
88
+ //resolve(msg);
89
+ saveHandleCallback(msg, resolve);
90
+ };
93
91
 
94
- showStatus(node, Object.keys(started_external_tasks).length);
92
+ eventEmitter.once(`handle-${externalTask.flowNodeInstanceId}`, (msg, isError = false) => {
93
+ node.log(
94
+ `handle event for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}' with *msg._msgid* '${msg._msgid}' and *isError* '${isError}'`
95
+ );
95
96
 
96
- let msg = {
97
- _msgid: RED.util.generateId(),
98
- task: RED.util.encodeObject(externalTask),
99
- payload: payload,
100
- flowNodeInstanceId: externalTask.flowNodeInstanceId,
101
- processInstanceId: externalTask.processInstanceId
102
- };
97
+ if (isError) {
98
+ handleErrorTask(msg);
99
+ } else {
100
+ handleFinishTask(msg);
101
+ }
102
+ });
103
103
 
104
- node.log(
105
- `Received *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}' with *msg._msgid* '${msg._msgid}'`
106
- );
104
+ started_external_tasks[externalTask.flowNodeInstanceId] = externalTask;
107
105
 
108
- node.send(msg);
109
- });
110
- };
106
+ showStatus(node, Object.keys(started_external_tasks).length);
111
107
 
112
- client.externalTasks
113
- .subscribeToExternalTaskTopic(config.topic, etwCallback, RED.util.evaluateNodeProperty(config.workerConfig, 'json', node))
114
- .then(async (externalTaskWorker) => {
115
- node.status({ fill: 'blue', shape: 'ring', text: 'subcribed' });
108
+ let msg = {
109
+ _msgid: RED.util.generateId(),
110
+ task: RED.util.encodeObject(externalTask),
111
+ payload: payload,
112
+ flowNodeInstanceId: externalTask.flowNodeInstanceId,
113
+ processInstanceId: externalTask.processInstanceId,
114
+ };
116
115
 
117
- externalTaskWorker.identity = engine.identity;
118
- engine.registerOnIdentityChanged((identity) => {
119
- externalTaskWorker.identity = identity;
120
- });
116
+ node.log(
117
+ `Received *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}' with *msg._msgid* '${msg._msgid}'`
118
+ );
121
119
 
122
- // export type WorkerErrorHandler = (errorType: 'fetchAndLock' | 'extendLock' | 'processExternalTask' | 'finishExternalTask', error: Error, externalTask?: ExternalTask<any>) => void;
123
- externalTaskWorker.onWorkerError((errorType, error, externalTask) => {
124
- switch (errorType) {
125
- case 'extendLock':
126
- case 'finishExternalTask':
127
- case 'processExternalTask':
128
- node.error(
129
- `Worker error ${errorType} for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}': ${error.message}`
130
- );
131
-
132
- if (externalTask) {
133
- delete started_external_tasks[externalTask.flowNodeInstanceId];
134
- }
135
-
136
- showStatus(node, Object.keys(started_external_tasks).length);
137
- break;
138
- default:
139
- node.error(`Worker error ${errorType}: ${error.message}`);
140
- break;
141
- }
120
+ node.send(msg);
142
121
  });
122
+ };
143
123
 
144
- try {
145
- externalTaskWorker.start();
146
- } catch (error) {
147
- node.error(`Worker start 'externalTaskWorker.start' failed: ${error.message}`);
148
- }
124
+ let options = RED.util.evaluateNodeProperty(config.workerConfig, 'json', node);
125
+
126
+ client.externalTasks
127
+ .subscribeToExternalTaskTopic(config.topic, etwCallback, options)
128
+ .then(async (externalTaskWorker) => {
129
+ node.status({ fill: 'blue', shape: 'ring', text: 'subcribed' });
130
+
131
+ externalTaskWorker.identity = engine.identity;
132
+ engine.registerOnIdentityChanged((identity) => {
133
+ externalTaskWorker.identity = identity;
134
+ });
135
+
136
+ // export type WorkerErrorHandler = (errorType: 'fetchAndLock' | 'extendLock' | 'processExternalTask' | 'finishExternalTask', error: Error, externalTask?: ExternalTask<any>) => void;
137
+ externalTaskWorker.onWorkerError((errorType, error, externalTask) => {
138
+ switch (errorType) {
139
+ case 'extendLock':
140
+ case 'finishExternalTask':
141
+ case 'processExternalTask':
142
+ node.error(
143
+ `Worker error ${errorType} for *external task flowNodeInstanceId* '${externalTask.flowNodeInstanceId}' and *processInstanceId* '${externalTask.processInstanceId}': ${error.message}`
144
+ );
145
+
146
+ if (externalTask) {
147
+ delete started_external_tasks[externalTask.flowNodeInstanceId];
148
+ }
149
+
150
+ showStatus(node, Object.keys(started_external_tasks).length);
151
+ break;
152
+ default:
153
+ // reduce noise error logs
154
+ // node.error(`Worker error ${errorType}: ${error.message}`);
155
+ break;
156
+ }
157
+ });
149
158
 
150
- node.on('close', () => {
151
159
  try {
152
- externalTaskWorker.stop();
153
- } catch {
154
- node.error('Client close failed');
160
+ externalTaskWorker.start();
161
+ } catch (error) {
162
+ node.error(`Worker start 'externalTaskWorker.start' failed: ${error.message}`);
155
163
  }
164
+
165
+ node.on('close', () => {
166
+ try {
167
+ externalTaskWorker.stop();
168
+ } catch {
169
+ node.error('Client close failed');
170
+ }
171
+ });
172
+ })
173
+ .catch((error) => {
174
+ node.error(`Error in subscribeToExternalTaskTopic: ${error.message}`);
156
175
  });
157
- })
158
- .catch((error) => {
159
- node.error(`Error in subscribeToExternalTaskTopic: ${error.message}`);
160
- });
176
+ };
177
+
178
+ if (node.engine) {
179
+ register();
180
+ }
161
181
  }
162
182
 
163
183
  RED.nodes.registerType('externaltask-input', ExternalTaskInput);
@@ -71,6 +71,22 @@
71
71
  "info": "",
72
72
  "env": []
73
73
  },
74
+ {
75
+ "id": "76c047e0d8770a20",
76
+ "type": "tab",
77
+ "label": "Other Events",
78
+ "disabled": false,
79
+ "info": "",
80
+ "env": []
81
+ },
82
+ {
83
+ "id": "2766c40d84283368",
84
+ "type": "tab",
85
+ "label": "Placeholder",
86
+ "disabled": false,
87
+ "info": "",
88
+ "env": []
89
+ },
74
90
  {
75
91
  "id": "4c59118134081e05",
76
92
  "type": "group",
@@ -481,6 +497,7 @@
481
497
  "color": "#a4a4a4"
482
498
  },
483
499
  "nodes": [
500
+
484
501
  "2fadb4c4667ecaf2",
485
502
  "93331783b7ef3fc5",
486
503
  "bc26f9821540f097",
@@ -1485,7 +1502,7 @@
1485
1502
  "g": "a71a168415778e2c",
1486
1503
  "name": "",
1487
1504
  "engine": "42e6796dddd9d4db",
1488
- "query": "{\"includeXml\":false}",
1505
+ "query": "{\"includeXml\":false,\"processDefinitionId\":\"External-Task-Sample_Definition\"}",
1489
1506
  "query_type": "json",
1490
1507
  "x": 320,
1491
1508
  "y": 140,
@@ -2094,5 +2111,95 @@
2094
2111
  "x": 760,
2095
2112
  "y": 60,
2096
2113
  "wires": []
2114
+ },
2115
+ {
2116
+ "id": "930624edc6169c55",
2117
+ "type": "process-event-listener",
2118
+ "z": "76c047e0d8770a20",
2119
+ "g": "865723b71ced9418",
2120
+ "name": "",
2121
+ "engine": "42e6796dddd9d4db",
2122
+ "processmodel": "External-Task-Sample_Process",
2123
+ "eventtype": "starting",
2124
+ "query": "{}",
2125
+ "query_type": "json",
2126
+ "x": 160,
2127
+ "y": 140,
2128
+ "wires": [
2129
+ [
2130
+ "2f2ec1cc0213eab5"
2131
+ ]
2132
+ ]
2133
+ },
2134
+ {
2135
+ "id": "2f2ec1cc0213eab5",
2136
+ "type": "debug",
2137
+ "z": "76c047e0d8770a20",
2138
+ "g": "865723b71ced9418",
2139
+ "name": "debug 34",
2140
+ "active": true,
2141
+ "tosidebar": true,
2142
+ "console": false,
2143
+ "tostatus": false,
2144
+ "complete": "false",
2145
+ "statusVal": "",
2146
+ "statusType": "auto",
2147
+ "x": 430,
2148
+ "y": 140,
2149
+ "wires": []
2150
+ },
2151
+ {
2152
+ "id": "bde205e77cd20558",
2153
+ "type": "comment",
2154
+ "z": "76c047e0d8770a20",
2155
+ "g": "865723b71ced9418",
2156
+ "name": "Hört auf die Events der Processe",
2157
+ "info": "",
2158
+ "x": 190,
2159
+ "y": 80,
2160
+ "wires": []
2161
+ },
2162
+ {
2163
+ "id": "03ac7bc273197c45",
2164
+ "type": "process-terminate",
2165
+ "z": "2766c40d84283368",
2166
+ "g": "9081b057a931f0cf",
2167
+ "name": "",
2168
+ "engine": "42e6796dddd9d4db",
2169
+ "x": 170,
2170
+ "y": 140,
2171
+ "wires": [
2172
+ [
2173
+ "bb734a85d4b37728"
2174
+ ]
2175
+ ]
2176
+ },
2177
+ {
2178
+ "id": "bb734a85d4b37728",
2179
+ "type": "debug",
2180
+ "z": "2766c40d84283368",
2181
+ "g": "9081b057a931f0cf",
2182
+ "name": "debug 35",
2183
+ "active": true,
2184
+ "tosidebar": true,
2185
+ "console": false,
2186
+ "tostatus": false,
2187
+ "complete": "false",
2188
+ "statusVal": "",
2189
+ "statusType": "auto",
2190
+ "x": 370,
2191
+ "y": 140,
2192
+ "wires": []
2193
+ },
2194
+ {
2195
+ "id": "3d03550f7d93bfd3",
2196
+ "type": "comment",
2197
+ "z": "2766c40d84283368",
2198
+ "g": "9081b057a931f0cf",
2199
+ "name": "Event for Terminating a Process",
2200
+ "info": "",
2201
+ "x": 210,
2202
+ "y": 80,
2203
+ "wires": []
2097
2204
  }
2098
2205
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@5minds/node-red-contrib-processcube",
3
- "version": "1.5.6",
3
+ "version": "1.5.7-develop-10cfa5-m3qdjs6o",
4
4
  "license": "MIT",
5
5
  "description": "Node-RED nodes for ProcessCube",
6
6
  "scripts": {
@@ -4,6 +4,19 @@ module.exports = function (RED) {
4
4
  var node = this;
5
5
  node.engine = RED.nodes.getNode(config.engine);
6
6
 
7
+ let subscription;
8
+
9
+ const eventEmitter = node.engine.eventEmitter;
10
+
11
+ engineEventEmitter.on('engine-client-dispose', () => {
12
+ node.engine.engineClient.notification.removeSubscription(subscription, node.engine.identity);
13
+ });
14
+
15
+ eventEmitter.on('engine-client-changed', () => {
16
+ node.log('new engineClient received');
17
+ register();
18
+ });
19
+
7
20
  const register = async () => {
8
21
  const client = node.engine.engineClient;
9
22
 
@@ -14,7 +27,6 @@ module.exports = function (RED) {
14
27
 
15
28
  let currentIdentity = node.engine.identity;
16
29
 
17
- let subscription;
18
30
  const query = RED.util.evaluateNodeProperty(config.query, config.query_type, node);
19
31
 
20
32
  async function subscribe(eventType) {
@@ -24,7 +36,8 @@ module.exports = function (RED) {
24
36
  async (processNotification) => {
25
37
  if (
26
38
  config.processmodel != '' &&
27
- config.processmodel != processNotification.processModelId) {
39
+ config.processmodel != processNotification.processModelId
40
+ ) {
28
41
  return;
29
42
  }
30
43
 
@@ -65,7 +78,8 @@ module.exports = function (RED) {
65
78
  async (processNotification) => {
66
79
  if (
67
80
  config.processmodel != '' &&
68
- config.processmodel != processNotification.processModelId) {
81
+ config.processmodel != processNotification.processModelId
82
+ ) {
69
83
  return;
70
84
  }
71
85
 
@@ -433,7 +447,6 @@ module.exports = function (RED) {
433
447
  },
434
448
  { identity: currentIdentity }
435
449
  );
436
-
437
450
  });
438
451
 
439
452
  node.on('close', () => {
@@ -29,9 +29,10 @@
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
- ## Inputs
32
+ ## Configs
33
33
 
34
- : payload (string): The id of the processinstance that is going to be terminated.
34
+ : name (string): name of the node
35
+ : engine (string): the engine to connect to
35
36
 
36
37
  ## Outputs
37
38
 
@@ -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
- // known issue: kann bei falschem timing zu laufzeitfehlern führen (absprache MM)
16
+ node.eventEmitter = new EventEmitter();
17
+
16
18
  // set the engine url
17
19
  const stopRefreshing = periodicallyRefreshEngineClient(this, n, 10000);
18
20
 
@@ -41,23 +43,29 @@ 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 == newUrl) {
46
+ if (node.url === newUrl) {
45
47
  return;
46
48
  }
47
49
 
48
50
  node.url = newUrl;
49
51
  if (node.credentials.clientId && node.credentials.clientSecret) {
50
- if (this.engineClient) {
51
- this.engineClient.dispose();
52
+ if (node.engineClient) {
53
+ node.eventEmitter.emit('engine-client-dispose');
54
+ node.engineClient.dispose();
52
55
  }
53
56
  node.engineClient = new engine_client.EngineClient(node.url, () =>
54
57
  getFreshIdentity(node.url, node)
55
58
  );
59
+
60
+ node.eventEmitter.emit('engine-client-changed');
56
61
  } else {
57
- if (this.engineClient) {
58
- this.engineClient.dispose();
62
+ if (node.engineClient) {
63
+ node.eventEmitter.emit('engine-client-dispose');
64
+ node.engineClient.dispose();
59
65
  }
60
66
  node.engineClient = new engine_client.EngineClient(node.url);
67
+
68
+ node.eventEmitter.emit('engine-client-changed');
61
69
  }
62
70
  }
63
71