@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.
- package/CHANGELOG.md +33 -0
- package/README.md +45 -11
- package/bin/start-instance.js +40 -16
- package/components/auditing.js +3 -3
- package/components/exchange/default/default-message-receiver.js +6 -2
- package/components/exchange/default/default-message-sender.js +6 -2
- package/components/exchange/message-dispatcher.js +13 -9
- package/components/exchange/message-exchange.js +57 -21
- package/components/exchange/message-memory-cache.js +17 -3
- package/components/exchange/message-tracer.js +138 -92
- package/components/service-caller.js +6 -6
- package/components/service-consumer.js +3 -3
- package/components/service-executor.js +38 -16
- package/components/service-instance.js +39 -24
- package/components/service-provider.js +5 -5
- package/integrations/gcloud-integration.js +3 -2
- package/integrations/redis-integration.js +135 -43
- package/package.json +6 -6
- package/utils/cache.js +24 -7
- package/utils/config.js +9 -1
- package/utils/localization.js +2 -2
- package/utils/logger.js +3 -4
|
@@ -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-
|
|
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
|
|
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-
|
|
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 {
|
|
92
|
-
* @param {number}
|
|
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,
|
|
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:
|
|
120
|
-
maxRetriesPerRequest:
|
|
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
|
-
|
|
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
|
-
|
|
299
|
-
|
|
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
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
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 {
|
|
348
|
-
* @param {number} [
|
|
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,
|
|
353
|
-
return Object.freeze( new RedisClient( identifier, host, port, authKey, user, defaultDB,
|
|
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.
|
|
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": "^
|
|
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,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-
|
|
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() {
|
|
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() {
|
|
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
|
|
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-
|
|
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 ) {
|
package/utils/localization.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-
|
|
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-
|
|
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
|
+
};
|