@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.
Files changed (30) hide show
  1. 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
  2. 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
  3. package/.yarn/cache/@typescript-eslint-eslint-plugin-npm-8.46.0-e6114965b4-415afd894a.zip +0 -0
  4. package/.yarn/cache/@typescript-eslint-parser-npm-8.46.0-c44629050a-6838fde776.zip +0 -0
  5. package/.yarn/cache/@typescript-eslint-project-service-npm-8.46.0-85a4b9bb9c-de11af23ae.zip +0 -0
  6. package/.yarn/cache/@typescript-eslint-scope-manager-npm-8.46.0-fd8edaba78-ed85abd08c.zip +0 -0
  7. package/.yarn/cache/@typescript-eslint-tsconfig-utils-npm-8.46.0-8919c1f746-e78a66a854.zip +0 -0
  8. package/.yarn/cache/@typescript-eslint-type-utils-npm-8.46.0-dbfff922bb-5405b71b91.zip +0 -0
  9. package/.yarn/cache/@typescript-eslint-types-npm-8.46.0-b013400d3e-0118b0dd59.zip +0 -0
  10. package/.yarn/cache/@typescript-eslint-typescript-estree-npm-8.46.0-0b10d4388a-61053bd0c3.zip +0 -0
  11. package/.yarn/cache/@typescript-eslint-utils-npm-8.46.0-a7d3832f43-4e0da60de3.zip +0 -0
  12. package/.yarn/cache/@typescript-eslint-visitor-keys-npm-8.46.0-7d793afea5-37e6145b6a.zip +0 -0
  13. package/.yarn/install-state.gz +0 -0
  14. package/.yarn/releases/{yarn-4.10.2.cjs → yarn-4.10.3.cjs} +126 -126
  15. package/.yarnrc.yml +1 -1
  16. package/CLAUDE.md +186 -0
  17. package/modules/api-svc/package.json +2 -2
  18. package/modules/api-svc/src/ControlAgent/index.js +42 -11
  19. package/modules/api-svc/src/OutboundServer/handlers.js +1 -1
  20. package/modules/api-svc/src/config.js +1 -0
  21. package/modules/api-svc/src/index.js +244 -188
  22. package/modules/api-svc/src/lib/cache.js +3 -1
  23. package/modules/api-svc/src/lib/logger.js +1 -2
  24. package/modules/api-svc/test/unit/index.configPolling.test.js +229 -0
  25. package/modules/api-svc/test/unit/lib/model/InboundPingModel.test.js +2 -2
  26. package/modules/outbound-command-event-handler/package.json +4 -4
  27. package/modules/outbound-domain-event-handler/package.json +3 -3
  28. package/modules/private-shared-lib/package.json +4 -4
  29. package/package.json +4 -4
  30. 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 = 30000;
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.Client.Create({
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.isDebugEnabled && this.logger.debug('Server is restarting...');
335
+ this.logger.debug('Server is restarting...', { source });
336
+ this._configUpdateInProgress = true;
266
337
 
267
- let oldCache;
268
- const updateCache = !_.isEqual(this.conf.cacheUrl, newConf.cacheUrl)
338
+ try {
339
+ let oldCache;
340
+ const updateCache = !_.isEqual(this.conf.cacheUrl, newConf.cacheUrl)
269
341
  || !_.isEqual(this.conf.enableTestFeatures, newConf.enableTestFeatures);
270
- if (updateCache) {
271
- oldCache = this.cache;
272
- await this.cache.disconnect();
273
- this.cache = createCache(newConf);
274
- await this.cache.connect();
275
- restartActionsTaken.updateCache = true;
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
- const updateOIDC = !_.isEqual(this.conf.oidc, newConf.oidc)
350
+ const updateOIDC = !_.isEqual(this.conf.oidc, newConf.oidc)
279
351
  || !_.isEqual(this.conf.outbound.tls, newConf.outbound.tls);
280
- if (updateOIDC) {
281
- this.oidc.auth.stop();
282
- this.oidc = createAuthClient(newConf, this.logger);
283
- this.oidc.auth.on('error', (msg) => {
284
- this.emit('error', 'OIDC auth error in InboundApi', msg);
285
- });
286
- await this.oidc.auth.start();
287
- restartActionsTaken.updateOIDC = true;
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
- this.logger.isDebugEnabled && this.logger.push({ oldConf: this.conf.inbound, newConf: newConf.inbound }).debug('Inbound server configuration');
291
- const updateInboundServer = this._shouldUpdateInboundServer(newConf);
292
- if (updateInboundServer) {
293
- const stopStartLabel = 'InboundServer stop/start duration';
294
- // eslint-disable-next-line no-console
295
- console.time(stopStartLabel);
296
- await this.inboundServer.stop();
297
-
298
- this.mojaloopSharedAgents = this._createMojaloopSharedAgents(newConf);
299
- this.inboundServer = new InboundServer(
300
- newConf,
301
- this.logger,
302
- this.cache,
303
- this.oidc,
304
- this.mojaloopSharedAgents,
305
- );
306
- this.inboundServer.on('error', (...args) => {
307
- const errMessage = 'Unhandled error in Inbound Server';
308
- this.logger.push({ args }).error(errMessage);
309
- this.emit('error', errMessage);
310
- });
311
- await this.inboundServer.start();
312
- // eslint-disable-next-line no-console
313
- console.timeEnd(stopStartLabel);
314
- restartActionsTaken.updateInboundServer = true;
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
- this.logger.isDebugEnabled && this.logger.push({ oldConf: this.conf.outbound, newConf: newConf.outbound }).debug('Outbound server configuration');
318
- const updateOutboundServer = this._shouldUpdateOutboundServer(newConf);
319
- if (updateOutboundServer) {
320
- const stopStartLabel = 'OutboundServer stop/start duration';
321
- // eslint-disable-next-line no-console
322
- console.time(stopStartLabel);
323
- await this.outboundServer.stop();
324
-
325
- this.mojaloopSharedAgents = this._createMojaloopSharedAgents(newConf);
326
- this.outboundServer = new OutboundServer(
327
- newConf,
328
- this.logger,
329
- this.cache,
330
- this.metricsClient,
331
- this.oidc,
332
- this.mojaloopSharedAgents,
333
- );
334
- this.outboundServer.on('error', (...args) => {
335
- const errMessage = 'Unhandled error in Outbound Server';
336
- this.logger.push({ args }).error(errMessage);
337
- this.emit('error', errMessage);
338
- });
339
- await this.outboundServer.start();
340
- // eslint-disable-next-line no-console
341
- console.timeEnd(stopStartLabel);
342
- restartActionsTaken.updateOutboundServer = true;
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
- const updateFspiopEventHandler = !_.isEqual(this.conf.outbound, newConf.outbound)
417
+ const updateFspiopEventHandler = !_.isEqual(this.conf.outbound, newConf.outbound)
346
418
  && this.conf.fspiopEventHandler.enabled;
347
- if (updateFspiopEventHandler) {
348
- await this.fspiopEventHandler.stop();
349
- this.fspiopEventHandler = new FSPIOPEventHandler({
350
- config: newConf,
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
- appConfig: newConf,
424
+ cache: this.cache,
425
+ oidc: this.oidc,
382
426
  });
383
- this.controlClient.on(ControlAgent.EVENT.RECONFIGURE, this.restart.bind(this));
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
- this.controlClient.on('close', () => {
393
- clearTimeout(this.pingTimeout);
394
- setTimeout(() => {
395
- this.logger.debug('Control client closed. Restarting server...');
396
- this.restart(_.merge({}, newConf, {
397
- control: { stopped: Date.now() }
398
- }));
399
- }, RESTART_INTERVAL_MS);
400
- });
401
-
402
- restartActionsTaken.updateControlClient = true;
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
- const updateOAuthTestServer = !_.isEqual(newConf.oauthTestServer, this.conf.oauthTestServer);
407
- if (updateOAuthTestServer) {
408
- await this.oauthTestServer?.stop();
409
- if (this.conf.oauthTestServer.enabled) {
410
- this.oauthTestServer = new OAuthTestServer({
411
- clientKey: newConf.oauthTestServer.clientKey,
412
- clientSecret: newConf.oauthTestServer.clientSecret,
413
- port: newConf.oauthTestServer.listenPort,
414
- logger: this.logger,
415
- });
416
- await this.oauthTestServer.start();
417
- restartActionsTaken.updateOAuthTestServer = true;
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
- const updateTestServer = !_.isEqual(newConf.test.port, this.conf.test.port);
422
- if (updateTestServer) {
423
- await this.testServer?.stop();
424
- if (this.conf.enableTestFeatures) {
425
- this.testServer = new TestServer({
426
- port: newConf.test.port,
427
- logger: this.logger,
428
- cache: this.cache,
429
- });
430
- await this.testServer.start();
431
- restartActionsTaken.updateTestServer = true;
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
- this.conf = newConf;
500
+ this.conf = newConf;
436
501
 
437
- await oldCache?.disconnect();
502
+ await oldCache?.disconnect();
438
503
 
439
- if (Object.keys(restartActionsTaken).length > 0) {
440
- this.logger.info('Server is restarted', { restartActionsTaken });
441
- } else {
442
- this.logger.verbose('Server not restarted, no config changes detected');
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.Client.Create({
511
- appConfig: config,
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.push({ err }).error('Unhandled server error');
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.push({ err }).error('Error starting server');
592
+ logger.error('Error starting server: ', err);
537
593
  process.exit(1);
538
594
  });
539
595
 
540
- logger.info('SDK server is started!', { name, version });
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([this._getClient(), this._getClient()]);
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;