@ti-engine/core 1.1.5 → 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.
@@ -1,12 +1,13 @@
1
1
  /*
2
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>
3
+ * Copyright © 2021-2025 Boris Kostadinov <kostadinov.boris@gmail.com>
4
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
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
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
7
  */
8
8
 
9
9
  const config = require( "#config" );
10
+ const tools = require( "#tools" );
10
11
 
11
12
  /**
12
13
  * Used to verify if the GCloud integration is enabled.
@@ -16,7 +17,7 @@ const config = require( "#config" );
16
17
  * @public
17
18
  */
18
19
  module.exports.isEnabled = () => {
19
- return process.env.TI_GCLOUD_ENABLED === true;
20
+ return tools.toBool( process.env.TI_GCLOUD_ENABLED );
20
21
  };
21
22
 
22
23
  /**
@@ -1,6 +1,6 @@
1
1
  /*
2
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>
3
+ * Copyright © 2021-2025 Boris Kostadinov <kostadinov.boris@gmail.com>
4
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
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
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/>.
@@ -20,27 +20,27 @@ const _ = require( "lodash" );
20
20
  * @enum {string}
21
21
  */
22
22
  let cacheCommandsEnum = tools.enum( {
23
- ADD_TO_SET: [ "sadd", "add to set", "https://redis.io/commands/sadd" ],
24
- DELETE_VALUE: [ "del", "delete value", "https://redis.io/commands/del" ],
25
- EXPIRE: [ "expire", "expire", "https://redis.io/commands/expire" ],
26
- GET_ALL_FROM_SET: [ "smembers", "get all set members", "https://redis.io/commands/smembers" ],
27
- GET_VALUE: [ "get", "get value", "https://redis.io/commands/get" ],
28
- HASH_GET: [ "hget", "hash get", "https://redis.io/commands/hget" ],
29
- HASH_GET_ALL: [ "hgetall", "hash get all", "https://redis.io/commands/hgetall" ],
30
- HASH_REMOVE: [ "hdel", "hash remove", "https://redis.io/commands/hdel" ],
31
- HASH_SET: [ "hset", "", "https://redis.io/commands/hset" ],
32
- HASH_SET_MANY: [ "hmset", "", "https://redis.io/commands/hmset" ],
33
- IS_SET_MEMBER: [ "sismember", "", "https://redis.io/commands/sismember" ],
34
- JSON_ARRAY_APPEND: [ "json.arrappend", "", "https://redis.io/commands/json.arrappend" ],
35
- JSON_GET: [ "json.get", "", "https://redis.io/commands/json.get" ],
36
- JSON_SET: [ "json.set", "", "https://redis.io/commands/json.set" ],
37
- KEYS: [ "keys", "", "https://redis.io/commands/keys" ],
38
- LIST_PUSH: [ "lpush", "list push", "https://redis.io/commands/lpush" ],
39
- LIST_POP_TAIL_BLOCKING: [ "brpop", "list pop tail blocking", "https://redis.io/commands/brpop" ],
40
- LIST_POP_TAIL_PUSH_HEAD_BLOCKING: [ "brpoplpush", "list pop tail push head blocking", "https://redis.io/commands/brpoplpush" ],
41
- LIST_REMOVE: [ "lrem", "list remove", "https://redis.io/commands/lrem" ],
42
- SET_VALUE: [ "set", "set value", "https://redis.io/commands/set" ],
43
- 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/" ]
44
44
  } );
45
45
 
46
46
  /**
@@ -66,6 +66,9 @@ module.exports.cacheOverrideMode = cacheOverrideModeEnum;
66
66
 
67
67
  /**
68
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.
69
72
  *
70
73
  * @class RedisClient
71
74
  * @public
@@ -79,6 +82,7 @@ class RedisClient {
79
82
  #serverInfo = {};
80
83
  #serverFeatures = {};
81
84
  #connectionObservers = [];
85
+ #messageHandlersByChannel = new Map();
82
86
 
83
87
  /**
84
88
  * @constructor
@@ -88,11 +92,13 @@ class RedisClient {
88
92
  * @param {string} authKey
89
93
  * @param {string} user
90
94
  * @param {number} defaultDB
91
- * @param {boolean} autoRetryUnfulfilled
92
- * @param {number} maxRetries
95
+ * @param {number} [retryMaxIntervalMs=1000] Optional max backoff interval.
96
+ * @param {number|undefined} [retryMaxAttempts=undefined] Optional max (re)connection attempts before abort.
93
97
  */
