@mojaloop/sdk-scheme-adapter 24.10.6-snapshot.0 → 24.10.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.yarn/cache/{@eslint-compat-npm-1.3.1-41a44c7960-688231f00b.zip → @eslint-compat-npm-1.3.2-b403da4a15-e710ec5ed8.zip} +0 -0
- package/.yarn/cache/@hapi-address-npm-5.1.1-2944e6ed9b-9462b22f96.zip +0 -0
- package/.yarn/cache/@hapi-formula-npm-3.0.2-70d8fffc4e-c6d4fdcd19.zip +0 -0
- package/.yarn/cache/@hapi-hapi-npm-21.4.2-b5f92c52c3-efe9025469.zip +0 -0
- package/.yarn/cache/@hapi-pinpoint-npm-2.0.1-4da9d8fcbc-28e72305c1.zip +0 -0
- package/.yarn/cache/@hapi-tlds-npm-1.1.2-80b5f7031d-339761cd1a.zip +0 -0
- package/.yarn/cache/@ioredis-commands-npm-1.3.0-c1ff038fb4-203029f09d.zip +0 -0
- package/.yarn/cache/@mojaloop-central-services-shared-npm-18.30.7-291fa1aea3-aee239baa2.zip +0 -0
- package/.yarn/cache/@redocly-openapi-core-npm-1.34.5-6e131049a1-9ecce1975b.zip +0 -0
- package/.yarn/cache/@standard-schema-spec-npm-1.0.0-e86c6647f1-aee780cc14.zip +0 -0
- package/.yarn/cache/{@types-node-npm-24.2.0-62c65eafa6-b81501e05f.zip → @types-node-npm-24.2.1-00ab09acd1-cdfa7b30b2.zip} +0 -0
- package/.yarn/cache/ioredis-npm-5.7.0-870b1dbe10-7407736226.zip +0 -0
- package/.yarn/cache/joi-npm-18.0.0-1ebac7eadf-568004d69f.zip +0 -0
- package/.yarn/cache/openapi-typescript-npm-7.9.0-08903574eb-c787cfde94.zip +0 -0
- package/.yarn/cache/supports-color-npm-10.1.0-48517f80a7-28d191c4ad.zip +0 -0
- package/.yarn/cache/yaml-npm-2.8.1-b364b3bec4-eae07b3947.zip +0 -0
- package/.yarn/install-state.gz +0 -0
- package/CHANGELOG.md +36 -0
- package/modules/api-svc/package.json +2 -2
- package/modules/api-svc/src/lib/cache.js +79 -27
- package/modules/api-svc/src/lib/model/OutboundTransfersModel.js +4 -4
- package/modules/api-svc/test/unit/lib/cache.test.js +150 -0
- package/modules/outbound-command-event-handler/package.json +3 -3
- package/modules/outbound-domain-event-handler/package.json +1 -1
- package/modules/private-shared-lib/package.json +3 -3
- package/package.json +2 -2
- package/{sbom-v24.10.5.csv → sbom-v24.10.7.csv} +88 -92
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/.yarn/install-state.gz
CHANGED
|
Binary file
|
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,40 @@
|
|
|
1
1
|
# Changelog: [mojaloop/sdk-scheme-adapter](https://github.com/mojaloop/sdk-scheme-adapter)
|
|
2
|
+
### [24.10.8](https://github.com/mojaloop/sdk-scheme-adapter/compare/v24.10.7...v24.10.8) (2025-08-11)
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
### Bug Fixes
|
|
6
|
+
|
|
7
|
+
* concurrency issues ([#601](https://github.com/mojaloop/sdk-scheme-adapter/issues/601)) ([b693e2f](https://github.com/mojaloop/sdk-scheme-adapter/commit/b693e2fe618f256e4511fe9fad256f48d814ca01))
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Chore
|
|
11
|
+
|
|
12
|
+
* **sbom:** update sbom [skip ci] ([63b0609](https://github.com/mojaloop/sdk-scheme-adapter/commit/63b06090017264a5d375d48bb9800ca9ae183ddd))
|
|
13
|
+
|
|
14
|
+
### [24.10.7](https://github.com/mojaloop/sdk-scheme-adapter/compare/v24.10.6...v24.10.7) (2025-08-08)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Bug Fixes
|
|
18
|
+
|
|
19
|
+
* revert dockerfile change ([#604](https://github.com/mojaloop/sdk-scheme-adapter/issues/604)) ([8ae897c](https://github.com/mojaloop/sdk-scheme-adapter/commit/8ae897cd4e566aed3469528f829ca201686dfeee))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
### Chore
|
|
23
|
+
|
|
24
|
+
* **sbom:** update sbom [skip ci] ([e831089](https://github.com/mojaloop/sdk-scheme-adapter/commit/e831089e0a8df20a8c002b1fccda92de89631eac))
|
|
25
|
+
|
|
26
|
+
### [24.10.6](https://github.com/mojaloop/sdk-scheme-adapter/compare/v24.10.5...v24.10.6) (2025-08-07)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
### Bug Fixes
|
|
30
|
+
|
|
31
|
+
* issue EROFS from Yarn + Node 22 ([#603](https://github.com/mojaloop/sdk-scheme-adapter/issues/603)) ([503fe96](https://github.com/mojaloop/sdk-scheme-adapter/commit/503fe96d09e633b151132acd3695b518f0dd9057))
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
### Chore
|
|
35
|
+
|
|
36
|
+
* **sbom:** update sbom [skip ci] ([b361f4f](https://github.com/mojaloop/sdk-scheme-adapter/commit/b361f4f4f6a09b7e9e19d9e267e4e875ea76b668))
|
|
37
|
+
|
|
2
38
|
### [24.10.5](https://github.com/mojaloop/sdk-scheme-adapter/compare/v24.10.4...v24.10.5) (2025-08-01)
|
|
3
39
|
|
|
4
40
|
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"@mojaloop/central-services-error-handling": "13.1.0",
|
|
69
69
|
"@mojaloop/central-services-logger": "11.9.0",
|
|
70
70
|
"@mojaloop/central-services-metrics": "12.6.0",
|
|
71
|
-
"@mojaloop/central-services-shared": "18.30.
|
|
71
|
+
"@mojaloop/central-services-shared": "18.30.7",
|
|
72
72
|
"@mojaloop/event-sdk": "14.6.1",
|
|
73
73
|
"@mojaloop/logging-bc-client-lib": "0.5.8",
|
|
74
74
|
"@mojaloop/ml-schema-transformer-lib": "2.7.7",
|
|
@@ -115,7 +115,7 @@
|
|
|
115
115
|
"jest-junit": "16.0.0",
|
|
116
116
|
"npm-check-updates": "16.7.10",
|
|
117
117
|
"openapi-response-validator": "12.1.3",
|
|
118
|
-
"openapi-typescript": "7.
|
|
118
|
+
"openapi-typescript": "7.9.0",
|
|
119
119
|
"redis-mock": "0.56.3",
|
|
120
120
|
"replace": "1.2.2",
|
|
121
121
|
"standard-version": "9.5.0",
|
|
@@ -200,52 +200,104 @@ class Cache {
|
|
|
200
200
|
}
|
|
201
201
|
|
|
202
202
|
/**
|
|
203
|
-
* Subscribes to a channel for
|
|
203
|
+
* Subscribes to a channel and waits for a single message with timeout support.
|
|
204
|
+
*
|
|
205
|
+
* NOTE:
|
|
206
|
+
* This implementation uses EventEmitter to handle Redis pub/sub concurrency issues
|
|
207
|
+
* that occur when multiple subscribers listen to the same channel simultaneously.
|
|
208
|
+
* It's designed to prevent race conditions in party lookups where concurrent requests
|
|
209
|
+
* for the same party ID could interfere with each other.
|
|
210
|
+
* Currently used for: Party lookup operations
|
|
211
|
+
* Future potential: This function can be extended to other scenarios and potentially
|
|
212
|
+
* replace the existing subscribe, unsubscribe, and subscribeToOneMessageWithTimer
|
|
213
|
+
* functions for a more robust and concurrency-safe pub/sub implementation.
|
|
204
214
|
*
|
|
205
215
|
* @param {string} channel - The channel name to subscribe to
|
|
206
|
-
* @param {
|
|
216
|
+
* @param {number} requestProcessingTimeoutSeconds - Timeout in seconds before rejecting with TimeoutError
|
|
217
|
+
* @param {boolean} [needParse=true] - Whether to JSON.parse the received message
|
|
207
218
|
*
|
|
208
|
-
* @returns {Promise}
|
|
219
|
+
* @returns {Promise<any>} Promise that resolves with the message or rejects with TimeoutError/Error
|
|
209
220
|
*/
|
|
210
221
|
async subscribeToOneMessageWithTimerNew(channel, requestProcessingTimeoutSeconds, needParse = true) {
|
|
211
|
-
let subscription;
|
|
212
|
-
|
|
213
222
|
return new Promise((resolve, reject) => {
|
|
223
|
+
let timeoutHandle = null;
|
|
224
|
+
let subscription = null;
|
|
225
|
+
let isResolved = false;
|
|
226
|
+
|
|
227
|
+
// Helper to safely unsubscribe from Redis channel
|
|
228
|
+
const unsubscribeFromRedis = async (reason = 'cleanup') => {
|
|
229
|
+
if (this._channelEmitter.listenerCount(channel) === 0 && this._subscriptionClient) {
|
|
230
|
+
try {
|
|
231
|
+
await this._subscriptionClient.unsubscribe(channel);
|
|
232
|
+
this._logger.push({ channel, reason }).debug('Unsubscribed from Redis channel');
|
|
233
|
+
} catch (unsubscribeErr) {
|
|
234
|
+
this._logger.push({ channel, reason }).warn('Failed to unsubscribe from Redis channel', unsubscribeErr);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
};
|
|
214
238
|
|
|
215
|
-
|
|
239
|
+
// Helper to clean up resources and prevent multiple resolutions
|
|
240
|
+
const cleanup = () => {
|
|
241
|
+
if (timeoutHandle) {
|
|
242
|
+
clearTimeout(timeoutHandle);
|
|
243
|
+
timeoutHandle = null;
|
|
244
|
+
}
|
|
216
245
|
if (subscription) {
|
|
217
246
|
this._channelEmitter.removeListener(channel, subscription);
|
|
247
|
+
subscription = null;
|
|
218
248
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
// Set up timeout handler
|
|
252
|
+
timeoutHandle = setTimeout(async () => {
|
|
253
|
+
if (isResolved) return;
|
|
254
|
+
isResolved = true;
|
|
255
|
+
|
|
256
|
+
cleanup();
|
|
257
|
+
await unsubscribeFromRedis('timeout');
|
|
258
|
+
|
|
259
|
+
const errMessage = `Subscription timeout after ${requestProcessingTimeoutSeconds}s`;
|
|
260
|
+
this._logger.push({ channel, timeout: requestProcessingTimeoutSeconds }).warn(errMessage);
|
|
227
261
|
reject(new TimeoutError(errMessage));
|
|
228
262
|
}, requestProcessingTimeoutSeconds * 1000);
|
|
229
263
|
|
|
264
|
+
// Set up message handler
|
|
230
265
|
subscription = (message) => {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
266
|
+
if (isResolved) return;
|
|
267
|
+
isResolved = true;
|
|
268
|
+
|
|
269
|
+
this._logger.push({ channel, needParse }).debug('Received message on subscribed channel');
|
|
270
|
+
|
|
271
|
+
cleanup();
|
|
272
|
+
|
|
273
|
+
try {
|
|
274
|
+
const result = needParse ? JSON.parse(message) : message;
|
|
275
|
+
resolve(result);
|
|
276
|
+
} catch (parseErr) {
|
|
277
|
+
this._logger.push({ channel, message }).error('Failed to parse received message', parseErr);
|
|
278
|
+
reject(parseErr);
|
|
279
|
+
}
|
|
234
280
|
};
|
|
281
|
+
|
|
282
|
+
// Register the one-time listener
|
|
235
283
|
this._channelEmitter.once(channel, subscription);
|
|
236
284
|
|
|
237
|
-
|
|
285
|
+
// Subscribe to Redis channel
|
|
286
|
+
this._subscriptionClient.subscribe(channel, (msg) => {
|
|
238
287
|
this._channelEmitter.emit(channel, msg);
|
|
239
|
-
|
|
240
|
-
if
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
}
|
|
288
|
+
|
|
289
|
+
// Auto-unsubscribe if no more listeners
|
|
290
|
+
unsubscribeFromRedis('auto-cleanup').catch(err => {
|
|
291
|
+
this._logger.push({ channel }).warn('Auto-unsubscribe failed', err);
|
|
292
|
+
});
|
|
245
293
|
})
|
|
246
|
-
.catch(
|
|
247
|
-
|
|
248
|
-
|
|
294
|
+
.catch(subscribeErr => {
|
|
295
|
+
if (isResolved) return;
|
|
296
|
+
isResolved = true;
|
|
297
|
+
|
|
298
|
+
cleanup();
|
|
299
|
+
this._logger.push({ channel }).error('Failed to subscribe to Redis channel', subscribeErr);
|
|
300
|
+
reject(subscribeErr);
|
|
249
301
|
});
|
|
250
302
|
});
|
|
251
303
|
}
|
|
@@ -340,7 +340,7 @@ class OutboundTransfersModel {
|
|
|
340
340
|
this.data.getPartiesRequest = res.originalRequest;
|
|
341
341
|
|
|
342
342
|
this.metrics.partyLookupRequests.inc();
|
|
343
|
-
this._logger.
|
|
343
|
+
this._logger.push({ peer: res }).debug('Party lookup sent to peer');
|
|
344
344
|
|
|
345
345
|
const message = await subscribing;
|
|
346
346
|
|
|
@@ -365,7 +365,7 @@ class OutboundTransfersModel {
|
|
|
365
365
|
|
|
366
366
|
payee = payee.party;
|
|
367
367
|
|
|
368
|
-
this._logger.
|
|
368
|
+
this._logger.push({ payee }).verbose('Payee resolved');
|
|
369
369
|
|
|
370
370
|
// check we got the right payee and info we need
|
|
371
371
|
if(payee.partyIdInfo.partyIdType !== this.data.to.idType) {
|
|
@@ -412,7 +412,7 @@ class OutboundTransfersModel {
|
|
|
412
412
|
this.data.supportedCurrencies = payee.supportedCurrencies;
|
|
413
413
|
}
|
|
414
414
|
|
|
415
|
-
this._logger.
|
|
415
|
+
this._logger.push({
|
|
416
416
|
transferId: this.data.transferId,
|
|
417
417
|
homeTransactionId: this.data.homeTransactionId,
|
|
418
418
|
needFx: this.data.needFx,
|
|
@@ -421,7 +421,7 @@ class OutboundTransfersModel {
|
|
|
421
421
|
return resolve(payee);
|
|
422
422
|
}
|
|
423
423
|
catch(err) {
|
|
424
|
-
this._logger.
|
|
424
|
+
this._logger.error(`Error in resolvePayee ${payeeKey}:`, err);
|
|
425
425
|
// If type of error is BackendError, it will be handled by the state machine
|
|
426
426
|
if (err instanceof BackendError) {
|
|
427
427
|
this.data.lastError = err;
|
|
@@ -210,4 +210,154 @@ describe('Cache Tests -->', () => {
|
|
|
210
210
|
expect(result).toEqual(error);
|
|
211
211
|
expect(unsubscribeSpy).not.toHaveBeenCalled();
|
|
212
212
|
});
|
|
213
|
+
|
|
214
|
+
test('subscribeToOneMessageWithTimerNew should resolve with parsed message when received before timeout', async () => {
|
|
215
|
+
const channel = `ch-${randomUUID()}`;
|
|
216
|
+
const message = { id: randomUUID(), data: 'test-data' };
|
|
217
|
+
const requestProcessingTimeoutSeconds = 1;
|
|
218
|
+
|
|
219
|
+
const subscribing = cache.subscribeToOneMessageWithTimerNew(channel, requestProcessingTimeoutSeconds);
|
|
220
|
+
|
|
221
|
+
// Simulate a message being published to the channel via EventEmitter
|
|
222
|
+
setTimeout(() => {
|
|
223
|
+
cache._channelEmitter.emit(channel, JSON.stringify(message));
|
|
224
|
+
}, 100);
|
|
225
|
+
|
|
226
|
+
const result = await subscribing;
|
|
227
|
+
expect(result).toStrictEqual(message);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
test('subscribeToOneMessageWithTimerNew should resolve with unparsed message when needParse is false', async () => {
|
|
231
|
+
const channel = `ch-${randomUUID()}`;
|
|
232
|
+
const message = 'raw-string-message';
|
|
233
|
+
const requestProcessingTimeoutSeconds = 1;
|
|
234
|
+
|
|
235
|
+
const subscribing = cache.subscribeToOneMessageWithTimerNew(channel, requestProcessingTimeoutSeconds, false);
|
|
236
|
+
|
|
237
|
+
// Simulate a message being published to the channel via EventEmitter
|
|
238
|
+
setTimeout(() => {
|
|
239
|
+
cache._channelEmitter.emit(channel, message);
|
|
240
|
+
}, 100);
|
|
241
|
+
|
|
242
|
+
const result = await subscribing;
|
|
243
|
+
expect(result).toBe(message);
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
test('subscribeToOneMessageWithTimerNew should reject with TimeoutError when no message received within timeout', async () => {
|
|
247
|
+
const channel = `ch-${randomUUID()}`;
|
|
248
|
+
const requestProcessingTimeoutSeconds = 0.1; // 100ms timeout
|
|
249
|
+
|
|
250
|
+
const subscribing = cache.subscribeToOneMessageWithTimerNew(channel, requestProcessingTimeoutSeconds);
|
|
251
|
+
|
|
252
|
+
await expect(subscribing).rejects.toThrow(`Subscription timeout after ${requestProcessingTimeoutSeconds}s`);
|
|
253
|
+
|
|
254
|
+
// Test that it's a TimeoutError instance
|
|
255
|
+
try {
|
|
256
|
+
await subscribing;
|
|
257
|
+
expect(true).toBe(false); // Should not reach here
|
|
258
|
+
} catch (error) {
|
|
259
|
+
expect(error.constructor.name).toBe('TimeoutError');
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
test('subscribeToOneMessageWithTimerNew should reject when JSON parsing fails', async () => {
|
|
264
|
+
const channel = `ch-${randomUUID()}`;
|
|
265
|
+
const invalidJson = '{ invalid json }';
|
|
266
|
+
const requestProcessingTimeoutSeconds = 1;
|
|
267
|
+
|
|
268
|
+
const subscribing = cache.subscribeToOneMessageWithTimerNew(channel, requestProcessingTimeoutSeconds, true);
|
|
269
|
+
|
|
270
|
+
// Simulate a message with invalid JSON
|
|
271
|
+
setTimeout(() => {
|
|
272
|
+
cache._channelEmitter.emit(channel, invalidJson);
|
|
273
|
+
}, 100);
|
|
274
|
+
|
|
275
|
+
await expect(subscribing).rejects.toThrow();
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
test('subscribeToOneMessageWithTimerNew should handle multiple subscribers to same channel', async () => {
|
|
279
|
+
const channel1 = `ch-${randomUUID()}`;
|
|
280
|
+
const channel2 = `ch-${randomUUID()}`;
|
|
281
|
+
const message1 = { id: 'msg1', data: 'test1' };
|
|
282
|
+
const message2 = { id: 'msg2', data: 'test2' };
|
|
283
|
+
const requestProcessingTimeoutSeconds = 1;
|
|
284
|
+
|
|
285
|
+
// Create two subscriptions to different channels to avoid interference
|
|
286
|
+
const subscribing1 = cache.subscribeToOneMessageWithTimerNew(channel1, requestProcessingTimeoutSeconds);
|
|
287
|
+
const subscribing2 = cache.subscribeToOneMessageWithTimerNew(channel2, requestProcessingTimeoutSeconds);
|
|
288
|
+
|
|
289
|
+
// Emit messages to each channel separately
|
|
290
|
+
setTimeout(() => {
|
|
291
|
+
cache._channelEmitter.emit(channel1, JSON.stringify(message1));
|
|
292
|
+
cache._channelEmitter.emit(channel2, JSON.stringify(message2));
|
|
293
|
+
}, 100);
|
|
294
|
+
|
|
295
|
+
// Both should resolve with their respective messages
|
|
296
|
+
const results = await Promise.all([subscribing1, subscribing2]);
|
|
297
|
+
expect(results[0]).toStrictEqual(message1);
|
|
298
|
+
expect(results[1]).toStrictEqual(message2);
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
test('subscribeToOneMessageWithTimerNew should handle concurrent subscribers to same channel (party lookup scenario)', async () => {
|
|
302
|
+
const channel = `party-lookup-${randomUUID()}`;
|
|
303
|
+
const partyResponse = { party: { partyIdInfo: { partyIdType: 'MSISDN', partyIdentifier: '123456789' }}};
|
|
304
|
+
const requestProcessingTimeoutSeconds = 1;
|
|
305
|
+
|
|
306
|
+
// Create multiple concurrent subscriptions to same channel (simulating concurrent party lookups)
|
|
307
|
+
const subscribing1 = cache.subscribeToOneMessageWithTimerNew(channel, requestProcessingTimeoutSeconds);
|
|
308
|
+
const subscribing2 = cache.subscribeToOneMessageWithTimerNew(channel, requestProcessingTimeoutSeconds);
|
|
309
|
+
const subscribing3 = cache.subscribeToOneMessageWithTimerNew(channel, requestProcessingTimeoutSeconds);
|
|
310
|
+
|
|
311
|
+
// Simulate a single party response that should resolve all subscribers
|
|
312
|
+
setTimeout(() => {
|
|
313
|
+
cache._channelEmitter.emit(channel, JSON.stringify(partyResponse));
|
|
314
|
+
}, 100);
|
|
315
|
+
|
|
316
|
+
// All subscribers should resolve with the same party response
|
|
317
|
+
const results = await Promise.all([subscribing1, subscribing2, subscribing3]);
|
|
318
|
+
expect(results[0]).toStrictEqual(partyResponse);
|
|
319
|
+
expect(results[1]).toStrictEqual(partyResponse);
|
|
320
|
+
expect(results[2]).toStrictEqual(partyResponse);
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
test('subscribeToOneMessageWithTimerNew should clean up resources on timeout', async () => {
|
|
324
|
+
const channel = `ch-${randomUUID()}`;
|
|
325
|
+
const requestProcessingTimeoutSeconds = 0.1;
|
|
326
|
+
|
|
327
|
+
const removeListenerSpy = jest.spyOn(cache._channelEmitter, 'removeListener');
|
|
328
|
+
|
|
329
|
+
const subscribing = cache.subscribeToOneMessageWithTimerNew(channel, requestProcessingTimeoutSeconds);
|
|
330
|
+
|
|
331
|
+
await expect(subscribing).rejects.toThrow(`Subscription timeout after ${requestProcessingTimeoutSeconds}s`);
|
|
332
|
+
|
|
333
|
+
// Test that it's a TimeoutError instance
|
|
334
|
+
try {
|
|
335
|
+
await subscribing;
|
|
336
|
+
expect(true).toBe(false); // Should not reach here
|
|
337
|
+
} catch (error) {
|
|
338
|
+
expect(error.constructor.name).toBe('TimeoutError');
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Verify cleanup was called
|
|
342
|
+
expect(removeListenerSpy).toHaveBeenCalledWith(channel, expect.any(Function));
|
|
343
|
+
|
|
344
|
+
removeListenerSpy.mockRestore();
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
test('subscribeToOneMessageWithTimerNew should reject when subscription fails', async () => {
|
|
348
|
+
const channel = `ch-${randomUUID()}`;
|
|
349
|
+
const requestProcessingTimeoutSeconds = 1;
|
|
350
|
+
const subscriptionError = new Error('subscription failed');
|
|
351
|
+
|
|
352
|
+
// Mock the _subscriptionClient.subscribe to reject
|
|
353
|
+
const originalSubscribe = cache._subscriptionClient.subscribe;
|
|
354
|
+
cache._subscriptionClient.subscribe = jest.fn().mockRejectedValue(subscriptionError);
|
|
355
|
+
|
|
356
|
+
const subscribing = cache.subscribeToOneMessageWithTimerNew(channel, requestProcessingTimeoutSeconds);
|
|
357
|
+
|
|
358
|
+
await expect(subscribing).rejects.toThrow('subscription failed');
|
|
359
|
+
|
|
360
|
+
// Restore original method
|
|
361
|
+
cache._subscriptionClient.subscribe = originalSubscribe;
|
|
362
|
+
});
|
|
213
363
|
});
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@mojaloop/api-snippets": "18.1.1",
|
|
45
|
-
"@mojaloop/central-services-shared": "18.30.
|
|
45
|
+
"@mojaloop/central-services-shared": "18.30.7",
|
|
46
46
|
"@mojaloop/logging-bc-client-lib": "0.5.8",
|
|
47
47
|
"@mojaloop/logging-bc-public-types-lib": "0.5.6",
|
|
48
48
|
"@mojaloop/sdk-scheme-adapter-private-shared-lib": "workspace:^",
|
|
@@ -56,11 +56,11 @@
|
|
|
56
56
|
"yamljs": "0.3.0"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
|
-
"@eslint/compat": "1.3.
|
|
59
|
+
"@eslint/compat": "1.3.2",
|
|
60
60
|
"@types/convict": "6.1.6",
|
|
61
61
|
"@types/express": "5.0.3",
|
|
62
62
|
"@types/jest": "30.0.0",
|
|
63
|
-
"@types/node": "24.2.
|
|
63
|
+
"@types/node": "24.2.1",
|
|
64
64
|
"@types/node-cache": "4.2.5",
|
|
65
65
|
"@types/supertest": "6.0.3",
|
|
66
66
|
"@types/swagger-ui-express": "4.1.8",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@mojaloop/api-snippets": "18.1.1",
|
|
33
|
-
"@mojaloop/central-services-shared": "18.30.
|
|
33
|
+
"@mojaloop/central-services-shared": "18.30.7",
|
|
34
34
|
"@mojaloop/logging-bc-public-types-lib": "0.5.6",
|
|
35
35
|
"@mojaloop/platform-shared-lib-messaging-types-lib": "0.7.3",
|
|
36
36
|
"@mojaloop/platform-shared-lib-nodejs-kafka-client-lib": "0.5.18",
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"uuid": "11.1.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@eslint/compat": "1.3.
|
|
43
|
-
"@types/node": "24.2.
|
|
42
|
+
"@eslint/compat": "1.3.2",
|
|
43
|
+
"@types/node": "24.2.1",
|
|
44
44
|
"@types/uuid": "10.0.0",
|
|
45
45
|
"@typescript-eslint/eslint-plugin": "8.39.0",
|
|
46
46
|
"@typescript-eslint/parser": "8.39.0",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mojaloop/sdk-scheme-adapter",
|
|
3
|
-
"version": "24.10.
|
|
3
|
+
"version": "24.10.8",
|
|
4
4
|
"description": "mojaloop sdk-scheme-adapter",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://github.com/mojaloop/sdk-scheme-adapter",
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
},
|
|
83
83
|
"devDependencies": {
|
|
84
84
|
"@types/jest": "30.0.0",
|
|
85
|
-
"@types/node": "24.2.
|
|
85
|
+
"@types/node": "24.2.1",
|
|
86
86
|
"@types/node-cache": "4.2.5",
|
|
87
87
|
"@typescript-eslint/eslint-plugin": "8.39.0",
|
|
88
88
|
"@typescript-eslint/parser": "8.39.0",
|