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

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.
@@ -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