94
- constructor( identifier, host, port, authKey, user, defaultDB, autoRetryUnfulfilled, maxRetries ) {
98
+ constructor( identifier, host, port, authKey, user, defaultDB, retryMaxIntervalMs = 1000, retryMaxAttempts = undefined ) {
95
99
  this.#clientIdentifier = identifier || "redis-client-" + tools.getUUID();
100
+ this.#retryMaxInterval = retryMaxIntervalMs;
101
+ this.#retryMaxAttempts = retryMaxAttempts;
96
102
 
97
103
  let retryStrategy = ( attempt ) => {
98
104
  let result = Math.min( attempt * 50, this.#retryMaxInterval );
@@ -116,8 +122,8 @@ class RedisClient {
116
122
  username: user,
117
123
  password: authKey,
118
124
  db: defaultDB,
119
- autoResendUnfulfilledCommands: autoRetryUnfulfilled,
120
- maxRetriesPerRequest: maxRetries,
125
+ autoResendUnfulfilledCommands: true,
126
+ maxRetriesPerRequest: null,
121
127
  retryStrategy: retryStrategy,
122
128
  reconnectOnError: reconnectOnError
123
129
  };
@@ -208,7 +214,8 @@ class RedisClient {
208
214
  * @public
209
215
  */
210
216
  get isJSONSupported() {
211
- return !_.isNil( this.#serverFeatures[ "ReJSON" ] );
217
+ // Detect RedisJSON module variants (e.g., ReJSON, ReJSON2):
218
+ return !_.isNil( this.#serverFeatures[ "ReJSON" ] ) || !_.isNil( this.#serverFeatures[ "ReJSON2" ] );
212
219
  }
213
220
 
214
221
  /**
@@ -286,25 +293,69 @@ class RedisClient {
286
293
 
287
294
  /**
288
295
  * Used to subscribe to the specified channel for messages.
296
+ * <br/>
297
+ * NOTE: Call unsubscribeCommand(channel) to detach later.
289
298
  *
290
299
  * @method
291
- * @param {string} channel
300
+ * @param {string} channel Unique identifier of the channel to subscribe to.
292
301
  * @param {function( Object )} messageHandler Will execute this handler every time a new message is received.
293
302
  * @return {Promise}
294
303
  * @public
295
304
  */
296
305
  subscribeCommand( channel, messageHandler ) {
297
306
  return new Promise( ( resolve, reject ) => {
298
- this.#redisClient.on( "subscribe", ( channel, count ) => {
299
- logger.log( "Subscription to message channel '" + channel + "' successful.", logger.logSeverity.DEBUG );
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 );
300
310
  resolve();
301
- } );
302
- this.#redisClient.on( "message", ( channel, message ) => {
303
- if ( typeof ( messageHandler ) === "function" ) {
304
- messageHandler( tools.parseJSON( message ) );
305
- }
306
- } );
307
- this.#redisClient.subscribe( channel ).catch( ( error ) => {
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 ) => {
308
359
  reject( exceptions.raise( error ) );
309
360
  } );
310
361
  } );
@@ -332,6 +383,47 @@ class RedisClient {
332
383
  } );
333
384
  }
334
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
+
335
427
  }
336
428
 
337
429
  /**
@@ -344,11 +436,11 @@ class RedisClient {
344
436
  * @param {string} [authKey=undefined]
345
437
  * @param {string} [user="default"]
346
438
  * @param {number} [defaultDB=0]
347
- * @param {boolean} [autoRetryUnfulfilled=true]
348
- * @param {number} [maxRetries=20]
439
+ * @param {number} [retryMaxIntervalMs=1000]
440
+ * @param {number|undefined} [retryMaxAttempts=undefined]
349
441
  * @return {RedisClient}
350
442
  * @public
351
443
  */
