@ti-engine/core 1.1.4 → 1.1.8
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/CHANGELOG.md +41 -0
- package/README.md +47 -12
- package/bin/start-instance.js +45 -18
- package/components/auditing.js +8 -5
- package/components/connection-observer.js +6 -3
- package/components/exchange/default/default-message-exchange.js +8 -5
- package/components/exchange/default/default-message-receiver.js +13 -6
- package/components/exchange/default/default-message-sender.js +13 -6
- package/components/exchange/message-dispatcher.js +20 -13
- package/components/exchange/message-exchange.js +65 -26
- package/components/exchange/message-handler.js +7 -4
- package/components/exchange/message-memory-cache.js +23 -6
- package/components/exchange/message-observer.js +6 -3
- package/components/exchange/message-receiver.js +8 -5
- package/components/exchange/message-sender.js +7 -4
- package/components/exchange/message-tracer.js +143 -94
- package/components/service-caller.js +11 -8
- package/components/service-consumer.js +25 -6
- package/components/service-executor.js +44 -19
- package/components/service-instance.js +44 -26
- package/components/service-provider.js +26 -7
- package/integrations/gcloud-integration.js +8 -4
- package/integrations/redis-integration.js +140 -45
- package/package.json +7 -7
- package/utils/cache.js +29 -9
- package/utils/config.js +14 -3
- package/utils/exceptions.js +6 -3
- package/utils/localization.js +7 -4
- package/utils/logger.js +8 -6
- package/utils/tools.js +7 -4
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/*
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
|
|
2
|
+
* The ti-engine is an open source, free to use—both for personal and commercial projects—framework for the creation of microservice-based solutions using node.js.
|
|
3
|
+
* Copyright © 2021-2023 Boris Kostadinov <kostadinov.boris@gmail.com>
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
5
|
+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
6
|
+
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
7
|
+
*/
|
|
5
8
|
|
|
6
9
|
const MessageObserver = require( "#message-observer" );
|
|
7
10
|
const _ = require( "lodash" );
|
|
@@ -92,7 +95,9 @@ class MessageExchange extends MessageObserver {
|
|
|
92
95
|
* @returns {string}
|
|
93
96
|
* @public
|
|
94
97
|
*/
|
|
95
|
-
static get connectionNameRequestsOut() {
|
|
98
|
+
static get connectionNameRequestsOut() {
|
|
99
|
+
return this.#connectionNameRequestsOut;
|
|
100
|
+
}
|
|
96
101
|
|
|
97
102
|
/**
|
|
98
103
|
* Used to set the connection name for the outgoing message requests.
|
|
@@ -101,7 +106,9 @@ class MessageExchange extends MessageObserver {
|
|
|
101
106
|
* @param {string} value
|
|
102
107
|
* @public
|
|
103
108
|
*/
|
|
104
|
-
static set connectionNameRequestsOut( value ) {
|
|
109
|
+
static set connectionNameRequestsOut( value ) {
|
|
110
|
+
this.#connectionNameRequestsOut = value;
|
|
111
|
+
}
|
|
105
112
|
|
|
106
113
|
/**
|
|
107
114
|
* Property returning the configured connection name for the incoming message requests.
|
|
@@ -110,7 +117,9 @@ class MessageExchange extends MessageObserver {
|
|
|
110
117
|
* @returns {string}
|
|
111
118
|
* @public
|
|
112
119
|
*/
|
|
113
|
-
static get connectionNameRequestsIn() {
|
|
120
|
+
static get connectionNameRequestsIn() {
|
|
121
|
+
return this.#connectionNameRequestsIn;
|
|
122
|
+
}
|
|
114
123
|
|
|
115
124
|
/**
|
|
116
125
|
* Used to set the connection name for the incoming message requests.
|
|
@@ -119,7 +128,9 @@ class MessageExchange extends MessageObserver {
|
|
|
119
128
|
* @param {string} value
|
|
120
129
|
* @public
|
|
121
130
|
*/
|
|
122
|
-
static set connectionNameRequestsIn( value ) {
|
|
131
|
+
static set connectionNameRequestsIn( value ) {
|
|
132
|
+
this.#connectionNameRequestsIn = value;
|
|
133
|
+
}
|
|
123
134
|
|
|
124
135
|
/**
|
|
125
136
|
* Property returning the configured connection name for the outgoing message responses.
|
|
@@ -128,7 +139,9 @@ class MessageExchange extends MessageObserver {
|
|
|
128
139
|
* @returns {string}
|
|
129
140
|
* @public
|
|
130
141
|
*/
|
|
131
|
-
static get connectionNameResponsesOut() {
|
|
142
|
+
static get connectionNameResponsesOut() {
|
|
143
|
+
return this.#connectionNameResponsesOut;
|
|
144
|
+
}
|
|
132
145
|
|
|
133
146
|
/**
|
|
134
147
|
* Used to set the connection name for the outgoing message responses.
|
|
@@ -137,7 +150,9 @@ class MessageExchange extends MessageObserver {
|
|
|
137
150
|
* @param {string} value
|
|
138
151
|
* @public
|
|
139
152
|
*/
|
|
140
|
-
static set connectionNameResponsesOut( value ) {
|
|
153
|
+
static set connectionNameResponsesOut( value ) {
|
|
154
|
+
this.#connectionNameResponsesOut = value;
|
|
155
|
+
}
|
|
141
156
|
|
|
142
157
|
/**
|
|
143
158
|
* Property returning the configured connection name for the incoming message responses.
|
|
@@ -146,7 +161,9 @@ class MessageExchange extends MessageObserver {
|
|
|
146
161
|
* @returns {string}
|
|
147
162
|
* @public
|
|
148
163
|
*/
|
|
149
|
-
static get connectionNameResponsesIn() {
|
|
164
|
+
static get connectionNameResponsesIn() {
|
|
165
|
+
return this.#connectionNameResponsesIn;
|
|
166
|
+
}
|
|
150
167
|
|
|
151
168
|
/**
|
|
152
169
|
* Used to set the connection name for the incoming message responses.
|
|
@@ -155,7 +172,9 @@ class MessageExchange extends MessageObserver {
|
|
|
155
172
|
* @param {string} value
|
|
156
173
|
* @public
|
|
157
174
|
*/
|
|
158
|
-
static set connectionNameResponsesIn( value ) {
|
|
175
|
+
static set connectionNameResponsesIn( value ) {
|
|
176
|
+
this.#connectionNameResponsesIn = value;
|
|
177
|
+
}
|
|
159
178
|
|
|
160
179
|
/**
|
|
161
180
|
* Property returning the identifier of the pending messages queue.
|
|
@@ -164,7 +183,9 @@ class MessageExchange extends MessageObserver {
|
|
|
164
183
|
* @returns {string}
|
|
165
184
|
* @public
|
|
166
185
|
*/
|
|
167
|
-
static get pendingQueue() {
|
|
186
|
+
static get pendingQueue() {
|
|
187
|
+
return "pending:";
|
|
188
|
+
}
|
|
168
189
|
|
|
169
190
|
/**
|
|
170
191
|
* Property returning the identifier of the processed messages queue.
|
|
@@ -173,7 +194,9 @@ class MessageExchange extends MessageObserver {
|
|
|
173
194
|
* @returns {string}
|
|
174
195
|
* @public
|
|
175
196
|
*/
|
|
176
|
-
static get processedQueue() {
|
|
197
|
+
static get processedQueue() {
|
|
198
|
+
return "processed:";
|
|
199
|
+
}
|
|
177
200
|
|
|
178
201
|
/**
|
|
179
202
|
* Property returning the configured service instance ID.
|
|
@@ -182,7 +205,9 @@ class MessageExchange extends MessageObserver {
|
|
|
182
205
|
* @returns {string}
|
|
183
206
|
* @public
|
|
184
207
|
*/
|
|
185
|
-
get instanceID() {
|
|
208
|
+
get instanceID() {
|
|
209
|
+
return this.#instanceID;
|
|
210
|
+
}
|
|
186
211
|
|
|
187
212
|
/**
|
|
188
213
|
* Property returning the configured service domain name.
|
|
@@ -191,7 +216,9 @@ class MessageExchange extends MessageObserver {
|
|
|
191
216
|
* @returns {string}
|
|
192
217
|
* @public
|
|
193
218
|
*/
|
|
194
|
-
get serviceDomainName() {
|
|
219
|
+
get serviceDomainName() {
|
|
220
|
+
return this.#serviceDomainName;
|
|
221
|
+
}
|
|
195
222
|
|
|
196
223
|
/**
|
|
197
224
|
* Returns the currently configured {@link MessageSender} for outbound message requests.
|
|
@@ -200,7 +227,9 @@ class MessageExchange extends MessageObserver {
|
|
|
200
227
|
* @returns {MessageSender}
|
|
201
228
|
* @public
|
|
202
229
|
*/
|
|
203
|
-
get messageRequestsOut() {
|
|
230
|
+
get messageRequestsOut() {
|
|
231
|
+
return this.#messageRequestsOut;
|
|
232
|
+
}
|
|
204
233
|
|
|
205
234
|
/**
|
|
206
235
|
* Returns the currently configured {@link MessageSender} for outbound message responses.
|
|
@@ -209,7 +238,9 @@ class MessageExchange extends MessageObserver {
|
|
|
209
238
|
* @returns {MessageSender}
|
|
210
239
|
* @public
|
|
211
240
|
*/
|
|
212
|
-
get messageResponsesOut() {
|
|
241
|
+
get messageResponsesOut() {
|
|
242
|
+
return this.#messageResponsesOut;
|
|
243
|
+
}
|
|
213
244
|
|
|
214
245
|
/**
|
|
215
246
|
* Returns the currently configured {@link MessageReceiver} for inbound message requests.
|
|
@@ -218,7 +249,9 @@ class MessageExchange extends MessageObserver {
|
|
|
218
249
|
* @returns {MessageReceiver}
|
|
219
250
|
* @public
|
|
220
251
|
*/
|
|
221
|
-
get messageRequestsIn() {
|
|
252
|
+
get messageRequestsIn() {
|
|
253
|
+
return this.#messageRequestsIn;
|
|
254
|
+
}
|
|
222
255
|
|
|
223
256
|
/**
|
|
224
257
|
* Returns the currently configured {@link MessageReceiver} for inbound message responses.
|
|
@@ -227,7 +260,9 @@ class MessageExchange extends MessageObserver {
|
|
|
227
260
|
* @returns {MessageReceiver}
|
|
228
261
|
* @public
|
|
229
262
|
*/
|
|
230
|
-
get messageResponsesIn() {
|
|
263
|
+
get messageResponsesIn() {
|
|
264
|
+
return this.#messageResponsesIn;
|
|
265
|
+
}
|
|
231
266
|
|
|
232
267
|
/**
|
|
233
268
|
* Returns a flag indicating if the message exchange is configured for outbound communication.
|
|
@@ -236,7 +271,9 @@ class MessageExchange extends MessageObserver {
|
|
|
236
271
|
* @returns {boolean}
|
|
237
272
|
* @public
|
|
238
273
|
*/
|
|
239
|
-
get configuredOutbound() {
|
|
274
|
+
get configuredOutbound() {
|
|
275
|
+
return this.#configuredOutbound;
|
|
276
|
+
}
|
|
240
277
|
|
|
241
278
|
/**
|
|
242
279
|
* Returns a flag indicating if the message exchange is configured for inbound communication.
|
|
@@ -245,7 +282,9 @@ class MessageExchange extends MessageObserver {
|
|
|
245
282
|
* @returns {boolean}
|
|
246
283
|
* @public
|
|
247
284
|
*/
|
|
248
|
-
get configuredInbound() {
|
|
285
|
+
get configuredInbound() {
|
|
286
|
+
return this.#configuredInbound;
|
|
287
|
+
}
|
|
249
288
|
|
|
250
289
|
/**
|
|
251
290
|
* Should be used to enable all communication channels for messaging.
|
|
@@ -253,8 +292,8 @@ class MessageExchange extends MessageObserver {
|
|
|
253
292
|
* NOTE: Override this to implement messaging initialization.
|
|
254
293
|
*
|
|
255
294
|
* @method
|
|
256
|
-
* @param {boolean} configureInbound If set to 'true' it tells the message exchange to
|
|
257
|
-
* @param {boolean} configureOutbound If set to 'true' it tells the message exchange to
|
|
295
|
+
* @param {boolean} configureInbound If set to 'true' it tells the message exchange to set up inbound messaging.
|
|
296
|
+
* @param {boolean} configureOutbound If set to 'true' it tells the message exchange to set up outbound messaging.
|
|
258
297
|
* @returns {Promise}
|
|
259
298
|
* @abstract
|
|
260
299
|
* @public
|
|
@@ -368,9 +407,9 @@ class MessageExchange extends MessageObserver {
|
|
|
368
407
|
message.destination.instanceID = this.#instanceID;
|
|
369
408
|
|
|
370
409
|
if ( MessageExchange.connectionNameRequestsIn === identifier ) {
|
|
371
|
-
messageTracer.recordTraceEntry( message, messageTracer.messageType.MESSAGE_REQUEST, messageTracer.dispatchEvent.RECEIVED, messageTracer.messageState.PENDING );
|
|
410
|
+
messageTracer.instance.recordTraceEntry( message, messageTracer.messageType.MESSAGE_REQUEST, messageTracer.dispatchEvent.RECEIVED, messageTracer.messageState.PENDING );
|
|
372
411
|
} else if ( MessageExchange.connectionNameResponsesIn === identifier ) {
|
|
373
|
-
messageTracer.recordTraceEntry( message, messageTracer.messageType.MESSAGE_RESPONSE, messageTracer.dispatchEvent.RECEIVED, messageTracer.messageState.PROCESSED );
|
|
412
|
+
messageTracer.instance.recordTraceEntry( message, messageTracer.messageType.MESSAGE_RESPONSE, messageTracer.dispatchEvent.RECEIVED, messageTracer.messageState.PROCESSED );
|
|
374
413
|
}
|
|
375
414
|
}
|
|
376
415
|
|
|
@@ -416,4 +455,4 @@ class MessageExchange extends MessageObserver {
|
|
|
416
455
|
|
|
417
456
|
}
|
|
418
457
|
|
|
419
|
-
module.exports = MessageExchange;
|
|
458
|
+
module.exports = MessageExchange;
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/*
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
|
|
2
|
+
* The ti-engine is an open source, free to use—both for personal and commercial projects—framework for the creation of microservice-based solutions using node.js.
|
|
3
|
+
* Copyright © 2021-2023 Boris Kostadinov <kostadinov.boris@gmail.com>
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
5
|
+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
6
|
+
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
7
|
+
*/
|
|
5
8
|
|
|
6
9
|
const ConnectionObserver = require( "#connection-observer" );
|
|
7
10
|
const _ = require( "lodash" );
|
|
@@ -88,7 +91,7 @@ class MessageHandler extends ConnectionObserver {
|
|
|
88
91
|
}
|
|
89
92
|
|
|
90
93
|
/**
|
|
91
|
-
* Used to
|
|
94
|
+
* Used to shut down and disable the communication behavior of the handler.
|
|
92
95
|
* <br/>
|
|
93
96
|
* NOTE: Override this to add functionality.
|
|
94
97
|
*
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/*
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
|
|
2
|
+
* The ti-engine is an open source, free to use—both for personal and commercial projects—framework for the creation of microservice-based solutions using node.js.
|
|
3
|
+
* Copyright © 2021-2025 Boris Kostadinov <kostadinov.boris@gmail.com>
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
5
|
+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
6
|
+
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
7
|
+
*/
|
|
5
8
|
|
|
6
9
|
const config = require( "#config" );
|
|
7
10
|
const tools = require( "#tools" );
|
|
@@ -28,11 +31,25 @@ class MessageMemoryCache {
|
|
|
28
31
|
let db = config.getSetting( config.setting.MEMORY_CACHE_REDIS_DB );
|
|
29
32
|
let authKey = config.getSetting( config.setting.MEMORY_CACHE_AUTH_KEY );
|
|
30
33
|
let user = config.getSetting( config.setting.MEMORY_CACHE_USER );
|
|
31
|
-
|
|
34
|
+
let retryMaxAttempts = config.getSetting( config.setting.MEMORY_CACHE_RETRY_MAX_ATTEMPTS );
|
|
35
|
+
let retryMaxInterval = config.getSetting( config.setting.MEMORY_CACHE_RETRY_MAX_INTERVAL );
|
|
36
|
+
this.#redisClient = redis.createRedisClient( identifier, host, port, authKey, user, db, retryMaxInterval, retryMaxAttempts );
|
|
32
37
|
}
|
|
33
38
|
|
|
34
39
|
/* Public interface */
|
|
35
40
|
|
|
41
|
+
/**
|
|
42
|
+
* Used to gracefully shut down the cache service.
|
|
43
|
+
*
|
|
44
|
+
* @method
|
|
45
|
+
* @param {number} [timeoutMs]
|
|
46
|
+
* @return {Promise}
|
|
47
|
+
* @public
|
|
48
|
+
*/
|
|
49
|
+
shutDown( timeoutMs ) {
|
|
50
|
+
return this.#redisClient.shutDown( timeoutMs );
|
|
51
|
+
}
|
|
52
|
+
|
|
36
53
|
/**
|
|
37
54
|
* Used to register a new {@link ConnectionObserver} for events related to the Redis connection state.
|
|
38
55
|
*
|
|
@@ -71,7 +88,7 @@ class MessageMemoryCache {
|
|
|
71
88
|
* @method
|
|
72
89
|
* @param {Object} payload
|
|
73
90
|
* @param {string} storeLocation
|
|
74
|
-
* @returns {Promise<string>} Will return
|
|
91
|
+
* @returns {Promise<string>} Will return a unique ID of the storage location for the payload.
|
|
75
92
|
* @public
|
|
76
93
|
*/
|
|
77
94
|
storeMessagePayload( payload, storeLocation ) {
|
|
@@ -148,4 +165,4 @@ class MessageMemoryCache {
|
|
|
148
165
|
*/
|
|
149
166
|
module.exports.create = ( identifier ) => {
|
|
150
167
|
return Object.freeze( new MessageMemoryCache( identifier ) );
|
|
151
|
-
};
|
|
168
|
+
};
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/*
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
|
|
2
|
+
* The ti-engine is an open source, free to use—both for personal and commercial projects—framework for the creation of microservice-based solutions using node.js.
|
|
3
|
+
* Copyright © 2021-2023 Boris Kostadinov <kostadinov.boris@gmail.com>
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
5
|
+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
6
|
+
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
7
|
+
*/
|
|
5
8
|
|
|
6
9
|
const ConnectionObserver = require( "#connection-observer" );
|
|
7
10
|
const exceptions = require( "#exceptions" );
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/*
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
|
|
2
|
+
* The ti-engine is an open source, free to use—both for personal and commercial projects—framework for the creation of microservice-based solutions using node.js.
|
|
3
|
+
* Copyright © 2021-2023 Boris Kostadinov <kostadinov.boris@gmail.com>
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
5
|
+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
6
|
+
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
7
|
+
*/
|
|
5
8
|
|
|
6
9
|
const MessageHandler = require( "#message-handler" );
|
|
7
10
|
const logger = require( "#logger" );
|
|
@@ -39,7 +42,7 @@ class MessageReceiver extends MessageHandler {
|
|
|
39
42
|
/* Public interface */
|
|
40
43
|
|
|
41
44
|
/**
|
|
42
|
-
* Property returning the configured
|
|
45
|
+
* Property returning the configured receiving queue.
|
|
43
46
|
*
|
|
44
47
|
* @property
|
|
45
48
|
* @returns {string}
|
|
@@ -62,7 +65,7 @@ class MessageReceiver extends MessageHandler {
|
|
|
62
65
|
}
|
|
63
66
|
|
|
64
67
|
/**
|
|
65
|
-
* Used to
|
|
68
|
+
* Used to shut down and disable the communication behavior of the handler.
|
|
66
69
|
* <br/>
|
|
67
70
|
* NOTE: Override this to add functionality.
|
|
68
71
|
*
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/*
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
|
|
2
|
+
* The ti-engine is an open source, free to use—both for personal and commercial projects—framework for the creation of microservice-based solutions using node.js.
|
|
3
|
+
* Copyright © 2021-2023 Boris Kostadinov <kostadinov.boris@gmail.com>
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
5
|
+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
6
|
+
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
7
|
+
*/
|
|
5
8
|
|
|
6
9
|
const MessageHandler = require( "#message-handler" );
|
|
7
10
|
const exceptions = require( "#exceptions" );
|
|
@@ -47,7 +50,7 @@ class MessageSender extends MessageHandler {
|
|
|
47
50
|
}
|
|
48
51
|
|
|
49
52
|
/**
|
|
50
|
-
* Used to
|
|
53
|
+
* Used to shut down and disable the communication behavior of the handler.
|
|
51
54
|
* <br/>
|
|
52
55
|
* NOTE: Override this to add functionality.
|
|
53
56
|
*
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/*
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
|
|
2
|
+
* The ti-engine is an open source, free to use—both for personal and commercial projects—framework for the creation of microservice-based solutions using node.js.
|
|
3
|
+
* Copyright © 2021-2025 Boris Kostadinov <kostadinov.boris@gmail.com>
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
5
|
+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
6
|
+
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
7
|
+
*/
|
|
5
8
|
|
|
6
9
|
const _ = require( "lodash" );
|
|
7
10
|
const tools = require( "#tools" );
|
|
@@ -79,103 +82,149 @@ let messageStateEnum = tools.enum( {
|
|
|
79
82
|
module.exports.messageState = messageStateEnum;
|
|
80
83
|
|
|
81
84
|
/**
|
|
82
|
-
* Used
|
|
83
|
-
*
|
|
84
|
-
* @method
|
|
85
|
-
* @param {TiTraceEntry} traceEntry The trace entry to log.
|
|
86
|
-
* @param {TiLogSeverity} severity The log entry severity.
|
|
87
|
-
* @private
|
|
88
|
-
*/
|
|
89
|
-
let createLogEntry = ( traceEntry, severity ) => {
|
|
90
|
-
logger.log( formatLogEntry( traceEntry ), severity, traceEntry );
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Used to format trace entry into log-suitable string.
|
|
85
|
+
* Used for recording message trace entries.
|
|
95
86
|
*
|
|
96
|
-
* @
|
|
97
|
-
* @
|
|
98
|
-
* @
|
|
99
|
-
* @private
|
|
87
|
+
* @class MessageTracer
|
|
88
|
+
* @singleton
|
|
89
|
+
* @public
|
|
100
90
|
*/
|
|
101
|
-
|
|
102
|
-
return `Message(${ traceEntry.chainID || traceEntry.messageID }) Trace: '${ traceEntry.messageType } ${ traceEntry.dispatchEvent } ${ traceEntry.messageState }' From: '${ traceEntry.fromAddress }' To: '${ traceEntry.toAddress }'`;
|
|
103
|
-
};
|
|
91
|
+
class MessageTracer {
|
|
104
92
|
|
|
105
|
-
|
|
106
|
-
* Used to obscure sensitive data in the message, remove the payload, and return a snapshot.
|
|
107
|
-
*
|
|
108
|
-
* @method
|
|
109
|
-
* @param {Message} message
|
|
110
|
-
* @returns {Message}
|
|
111
|
-
* @private
|
|
112
|
-
*/
|
|
113
|
-
let obscureSensitiveData = ( message ) => {
|
|
114
|
-
/** @type Message */
|
|
115
|
-
let messageSnapshot = tools.parseJSON( _.replace( tools.stringifyJSON( message ), /("\w*?pin\w*?"|"\w*?pass\w*?"|"\w*?otp\w*?"):"(.*?)"/gmi, "\"SENSITIVE_PROPERTY\":\"OBSCURED_BY_SYSTEM\"" ) );
|
|
116
|
-
delete messageSnapshot.payload;
|
|
117
|
-
return messageSnapshot;
|
|
118
|
-
};
|
|
93
|
+
static #instance = null;
|
|
119
94
|
|
|
120
|
-
/**
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
* @method
|
|
130
|
-
* @param {Message} message The message to trace.
|
|
131
|
-
* @param {TiMessageType} messageType The type of the message.
|
|
132
|
-
* @param {TiDispatchEvent} dispatchEvent The event in the dispatch system that triggered the trace entry.
|
|
133
|
-
* @param {TiMessageState} messageState The state of the processing of the message.
|
|
134
|
-
* @public
|
|
135
|
-
*/
|
|
136
|
-
module.exports.recordTraceEntry = ( message, messageType, dispatchEvent, messageState ) => {
|
|
137
|
-
// depending on whether the message comes as request or response, the from and to addresses will be opposite:
|
|
138
|
-
let source = message.source.route + "." + message.source.instanceID;
|
|
139
|
-
let destination = message.destination.route + ( ( message.destination.instanceID != null ) ? "." + message.destination.instanceID : "" );
|
|
140
|
-
let messageSnapshot = obscureSensitiveData( message );
|
|
141
|
-
delete messageSnapshot.chainID;
|
|
142
|
-
delete messageSnapshot.messageID;
|
|
143
|
-
let currentDate = new Date();
|
|
144
|
-
|
|
145
|
-
/** @type TiTraceEntry */
|
|
146
|
-
let traceEntry = {
|
|
147
|
-
chainID: message.chainID,
|
|
148
|
-
dispatchEvent: tools.getEnumName( dispatchEventEnum, dispatchEvent ),
|
|
149
|
-
fromAddress: ( messageType === messageTypeEnum.MESSAGE_REQUEST ) ? source : destination,
|
|
150
|
-
messageID: message.messageID,
|
|
151
|
-
messageSnapshot: messageSnapshot,
|
|
152
|
-
messageState: tools.getEnumName( messageStateEnum, messageState ),
|
|
153
|
-
messageType: tools.getEnumName( messageTypeEnum, messageType ),
|
|
154
|
-
toAddress: ( messageType === messageTypeEnum.MESSAGE_REQUEST ) ? destination : source,
|
|
155
|
-
traceTimestamp: currentDate.getTime(),
|
|
156
|
-
traceID: tools.getUUID()
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
// only write the trace in the general log if this is enabled:
|
|
160
|
-
if ( config.getSetting( config.setting.MESSAGE_EXCHANGE_TRACE_LOG_ENABLED ) === true ) {
|
|
161
|
-
createLogEntry( traceEntry, ( dispatchEvent === dispatchEventEnum.FAILED ) ? logger.logSeverity.ERROR : logger.logSeverity.NOTICE );
|
|
95
|
+
/**
|
|
96
|
+
* @constructor
|
|
97
|
+
* @return {MessageTracer}
|
|
98
|
+
*/
|
|
99
|
+
constructor() {
|
|
100
|
+
if ( !MessageTracer.#instance ) {
|
|
101
|
+
MessageTracer.#instance = this;
|
|
102
|
+
}
|
|
103
|
+
return MessageTracer.#instance;
|
|
162
104
|
}
|
|
163
105
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
106
|
+
/* Public interface */
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Used to initialize the message tracer.
|
|
110
|
+
*
|
|
111
|
+
* @method
|
|
112
|
+
* @returns {Promise}
|
|
113
|
+
* @public
|
|
114
|
+
*/
|
|
115
|
+
initialize() {
|
|
116
|
+
return new Promise( ( resolve, reject ) => {
|
|
117
|
+
cache.instance.setJSON( config.getSetting( config.setting.MESSAGE_EXCHANGE_TRACE_REPOSITORY ), traceRoot, "$", 1 ).then( () => {
|
|
118
|
+
resolve();
|
|
119
|
+
} ).catch( ( error ) => {
|
|
120
|
+
reject( exceptions.raise( error ) );
|
|
175
121
|
} );
|
|
176
|
-
}
|
|
177
|
-
|
|
122
|
+
} );
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Used to create a trace entry for the provided {@link Message} and parameters.
|
|
127
|
+
* <br/>
|
|
128
|
+
* NOTE: By default all trace events are stored in the memory cache for further processing and analysis. The
|
|
129
|
+
* location is configured in the MESSAGE_EXCHANGE_TRACE_REPOSITORY setting.
|
|
130
|
+
* <br/>
|
|
131
|
+
* NOTE: Trace events are logged with severity level NOTICE or ERROR for failed dispatches. They still might be
|
|
132
|
+
* filtered out if the minimum log level setting is set too high.
|
|
133
|
+
*
|
|
134
|
+
* @method
|
|
135
|
+
* @param {Message} message The message to trace.
|
|
136
|
+
* @param {TiMessageType} messageType The type of the message.
|
|
137
|
+
* @param {TiDispatchEvent} dispatchEvent The event in the dispatch system that triggered the trace entry.
|
|
138
|
+
* @param {TiMessageState} messageState The state of the message processing.
|
|
139
|
+
* @public
|
|
140
|
+
*/
|
|
141
|
+
recordTraceEntry( message, messageType, dispatchEvent, messageState ) {
|
|
142
|
+
// Depending on whether the message comes as request or response, the from and to addresses will be opposite:
|
|
143
|
+
let source = message.source.route + "." + message.source.instanceID;
|
|
144
|
+
let destination = message.destination.route + ( ( message.destination.instanceID != null ) ? "." + message.destination.instanceID : "" );
|
|
145
|
+
let messageSnapshot = MessageTracer.#obscureSensitiveData( message );
|
|
146
|
+
delete messageSnapshot.chainID;
|
|
147
|
+
delete messageSnapshot.messageID;
|
|
148
|
+
let currentDate = new Date();
|
|
149
|
+
|
|
150
|
+
/** @type TiTraceEntry */
|
|
151
|
+
let traceEntry = {
|
|
152
|
+
chainID: message.chainID,
|
|
153
|
+
dispatchEvent: tools.getEnumName( dispatchEventEnum, dispatchEvent ),
|
|
154
|
+
fromAddress: ( messageType === messageTypeEnum.MESSAGE_REQUEST ) ? source : destination,
|
|
155
|
+
messageID: message.messageID,
|
|
156
|
+
messageSnapshot: messageSnapshot,
|
|
157
|
+
messageState: tools.getEnumName( messageStateEnum, messageState ),
|
|
158
|
+
messageType: tools.getEnumName( messageTypeEnum, messageType ),
|
|
159
|
+
toAddress: ( messageType === messageTypeEnum.MESSAGE_REQUEST ) ? destination : source,
|
|
160
|
+
traceTimestamp: currentDate.getTime(),
|
|
161
|
+
traceID: tools.getUUID()
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
// Only write the trace in the general log if this is enabled:
|
|
165
|
+
if ( config.getSetting( config.setting.MESSAGE_EXCHANGE_TRACE_LOG_ENABLED ) === true ) {
|
|
166
|
+
MessageTracer.#createLogEntry( traceEntry, ( dispatchEvent === dispatchEventEnum.FAILED ) ? logger.logSeverity.ERROR : logger.logSeverity.NOTICE );
|
|
178
167
|
}
|
|
179
|
-
} );
|
|
180
168
|
|
|
181
|
-
|
|
169
|
+
// Add the trace entry to the repository in the memory cache:
|
|
170
|
+
cache.instance.arrayAppendJSON( config.getSetting( config.setting.MESSAGE_EXCHANGE_TRACE_REPOSITORY ), traceEntry, "$.trace" ).then( () => {
|
|
171
|
+
// This will refresh the expiration time for the trace repository on each new record:
|
|
172
|
+
let expiration = config.getSetting( config.setting.MESSAGE_EXCHANGE_TRACE_EXPIRATION_TIME );
|
|
173
|
+
return ( expiration > 0 ) ? cache.instance.expireValue( config.getSetting( config.setting.MESSAGE_EXCHANGE_TRACE_REPOSITORY ), expiration ) : expiration;
|
|
174
|
+
} ).catch( ( error ) => {
|
|
175
|
+
// If JSON is unsupported in Redis server, then try to store the trace entry in a Set:
|
|
176
|
+
if ( error.code === exceptions.exceptionCode.E_GEN_FEATURE_UNSUPPORTED ) {
|
|
177
|
+
cache.instance.addToSet( config.getSetting( config.setting.MESSAGE_EXCHANGE_TRACE_REPOSITORY ), traceEntry ).catch( ( error ) => {
|
|
178
|
+
logger.log( `Failed to add message trace entry to the trace repository. While this will not prevent the application from running, it might still be a sign of a more serious problem!`, logger.logSeverity.WARNING, error );
|
|
179
|
+
} );
|
|
180
|
+
} else {
|
|
181
|
+
logger.log( `Failed to add message trace entry to the trace repository. While this will not prevent the application from running, it might still be a sign of a more serious problem!`, logger.logSeverity.WARNING, error );
|
|
182
|
+
}
|
|
183
|
+
} );
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/* Private interface */
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Used to create a log entry from the trace entry.
|
|
190
|
+
*
|
|
191
|
+
* @method
|
|
192
|
+
* @param {TiTraceEntry} traceEntry The trace entry to log.
|
|
193
|
+
* @param {TiLogSeverity} severity The log entry severity.
|
|
194
|
+
* @private
|
|
195
|
+
*/
|
|
196
|
+
static #createLogEntry( traceEntry, severity ) {
|
|
197
|
+
logger.log( MessageTracer.#formatLogEntry( traceEntry ), severity, traceEntry );
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Used to format trace entry into log-suitable string.
|
|
202
|
+
*
|
|
203
|
+
* @method
|
|
204
|
+
* @param {TiTraceEntry} traceEntry
|
|
205
|
+
* @return {string} Prepared trace info.
|
|
206
|
+
* @private
|
|
207
|
+
*/
|
|
208
|
+
static #formatLogEntry( traceEntry ) {
|
|
209
|
+
return `Message(${ traceEntry.chainID || traceEntry.messageID }) Trace: '${ traceEntry.messageType } ${ traceEntry.dispatchEvent } ${ traceEntry.messageState }' From: '${ traceEntry.fromAddress }' To: '${ traceEntry.toAddress }'`;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Used to obscure sensitive data in the message, remove the payload, and return a snapshot.
|
|
214
|
+
*
|
|
215
|
+
* @method
|
|
216
|
+
* @param {Message} message
|
|
217
|
+
* @returns {Message}
|
|
218
|
+
* @private
|
|
219
|
+
*/
|
|
220
|
+
static #obscureSensitiveData( message ) {
|
|
221
|
+
/** @type Message */
|
|
222
|
+
let messageSnapshot = tools.parseJSON( _.replace( tools.stringifyJSON( message ), /("\w*?pin\w*?"|"\w*?pass\w*?"|"\w*?otp\w*?"):"(.*?)"/gmi, "\"SENSITIVE_PROPERTY\":\"OBSCURED_BY_SYSTEM\"" ) );
|
|
223
|
+
delete messageSnapshot.payload;
|
|
224
|
+
return messageSnapshot;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const instance = new MessageTracer();
|
|
230
|
+
module.exports.instance = Object.freeze( instance );
|