@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 MessageObserver = require( "#message-observer" );
7
10
  const tools = require( "#tools" );
@@ -92,7 +95,7 @@ class ServiceCaller extends MessageObserver {
92
95
  this.#findServiceInRegistry( serviceAddress ).then( () => {
93
96
  return this.#prepareServiceCall( serviceAddress, serviceParams, serviceExecContext );
94
97
  } ).then( ( serviceCall ) => {
95
- return messageDispatcher.sendRequest( serviceCall );
98
+ return messageDispatcher.instance.sendRequest( serviceCall );
96
99
  } ).then( ( messageID ) => {
97
100
  this.#addTaskHandler( messageID, ( serviceCall ) => {
98
101
  this.#completeServiceCall( serviceCall ).then( ( serviceCall ) => {
@@ -184,7 +187,7 @@ class ServiceCaller extends MessageObserver {
184
187
  #findServiceInRegistry( serviceAddress ) {
185
188
  return new Promise( ( resolve, reject ) => {
186
189
  let serviceCatalog = config.getSetting( config.setting.SERVICE_REGISTRY_ADDRESS ) + serviceAddress.serviceDomainName;
187
- cache.isSetMember( serviceCatalog, serviceAddress.serviceAlias ).then( ( result ) => {
190
+ cache.instance.isSetMember( serviceCatalog, serviceAddress.serviceAlias ).then( ( result ) => {
188
191
  if ( result === true ) {
189
192
  resolve();
190
193
  } else {
@@ -207,7 +210,7 @@ class ServiceCaller extends MessageObserver {
207
210
  * @private
208
211
  */
209
212
  #prepareServiceCall( serviceAddress, serviceParams, serviceExecContext ) {
210
- return new Promise( ( resolve, reject ) => {
213
+ return new Promise( ( resolve ) => {
211
214
  const ServiceInstance = require( "#service-instance" );
212
215
 
213
216
  // assemble the new service call:
@@ -255,7 +258,7 @@ class ServiceCaller extends MessageObserver {
255
258
  * @private
256
259
  */
257
260
  #completeServiceCall( serviceCall ) {
258
- return new Promise( ( resolve, reject ) => {
261
+ return new Promise( ( resolve ) => {
259
262
  serviceCall.finishedOn = Date.now();
260
263
  serviceCall.executionTime = serviceCall.finishedOn - serviceCall.createdOn;
261
264
  serviceCall.isCompleted = true;
@@ -303,4 +306,4 @@ class ServiceCaller extends MessageObserver {
303
306
 
304
307
  }
305
308
 
306
- module.exports = ServiceCaller;
309
+ module.exports = ServiceCaller;
@@ -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 ServiceInstance = require( "#service-instance" );
7
10
  const exceptions = require( "#exceptions" );
@@ -10,7 +13,7 @@ const messageDispatcher = require( "#message-dispatcher" );
10
13
  /**
11
14
  * Abstract class used to define a Service Consumer behavior.
12
15
  * <br/>
13
- * NOTE: Inherit this to create an a module that can be started as a microservice consumer instance.
16
+ * NOTE: Inherit this to create a module that can be started as a microservice consumer instance.
14
17
  * <br/>
15
18
  * NOTE: A service consumer is a microservice that can invoke named business services in the APIs of other
16
19
  * microservices using {@link ServiceCall} objects. The consumer does not need to know the specifics of
@@ -62,7 +65,7 @@ class ServiceConsumer extends ServiceInstance {
62
65
  this.#serviceCaller = new ServiceCaller();
63
66
 
64
67
  super.onStart().then( () => {
65
- messageDispatcher.addMessageObserverResponsesIn( this.#serviceCaller );
68
+ messageDispatcher.instance.addMessageObserverResponsesIn( this.#serviceCaller );
66
69
  resolve();
67
70
  } ).catch( ( error ) => {
68
71
  reject( exceptions.raise( error ) );
@@ -93,6 +96,22 @@ class ServiceConsumer extends ServiceInstance {
93
96
  } );
94
97
  }
95
98
 
99
+ /**
100
+ * Used to report health status of the service instance for external monitoring.
101
+ * This is a scheduled job that will be executed at SERVICE_HEALTH_CHECK_INTERVAL time.
102
+ * <br/>
103
+ * NOTE: By default this method will update a Redis key with an expiration timer. You can override this
104
+ * functionality with something custom like calling an HTTP endpoint.
105
+ *
106
+ * @method
107
+ * @override
108
+ * @virtual
109
+ * @public
110
+ */
111
+ reportHealthy() {
112
+ super.reportHealthy();
113
+ }
114
+
96
115
  /**
97
116
  * Used to invoke a business service in any {@link ServiceInstance}.
98
117
  *
@@ -109,4 +128,4 @@ class ServiceConsumer extends ServiceInstance {
109
128
 
110
129
  }
111
130
 
112
- module.exports = ServiceConsumer;
131
+ module.exports = ServiceConsumer;
@@ -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 MessageObserver = require( "#message-observer" );
7
10
  const ServiceInstance = require( "#service-instance" );
@@ -55,6 +58,8 @@ class ServiceExecutor extends MessageObserver {
55
58
  #serviceInterface = {};
56
59
  /** @type VerifyAccessMethod */
57
60
  #verifyAccess;
61
+ #registrationTasks = {};
62
+ #registrationRetryInterval = 500;
58
63
 
59
64
  /**
60
65
  * @constructor
@@ -62,11 +67,12 @@ class ServiceExecutor extends MessageObserver {
62
67
  constructor() {
63
68
  super();
64
69
 
70
+ // Setup a default empty verify access method:
65
71
  this.#verifyAccess = () => {
66
72
  return Promise.resolve();
67
73
  };
68
74
 
69
- cache.addConnectionObserver( this );
75
+ cache.instance.addConnectionObserver( this );
70
76
  }
71
77
 
72
78
  /* Public interface */
@@ -78,7 +84,9 @@ class ServiceExecutor extends MessageObserver {
78
84
  * @returns {ServiceInterface}
79
85
  * @public
80
86
  */
81
- get serviceInterface() { return this.#serviceInterface; }
87
+ get serviceInterface() {
88
+ return this.#serviceInterface;
89
+ }
82
90
 
83
91
  /**
84
92
  *
@@ -91,7 +99,7 @@ class ServiceExecutor extends MessageObserver {
91
99
  */
92
100
  onMessage( identifier, message ) {
93
101
  this.#processServiceCall( message ).then( ( serviceCall ) => {
94
- return messageDispatcher.sendResponse( serviceCall );
102
+ return messageDispatcher.instance.sendResponse( serviceCall );
95
103
  } ).catch( ( error ) => {
96
104
  logger.log( `Failed to send service call response after processing! Service call ID was: '${ message.messageID }'`, logger.logSeverity.ERROR, error );
97
105
  } );
@@ -120,17 +128,15 @@ class ServiceExecutor extends MessageObserver {
120
128
  onConnectionRecovered( identifier ) {
121
129
  super.onConnectionRecovered( identifier );
122
130
 
123
- if ( identifier !== cache.connectionIdentifier ) {
124
- if ( cache.isOperational ) {
125
- let serviceCatalog = config.getSetting( config.setting.SERVICE_REGISTRY_ADDRESS ) + ServiceInstance.serviceDomainName;
126
- _.forOwn( this.#serviceInterface, ( versions, serviceAlias ) => {
127
- cache.addToSet( serviceCatalog, serviceAlias ).catch( ( error ) => {
128
- logger.log( `Record for service '${ serviceAlias }' could not be added to the service registry.`, logger.logSeverity.ERROR, error );
129
- } );
130
- } );
131
- } else {
132
- //TODO: Retry service registration after 0.5 seconds.
133
- }
131
+ if ( identifier !== cache.instance.connectionIdentifier ) {
132
+ let serviceCatalog = config.getSetting( config.setting.SERVICE_REGISTRY_ADDRESS ) + ServiceInstance.serviceDomainName;
133
+ _.forOwn( this.#serviceInterface, ( versions, serviceAlias ) => {
134
+ if ( !this.#registrationTasks[ serviceAlias ] ) {
135
+ this.#registrationTasks[ serviceAlias ] = setInterval( () => {
136
+ this.#registerServiceToCatalog( serviceCatalog, serviceAlias );
137
+ }, this.#registrationRetryInterval );
138
+ }
139
+ } );
134
140
  }
135
141
  }
136
142
 
@@ -197,6 +203,25 @@ class ServiceExecutor extends MessageObserver {
197
203
  };
198
204
  }
199
205
 
206
+ /**
207
+ * Used to register a service in the service registry.
208
+ *
209
+ * @method
210
+ * @param {string} serviceCatalog
211
+ * @param {string} serviceAlias
212
+ * @private
213
+ */
214
+ #registerServiceToCatalog( serviceCatalog, serviceAlias ) {
215
+ if ( cache.instance.isOperational ) {
216
+ cache.instance.addToSet( serviceCatalog, serviceAlias ).then( () => {
217
+ clearTimeout( this.#registrationTasks[ serviceAlias ] );
218
+ delete this.#registrationTasks[ serviceAlias ];
219
+ } ).catch( ( error ) => {
220
+ logger.log( `Record for service '${ serviceAlias }' could not be added to the service registry. Will retry in '${ this.#registrationRetryInterval }' milliseconds.`, logger.logSeverity.ERROR, error );
221
+ } );
222
+ }
223
+ }
224
+
200
225
  /**
201
226
  * Used to process the actual service call.
202
227
  *
@@ -206,7 +231,7 @@ class ServiceExecutor extends MessageObserver {
206
231
  * @private
207
232
  */
208
233
  #processServiceCall( serviceCall ) {
209
- return new Promise( ( resolve, reject ) => {
234
+ return new Promise( ( resolve ) => {
210
235
  this.#verifyAccess( serviceCall.authToken, serviceCall.serviceAddress ).then( () => {
211
236
  return this.#identifyService( serviceCall.serviceAddress );
212
237
  } ).then( ( serviceHandler ) => {
@@ -253,4 +278,4 @@ class ServiceExecutor extends MessageObserver {
253
278
 
254
279
  }
255
280
 
256
- module.exports = ServiceExecutor;
281
+ module.exports = ServiceExecutor;
@@ -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 schedule = require( "node-schedule" );
@@ -21,8 +24,6 @@ const messageDispatcher = require( "#message-dispatcher" );
21
24
  * Abstract class used to define a Service Instance behavior.
22
25
  * <br/>
23
26
  * NOTE: Inherit this to create a module that can be started as a microservice instance.
24
- * <br/>
25
- * NOTE: This class does not
26
27
  *
27
28
  * @class ServiceInstance
28
29
  * @abstract
@@ -43,12 +44,22 @@ class ServiceInstance {
43
44
  * @param {Object} [serviceConfig={}] The JSON configuration for this service.
44
45
  */
45
46
  constructor( serviceDomainName, serviceConfig = {} ) {
46
- // make sure this abstract class cannot be instantiated:
47
+ // Ensure this abstract class cannot be instantiated:
47
48
  if ( new.target === ServiceInstance ) {
48
49
  throw exceptions.raise( exceptions.exceptionCode.E_GEN_ABSTRACT_CLASS_INIT, { name: this.constructor.name } );
49
50
  }
50
51
 
51
- ServiceInstance.#instanceID = process.env.TI_INSTANCE_ID || tools.getUUID();
52
+ // Guard against multiple instances in a single process (not supported):
53
+ if ( ServiceInstance.#instanceID && ServiceInstance.#serviceDomainName ) {
54
+ throw exceptions.raise( exceptions.exceptionCode.E_GEN_FEATURE_UNSUPPORTED, {
55
+ details: "Multiple ServiceInstance initializations per process are not supported."
56
+ } );
57
+ }
58
+
59
+ // Ensure uniform 'ti-' prefix even if env is missing or custom starter script is used:
60
+ const envID = process.env.TI_INSTANCE_ID;
61
+ ServiceInstance.#instanceID = ( envID && String( envID ).startsWith( "ti-" ) ) ? envID : ( "ti-" + ( envID || tools.getUUID() ) );
62
+
52
63
  ServiceInstance.#serviceDomainName = serviceDomainName;
53
64
  this.#serviceConfig = ( _.isObjectLike( serviceConfig ) ) ? serviceConfig : { services: [] };
54
65
  }
@@ -62,7 +73,9 @@ class ServiceInstance {
62
73
  * @returns {string}
63
74
  * @public
64
75
  */
65
- static get instanceID() { return ServiceInstance.#instanceID; }
76
+ static get instanceID() {
77
+ return ServiceInstance.#instanceID;
78
+ }
66
79
 
67
80
  /**
68
81
  * Property returning the current service domain name.
@@ -71,7 +84,9 @@ class ServiceInstance {
71
84
  * @returns {string}
72
85
  * @public
73
86
  */
74
- static get serviceDomainName() { return ServiceInstance.#serviceDomainName; }
87
+ static get serviceDomainName() {
88
+ return ServiceInstance.#serviceDomainName;
89
+ }
75
90
 
76
91
  /**
77
92
  * Property to indicate that this and every child class is a {@link ServiceInstance}.
@@ -80,7 +95,9 @@ class ServiceInstance {
80
95
  * @returns {boolean}
81
96
  * @public
82
97
  */
83
- get isServiceInstance() { return true; }
98
+ get isServiceInstance() {
99
+ return true;
100
+ }
84
101
 
85
102
  /**
86
103
  * Property returning the service configuration JSON.
@@ -89,7 +106,9 @@ class ServiceInstance {
89
106
  * @returns {ServiceConfiguration}
90
107
  * @public
91
108
  */
92
- get serviceConfig() { return this.#serviceConfig; }
109
+ get serviceConfig() {
110
+ return this.#serviceConfig;
111
+ }
93
112
 
94
113
  /**
95
114
  * Initializes the instance.
@@ -137,8 +156,7 @@ class ServiceInstance {
137
156
 
138
157
  let configureInbound = ( this instanceof ServiceProvider );
139
158
  let configureOutbound = ( this instanceof ServiceConsumer );
140
-
141
- messageDispatcher.initialize( new DefaultMessageExchange( ServiceInstance.instanceID, ServiceInstance.serviceDomainName ), configureInbound, configureOutbound ).then( () => {
159
+ messageDispatcher.instance.initialize( new DefaultMessageExchange( ServiceInstance.instanceID, ServiceInstance.serviceDomainName ), configureInbound, configureOutbound ).then( () => {
142
160
  resolve();
143
161
  } ).catch( ( error ) => {
144
162
  reject( exceptions.raise( error ) );
@@ -157,6 +175,8 @@ class ServiceInstance {
157
175
  return new Promise( ( resolve, reject ) => {
158
176
  this.#preStop().then( () => {
159
177
  return this.onStop();
178
+ } ).then( () => {
179
+ return cache.instance.shutDown();
160
180
  } ).then( () => {
161
181
  return this.#postStop();
162
182
  } ).then( () => {
@@ -172,7 +192,7 @@ class ServiceInstance {
172
192
  * <br/>
173
193
  * NOTE: This method will be invoked automatically.
174
194
  * <br/>
175
- * NOTE: If you need to add more onStop logic you can override this method but make sure to call it in the
195
+ * NOTE: If you need to add more onStop logic, you can override this method but make sure to call it in the
176
196
  * overriding method using: super.onStop()
177
197
  *
178
198
  * @method
@@ -182,7 +202,7 @@ class ServiceInstance {
182
202
  */
183
203
  onStop() {
184
204
  return new Promise( ( resolve, reject ) => {
185
- messageDispatcher.shutDown().then( () => {
205
+ messageDispatcher.instance.shutDown().then( () => {
186
206
  resolve();
187
207
  } ).catch( ( error ) => {
188
208
  reject( exceptions.raise( error ) );
@@ -202,9 +222,9 @@ class ServiceInstance {
202
222
  * @public
203
223
  */
204
224
  reportHealthy() {
205
- if ( cache.isOperational ) {
225
+ if ( cache.instance.isOperational ) {
206
226
  let timestamp = new Date();
207
- cache.setValue( this.#serviceHealthCheck, timestamp.toISOString(), config.getSetting( config.setting.SERVICE_HEALTH_CHECK_TIMEOUT ) ).catch( ( error ) => {
227
+ cache.instance.setValue( this.#serviceHealthCheck, timestamp.toISOString(), config.getSetting( config.setting.SERVICE_HEALTH_CHECK_TIMEOUT ) ).catch( ( error ) => {
208
228
  logger.log( `Error while trying to report for health check from '${ ServiceInstance.instanceID }'!`, logger.logSeverity.WARNING, error );
209
229
  } );
210
230
  }
@@ -222,8 +242,8 @@ class ServiceInstance {
222
242
  * @private
223
243
  */
224
244
  #preStart() {
225
- return new Promise( ( resolve, reject ) => {
226
- this.#serviceHealthCheck = config.getSetting( config.setting.SERVICE_HEALTH_CHECK_ADDRESS ) + process.env.TI_INSTANCE_NAME + ":" + ServiceInstance.instanceID;
245
+ return new Promise( ( resolve ) => {
246
+ this.#serviceHealthCheck = config.getSetting( config.setting.SERVICE_HEALTH_CHECK_ADDRESS ) + ServiceInstance.serviceDomainName + ":" + ServiceInstance.instanceID;
227
247
  resolve();
228
248
  } );
229
249
  }
@@ -238,8 +258,8 @@ class ServiceInstance {
238
258
  * @private
239
259
  */
240
260
  #postStart() {
241
- return new Promise( ( resolve, reject ) => {
242
- // schedule regular health check:
261
+ return new Promise( ( resolve ) => {
262
+ // Schedule regular health check:
243
263
  this.#reportHealthyJob = schedule.scheduleJob( config.getSetting( config.setting.SERVICE_HEALTH_CHECK_INTERVAL ), () => {
244
264
  this.reportHealthy();
245
265
  } );
@@ -263,11 +283,10 @@ class ServiceInstance {
263
283
  * @private
264
284
  */
265
285
  #preStop() {
266
- return new Promise( ( resolve, reject ) => {
286
+ return new Promise( ( resolve ) => {
267
287
  if ( this.#reportHealthyJob ) {
268
288
  this.#reportHealthyJob.cancel();
269
289
  }
270
-
271
290
  resolve();
272
291
  } );
273
292
  }
@@ -282,13 +301,12 @@ class ServiceInstance {
282
301
  * @private
283
302
  */
284
303
  #postStop() {
285
- return new Promise( ( resolve, reject ) => {
304
+ return new Promise( ( resolve ) => {
286
305
  logger.log( `Instance '${ ServiceInstance.instanceID }' shut down successfully.`, logger.logSeverity.NOTICE );
287
-
288
306
  resolve();
289
307
  } );
290
308
  }
291
309
 
292
310
  }
293
311
 
294
- module.exports = ServiceInstance;
312
+ module.exports = ServiceInstance;
@@ -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 ServiceConsumer = require( "#service-consumer" );
7
10
  const _ = require( "lodash" );
@@ -71,7 +74,7 @@ class ServiceProvider extends ServiceConsumer {
71
74
  let serviceDefinitions = this.serviceConfig.services;
72
75
  return this.registerServices( serviceDefinitions );
73
76
  } ).then( () => {
74
- messageDispatcher.addMessageObserverRequestsIn( this.#serviceExecutor );
77
+ messageDispatcher.instance.addMessageObserverRequestsIn( this.#serviceExecutor );
75
78
  resolve();
76
79
  } ).catch( ( error ) => {
77
80
  reject( exceptions.raise( error ) );
@@ -102,6 +105,22 @@ class ServiceProvider extends ServiceConsumer {
102
105
  } );
103
106
  }
104
107
 
108
+ /**
109
+ * Used to report health status of the service instance for external monitoring.
110
+ * This is a scheduled job that will be executed at SERVICE_HEALTH_CHECK_INTERVAL time.
111
+ * <br/>
112
+ * NOTE: By default this method will update a Redis key with an expiration timer. You can override this
113
+ * functionality with something custom like calling an HTTP endpoint.
114
+ *
115
+ * @method
116
+ * @override
117
+ * @virtual
118
+ * @public
119
+ */
120
+ reportHealthy() {
121
+ super.reportHealthy();
122
+ }
123
+
105
124
  /**
106
125
  * Used to verify whether the service caller has authorization to access the service.
107
126
  * <br/>
@@ -184,10 +203,10 @@ class ServiceProvider extends ServiceConsumer {
184
203
  // If this happens, a corresponding log entry will be created but the loading process will continue. Therefore, the following
185
204
  // promise will always resolve (unless a programming error occurs in it of course).
186
205
  let registrationPromise = ( serviceDefinition, defaultServiceHandler ) => {
187
- return new Promise( ( resolve, reject ) => {
206
+ return new Promise( ( resolve ) => {
188
207
  this.registerService( serviceDefinition, defaultServiceHandler ).then( () => {
189
208
  resolve( true );
190
- } ).catch( ( error ) => {
209
+ } ).catch( () => {
191
210
  resolve( false );
192
211
  } );
193
212
  } );
@@ -225,4 +244,4 @@ class ServiceProvider extends ServiceConsumer {
225
244
 
226
245
  }
227
246
 
228
- module.exports = ServiceProvider;
247
+ module.exports = ServiceProvider;
@@ -1,9 +1,13 @@
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 config = require( "#config" );
10
+ const tools = require( "#tools" );
7
11
 
8
12
  /**
9
13
  * Used to verify if the GCloud integration is enabled.
@@ -13,7 +17,7 @@ const config = require( "#config" );
13
17
  * @public
14
18
  */
15
19
  module.exports.isEnabled = () => {
16
- return process.env.TI_GCLOUD_ENABLED === true;
20
+ return tools.toBool( process.env.TI_GCLOUD_ENABLED );
17
21
  };
18
22
 
19
23
  /**