352
- module.exports.createRedisClient = ( identifier, host, port = 6379, authKey = undefined, user = "default", defaultDB = 0, autoRetryUnfulfilled = true, maxRetries = 20 ) => {
353
- return Object.freeze( new RedisClient( identifier, host, port, authKey, user, defaultDB, autoRetryUnfulfilled, maxRetries ) );
354
- };
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,6 +1,6 @@
1
1
  {
2
2
  "name": "@ti-engine/core",
3
- "version": "1.1.5",
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
6
  "license": "GPL-3.0-or-later",
@@ -44,15 +44,15 @@
44
44
  },
45
45
  "dependencies": {
46
46
  "blake2": "^5.0.0",
47
- "dotenv": "^16.3.1",
48
- "fs-extra": "^11.2.0",
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.3.2"
51
+ "ioredis": "^5.7.0"
52
52
  },
53
53
  "optionalDependencies": {
54
54
  "@google-cloud/error-reporting": "^3.0.5",
55
- "zeromq": "^6.0.0-beta.19"
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,6 +1,6 @@
1
1
  /*
2
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>
3
+ * Copyright © 2021-2025 Boris Kostadinov <kostadinov.boris@gmail.com>
4
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
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
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/>.
@@ -57,7 +57,9 @@ class CommonMemoryCache extends ConnectionObserver {
57
57
  * @returns {boolean}
58
58
  * @public
59
59
  */
60
- get isOperational() { return this.#isOperational; }
60
+ get isOperational() {
61
+ return this.#isOperational;
62
+ }
61
63
 
62
64
  /**
63
65
  * Property returning the connection identifier of the cache service.
@@ -66,7 +68,20 @@ class CommonMemoryCache extends ConnectionObserver {
66
68
  * @returns {string}
67
69
  * @public
68
70
  */
69
- get connectionIdentifier() { return this.#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
+ }
70
85
 
71
86
  /**
72
87
  * Needs to be invoked by the connection handler when the connection is disrupted.
@@ -108,7 +123,7 @@ class CommonMemoryCache extends ConnectionObserver {
108
123
  }
109
124
 
110
125
  /**
111
- * Used to search for keys by given pattern.
126
+ * Used to search for keys by a given pattern.
112
127
  *
113
128
  * @method
114
129
  * @param {string} pattern
@@ -364,7 +379,7 @@ class CommonMemoryCache extends ConnectionObserver {
364
379
  /**
365
380
  * Used to add multiple values to multiple sets in one transactional request.
366
381
  * <br/>
367
- * 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)!
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)!
368
383
  *
369
384
  * @method
370
385
  * @param {string[]} keys
@@ -391,7 +406,7 @@ class CommonMemoryCache extends ConnectionObserver {
391
406
  }
392
407
 
393
408
  /**
394
- * 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.
395
410
  *
396
411
  * @method
397
412
  * @param {string} setName
@@ -470,6 +485,7 @@ class CommonMemoryCache extends ConnectionObserver {
470
485
  * Used to set a single hash field.
471
486
  *
472
487
  * @method
488
+ * @deprecated
473
489
  * @param {string} key
474
490
  * @param {string} name
475
491
  * @param {*} value
@@ -495,6 +511,7 @@ class CommonMemoryCache extends ConnectionObserver {
495
511
  * Used to set multiple hash fields.
496
512
  *
497
513
  * @method
514
+ * @deprecated
498
515
  * @param {string} key
499
516
  * @param {Object[]} fields
500
517
  * @param {string} fields[].name
@@ -646,4 +663,4 @@ class CommonMemoryCache extends ConnectionObserver {
646
663
  }
647
664
 
648
665
  const instance = new CommonMemoryCache();
649
- module.exports = Object.freeze( instance );
666
+ module.exports.instance = Object.freeze( instance );
package/utils/config.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*
2
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>
3
+ * Copyright © 2021-2025 Boris Kostadinov <kostadinov.boris@gmail.com>
4
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
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
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/>.
@@ -33,6 +33,8 @@ const tools = require( "#tools" );
33
33
  * @property {EnvironmentVariable} env.TI_MEMORY_CACHE_REDIS_DB
34
34
  * @property {EnvironmentVariable} env.TI_MEMORY_CACHE_REDIS_HOST
35
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
36
38
  * @property {EnvironmentVariable} env.TI_MEMORY_CACHE_USER
37
39
  * @property {EnvironmentVariable} env.TI_MESSAGE_EXCHANGE_SECURITY_HASH_ENABLED
38
40
  * @property {EnvironmentVariable} env.TI_MESSAGE_EXCHANGE_SECURITY_HASH_KEY
@@ -80,6 +82,8 @@ const tools = require( "#tools" );
80
82
  * @property {number} redisDB
81
83
  * @property {string} redisHost
82
84
  * @property {number} redisPort
85
+ * @property {number} retryMaxAttempts
86
+ * @property {number} retryMaxInterval
83
87
  * @property {string} user
84
88
  */
85
89
 
@@ -122,6 +126,8 @@ let settingsEnum = tools.enum( {
122
126
  MEMORY_CACHE_REDIS_DB: [ "memoryCache.redisDB", "redisDB", "" ],
123
127
  MEMORY_CACHE_REDIS_HOST: [ "memoryCache.redisHost", "redisHost", "" ],
124
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", "" ],
125
131
  MEMORY_CACHE_USER: [ "memoryCache.user", "user", "" ],
126
132
  MESSAGE_EXCHANGE_QUEUE_PREFIX: [ "messageExchange.messageQueuePrefix", "messageQueuePrefix", "" ],
127
133
  MESSAGE_EXCHANGE_MESSAGE_STORE: [ "messageExchange.messageStore", "messageStore", "" ],
@@ -162,6 +168,8 @@ if ( settings.memoryCache ) {
162
168
  settings.memoryCache.redisDB = ( process.env.TI_MEMORY_CACHE_REDIS_DB !== undefined ) ? process.env.TI_MEMORY_CACHE_REDIS_DB : settings.memoryCache.redisDB;
163
169
  settings.memoryCache.redisHost = ( process.env.TI_MEMORY_CACHE_REDIS_HOST !== undefined ) ? process.env.TI_MEMORY_CACHE_REDIS_HOST : settings.memoryCache.redisHost;
164
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;
165
173
  settings.memoryCache.user = ( process.env.TI_MEMORY_CACHE_USER !== undefined ) ? process.env.TI_MEMORY_CACHE_USER : settings.memoryCache.user;
166
174
  }
167
175
  if ( settings.messageExchange ) {
@@ -1,6 +1,6 @@
1
1
  /*
2
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>
3
+ * Copyright © 2021-2025 Boris Kostadinov <kostadinov.boris@gmail.com>
4
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
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
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/>.
@@ -27,4 +27,4 @@ Object.freeze( labels );
27
27
  */
28
28
  module.exports.getLabel = ( label ) => {
29
29
  return _.get( labels, label + "." + config.getSetting( config.setting.LOCALIZATION_LANGUAGE ), defaultEmptyLabel );
30
- };
30
+ };
package/utils/logger.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*
2
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>
3
+ * Copyright © 2021-2025 Boris Kostadinov <kostadinov.boris@gmail.com>
4
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
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
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/>.
@@ -72,7 +72,6 @@ const exceptionToLog = ( exception ) => {
72
72
  * @public
73
73
  */
74
74
  module.exports.log = ( message, level = logSeverityEnum.DEFAULT, data = {}, thread = "main" ) => {
75
- /** @type {Auditing} */
76
75
  const auditing = require( "#auditing" );
77
76
 
78
77
  if ( data instanceof Error ) {
@@ -83,5 +82,5 @@ module.exports.log = ( message, level = logSeverityEnum.DEFAULT, data = {}, thre
83
82
  data.exception = exceptionToLog( data.exception );
84
83
  }
85
84
 
86
- auditing.log( message, level, thread, data );
87
- };
85
+ auditing.instance.log( message, level, thread, data );
86
+ };