@ti-engine/core 1.3.12 → 1.4.1
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 +36 -1
- package/bin/localization/labels.json +12 -0
- package/bin/start-instance.js +1 -1
- package/components/auditing.js +47 -22
- package/components/connection-observer.js +2 -2
- package/components/definitions.types.js +248 -0
- package/components/exchange/message-dispatcher.js +1 -1
- package/components/exchange/message-exchange.js +6 -30
- package/components/exchange/message-handler.js +2 -2
- package/components/exchange/message-memory-cache.js +1 -1
- package/components/exchange/message-observer.js +2 -2
- package/components/exchange/message-receiver.js +2 -2
- package/components/exchange/message-sender.js +2 -2
- package/components/exchange/message-tracer.js +4 -27
- package/components/service-caller.js +1 -40
- package/components/service-consumer.js +1 -1
- package/components/service-executor.js +1 -16
- package/components/service-instance.js +4 -9
- package/components/service-provider.js +9 -8
- package/integrations/redis-integration.js +8 -13
- package/package.json +8 -10
- package/utils/cache.js +57 -12
- package/utils/config.js +103 -200
- package/utils/exceptions.js +37 -20
- package/utils/localization.js +2 -17
- package/utils/logger.js +5 -8
- package/utils/tools.js +5 -20
- package/integrations/gcloud-integration.js +0 -65
|
@@ -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-2026 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/>.
|
|
@@ -13,20 +13,6 @@ const logger = require( "#logger" );
|
|
|
13
13
|
const exceptions = require( "#exceptions" );
|
|
14
14
|
const cache = require( "#cache" );
|
|
15
15
|
|
|
16
|
-
/**
|
|
17
|
-
* @typedef {Object} TiTraceEntry
|
|
18
|
-
* @property {string} chainID
|
|
19
|
-
* @property {string} dispatchEvent
|
|
20
|
-
* @property {string} fromAddress
|
|
21
|
-
* @property {string} messageID
|
|
22
|
-
* @property {Object} messageSnapshot
|
|
23
|
-
* @property {string} messageState
|
|
24
|
-
* @property {string} messageType
|
|
25
|
-
* @property {string} toAddress
|
|
26
|
-
* @property {string} traceID
|
|
27
|
-
* @property {number} traceTimestamp
|
|
28
|
-
*/
|
|
29
|
-
|
|
30
16
|
const traceRoot = {
|
|
31
17
|
trace: []
|
|
32
18
|
};
|
|
@@ -37,15 +23,12 @@ const UNKNOWN_TOKEN = "UNKNOWN";
|
|
|
37
23
|
*
|
|
38
24
|
* @readonly
|
|
39
25
|
* @enum {number}
|
|
26
|
+
* @typedef {number} TiMessageType
|
|
40
27
|
*/
|
|
41
28
|
let messageTypeEnum = tools.enum( {
|
|
42
29
|
MESSAGE_REQUEST: [ 1000, "REQUEST", "" ],
|
|
43
30
|
MESSAGE_RESPONSE: [ 1001, "RESPONSE", "" ]
|
|
44
31
|
} );
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* @typedef {number} TiMessageType
|
|
48
|
-
*/
|
|
49
32
|
module.exports.messageType = messageTypeEnum;
|
|
50
33
|
|
|
51
34
|
/**
|
|
@@ -53,6 +36,7 @@ module.exports.messageType = messageTypeEnum;
|
|
|
53
36
|
*
|
|
54
37
|
* @readonly
|
|
55
38
|
* @enum {number}
|
|
39
|
+
* @typedef {number} TiDispatchEvent
|
|
56
40
|
*/
|
|
57
41
|
let dispatchEventEnum = tools.enum( {
|
|
58
42
|
DELIVERED: [ 1100, "DELIVERED", "When message delivery is confirmed." ],
|
|
@@ -60,10 +44,6 @@ let dispatchEventEnum = tools.enum( {
|
|
|
60
44
|
RECEIVED: [ 1102, "RECEIVED", "When message was received." ],
|
|
61
45
|
SENT: [ 1103, "SENT", "When message was sent." ]
|
|
62
46
|
} );
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* @typedef {number} TiDispatchEvent
|
|
66
|
-
*/
|
|
67
47
|
module.exports.dispatchEvent = dispatchEventEnum;
|
|
68
48
|
|
|
69
49
|
/**
|
|
@@ -71,15 +51,12 @@ module.exports.dispatchEvent = dispatchEventEnum;
|
|
|
71
51
|
*
|
|
72
52
|
* @readonly
|
|
73
53
|
* @enum {number}
|
|
54
|
+
* @typedef {number} TiMessageState
|
|
74
55
|
*/
|
|
75
56
|
let messageStateEnum = tools.enum( {
|
|
76
57
|
PENDING: [ 1200, "PENDING", "" ],
|
|
77
58
|
PROCESSED: [ 1201, "PROCESSED", "" ]
|
|
78
59
|
} );
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* @typedef {number} TiMessageState
|
|
82
|
-
*/
|
|
83
60
|
module.exports.messageState = messageStateEnum;
|
|
84
61
|
|
|
85
62
|
/**
|
|
@@ -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-2026 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/>.
|
|
@@ -14,45 +14,6 @@ const config = require( "#config" );
|
|
|
14
14
|
const cache = require( "#cache" );
|
|
15
15
|
const messageDispatcher = require( "#message-dispatcher" );
|
|
16
16
|
|
|
17
|
-
/**
|
|
18
|
-
* @typedef {Object} ServiceAddress
|
|
19
|
-
* @property {string} serviceAlias A valid service alias.
|
|
20
|
-
* @property {string} serviceDomainName A valid service domain name.
|
|
21
|
-
* @property {number|undefined} serviceVersion Optional service version. If not provided, the latest version will be assumed as a target.
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* @typedef {Object} ServiceExecContext
|
|
26
|
-
* @property {string|undefined} authToken A valid authentication token that initialized the service call (if applicable).
|
|
27
|
-
* @property {ServiceCallPredecessor|undefined} previousServiceCall The previous service call in the execution chain (if such exists).
|
|
28
|
-
*/
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* @typedef {Message} ServiceCallPredecessor
|
|
32
|
-
* @property {string} predecessor The {@link Message.messageID} of the predecessor in the service call tree.
|
|
33
|
-
* @property {ServiceAddress} serviceAddress The address of the service that has to process the service call.
|
|
34
|
-
* @property {Object|undefined} serviceParams The named params to be provided to the API service.
|
|
35
|
-
*/
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* @typedef {ServiceCallPredecessor} ServiceCall
|
|
39
|
-
* @property {string} authToken A valid authentication token that initialized the service call.
|
|
40
|
-
* @property {number} createdOn A unix timestamp taken at creation time of the service call.
|
|
41
|
-
* @property {number} executionTime The total execution time of this service call in milliseconds.
|
|
42
|
-
* @property {Object|undefined} exception If there was exception during the service call processing, it will be set here. Otherwise, it will be 'undefined'.
|
|
43
|
-
* @property {number|undefined} finishedOn A unix timestamp taken at finish time of the service call.
|
|
44
|
-
* @property {boolean} isCompleted Flag to indicate if this service call has been completed.
|
|
45
|
-
* @property {boolean|undefined} isSuccessful A flag indicating if this service call can be considered successful or not. Will be 'undefined' until the service call is processed.
|
|
46
|
-
* @property {string[]} successors The service call IDs of the successors in the service call tree.
|
|
47
|
-
*/
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* @typedef {Object} ServiceCallResult
|
|
51
|
-
* @property {Exception|undefined} exception If there was exception during the service call processing, it will be set here. Otherwise, it will be 'undefined'.
|
|
52
|
-
* @property {boolean} isSuccessful A flag indicating if this service call can be considered successful or not.
|
|
53
|
-
* @property {Object|string|undefined} payload The payload containing the results from the service call processing. If a string, it is ID of the payload in the memory cache instead.
|
|
54
|
-
*/
|
|
55
|
-
|
|
56
17
|
/**
|
|
57
18
|
* Used to assemble and prepare a new {@link ServiceCall} object.
|
|
58
19
|
*
|
|
@@ -33,7 +33,7 @@ class ServiceConsumer extends ServiceInstance {
|
|
|
33
33
|
* @constructor
|
|
34
34
|
* @param {string} serviceDomainName The service domain name for this service instance.
|
|
35
35
|
* @param {ServiceConfiguration} [serviceConfig] The JSON configuration for this service.
|
|
36
|
-
* @throws {
|
|
36
|
+
* @throws {TiException.E_GEN_ABSTRACT_CLASS_INIT} If this class is instantiated directly.
|
|
37
37
|
*/
|
|
38
38
|
constructor( serviceDomainName, serviceConfig ) {
|
|
39
39
|
super( serviceDomainName, serviceConfig );
|
|
@@ -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-2026 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/>.
|
|
@@ -15,21 +15,6 @@ const config = require( "#config" );
|
|
|
15
15
|
const cache = require( "#cache" );
|
|
16
16
|
const messageDispatcher = require( "#message-dispatcher" );
|
|
17
17
|
|
|
18
|
-
/**
|
|
19
|
-
* @typedef {Object} ServiceDefinition
|
|
20
|
-
* @property {string} serviceAlias Service alias.
|
|
21
|
-
* @property {string} serviceFile The JS file containing the service itself. This has to be exposed via package.json import structure!
|
|
22
|
-
* @property {number} [serviceVersion] Service version.
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* @typedef {Object.<string, ServiceInterfaceVersion>} ServiceInterface
|
|
27
|
-
*/
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* @typedef {Object.<number, ServiceHandlerMethod>} ServiceInterfaceVersion
|
|
31
|
-
*/
|
|
32
|
-
|
|
33
18
|
/**
|
|
34
19
|
* @callback VerifyAccessMethod
|
|
35
20
|
* @param {string} authToken
|
|
@@ -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-2026 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/>.
|
|
@@ -15,11 +15,6 @@ const exceptions = require( "#exceptions" );
|
|
|
15
15
|
const cache = require( "#cache" );
|
|
16
16
|
const messageDispatcher = require( "#message-dispatcher" );
|
|
17
17
|
|
|
18
|
-
/**
|
|
19
|
-
* @typedef {Object} ServiceConfiguration
|
|
20
|
-
* @property {ServiceDefinition[]} [services] A list of service definitions to be registered with the {@link ServiceProvider}.
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
18
|
/**
|
|
24
19
|
* Abstract class used to define a Service Instance behavior.
|
|
25
20
|
* <br/>
|
|
@@ -43,8 +38,8 @@ class ServiceInstance {
|
|
|
43
38
|
* @constructor
|
|
44
39
|
* @param {string} serviceDomainName The service domain name for this service instance.
|
|
45
40
|
* @param {ServiceConfiguration} [serviceConfig={ services: [] }] The JSON configuration for this service.
|
|
46
|
-
* @throws {
|
|
47
|
-
* @throws {
|
|
41
|
+
* @throws {TiException.E_GEN_ABSTRACT_CLASS_INIT} If this class is instantiated directly.
|
|
42
|
+
* @throws {TiException.E_GEN_FEATURE_UNSUPPORTED} If multiple instances are started in the same process.
|
|
48
43
|
*/
|
|
49
44
|
constructor( serviceDomainName, serviceConfig = { services: [] } ) {
|
|
50
45
|
// Ensure this abstract class cannot be instantiated:
|
|
@@ -143,7 +138,7 @@ class ServiceInstance {
|
|
|
143
138
|
* <br/>
|
|
144
139
|
* NOTE: This method will be invoked automatically.
|
|
145
140
|
* <br/>
|
|
146
|
-
* NOTE: If you need to add more onStart logic you can override this method but make sure to call it in the
|
|
141
|
+
* NOTE: If you need to add more onStart logic, you can override this method but make sure to call it in the
|
|
147
142
|
* overriding method using: super.onStart()
|
|
148
143
|
*
|
|
149
144
|
* @method
|
|
@@ -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-2026 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/>.
|
|
@@ -38,7 +38,7 @@ class ServiceProvider extends ServiceConsumer {
|
|
|
38
38
|
* @constructor
|
|
39
39
|
* @param {string} serviceDomainName The service domain name for this service instance.
|
|
40
40
|
* @param {ServiceConfiguration} [serviceConfig] The JSON configuration for this service.
|
|
41
|
-
* @throws {
|
|
41
|
+
* @throws {TiException.E_GEN_ABSTRACT_CLASS_INIT} If this class is instantiated directly.
|
|
42
42
|
*/
|
|
43
43
|
constructor( serviceDomainName, serviceConfig ) {
|
|
44
44
|
super( serviceDomainName, serviceConfig );
|
|
@@ -56,7 +56,7 @@ class ServiceProvider extends ServiceConsumer {
|
|
|
56
56
|
* <br/>
|
|
57
57
|
* NOTE: This method will be invoked automatically.
|
|
58
58
|
* <br/>
|
|
59
|
-
* NOTE: If you need to add more onStart logic you can override this method but make sure to call it in the
|
|
59
|
+
* NOTE: If you need to add more onStart logic, you can override this method but make sure to call it in the
|
|
60
60
|
* overriding method using: super.onStart()
|
|
61
61
|
*
|
|
62
62
|
* @method
|
|
@@ -88,7 +88,7 @@ class ServiceProvider extends ServiceConsumer {
|
|
|
88
88
|
* <br/>
|
|
89
89
|
* NOTE: This method will be invoked automatically.
|
|
90
90
|
* <br/>
|
|
91
|
-
* NOTE: If you need to add more onStop logic you can override this method but make sure to call it in the
|
|
91
|
+
* NOTE: If you need to add more onStop logic, you can override this method but make sure to call it in the
|
|
92
92
|
* overriding method using: super.onStop()
|
|
93
93
|
*
|
|
94
94
|
* @method
|
|
@@ -110,7 +110,7 @@ class ServiceProvider extends ServiceConsumer {
|
|
|
110
110
|
* Used to report health status of the service instance for external monitoring.
|
|
111
111
|
* This is a scheduled job that will be executed at SERVICE_HEALTH_CHECK_INTERVAL time.
|
|
112
112
|
* <br/>
|
|
113
|
-
* NOTE: By default this method will update a Redis key with an expiration timer. You can override this
|
|
113
|
+
* NOTE: By default, this method will update a Redis key with an expiration timer. You can override this
|
|
114
114
|
* functionality with something custom like calling an HTTP endpoint.
|
|
115
115
|
*
|
|
116
116
|
* @method
|
|
@@ -204,13 +204,14 @@ class ServiceProvider extends ServiceConsumer {
|
|
|
204
204
|
let promises = [];
|
|
205
205
|
_.forEach( serviceDefinitions, ( serviceDefinition ) => {
|
|
206
206
|
// NOTE: we are not going to interrupt the service interface loading if one of the services fails to load or is not found!
|
|
207
|
-
// If this happens, a corresponding log entry will be created but the loading process will continue. Therefore, the following
|
|
208
|
-
// promise will always
|
|
207
|
+
// If this happens, a corresponding log entry will be created, but the loading process will continue. Therefore, the following
|
|
208
|
+
// promise will always be resolved (unless a programming error occurs in it, of course).
|
|
209
209
|
let registrationPromise = ( serviceDefinition, defaultServiceHandler ) => {
|
|
210
210
|
return new Promise( ( resolve ) => {
|
|
211
211
|
this.registerService( serviceDefinition, defaultServiceHandler ).then( () => {
|
|
212
212
|
resolve( true );
|
|
213
|
-
} ).catch( () => {
|
|
213
|
+
} ).catch( ( error ) => {
|
|
214
|
+
logger.log( `Service registration failed for '${ serviceDefinition?.serviceAlias || "unknown-service" }'.`, logger.logSeverity.ERROR, error );
|
|
214
215
|
resolve( false );
|
|
215
216
|
} );
|
|
216
217
|
} );
|
|
@@ -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-2026 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/>.
|
|
@@ -18,6 +18,7 @@ const _ = require( "lodash" );
|
|
|
18
18
|
*
|
|
19
19
|
* @readonly
|
|
20
20
|
* @enum {string}
|
|
21
|
+
* @typedef {string} TiRedisCommand
|
|
21
22
|
*/
|
|
22
23
|
let cacheCommandsEnum = tools.enum( {
|
|
23
24
|
ADD_TO_SET: [ "sadd", "add to set", "https://redis.io/docs/latest/commands/sadd/" ],
|
|
@@ -34,6 +35,8 @@ let cacheCommandsEnum = tools.enum( {
|
|
|
34
35
|
IS_SET_MEMBER: [ "sismember", "", "https://redis.io/docs/latest/commands/sismember/" ],
|
|
35
36
|
JSON_ARRAY_APPEND: [ "json.arrappend", "", "https://redis.io/docs/latest/commands/json.arrappend/" ],
|
|
36
37
|
JSON_GET: [ "json.get", "", "https://redis.io/docs/latest/commands/json.get/" ],
|
|
38
|
+
JSON_MERGE: [ "json.merge", "", "https://redis.io/docs/latest/commands/json.merge/" ],
|
|
39
|
+
JSON_MGET: [ "json.mget", "", "https://redis.io/docs/latest/commands/json.mget/" ],
|
|
37
40
|
JSON_SET: [ "json.set", "", "https://redis.io/docs/latest/commands/json.set/" ],
|
|
38
41
|
KEYS: [ "keys", "(warning: O(N), use SCAN where possible)", "https://redis.io/docs/latest/commands/keys/" ],
|
|
39
42
|
LIST_PUSH: [ "lpush", "list push", "https://redis.io/docs/latest/commands/lpush/" ],
|
|
@@ -43,12 +46,14 @@ let cacheCommandsEnum = tools.enum( {
|
|
|
43
46
|
SET_VALUE: [ "set", "set value", "https://redis.io/docs/latest/commands/set/" ],
|
|
44
47
|
UNION_OF_SETS: [ "sunion", "union of sets", "https://redis.io/docs/latest/commands/sunion/" ]
|
|
45
48
|
} );
|
|
49
|
+
module.exports.cacheCommands = cacheCommandsEnum;
|
|
46
50
|
|
|
47
51
|
/**
|
|
48
52
|
* Enum for listing all client statuses.
|
|
49
53
|
*
|
|
50
54
|
* @readonly
|
|
51
55
|
* @enum {number}
|
|
56
|
+
* @typedef {number} TiRedisClientStatus
|
|
52
57
|
*/
|
|
53
58
|
let clientStatusEnum = tools.enum( {
|
|
54
59
|
UNINITIALIZED: [ 0, "uninitialized", "Redis client is offline and not yet initialized." ],
|
|
@@ -58,31 +63,21 @@ let clientStatusEnum = tools.enum( {
|
|
|
58
63
|
SHUTTING_DOWN: [ 4, "shutting down", "Redis client is shutting down." ],
|
|
59
64
|
DISCONNECTED: [ 5, "disconnected", "Redis client is permanently disconnected from server." ]
|
|
60
65
|
} );
|
|
66
|
+
module.exports.clientStatus = clientStatusEnum;
|
|
61
67
|
|
|
62
68
|
/**
|
|
63
69
|
* Enum for listing the Redis key override modes.
|
|
64
70
|
*
|
|
65
71
|
* @readonly
|
|
66
72
|
* @enum {string}
|
|
73
|
+
* @typedef {string} TiRedisOverrideMode
|
|
67
74
|
*/
|
|
68
75
|
let cacheOverrideModeEnum = tools.enum( {
|
|
69
76
|
DEFAULT: [ "", "default", "Standard Redis behaviour when setting new key." ],
|
|
70
77
|
NX: [ "nx", "nx", "Sets the key only if it does not already exist." ],
|
|
71
78
|
XX: [ "xx", "xx", "Sets the key only if it already exists." ]
|
|
72
79
|
} );
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* @typedef {string} TiRedisCommand
|
|
76
|
-
*/
|
|
77
|
-
module.exports.cacheCommands = cacheCommandsEnum;
|
|
78
|
-
/**
|
|
79
|
-
* @typedef {string} TiRedisOverrideMode
|
|
80
|
-
*/
|
|
81
80
|
module.exports.cacheOverrideMode = cacheOverrideModeEnum;
|
|
82
|
-
/**
|
|
83
|
-
* @typedef {number} TiRedisClientStatus
|
|
84
|
-
*/
|
|
85
|
-
module.exports.clientStatus = clientStatusEnum;
|
|
86
81
|
|
|
87
82
|
/**
|
|
88
83
|
* Used to create a Redis Cache client.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ti-engine/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.1",
|
|
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
|
"keywords": [
|
|
6
6
|
"microservices",
|
|
@@ -35,7 +35,6 @@
|
|
|
35
35
|
"#default-message-receiver": "./components/exchange/default/default-message-receiver.js",
|
|
36
36
|
"#default-message-sender": "./components/exchange/default/default-message-sender.js",
|
|
37
37
|
"#exceptions": "./utils/exceptions.js",
|
|
38
|
-
"#gcloud-integration": "./integrations/gcloud-integration.js",
|
|
39
38
|
"#labels": "./bin/localization/labels.json",
|
|
40
39
|
"#localization": "./utils/localization.js",
|
|
41
40
|
"#logger": "./utils/logger.js",
|
|
@@ -57,14 +56,13 @@
|
|
|
57
56
|
"#tools": "./utils/tools.js"
|
|
58
57
|
},
|
|
59
58
|
"dependencies": {
|
|
60
|
-
"@dotenvx/dotenvx": "^1.
|
|
61
|
-
"blake2": "^5.0.
|
|
62
|
-
"ioredis": "^5.
|
|
63
|
-
"lodash": "^4.17.
|
|
59
|
+
"@dotenvx/dotenvx": "^1.55.1",
|
|
60
|
+
"blake2": "^5.0.1",
|
|
61
|
+
"ioredis": "^5.10.0",
|
|
62
|
+
"lodash": "^4.17.23",
|
|
64
63
|
"node-schedule": "^2.1.1"
|
|
65
64
|
},
|
|
66
65
|
"optionalDependencies": {
|
|
67
|
-
"@google-cloud/error-reporting": "^3.0.5",
|
|
68
66
|
"zeromq": "^6.5.0"
|
|
69
67
|
},
|
|
70
68
|
"files": [
|
|
@@ -75,7 +73,7 @@
|
|
|
75
73
|
"package.json",
|
|
76
74
|
"README.md",
|
|
77
75
|
"CHANGELOG.md",
|
|
78
|
-
"LICENSE"
|
|
76
|
+
"LICENSE.md"
|
|
79
77
|
],
|
|
80
78
|
"repository": {
|
|
81
79
|
"type": "git",
|
|
@@ -87,6 +85,6 @@
|
|
|
87
85
|
},
|
|
88
86
|
"homepage": "https://github.com/Belleal/ti-engine/tree/master/packages/core#readme",
|
|
89
87
|
"engines": {
|
|
90
|
-
"node": ">=
|
|
88
|
+
"node": ">=20.0.0"
|
|
91
89
|
}
|
|
92
|
-
}
|
|
90
|
+
}
|
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-2026 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/>.
|
|
@@ -129,7 +129,7 @@ class CommonMemoryCache extends ConnectionObserver {
|
|
|
129
129
|
*
|
|
130
130
|
* @method
|
|
131
131
|
* @param {string} identifier The identifier of the observed connection.
|
|
132
|
-
* @throws {
|
|
132
|
+
* @throws {TiException.E_GEN_SYSTEM_CACHE_UNAVAILABLE} If the cache service is no longer available.
|
|
133
133
|
* @override
|
|
134
134
|
* @public
|
|
135
135
|
*/
|
|
@@ -632,7 +632,7 @@ class CommonMemoryCache extends ConnectionObserver {
|
|
|
632
632
|
* @method
|
|
633
633
|
* @param {string} key
|
|
634
634
|
* @param {Object} value
|
|
635
|
-
* @param {string} [path=
|
|
635
|
+
* @param {string} [path="$"]
|
|
636
636
|
* @param {number} [overrideMode=0] By default this allows full override for existing keys.
|
|
637
637
|
* Option 1 will set the key only if it doesn't already exist. Option 2 will set it only if it already exists.
|
|
638
638
|
* @returns {Promise}
|
|
@@ -642,7 +642,7 @@ class CommonMemoryCache extends ConnectionObserver {
|
|
|
642
642
|
return new Promise( ( resolve, reject ) => {
|
|
643
643
|
if ( this.#isOperational === true ) {
|
|
644
644
|
if ( this.#redisClient.isJSONSupported ) {
|
|
645
|
-
let commandArguments = [ redis.cacheCommands.JSON_SET, key, path, tools.stringifyJSON( value ) ];
|
|
645
|
+
let commandArguments = [ redis.cacheCommands.JSON_SET, key, this.#normalizeJSONPath( path ), tools.stringifyJSON( value ) ];
|
|
646
646
|
if ( overrideMode !== 0 ) {
|
|
647
647
|
commandArguments.push( overrideMode === 1 ? redis.cacheOverrideMode.NX : redis.cacheOverrideMode.XX );
|
|
648
648
|
}
|
|
@@ -652,7 +652,7 @@ class CommonMemoryCache extends ConnectionObserver {
|
|
|
652
652
|
reject( error );
|
|
653
653
|
} );
|
|
654
654
|
} else {
|
|
655
|
-
reject( exceptions.raise( exceptions.exceptionCode.E_GEN_FEATURE_UNSUPPORTED
|
|
655
|
+
reject( exceptions.raise( exceptions.exceptionCode.E_GEN_FEATURE_UNSUPPORTED, { details: "No RedisJSON module installed on server." } ) );
|
|
656
656
|
}
|
|
657
657
|
} else {
|
|
658
658
|
reject( exceptions.raise( exceptions.exceptionCode.E_GEN_SYSTEM_CACHE_UNAVAILABLE ) );
|
|
@@ -667,7 +667,7 @@ class CommonMemoryCache extends ConnectionObserver {
|
|
|
667
667
|
*
|
|
668
668
|
* @method
|
|
669
669
|
* @param {string} key
|
|
670
|
-
* @param {string} path
|
|
670
|
+
* @param {string} [path="$"]
|
|
671
671
|
* @returns {Promise<Object>}
|
|
672
672
|
* @public
|
|
673
673
|
*/
|
|
@@ -675,14 +675,45 @@ class CommonMemoryCache extends ConnectionObserver {
|
|
|
675
675
|
return new Promise( ( resolve, reject ) => {
|
|
676
676
|
if ( this.#isOperational === true ) {
|
|
677
677
|
if ( this.#redisClient.isJSONSupported ) {
|
|
678
|
-
let commandArguments = [ redis.cacheCommands.JSON_GET, key, path ];
|
|
678
|
+
let commandArguments = [ redis.cacheCommands.JSON_GET, key, this.#normalizeJSONPath( path ) ];
|
|
679
679
|
this.#redisClient.callCommand( commandArguments ).then( ( result ) => {
|
|
680
|
-
resolve( tools.parseJSON( result ) );
|
|
680
|
+
resolve( result != null ? tools.parseJSON( String( result ) ) : null );
|
|
681
681
|
} ).catch( ( error ) => {
|
|
682
682
|
reject( error );
|
|
683
683
|
} );
|
|
684
684
|
} else {
|
|
685
|
-
reject( exceptions.raise( exceptions.exceptionCode.E_GEN_FEATURE_UNSUPPORTED
|
|
685
|
+
reject( exceptions.raise( exceptions.exceptionCode.E_GEN_FEATURE_UNSUPPORTED, { details: "No RedisJSON module installed on server." } ) );
|
|
686
|
+
}
|
|
687
|
+
} else {
|
|
688
|
+
reject( exceptions.raise( exceptions.exceptionCode.E_GEN_SYSTEM_CACHE_UNAVAILABLE ) );
|
|
689
|
+
}
|
|
690
|
+
} );
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
/**
|
|
694
|
+
* Used to update/edit an existing JSON variable.
|
|
695
|
+
* <br/>
|
|
696
|
+
* NOTE: Requires ReJSON module installed on server to work.
|
|
697
|
+
*
|
|
698
|
+
* @method
|
|
699
|
+
* @param {string} key
|
|
700
|
+
* @param {Object} value
|
|
701
|
+
* @param {string} [path="$"]
|
|
702
|
+
* @returns {Promise}
|
|
703
|
+
* @public
|
|
704
|
+
*/
|
|
705
|
+
editJSON( key, value, path = "$" ) {
|
|
706
|
+
return new Promise( ( resolve, reject ) => {
|
|
707
|
+
if ( this.#isOperational === true ) {
|
|
708
|
+
if ( this.#redisClient.isJSONSupported ) {
|
|
709
|
+
let commandArguments = [ redis.cacheCommands.JSON_MERGE, key, this.#normalizeJSONPath( path ), tools.stringifyJSON( value ) ];
|
|
710
|
+
this.#redisClient.callCommand( commandArguments ).then( () => {
|
|
711
|
+
resolve();
|
|
712
|
+
} ).catch( ( error ) => {
|
|
713
|
+
reject( error );
|
|
714
|
+
} );
|
|
715
|
+
} else {
|
|
716
|
+
reject( exceptions.raise( exceptions.exceptionCode.E_GEN_FEATURE_UNSUPPORTED, { details: "No RedisJSON module installed on server." } ) );
|
|
686
717
|
}
|
|
687
718
|
} else {
|
|
688
719
|
reject( exceptions.raise( exceptions.exceptionCode.E_GEN_SYSTEM_CACHE_UNAVAILABLE ) );
|
|
@@ -698,7 +729,7 @@ class CommonMemoryCache extends ConnectionObserver {
|
|
|
698
729
|
* @method
|
|
699
730
|
* @param {string} key
|
|
700
731
|
* @param {Object} value
|
|
701
|
-
* @param {string} path
|
|
732
|
+
* @param {string} [path="$"]
|
|
702
733
|
* @returns {Promise}
|
|
703
734
|
* @public
|
|
704
735
|
*/
|
|
@@ -706,14 +737,14 @@ class CommonMemoryCache extends ConnectionObserver {
|
|
|
706
737
|
return new Promise( ( resolve, reject ) => {
|
|
707
738
|
if ( this.#isOperational === true ) {
|
|
708
739
|
if ( this.#redisClient.isJSONSupported ) {
|
|
709
|
-
let commandArguments = [ redis.cacheCommands.JSON_ARRAY_APPEND, key, path, tools.stringifyJSON( value ) ];
|
|
740
|
+
let commandArguments = [ redis.cacheCommands.JSON_ARRAY_APPEND, key, this.#normalizeJSONPath( path ), tools.stringifyJSON( value ) ];
|
|
710
741
|
this.#redisClient.callCommand( commandArguments ).then( () => {
|
|
711
742
|
resolve();
|
|
712
743
|
} ).catch( ( error ) => {
|
|
713
744
|
reject( error );
|
|
714
745
|
} );
|
|
715
746
|
} else {
|
|
716
|
-
reject( exceptions.raise( exceptions.exceptionCode.E_GEN_FEATURE_UNSUPPORTED
|
|
747
|
+
reject( exceptions.raise( exceptions.exceptionCode.E_GEN_FEATURE_UNSUPPORTED, { details: "No RedisJSON module installed on server." } ) );
|
|
717
748
|
}
|
|
718
749
|
} else {
|
|
719
750
|
reject( exceptions.raise( exceptions.exceptionCode.E_GEN_SYSTEM_CACHE_UNAVAILABLE ) );
|
|
@@ -721,6 +752,20 @@ class CommonMemoryCache extends ConnectionObserver {
|
|
|
721
752
|
} );
|
|
722
753
|
}
|
|
723
754
|
|
|
755
|
+
/* Private interface */
|
|
756
|
+
|
|
757
|
+
/**
|
|
758
|
+
* Used to normalize a JSON path.
|
|
759
|
+
*
|
|
760
|
+
* @method
|
|
761
|
+
* @param {string} path
|
|
762
|
+
* @returns {string}
|
|
763
|
+
* @private
|
|
764
|
+
*/
|
|
765
|
+
#normalizeJSONPath( path ) {
|
|
766
|
+
return ( path.startsWith( "$" ) === false ) ? ( "$." + path ) : path;
|
|
767
|
+
}
|
|
768
|
+
|
|
724
769
|
}
|
|
725
770
|
|
|
726
771
|
const instance = new CommonMemoryCache();
|