@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-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 ConnectionObserver = require( "#connection-observer" );
|
|
7
10
|
const Redis = require( "ioredis" );
|
|
@@ -17,27 +20,27 @@ const _ = require( "lodash" );
|
|
|
17
20
|
* @enum {string}
|
|
18
21
|
*/
|
|
19
22
|
let cacheCommandsEnum = tools.enum( {
|
|
20
|
-
ADD_TO_SET: [ "sadd", "add to set", "https://redis.io/commands/sadd" ],
|
|
21
|
-
DELETE_VALUE: [ "del", "delete value", "https://redis.io/commands/del" ],
|
|
22
|
-
EXPIRE: [ "expire", "expire", "https://redis.io/commands/expire" ],
|
|
23
|
-
GET_ALL_FROM_SET: [ "smembers", "get all set members", "https://redis.io/commands/smembers" ],
|
|
24
|
-
GET_VALUE: [ "get", "get value", "https://redis.io/commands/get" ],
|
|
25
|
-
HASH_GET: [ "hget", "hash get", "https://redis.io/commands/hget" ],
|
|
26
|
-
HASH_GET_ALL: [ "hgetall", "hash get all", "https://redis.io/commands/hgetall" ],
|
|
27
|
-
HASH_REMOVE: [ "hdel", "hash remove", "https://redis.io/commands/hdel" ],
|
|
28
|
-
HASH_SET: [ "hset", "", "https://redis.io/commands/hset" ],
|
|
29
|
-
HASH_SET_MANY: [ "hmset", "", "https://redis.io/commands/hmset" ],
|
|
30
|
-
IS_SET_MEMBER: [ "sismember", "", "https://redis.io/commands/sismember" ],
|
|
31
|
-
JSON_ARRAY_APPEND: [ "json.arrappend", "", "https://redis.io/commands/json.arrappend" ],
|
|
32
|
-
JSON_GET: [ "json.get", "", "https://redis.io/commands/json.get" ],
|
|
33
|
-
JSON_SET: [ "json.set", "", "https://redis.io/commands/json.set" ],
|
|
34
|
-
KEYS: [ "keys", "", "https://redis.io/commands/keys" ],
|
|
35
|
-
LIST_PUSH: [ "lpush", "list push", "https://redis.io/commands/lpush" ],
|
|
36
|
-
LIST_POP_TAIL_BLOCKING: [ "brpop", "list pop tail blocking", "https://redis.io/commands/brpop" ],
|
|
37
|
-
LIST_POP_TAIL_PUSH_HEAD_BLOCKING: [ "brpoplpush", "list pop tail push head blocking", "https://redis.io/commands/brpoplpush" ],
|
|
38
|
-
LIST_REMOVE: [ "lrem", "list remove", "https://redis.io/commands/lrem" ],
|
|
39
|
-
SET_VALUE: [ "set", "set value", "https://redis.io/commands/set" ],
|
|
40
|
-
UNION_OF_SETS: [ "sunion", "union of sets", "https://redis.io/commands/sunion" ]
|
|
23
|
+
ADD_TO_SET: [ "sadd", "add to set", "https://redis.io/docs/latest/commands/sadd/" ],
|
|
24
|
+
DELETE_VALUE: [ "del", "delete value", "https://redis.io/docs/latest/commands/del/" ],
|
|
25
|
+
EXPIRE: [ "expire", "expire", "https://redis.io/docs/latest/commands/expire/" ],
|
|
26
|
+
GET_ALL_FROM_SET: [ "smembers", "get all set members", "https://redis.io/docs/latest/commands/smembers/" ],
|
|
27
|
+
GET_VALUE: [ "get", "get value", "https://redis.io/docs/latest/commands/get/" ],
|
|
28
|
+
HASH_GET: [ "hget", "hash get", "https://redis.io/docs/latest/commands/hget/" ],
|
|
29
|
+
HASH_GET_ALL: [ "hgetall", "hash get all", "https://redis.io/docs/latest/commands/hgetall/" ],
|
|
30
|
+
HASH_REMOVE: [ "hdel", "hash remove", "https://redis.io/docs/latest/commands/hdel/" ],
|
|
31
|
+
HASH_SET: [ "hset", "", "https://redis.io/docs/latest/commands/hset/" ],
|
|
32
|
+
HASH_SET_MANY: [ "hmset", "(deprecated) use HSET with multiple fields", "https://redis.io/docs/latest/commands/hmset/" ],
|
|
33
|
+
IS_SET_MEMBER: [ "sismember", "", "https://redis.io/docs/latest/commands/sismember/" ],
|
|
34
|
+
JSON_ARRAY_APPEND: [ "json.arrappend", "", "https://redis.io/docs/latest/commands/json.arrappend/" ],
|
|
35
|
+
JSON_GET: [ "json.get", "", "https://redis.io/docs/latest/commands/json.get/" ],
|
|
36
|
+
JSON_SET: [ "json.set", "", "https://redis.io/docs/latest/commands/json.set/" ],
|
|
37
|
+
KEYS: [ "keys", "(warning: O(N), use SCAN where possible)", "https://redis.io/docs/latest/commands/keys/" ],
|
|
38
|
+
LIST_PUSH: [ "lpush", "list push", "https://redis.io/docs/latest/commands/lpush/" ],
|
|
39
|
+
LIST_POP_TAIL_BLOCKING: [ "brpop", "list pop tail blocking", "https://redis.io/docs/latest/commands/brpop/" ],
|
|
40
|
+
LIST_POP_TAIL_PUSH_HEAD_BLOCKING: [ "brpoplpush", "list pop tail push head blocking", "https://redis.io/docs/latest/commands/brpoplpush/" ],
|
|
41
|
+
LIST_REMOVE: [ "lrem", "list remove", "https://redis.io/docs/latest/commands/lrem/" ],
|
|
42
|
+
SET_VALUE: [ "set", "set value", "https://redis.io/docs/latest/commands/set/" ],
|
|
43
|
+
UNION_OF_SETS: [ "sunion", "union of sets", "https://redis.io/docs/latest/commands/sunion/" ]
|
|
41
44
|
} );
|
|
42
45
|
|
|
43
46
|
/**
|
|
@@ -63,6 +66,9 @@ module.exports.cacheOverrideMode = cacheOverrideModeEnum;
|
|
|
63
66
|
|
|
64
67
|
/**
|
|
65
68
|
* Used to create a Redis Cache client.
|
|
69
|
+
* <br/>
|
|
70
|
+
* NOTE: This client is set to automatically resend all pending commands on connection recovery with no limit on the retry attempts.
|
|
71
|
+
* This is done to avoid losing any pending commands in case of a connection failure. For a different behavior, use custom implementation.
|
|
66
72
|
*
|
|
67
73
|
* @class RedisClient
|
|
68
74
|
* @public
|
|
@@ -76,6 +82,7 @@ class RedisClient {
|
|
|
76
82
|
#serverInfo = {};
|
|
77
83
|
#serverFeatures = {};
|
|
78
84
|
#connectionObservers = [];
|
|
85
|
+
#messageHandlersByChannel = new Map();
|
|
79
86
|
|
|
80
87
|
/**
|
|
81
88
|
* @constructor
|
|
@@ -85,11 +92,13 @@ class RedisClient {
|
|
|
85
92
|
* @param {string} authKey
|
|
86
93
|
* @param {string} user
|
|
87
94
|
* @param {number} defaultDB
|
|
88
|
-
* @param {
|
|
89
|
-
* @param {number}
|
|
95
|
+
* @param {number} [retryMaxIntervalMs=1000] Optional max backoff interval.
|
|
96
|
+
* @param {number|undefined} [retryMaxAttempts=undefined] Optional max (re)connection attempts before abort.
|
|
90
97
|
*/
|
|
91
|
-
constructor( identifier, host, port, authKey, user, defaultDB,
|
|
98
|
+
constructor( identifier, host, port, authKey, user, defaultDB, retryMaxIntervalMs = 1000, retryMaxAttempts = undefined ) {
|
|
92
99
|
this.#clientIdentifier = identifier || "redis-client-" + tools.getUUID();
|
|
100
|
+
this.#retryMaxInterval = retryMaxIntervalMs;
|
|
101
|
+
this.#retryMaxAttempts = retryMaxAttempts;
|
|
93
102
|
|
|
94
103
|
let retryStrategy = ( attempt ) => {
|
|
95
104
|
let result = Math.min( attempt * 50, this.#retryMaxInterval );
|
|
@@ -113,8 +122,8 @@ class RedisClient {
|
|
|
113
122
|
username: user,
|
|
114
123
|
password: authKey,
|
|
115
124
|
db: defaultDB,
|
|
116
|
-
autoResendUnfulfilledCommands:
|
|
117
|
-
maxRetriesPerRequest:
|
|
125
|
+
autoResendUnfulfilledCommands: true,
|
|
126
|
+
maxRetriesPerRequest: null,
|
|
118
127
|
retryStrategy: retryStrategy,
|
|
119
128
|
reconnectOnError: reconnectOnError
|
|
120
129
|
};
|
|
@@ -205,7 +214,8 @@ class RedisClient {
|
|
|
205
214
|
* @public
|
|
206
215
|
*/
|
|
207
216
|
get isJSONSupported() {
|
|
208
|
-
|
|
217
|
+
// Detect RedisJSON module variants (e.g., ReJSON, ReJSON2):
|
|
218
|
+
return !_.isNil( this.#serverFeatures[ "ReJSON" ] ) || !_.isNil( this.#serverFeatures[ "ReJSON2" ] );
|
|
209
219
|
}
|
|
210
220
|
|
|
211
221
|
/**
|
|
@@ -283,25 +293,69 @@ class RedisClient {
|
|
|
283
293
|
|
|
284
294
|
/**
|
|
285
295
|
* Used to subscribe to the specified channel for messages.
|
|
296
|
+
* <br/>
|
|
297
|
+
* NOTE: Call unsubscribeCommand(channel) to detach later.
|
|
286
298
|
*
|
|
287
299
|
* @method
|
|
288
|
-
* @param {string} channel
|
|
300
|
+
* @param {string} channel Unique identifier of the channel to subscribe to.
|
|
289
301
|
* @param {function( Object )} messageHandler Will execute this handler every time a new message is received.
|
|
290
302
|
* @return {Promise}
|
|
291
303
|
* @public
|
|
292
304
|
*/
|
|
293
305
|
subscribeCommand( channel, messageHandler ) {
|
|
294
306
|
return new Promise( ( resolve, reject ) => {
|
|
295
|
-
|
|
296
|
-
|
|
307
|
+
// Avoid attaching multiple listeners for the same channel:
|
|
308
|
+
if ( this.#messageHandlersByChannel.has( channel ) ) {
|
|
309
|
+
logger.log( "Attempting to subscribe to message channel '" + channel + "' while already subscribed to it.", logger.logSeverity.WARNING );
|
|
297
310
|
resolve();
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
311
|
+
} else {
|
|
312
|
+
const onMessage = ( subscribedChannel, message ) => {
|
|
313
|
+
if ( subscribedChannel === channel && typeof messageHandler === "function" ) {
|
|
314
|
+
messageHandler( tools.parseJSON( message ) );
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
this.#redisClient.once( "subscribe", ( subscribedChannel ) => {
|
|
319
|
+
if ( subscribedChannel === channel ) {
|
|
320
|
+
logger.log( "Subscription to message channel '" + channel + "' successful.", logger.logSeverity.DEBUG );
|
|
321
|
+
resolve();
|
|
322
|
+
}
|
|
323
|
+
} );
|
|
324
|
+
|
|
325
|
+
this.#redisClient.on( "message", onMessage );
|
|
326
|
+
this.#messageHandlersByChannel.set( channel, onMessage );
|
|
327
|
+
|
|
328
|
+
this.#redisClient.subscribe( channel ).catch( ( error ) => {
|
|
329
|
+
// Cleanup partial state if subscribe fails:
|
|
330
|
+
const handler = this.#messageHandlersByChannel.get( channel );
|
|
331
|
+
if ( handler ) {
|
|
332
|
+
this.#redisClient.off( "message", handler );
|
|
333
|
+
this.#messageHandlersByChannel.delete( channel );
|
|
334
|
+
}
|
|
335
|
+
reject( exceptions.raise( error ) );
|
|
336
|
+
} );
|
|
337
|
+
}
|
|
338
|
+
} );
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Used to unsubscribe from a channel and remove its message handler.
|
|
343
|
+
*
|
|
344
|
+
* @method
|
|
345
|
+
* @param {string} channel Unique identifier of the channel to unsubscribe from.
|
|
346
|
+
* @return {Promise}
|
|
347
|
+
* @public
|
|
348
|
+
*/
|
|
349
|
+
unsubscribeCommand( channel ) {
|
|
350
|
+
return new Promise( ( resolve, reject ) => {
|
|
351
|
+
const handler = this.#messageHandlersByChannel.get( channel );
|
|
352
|
+
if ( handler ) {
|
|
353
|
+
this.#redisClient.off( "message", handler );
|
|
354
|
+
this.#messageHandlersByChannel.delete( channel );
|
|
355
|
+
}
|
|
356
|
+
this.#redisClient.unsubscribe( channel ).then( () => {
|
|
357
|
+
resolve();
|
|
358
|
+
} ).catch( ( error ) => {
|
|
305
359
|
reject( exceptions.raise( error ) );
|
|
306
360
|
} );
|
|
307
361
|
} );
|
|
@@ -329,6 +383,47 @@ class RedisClient {
|
|
|
329
383
|
} );
|
|
330
384
|
}
|
|
331
385
|
|
|
386
|
+
/**
|
|
387
|
+
* Used to gracefully close the Redis connection.
|
|
388
|
+
* Attempts to quit(), then falls back to disconnect() on timeout.
|
|
389
|
+
*
|
|
390
|
+
* @method
|
|
391
|
+
* @param {number} [timeoutMs=1000]
|
|
392
|
+
* @returns {Promise<Object>}
|
|
393
|
+
* @public
|
|
394
|
+
*/
|
|
395
|
+
shutDown( timeoutMs = 1000 ) {
|
|
396
|
+
return new Promise( ( resolve ) => {
|
|
397
|
+
let finished = false;
|
|
398
|
+
const done = () => {
|
|
399
|
+
if ( !finished ) {
|
|
400
|
+
finished = true;
|
|
401
|
+
resolve();
|
|
402
|
+
}
|
|
403
|
+
};
|
|
404
|
+
|
|
405
|
+
const timeout = setTimeout( () => {
|
|
406
|
+
try {
|
|
407
|
+
this.#redisClient.disconnect();
|
|
408
|
+
} catch ( error ) {
|
|
409
|
+
}
|
|
410
|
+
done();
|
|
411
|
+
}, timeoutMs );
|
|
412
|
+
|
|
413
|
+
this.#redisClient.quit().then( () => {
|
|
414
|
+
clearTimeout( timeout );
|
|
415
|
+
done();
|
|
416
|
+
} ).catch( () => {
|
|
417
|
+
clearTimeout( timeout );
|
|
418
|
+
try {
|
|
419
|
+
this.#redisClient.disconnect();
|
|
420
|
+
} catch ( error ) {
|
|
421
|
+
}
|
|
422
|
+
done();
|
|
423
|
+
} );
|
|
424
|
+
} );
|
|
425
|
+
}
|
|
426
|
+
|
|
332
427
|
}
|
|
333
428
|
|
|
334
429
|
/**
|
|
@@ -341,11 +436,11 @@ class RedisClient {
|
|
|
341
436
|
* @param {string} [authKey=undefined]
|
|
342
437
|
* @param {string} [user="default"]
|
|
343
438
|
* @param {number} [defaultDB=0]
|
|
344
|
-
* @param {
|
|
345
|
-
* @param {number} [
|
|
439
|
+
* @param {number} [retryMaxIntervalMs=1000]
|
|
440
|
+
* @param {number|undefined} [retryMaxAttempts=undefined]
|
|
346
441
|
* @return {RedisClient}
|
|
347
442
|
* @public
|
|
348
443
|
*/
|
|
349
|
-
module.exports.createRedisClient = ( identifier, host, port = 6379, authKey = undefined, user = "default", defaultDB = 0,
|
|
350
|
-
return Object.freeze( new RedisClient( identifier, host, port, authKey, user, defaultDB,
|
|
351
|
-
};
|
|
444
|
+
module.exports.createRedisClient = ( identifier, host, port = 6379, authKey = undefined, user = "default", defaultDB = 0, retryMaxIntervalMs = 1000, retryMaxAttempts = undefined ) => {
|
|
445
|
+
return Object.freeze( new RedisClient( identifier, host, port, authKey, user, defaultDB, retryMaxIntervalMs, retryMaxAttempts ) );
|
|
446
|
+
};
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ti-engine/core",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.8",
|
|
4
4
|
"description": "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.",
|
|
5
5
|
"author": "Boris Kostadinov <kostadinov.boris@gmail.com>",
|
|
6
|
-
"license": "
|
|
6
|
+
"license": "GPL-3.0-or-later",
|
|
7
7
|
"exports": {
|
|
8
8
|
"./exceptions": "./utils/exceptions.js",
|
|
9
9
|
"./localization": "./utils/localization.js",
|
|
@@ -44,15 +44,15 @@
|
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"blake2": "^5.0.0",
|
|
47
|
-
"dotenv": "^
|
|
48
|
-
"fs-extra": "^11.
|
|
47
|
+
"dotenv": "^17.2.1",
|
|
48
|
+
"fs-extra": "^11.3.1",
|
|
49
49
|
"lodash": "^4.17.21",
|
|
50
50
|
"node-schedule": "^2.1.1",
|
|
51
|
-
"ioredis": "^5.
|
|
51
|
+
"ioredis": "^5.7.0"
|
|
52
52
|
},
|
|
53
53
|
"optionalDependencies": {
|
|
54
54
|
"@google-cloud/error-reporting": "^3.0.5",
|
|
55
|
-
"zeromq": "^6.
|
|
55
|
+
"zeromq": "^6.5.0"
|
|
56
56
|
},
|
|
57
57
|
"repository": {
|
|
58
58
|
"type": "git",
|
|
@@ -61,4 +61,4 @@
|
|
|
61
61
|
"engines": {
|
|
62
62
|
"node": ">=14.17.0"
|
|
63
63
|
}
|
|
64
|
-
}
|
|
64
|
+
}
|
package/utils/cache.js
CHANGED
|
@@ -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 ConnectionObserver = require( "#connection-observer" );
|
|
7
10
|
const _ = require( "lodash" );
|
|
@@ -54,7 +57,9 @@ class CommonMemoryCache extends ConnectionObserver {
|
|
|
54
57
|
* @returns {boolean}
|
|
55
58
|
* @public
|
|
56
59
|
*/
|
|
57
|
-
get isOperational() {
|
|
60
|
+
get isOperational() {
|
|
61
|
+
return this.#isOperational;
|
|
62
|
+
}
|
|
58
63
|
|
|
59
64
|
/**
|
|
60
65
|
* Property returning the connection identifier of the cache service.
|
|
@@ -63,7 +68,20 @@ class CommonMemoryCache extends ConnectionObserver {
|
|
|
63
68
|
* @returns {string}
|
|
64
69
|
* @public
|
|
65
70
|
*/
|
|
66
|
-
get connectionIdentifier() {
|
|
71
|
+
get connectionIdentifier() {
|
|
72
|
+
return this.#connectionIdentifier;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Used to gracefully shut down the cache service.
|
|
77
|
+
*
|
|
78
|
+
* @method
|
|
79
|
+
* @return {Promise}
|
|
80
|
+
* @public
|
|
81
|
+
*/
|
|
82
|
+
shutDown() {
|
|
83
|
+
return this.#redisClient.shutDown( 250 );
|
|
84
|
+
}
|
|
67
85
|
|
|
68
86
|
/**
|
|
69
87
|
* Needs to be invoked by the connection handler when the connection is disrupted.
|
|
@@ -105,7 +123,7 @@ class CommonMemoryCache extends ConnectionObserver {
|
|
|
105
123
|
}
|
|
106
124
|
|
|
107
125
|
/**
|
|
108
|
-
* Used to search for keys by given pattern.
|
|
126
|
+
* Used to search for keys by a given pattern.
|
|
109
127
|
*
|
|
110
128
|
* @method
|
|
111
129
|
* @param {string} pattern
|
|
@@ -361,7 +379,7 @@ class CommonMemoryCache extends ConnectionObserver {
|
|
|
361
379
|
/**
|
|
362
380
|
* Used to add multiple values to multiple sets in one transactional request.
|
|
363
381
|
* <br/>
|
|
364
|
-
* NOTE: The two arrays of keys and values must have correct index relations (i.e
|
|
382
|
+
* NOTE: The two arrays of keys and values must have correct index relations (i.e., first pair on keys[0] and values[0] and so on)!
|
|
365
383
|
*
|
|
366
384
|
* @method
|
|
367
385
|
* @param {string[]} keys
|
|
@@ -388,7 +406,7 @@ class CommonMemoryCache extends ConnectionObserver {
|
|
|
388
406
|
}
|
|
389
407
|
|
|
390
408
|
/**
|
|
391
|
-
* Used to check if the provided value is member of the specified set.
|
|
409
|
+
* Used to check if the provided value is a member of the specified set.
|
|
392
410
|
*
|
|
393
411
|
* @method
|
|
394
412
|
* @param {string} setName
|
|
@@ -467,6 +485,7 @@ class CommonMemoryCache extends ConnectionObserver {
|
|
|
467
485
|
* Used to set a single hash field.
|
|
468
486
|
*
|
|
469
487
|
* @method
|
|
488
|
+
* @deprecated
|
|
470
489
|
* @param {string} key
|
|
471
490
|
* @param {string} name
|
|
472
491
|
* @param {*} value
|
|
@@ -492,6 +511,7 @@ class CommonMemoryCache extends ConnectionObserver {
|
|
|
492
511
|
* Used to set multiple hash fields.
|
|
493
512
|
*
|
|
494
513
|
* @method
|
|
514
|
+
* @deprecated
|
|
495
515
|
* @param {string} key
|
|
496
516
|
* @param {Object[]} fields
|
|
497
517
|
* @param {string} fields[].name
|
|
@@ -643,4 +663,4 @@ class CommonMemoryCache extends ConnectionObserver {
|
|
|
643
663
|
}
|
|
644
664
|
|
|
645
665
|
const instance = new CommonMemoryCache();
|
|
646
|
-
module.exports = Object.freeze( instance );
|
|
666
|
+
module.exports.instance = Object.freeze( instance );
|
package/utils/config.js
CHANGED
|
@@ -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" );
|
|
@@ -30,6 +33,8 @@ const tools = require( "#tools" );
|
|
|
30
33
|
* @property {EnvironmentVariable} env.TI_MEMORY_CACHE_REDIS_DB
|
|
31
34
|
* @property {EnvironmentVariable} env.TI_MEMORY_CACHE_REDIS_HOST
|
|
32
35
|
* @property {EnvironmentVariable} env.TI_MEMORY_CACHE_REDIS_PORT
|
|
36
|
+
* @property {EnvironmentVariable} env.TI_MEMORY_CACHE_RETRY_MAX_ATTEMPTS
|
|
37
|
+
* @property {EnvironmentVariable} env.TI_MEMORY_CACHE_RETRY_MAX_INTERVAL
|
|
33
38
|
* @property {EnvironmentVariable} env.TI_MEMORY_CACHE_USER
|
|
34
39
|
* @property {EnvironmentVariable} env.TI_MESSAGE_EXCHANGE_SECURITY_HASH_ENABLED
|
|
35
40
|
* @property {EnvironmentVariable} env.TI_MESSAGE_EXCHANGE_SECURITY_HASH_KEY
|
|
@@ -77,6 +82,8 @@ const tools = require( "#tools" );
|
|
|
77
82
|
* @property {number} redisDB
|
|
78
83
|
* @property {string} redisHost
|
|
79
84
|
* @property {number} redisPort
|
|
85
|
+
* @property {number} retryMaxAttempts
|
|
86
|
+
* @property {number} retryMaxInterval
|
|
80
87
|
* @property {string} user
|
|
81
88
|
*/
|
|
82
89
|
|
|
@@ -119,6 +126,8 @@ let settingsEnum = tools.enum( {
|
|
|
119
126
|
MEMORY_CACHE_REDIS_DB: [ "memoryCache.redisDB", "redisDB", "" ],
|
|
120
127
|
MEMORY_CACHE_REDIS_HOST: [ "memoryCache.redisHost", "redisHost", "" ],
|
|
121
128
|
MEMORY_CACHE_REDIS_PORT: [ "memoryCache.redisPort", "redisPort", "" ],
|
|
129
|
+
MEMORY_CACHE_RETRY_MAX_ATTEMPTS: [ "memoryCache.retryMaxAttempts", "retryMaxAttempts", "" ],
|
|
130
|
+
MEMORY_CACHE_RETRY_MAX_INTERVAL: [ "memoryCache.retryMaxInterval", "retryMaxInterval", "" ],
|
|
122
131
|
MEMORY_CACHE_USER: [ "memoryCache.user", "user", "" ],
|
|
123
132
|
MESSAGE_EXCHANGE_QUEUE_PREFIX: [ "messageExchange.messageQueuePrefix", "messageQueuePrefix", "" ],
|
|
124
133
|
MESSAGE_EXCHANGE_MESSAGE_STORE: [ "messageExchange.messageStore", "messageStore", "" ],
|
|
@@ -159,6 +168,8 @@ if ( settings.memoryCache ) {
|
|
|
159
168
|
settings.memoryCache.redisDB = ( process.env.TI_MEMORY_CACHE_REDIS_DB !== undefined ) ? process.env.TI_MEMORY_CACHE_REDIS_DB : settings.memoryCache.redisDB;
|
|
160
169
|
settings.memoryCache.redisHost = ( process.env.TI_MEMORY_CACHE_REDIS_HOST !== undefined ) ? process.env.TI_MEMORY_CACHE_REDIS_HOST : settings.memoryCache.redisHost;
|
|
161
170
|
settings.memoryCache.redisPort = ( process.env.TI_MEMORY_CACHE_REDIS_PORT !== undefined ) ? process.env.TI_MEMORY_CACHE_REDIS_PORT : settings.memoryCache.redisPort;
|
|
171
|
+
settings.memoryCache.retryMaxAttempts = ( process.env.TI_MEMORY_CACHE_RETRY_MAX_ATTEMPTS !== undefined ) ? process.env.TI_MEMORY_CACHE_RETRY_MAX_ATTEMPTS : settings.memoryCache.retryMaxAttempts;
|
|
172
|
+
settings.memoryCache.retryMaxInterval = ( process.env.TI_MEMORY_CACHE_RETRY_MAX_INTERVAL !== undefined ) ? process.env.TI_MEMORY_CACHE_RETRY_MAX_INTERVAL : settings.memoryCache.retryMaxInterval;
|
|
162
173
|
settings.memoryCache.user = ( process.env.TI_MEMORY_CACHE_USER !== undefined ) ? process.env.TI_MEMORY_CACHE_USER : settings.memoryCache.user;
|
|
163
174
|
}
|
|
164
175
|
if ( settings.messageExchange ) {
|
package/utils/exceptions.js
CHANGED
|
@@ -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 _ = require( "lodash" );
|
|
7
10
|
const tools = require( "#tools" );
|
package/utils/localization.js
CHANGED
|
@@ -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 path = require( "path" );
|
|
@@ -24,4 +27,4 @@ Object.freeze( labels );
|
|
|
24
27
|
*/
|
|
25
28
|
module.exports.getLabel = ( label ) => {
|
|
26
29
|
return _.get( labels, label + "." + config.getSetting( config.setting.LOCALIZATION_LANGUAGE ), defaultEmptyLabel );
|
|
27
|
-
};
|
|
30
|
+
};
|
package/utils/logger.js
CHANGED
|
@@ -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" );
|
|
@@ -69,7 +72,6 @@ const exceptionToLog = ( exception ) => {
|
|
|
69
72
|
* @public
|
|
70
73
|
*/
|
|
71
74
|
module.exports.log = ( message, level = logSeverityEnum.DEFAULT, data = {}, thread = "main" ) => {
|
|
72
|
-
/** @type {Auditing} */
|
|
73
75
|
const auditing = require( "#auditing" );
|
|
74
76
|
|
|
75
77
|
if ( data instanceof Error ) {
|
|
@@ -80,5 +82,5 @@ module.exports.log = ( message, level = logSeverityEnum.DEFAULT, data = {}, thre
|
|
|
80
82
|
data.exception = exceptionToLog( data.exception );
|
|
81
83
|
}
|
|
82
84
|
|
|
83
|
-
auditing.log( message, level, thread, data );
|
|
84
|
-
};
|
|
85
|
+
auditing.instance.log( message, level, thread, data );
|
|
86
|
+
};
|
package/utils/tools.js
CHANGED
|
@@ -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 _ = require( "lodash" );
|
|
7
10
|
const fs = require( "fs-extra" );
|
|
@@ -250,7 +253,7 @@ module.exports.decycle = ( object, replacer ) => {
|
|
|
250
253
|
* replaced with references to the value found by the PATH. This will restore cycles. The object will be mutated.
|
|
251
254
|
*
|
|
252
255
|
* The eval function is used to locate the values described by a PATH. The root object is kept in a $ variable. A
|
|
253
|
-
* regular expression is used to assure that the PATH is extremely well
|
|
256
|
+
* regular expression is used to assure that the PATH is extremely well-formed. The regexp contains nested quantifiers.
|
|
254
257
|
* That has been known to have extremely bad performance problems on some browsers for very long strings. A PATH is
|
|
255
258
|
* expected to be reasonably short. A PATH is allowed to belong to a very restricted subset of Goessner's JSONPath.
|
|
256
259
|
*
|