@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.
@@ -1,7 +1,10 @@
1
1
  /*
2
- * SPDX-FileCopyrightText: © 2021-2023 Boris Kostadinov <kostadinov.boris@gmail.com>
3
- * SPDX-License-Identifier: ICU
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 {boolean} autoRetryUnfulfilled
89
- * @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.
90
97
  */
91
- constructor( identifier, host, port, authKey, user, defaultDB, autoRetryUnfulfilled, maxRetries ) {
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: autoRetryUnfulfilled,
117
- maxRetriesPerRequest: maxRetries,
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
- return !_.isNil( this.#serverFeatures[ "ReJSON" ] );
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
- this.#redisClient.on( "subscribe", ( channel, count ) => {
296
- 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 );
297
310
  resolve();
298
- } );
299
- this.#redisClient.on( "message", ( channel, message ) => {
300
- if ( typeof ( messageHandler ) === "function" ) {
301
- messageHandler( tools.parseJSON( message ) );
302
- }
303
- } );
304
- 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 ) => {
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 {boolean} [autoRetryUnfulfilled=true]
345
- * @param {number} [maxRetries=20]
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, autoRetryUnfulfilled = true, maxRetries = 20 ) => {
350
- return Object.freeze( new RedisClient( identifier, host, port, authKey, user, defaultDB, autoRetryUnfulfilled, maxRetries ) );
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.4",
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": "ISC",
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": "^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,7 +1,10 @@
1
1
  /*
2
- * SPDX-FileCopyrightText: © 2021-2023 Boris Kostadinov <kostadinov.boris@gmail.com>
3
- * SPDX-License-Identifier: ICU
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() { return this.#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() { 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
+ }
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. 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)!
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
- * SPDX-FileCopyrightText: © 2021-2023 Boris Kostadinov <kostadinov.boris@gmail.com>
3
- * SPDX-License-Identifier: ICU
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 ) {
@@ -1,7 +1,10 @@
1
1
  /*
2
- * SPDX-FileCopyrightText: © 2021-2023 Boris Kostadinov <kostadinov.boris@gmail.com>
3
- * SPDX-License-Identifier: ICU
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" );
@@ -1,7 +1,10 @@
1
1
  /*
2
- * SPDX-FileCopyrightText: © 2021-2023 Boris Kostadinov <kostadinov.boris@gmail.com>
3
- * SPDX-License-Identifier: ICU
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
- * SPDX-FileCopyrightText: © 2021-2023 Boris Kostadinov <kostadinov.boris@gmail.com>
3
- * SPDX-License-Identifier: ICU
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
- * SPDX-FileCopyrightText: © 2021-2023 Boris Kostadinov <kostadinov.boris@gmail.com>
3
- * SPDX-License-Identifier: ICU
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 formed. The regexp contains nested quantifiers.
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
  *