@mojaloop/sdk-scheme-adapter 24.13.0 → 24.14.0-snapshot.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/.yarn/cache/{@mojaloop-central-services-shared-npm-18.34.0-98deaad7cb-660f407a57.zip → @mojaloop-central-services-shared-npm-18.34.1-fc3be8e73c-f7ad2f9394.zip} +0 -0
- package/.yarn/cache/{@mojaloop-inter-scheme-proxy-cache-lib-npm-2.7.0-84455815f8-7748014a4c.zip → @mojaloop-inter-scheme-proxy-cache-lib-npm-2.9.0-cb33cd6786-fd3f20e6a7.zip} +0 -0
- package/.yarn/cache/@typescript-eslint-eslint-plugin-npm-8.46.0-e6114965b4-415afd894a.zip +0 -0
- package/.yarn/cache/@typescript-eslint-parser-npm-8.46.0-c44629050a-6838fde776.zip +0 -0
- package/.yarn/cache/@typescript-eslint-project-service-npm-8.46.0-85a4b9bb9c-de11af23ae.zip +0 -0
- package/.yarn/cache/@typescript-eslint-scope-manager-npm-8.46.0-fd8edaba78-ed85abd08c.zip +0 -0
- package/.yarn/cache/@typescript-eslint-tsconfig-utils-npm-8.46.0-8919c1f746-e78a66a854.zip +0 -0
- package/.yarn/cache/@typescript-eslint-type-utils-npm-8.46.0-dbfff922bb-5405b71b91.zip +0 -0
- package/.yarn/cache/@typescript-eslint-types-npm-8.46.0-b013400d3e-0118b0dd59.zip +0 -0
- package/.yarn/cache/@typescript-eslint-typescript-estree-npm-8.46.0-0b10d4388a-61053bd0c3.zip +0 -0
- package/.yarn/cache/@typescript-eslint-utils-npm-8.46.0-a7d3832f43-4e0da60de3.zip +0 -0
- package/.yarn/cache/@typescript-eslint-visitor-keys-npm-8.46.0-7d793afea5-37e6145b6a.zip +0 -0
- package/.yarn/install-state.gz +0 -0
- package/.yarn/releases/{yarn-4.10.2.cjs → yarn-4.10.3.cjs} +126 -126
- package/.yarnrc.yml +1 -1
- package/CLAUDE.md +186 -0
- package/modules/api-svc/package.json +2 -2
- package/modules/api-svc/src/ControlAgent/index.js +42 -11
- package/modules/api-svc/src/OutboundServer/handlers.js +1 -1
- package/modules/api-svc/src/config.js +1 -0
- package/modules/api-svc/src/index.js +244 -188
- package/modules/api-svc/src/lib/cache.js +3 -1
- package/modules/api-svc/src/lib/logger.js +1 -2
- package/modules/api-svc/test/unit/index.configPolling.test.js +229 -0
- package/modules/api-svc/test/unit/lib/model/InboundPingModel.test.js +2 -2
- package/modules/outbound-command-event-handler/package.json +4 -4
- package/modules/outbound-domain-event-handler/package.json +3 -3
- package/modules/private-shared-lib/package.json +4 -4
- package/package.json +4 -4
- package/{sbom-v24.12.0.csv → sbom-v24.13.0.csv} +220 -231
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
******/
|
|
27
27
|
'use strict';
|
|
28
28
|
|
|
29
|
+
const { hostname } = require('node:os');
|
|
29
30
|
const EventEmitter = require('node:events');
|
|
30
31
|
const http = require('http');
|
|
31
32
|
const https = require('https');
|
|
@@ -53,7 +54,7 @@ const { SDKStateEnum } = require('./lib/model/common');
|
|
|
53
54
|
const { createAuthClient } = require('./lib/utils');
|
|
54
55
|
const { logger } = require('./lib/logger');
|
|
55
56
|
|
|
56
|
-
const PING_INTERVAL_MS =
|
|
57
|
+
const PING_INTERVAL_MS = 30_000;
|
|
57
58
|
|
|
58
59
|
const createCache = (config) => new Cache({
|
|
59
60
|
logger,
|
|
@@ -203,6 +204,71 @@ class Server extends EventEmitter {
|
|
|
203
204
|
return isOutboundDifferent || isJwsSigningKeyDifferent;
|
|
204
205
|
}
|
|
205
206
|
|
|
207
|
+
/**
|
|
208
|
+
* Starts periodic polling of Management API for configuration updates.
|
|
209
|
+
* Only runs if PM4ML enabled and a polling interval configured.
|
|
210
|
+
*/
|
|
211
|
+
_startConfigPolling() {
|
|
212
|
+
if (!this.conf.pm4mlEnabled || !this.conf.control.mgmtAPIPollIntervalMs) {
|
|
213
|
+
this.logger.info('No failsafe config polling configured');
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
this.logger.info('starting failsafe config polling from Management API...', { intervalMs: this.conf.control.mgmtAPIPollIntervalMs });
|
|
218
|
+
|
|
219
|
+
this._configPollInterval = setInterval(
|
|
220
|
+
() => this._pollConfigFromMgmtAPI(),
|
|
221
|
+
this.conf.control.mgmtAPIPollIntervalMs
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
// Unref so it doesn't prevent process exit
|
|
225
|
+
this._configPollInterval.unref();
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Polls Management API for configuration updates.
|
|
230
|
+
* Reuses the existing persistent WebSocket client (this.controlClient).
|
|
231
|
+
* Skips polling if:
|
|
232
|
+
* - Another config update is in progress
|
|
233
|
+
* - WebSocket client is not connected
|
|
234
|
+
*/
|
|
235
|
+
async _pollConfigFromMgmtAPI() {
|
|
236
|
+
// Race condition prevention: skip if restart in progress
|
|
237
|
+
if (this._configUpdateInProgress) {
|
|
238
|
+
this.logger.info('config updating already in progress, skipping poll');
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// WebSocket readyState: 0=CONNECTING, 1=OPEN, 2=CLOSING, 3=CLOSED
|
|
243
|
+
if (this.controlClient?.readyState !== 1) {
|
|
244
|
+
this.logger.warn('Control client not ready (not OPEN), skipping poll', { readyState: this.controlClient?.readyState });
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
try {
|
|
249
|
+
const newConfig = await this.controlClient.getUpdatedConfig();
|
|
250
|
+
if (!newConfig) {
|
|
251
|
+
this.logger.warn('No config received from polling');
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
this.logger.info('polling config from mgmt-api is done, checking if SDK server restart needed...');
|
|
255
|
+
|
|
256
|
+
const mergedConfig = _.merge({}, this.conf, newConfig);
|
|
257
|
+
await this.restart(mergedConfig, { source: 'polling' });
|
|
258
|
+
} catch (err) {
|
|
259
|
+
this.logger.error('error in polling config from Management API: ', err);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/** Stops the config polling interval. */
|
|
264
|
+
_stopConfigPolling() {
|
|
265
|
+
if (this._configPollInterval) {
|
|
266
|
+
this.logger.verbose('stopping config polling');
|
|
267
|
+
clearInterval(this._configPollInterval);
|
|
268
|
+
this._configPollInterval = null;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
206
272
|
async start() {
|
|
207
273
|
await this.cache.connect();
|
|
208
274
|
await this.oidc.auth.start();
|
|
@@ -213,12 +279,7 @@ class Server extends EventEmitter {
|
|
|
213
279
|
// management protocol messages e.g configuration changes, certificate updates etc.
|
|
214
280
|
if (this.conf.pm4mlEnabled) {
|
|
215
281
|
const RESTART_INTERVAL_MS = 10000;
|
|
216
|
-
this.controlClient = await ControlAgent.
|
|
217
|
-
address: this.conf.control.mgmtAPIWsUrl,
|
|
218
|
-
port: this.conf.control.mgmtAPIWsPort,
|
|
219
|
-
logger: this.logger,
|
|
220
|
-
appConfig: this.conf,
|
|
221
|
-
});
|
|
282
|
+
this.controlClient = await ControlAgent.createConnectedControlAgentWs(this.conf, this.logger);
|
|
222
283
|
this.controlClient.on(ControlAgent.EVENT.RECONFIGURE, this.restart.bind(this));
|
|
223
284
|
|
|
224
285
|
const schedulePing = () => {
|
|
@@ -247,6 +308,7 @@ class Server extends EventEmitter {
|
|
|
247
308
|
});
|
|
248
309
|
|
|
249
310
|
schedulePing();
|
|
311
|
+
this._startConfigPolling();
|
|
250
312
|
}
|
|
251
313
|
|
|
252
314
|
await Promise.all([
|
|
@@ -260,190 +322,200 @@ class Server extends EventEmitter {
|
|
|
260
322
|
]);
|
|
261
323
|
}
|
|
262
324
|
|
|
263
|
-
async restart(newConf) {
|
|
325
|
+
async restart(newConf, options = {}) {
|
|
326
|
+
const source = options.source || 'websocket'; // Track source of restart call - websocket or polling
|
|
327
|
+
|
|
328
|
+
// Race condition prevention
|
|
329
|
+
if (this._configUpdateInProgress) {
|
|
330
|
+
this.logger.info('restart already in progress, skipping', { source });
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
|
|
264
334
|
const restartActionsTaken = {};
|
|
265
|
-
this.logger.
|
|
335
|
+
this.logger.debug('Server is restarting...', { source });
|
|
336
|
+
this._configUpdateInProgress = true;
|
|
266
337
|
|
|
267
|
-
|
|
268
|
-
|
|
338
|
+
try {
|
|
339
|
+
let oldCache;
|
|
340
|
+
const updateCache = !_.isEqual(this.conf.cacheUrl, newConf.cacheUrl)
|
|
269
341
|
|| !_.isEqual(this.conf.enableTestFeatures, newConf.enableTestFeatures);
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
342
|
+
if (updateCache) {
|
|
343
|
+
oldCache = this.cache;
|
|
344
|
+
await this.cache.disconnect();
|
|
345
|
+
this.cache = createCache(newConf);
|
|
346
|
+
await this.cache.connect();
|
|
347
|
+
restartActionsTaken.updateCache = true;
|
|
348
|
+
}
|
|
277
349
|
|
|
278
|
-
|
|
350
|
+
const updateOIDC = !_.isEqual(this.conf.oidc, newConf.oidc)
|
|
279
351
|
|| !_.isEqual(this.conf.outbound.tls, newConf.outbound.tls);
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
352
|
+
if (updateOIDC) {
|
|
353
|
+
this.oidc.auth.stop();
|
|
354
|
+
this.oidc = createAuthClient(newConf, this.logger);
|
|
355
|
+
this.oidc.auth.on('error', (msg) => {
|
|
356
|
+
this.emit('error', 'OIDC auth error in InboundApi', msg);
|
|
357
|
+
});
|
|
358
|
+
await this.oidc.auth.start();
|
|
359
|
+
restartActionsTaken.updateOIDC = true;
|
|
360
|
+
}
|
|
289
361
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
362
|
+
this.logger.isDebugEnabled && this.logger.push({ oldConf: this.conf.inbound, newConf: newConf.inbound }).debug('Inbound server configuration');
|
|
363
|
+
const updateInboundServer = this._shouldUpdateInboundServer(newConf);
|
|
364
|
+
if (updateInboundServer) {
|
|
365
|
+
const stopStartLabel = 'InboundServer stop/start duration';
|
|
366
|
+
// eslint-disable-next-line no-console
|
|
367
|
+
console.time(stopStartLabel); // todo: remove console.time
|
|
368
|
+
await this.inboundServer.stop();
|
|
369
|
+
|
|
370
|
+
this.mojaloopSharedAgents = this._createMojaloopSharedAgents(newConf);
|
|
371
|
+
this.inboundServer = new InboundServer(
|
|
372
|
+
newConf,
|
|
373
|
+
this.logger,
|
|
374
|
+
this.cache,
|
|
375
|
+
this.oidc,
|
|
376
|
+
this.mojaloopSharedAgents,
|
|
377
|
+
);
|
|
378
|
+
this.inboundServer.on('error', (...args) => {
|
|
379
|
+
const errMessage = 'Unhandled error in Inbound Server';
|
|
380
|
+
this.logger.push({ args }).error(errMessage);
|
|
381
|
+
this.emit('error', errMessage);
|
|
382
|
+
});
|
|
383
|
+
await this.inboundServer.start();
|
|
384
|
+
// eslint-disable-next-line no-console
|
|
385
|
+
console.timeEnd(stopStartLabel);
|
|
386
|
+
restartActionsTaken.updateInboundServer = true;
|
|
387
|
+
}
|
|
316
388
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
389
|
+
this.logger.isDebugEnabled && this.logger.push({ oldConf: this.conf.outbound, newConf: newConf.outbound }).debug('Outbound server configuration');
|
|
390
|
+
const updateOutboundServer = this._shouldUpdateOutboundServer(newConf);
|
|
391
|
+
if (updateOutboundServer) {
|
|
392
|
+
const stopStartLabel = 'OutboundServer stop/start duration';
|
|
393
|
+
// eslint-disable-next-line no-console
|
|
394
|
+
console.time(stopStartLabel);
|
|
395
|
+
await this.outboundServer.stop();
|
|
396
|
+
|
|
397
|
+
this.mojaloopSharedAgents = this._createMojaloopSharedAgents(newConf);
|
|
398
|
+
this.outboundServer = new OutboundServer(
|
|
399
|
+
newConf,
|
|
400
|
+
this.logger,
|
|
401
|
+
this.cache,
|
|
402
|
+
this.metricsClient,
|
|
403
|
+
this.oidc,
|
|
404
|
+
this.mojaloopSharedAgents,
|
|
405
|
+
);
|
|
406
|
+
this.outboundServer.on('error', (...args) => {
|
|
407
|
+
const errMessage = 'Unhandled error in Outbound Server';
|
|
408
|
+
this.logger.push({ args }).error(errMessage);
|
|
409
|
+
this.emit('error', errMessage);
|
|
410
|
+
});
|
|
411
|
+
await this.outboundServer.start();
|
|
412
|
+
// eslint-disable-next-line no-console
|
|
413
|
+
console.timeEnd(stopStartLabel);
|
|
414
|
+
restartActionsTaken.updateOutboundServer = true;
|
|
415
|
+
}
|
|
344
416
|
|
|
345
|
-
|
|
417
|
+
const updateFspiopEventHandler = !_.isEqual(this.conf.outbound, newConf.outbound)
|
|
346
418
|
&& this.conf.fspiopEventHandler.enabled;
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
logger: this.logger,
|
|
352
|
-
cache: this.cache,
|
|
353
|
-
oidc: this.oidc,
|
|
354
|
-
});
|
|
355
|
-
await this.fspiopEventHandler.start();
|
|
356
|
-
restartActionsTaken.updateFspiopEventHandler = true;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
const updateControlClient = !_.isEqual(this.conf.control, newConf.control);
|
|
360
|
-
if (updateControlClient) {
|
|
361
|
-
await this.controlClient?.stop();
|
|
362
|
-
if (this.conf.pm4mlEnabled) {
|
|
363
|
-
const RESTART_INTERVAL_MS = 10000;
|
|
364
|
-
|
|
365
|
-
const schedulePing = () => {
|
|
366
|
-
clearTimeout(this.pingTimeout);
|
|
367
|
-
this.pingTimeout = setTimeout(() => {
|
|
368
|
-
this.logger.error('Ping timeout, possible broken connection. Restarting server...');
|
|
369
|
-
this.restart(_.merge({}, newConf, {
|
|
370
|
-
control: { stopped: Date.now() }
|
|
371
|
-
}));
|
|
372
|
-
}, PING_INTERVAL_MS + this.conf.control.mgmtAPILatencyAssumption);
|
|
373
|
-
};
|
|
374
|
-
|
|
375
|
-
schedulePing();
|
|
376
|
-
|
|
377
|
-
this.controlClient = await ControlAgent.Client.Create({
|
|
378
|
-
address: newConf.control.mgmtAPIWsUrl,
|
|
379
|
-
port: newConf.control.mgmtAPIWsPort,
|
|
419
|
+
if (updateFspiopEventHandler) {
|
|
420
|
+
await this.fspiopEventHandler.stop();
|
|
421
|
+
this.fspiopEventHandler = new FSPIOPEventHandler({
|
|
422
|
+
config: newConf,
|
|
380
423
|
logger: this.logger,
|
|
381
|
-
|
|
424
|
+
cache: this.cache,
|
|
425
|
+
oidc: this.oidc,
|
|
382
426
|
});
|
|
383
|
-
|
|
384
|
-
|
|
427
|
+
await this.fspiopEventHandler.start();
|
|
428
|
+
restartActionsTaken.updateFspiopEventHandler = true;
|
|
429
|
+
}
|
|
385
430
|
|
|
431
|
+
const updateControlClient = !_.isEqual(this.conf.control, newConf.control);
|
|
432
|
+
if (updateControlClient) {
|
|
433
|
+
await this.controlClient?.stop();
|
|
434
|
+
if (this.conf.pm4mlEnabled) {
|
|
435
|
+
const RESTART_INTERVAL_MS = 10000;
|
|
436
|
+
|
|
437
|
+
const schedulePing = () => {
|
|
438
|
+
clearTimeout(this.pingTimeout);
|
|
439
|
+
this.pingTimeout = setTimeout(() => {
|
|
440
|
+
this.logger.error('Ping timeout, possible broken connection. Restarting server...');
|
|
441
|
+
this.restart(_.merge({}, newConf, {
|
|
442
|
+
control: { stopped: Date.now() }
|
|
443
|
+
}));
|
|
444
|
+
}, PING_INTERVAL_MS + this.conf.control.mgmtAPILatencyAssumption);
|
|
445
|
+
};
|
|
386
446
|
|
|
387
|
-
this.controlClient.on('ping', () => {
|
|
388
|
-
this.logger.debug('Received ping from control server');
|
|
389
447
|
schedulePing();
|
|
390
|
-
});
|
|
391
448
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
this.
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
449
|
+
this.controlClient = await ControlAgent.createConnectedControlAgentWs(newConf, this.logger);
|
|
450
|
+
this.controlClient.on(ControlAgent.EVENT.RECONFIGURE, this.restart.bind(this));
|
|
451
|
+
|
|
452
|
+
this.controlClient.on('ping', () => {
|
|
453
|
+
this.logger.debug('Received ping from control server');
|
|
454
|
+
schedulePing();
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
this.controlClient.on('close', () => {
|
|
458
|
+
clearTimeout(this.pingTimeout);
|
|
459
|
+
setTimeout(() => {
|
|
460
|
+
this.logger.debug('Control client closed. Restarting server...');
|
|
461
|
+
this.restart(_.merge({}, newConf, {
|
|
462
|
+
control: { stopped: Date.now() }
|
|
463
|
+
}));
|
|
464
|
+
}, RESTART_INTERVAL_MS);
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
restartActionsTaken.updateControlClient = true;
|
|
468
|
+
}
|
|
403
469
|
}
|
|
404
|
-
}
|
|
405
470
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
471
|
+
const updateOAuthTestServer = !_.isEqual(newConf.oauthTestServer, this.conf.oauthTestServer);
|
|
472
|
+
if (updateOAuthTestServer) {
|
|
473
|
+
await this.oauthTestServer?.stop();
|
|
474
|
+
if (this.conf.oauthTestServer.enabled) {
|
|
475
|
+
this.oauthTestServer = new OAuthTestServer({
|
|
476
|
+
clientKey: newConf.oauthTestServer.clientKey,
|
|
477
|
+
clientSecret: newConf.oauthTestServer.clientSecret,
|
|
478
|
+
port: newConf.oauthTestServer.listenPort,
|
|
479
|
+
logger: this.logger,
|
|
480
|
+
});
|
|
481
|
+
await this.oauthTestServer.start();
|
|
482
|
+
restartActionsTaken.updateOAuthTestServer = true;
|
|
483
|
+
}
|
|
418
484
|
}
|
|
419
|
-
}
|
|
420
485
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
486
|
+
const updateTestServer = !_.isEqual(newConf.test.port, this.conf.test.port);
|
|
487
|
+
if (updateTestServer) {
|
|
488
|
+
await this.testServer?.stop();
|
|
489
|
+
if (this.conf.enableTestFeatures) {
|
|
490
|
+
this.testServer = new TestServer({
|
|
491
|
+
port: newConf.test.port,
|
|
492
|
+
logger: this.logger,
|
|
493
|
+
cache: this.cache,
|
|
494
|
+
});
|
|
495
|
+
await this.testServer.start();
|
|
496
|
+
restartActionsTaken.updateTestServer = true;
|
|
497
|
+
}
|
|
432
498
|
}
|
|
433
|
-
}
|
|
434
499
|
|
|
435
|
-
|
|
500
|
+
this.conf = newConf;
|
|
436
501
|
|
|
437
|
-
|
|
502
|
+
await oldCache?.disconnect();
|
|
438
503
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
504
|
+
if (Object.keys(restartActionsTaken).length > 0) {
|
|
505
|
+
this.logger.info('Server is restarted', { restartActionsTaken, source });
|
|
506
|
+
} else {
|
|
507
|
+
this.logger.verbose('Server not restarted, no config changes detected', { source });
|
|
508
|
+
}
|
|
509
|
+
} catch (err) {
|
|
510
|
+
this.logger.error('error in Server restart: ', err);
|
|
511
|
+
} finally {
|
|
512
|
+
this._configUpdateInProgress = false;
|
|
443
513
|
}
|
|
444
514
|
}
|
|
445
515
|
|
|
446
516
|
stop() {
|
|
517
|
+
this._stopConfigPolling();
|
|
518
|
+
|
|
447
519
|
clearTimeout(this.pingTimeout);
|
|
448
520
|
this.oidc.auth.stop();
|
|
449
521
|
this.controlClient?.removeAllListeners();
|
|
@@ -452,10 +524,10 @@ class Server extends EventEmitter {
|
|
|
452
524
|
this.cache.disconnect(),
|
|
453
525
|
this.inboundServer.stop(),
|
|
454
526
|
this.outboundServer.stop(),
|
|
527
|
+
this.metricsServer.stop(),
|
|
455
528
|
this.oauthTestServer?.stop(),
|
|
456
529
|
this.testServer?.stop(),
|
|
457
530
|
this.controlClient?.stop(),
|
|
458
|
-
this.metricsServer.stop(),
|
|
459
531
|
this.backendEventHandler?.stop(),
|
|
460
532
|
this.fspiopEventHandler?.stop(),
|
|
461
533
|
]);
|
|
@@ -493,35 +565,19 @@ class Server extends EventEmitter {
|
|
|
493
565
|
}
|
|
494
566
|
}
|
|
495
567
|
|
|
496
|
-
/*
|
|
497
|
-
* Call the Connector Manager in Management API to get the updated config
|
|
498
|
-
*/
|
|
499
|
-
async function _GetUpdatedConfigFromMgmtAPI(conf, logger, client) {
|
|
500
|
-
logger.isInfoEnabled && logger.info(`Getting updated config from Management API at ${conf.control.mgmtAPIWsUrl}:${conf.control.mgmtAPIWsPort}...`);
|
|
501
|
-
const clientSendResponse = await client.send(ControlAgent.build.CONFIGURATION.READ());
|
|
502
|
-
logger.isDebugEnabled && logger.debug('client send returned:: ', clientSendResponse);
|
|
503
|
-
const responseRead = await client.receive();
|
|
504
|
-
logger.isDebugEnabled && logger.debug('client receive returned:: ', responseRead);
|
|
505
|
-
return responseRead.data;
|
|
506
|
-
}
|
|
507
|
-
|
|
508
568
|
async function start(config) {
|
|
509
569
|
if (config.pm4mlEnabled) {
|
|
510
|
-
const controlClient = await ControlAgent.
|
|
511
|
-
|
|
512
|
-
address: config.control.mgmtAPIWsUrl,
|
|
513
|
-
port: config.control.mgmtAPIWsPort,
|
|
514
|
-
logger,
|
|
515
|
-
});
|
|
516
|
-
const updatedConfigFromMgmtAPI = await _GetUpdatedConfigFromMgmtAPI(config, logger, controlClient);
|
|
517
|
-
logger.isInfoEnabled && logger.push({ updatedConfigFromMgmtAPIKeys: Object.keys(updatedConfigFromMgmtAPI) }).info('updatedConfigFromMgmtAPI keys:');
|
|
570
|
+
const controlClient = await ControlAgent.createConnectedControlAgentWs(config, logger);
|
|
571
|
+
const updatedConfigFromMgmtAPI = await controlClient.getUpdatedConfig();
|
|
518
572
|
_.merge(config, updatedConfigFromMgmtAPI);
|
|
519
573
|
controlClient.terminate();
|
|
574
|
+
// todo: - clarify, why do we need to terminate the client? (use .stop() method?)
|
|
575
|
+
// - can we use persistent ws controlClient from Server? (why do we need to establish a brand new ws connection here?)
|
|
520
576
|
}
|
|
521
577
|
|
|
522
578
|
const svr = new Server(config, logger);
|
|
523
579
|
svr.on('error', (err) => {
|
|
524
|
-
logger.
|
|
580
|
+
logger.error('Unhandled server error: ', err);
|
|
525
581
|
process.exit(2);
|
|
526
582
|
});
|
|
527
583
|
|
|
@@ -533,11 +589,11 @@ async function start(config) {
|
|
|
533
589
|
});
|
|
534
590
|
|
|
535
591
|
await svr.start().catch(err => {
|
|
536
|
-
logger.
|
|
592
|
+
logger.error('Error starting server: ', err);
|
|
537
593
|
process.exit(1);
|
|
538
594
|
});
|
|
539
595
|
|
|
540
|
-
logger.info('SDK server is started
|
|
596
|
+
logger.info('SDK server is started', { name, version, hostname: hostname() });
|
|
541
597
|
}
|
|
542
598
|
|
|
543
599
|
if (require.main === module) {
|
|
@@ -98,7 +98,9 @@ class Cache {
|
|
|
98
98
|
break;
|
|
99
99
|
}
|
|
100
100
|
this._connectionState = CONN_ST.CONNECTING;
|
|
101
|
-
this._inProgressConnection = Promise.all([
|
|
101
|
+
this._inProgressConnection = Promise.all([
|
|
102
|
+
this._getClient(), this._getClient()
|
|
103
|
+
]);
|
|
102
104
|
[this._client, this._subscriptionClient] = await this._inProgressConnection;
|
|
103
105
|
|
|
104
106
|
if (this._config.enableTestFeatures) {
|
|
@@ -25,15 +25,14 @@
|
|
|
25
25
|
--------------
|
|
26
26
|
******/
|
|
27
27
|
|
|
28
|
-
const { hostname } = require('node:os');
|
|
29
28
|
const { loggerFactory, LOG_LEVELS } = require('@mojaloop/sdk-standard-components').Logger;
|
|
30
29
|
|
|
31
30
|
const createLogger = (conf = {}) => {
|
|
32
31
|
const {
|
|
33
32
|
context = {
|
|
33
|
+
context: 'SDK',
|
|
34
34
|
// If we're running from a Mojaloop helm chart deployment, we'll have a SIM_NAME
|
|
35
35
|
simulator: process.env['SIM_NAME'],
|
|
36
|
-
hostname: hostname(),
|
|
37
36
|
},
|
|
38
37
|
isJsonOutput = false,
|
|
39
38
|
} = conf;
|