Skip to content

Commit 70c2306

Browse files
authored
RI-7659: Enhance RDI connection testing with per-source error handling (#5123)
1 parent 511bc92 commit 70c2306

File tree

2 files changed

+139
-30
lines changed

2 files changed

+139
-30
lines changed

redisinsight/api/src/modules/rdi/client/api.rdi.client.spec.ts

Lines changed: 106 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ const createMockPostImplementation = (
4545
};
4646
};
4747

48+
const axiosError = (status: number, message = 'Request failed') => ({
49+
isAxiosError: true,
50+
message,
51+
status,
52+
});
53+
4854
describe('ApiRdiClient', () => {
4955
let client: ApiRdiClient;
5056

@@ -432,7 +438,7 @@ describe('ApiRdiClient', () => {
432438
);
433439
});
434440

435-
it('should return targets data even if TestSourcesConnections fails', async () => {
441+
it('should return targets when single source test fails', async () => {
436442
const expectedTargetsResponse = {
437443
targets: { target1: { status: 'success' } },
438444
};
@@ -453,19 +459,19 @@ describe('ApiRdiClient', () => {
453459

454460
expect(response).toEqual({
455461
targets: expectedTargetsResponse.targets,
456-
sources: {},
462+
sources: {
463+
source1: {
464+
connected: false,
465+
error: 'Failed to test source connection.',
466+
},
467+
},
457468
});
458469

459470
expect(mockedAxios.post).toHaveBeenCalledTimes(2);
460-
461-
expect(loggerErrorSpy).toHaveBeenCalledWith(
462-
'Failed to fetch sources',
463-
expect.any(Error),
464-
);
465471
loggerErrorSpy.mockRestore();
466472
});
467473

468-
it('should return targets data even if TestSourcesConnections fails, asd', async () => {
474+
it('should return targets when one of multiple source tests fails', async () => {
469475
const expectedTargetsResponse = {
470476
targets: { target1: { status: 'success' } },
471477
};
@@ -496,17 +502,104 @@ describe('ApiRdiClient', () => {
496502
targets: expectedTargetsResponse.targets,
497503
sources: {
498504
source1: { connected: true, error: '' },
505+
source2: {
506+
connected: false,
507+
error: 'Failed to test source connection.',
508+
},
499509
},
500510
});
501511

502512
expect(mockedAxios.post).toHaveBeenCalledTimes(3);
503-
504-
expect(loggerErrorSpy).toHaveBeenCalledWith(
505-
'Failed to fetch sources',
506-
expect.any(Error),
507-
);
508513
loggerErrorSpy.mockRestore();
509514
});
515+
516+
it('should map 405 to the friendly message for a single source', async () => {
517+
const expectedTargetsResponse = {
518+
targets: { target1: { status: 'success' } },
519+
};
520+
521+
mockedAxios.post
522+
.mockResolvedValueOnce({ data: expectedTargetsResponse }) // TestTargetsConnections
523+
.mockRejectedValueOnce(axiosError(405)); // TestSourcesConnections
524+
525+
const response = await client.testConnections({
526+
sources: { source1: {} },
527+
});
528+
529+
expect(response).toEqual({
530+
targets: expectedTargetsResponse.targets,
531+
sources: {
532+
source1: {
533+
connected: false,
534+
error:
535+
'Testing source connections is not supported in your RDI version. Please upgrade to version 1.6.0 or later.',
536+
},
537+
},
538+
});
539+
540+
expect(mockedAxios.post).toHaveBeenCalledTimes(2);
541+
});
542+
543+
it('should map the 405 only to the failing source among multiple sources', async () => {
544+
const expectedTargetsResponse = {
545+
targets: { target1: { status: 'success' } },
546+
};
547+
548+
mockedAxios.post
549+
.mockResolvedValueOnce({ data: expectedTargetsResponse }) // TestTargetsConnections
550+
.mockResolvedValueOnce({ data: { connected: true, error: '' } }) // source1 OK
551+
.mockRejectedValueOnce(axiosError(405)); // source2 405
552+
553+
const response = await client.testConnections({
554+
sources: { source1: {}, source2: {} },
555+
});
556+
557+
expect(response).toEqual({
558+
targets: expectedTargetsResponse.targets,
559+
sources: {
560+
source1: { connected: true, error: '' },
561+
source2: {
562+
connected: false,
563+
error:
564+
'Testing source connections is not supported in your RDI version. Please upgrade to version 1.6.0 or later.',
565+
},
566+
},
567+
});
568+
569+
expect(mockedAxios.post).toHaveBeenCalledTimes(3);
570+
});
571+
572+
it('should handle mixed non-405 and 405 source failures', async () => {
573+
const expectedTargetsResponse = {
574+
targets: { target1: { status: 'success' } },
575+
};
576+
577+
mockedAxios.post
578+
.mockResolvedValueOnce({ data: expectedTargetsResponse }) // targets
579+
.mockRejectedValueOnce(axiosError(500, 'Internal error')) // source1 500
580+
.mockRejectedValueOnce(axiosError(405)); // source2 405
581+
582+
const response = await client.testConnections({
583+
sources: { source1: {}, source2: {} },
584+
});
585+
586+
expect(response).toEqual({
587+
targets: expectedTargetsResponse.targets,
588+
sources: {
589+
source1: {
590+
connected: false,
591+
error: 'Failed to test source connection.',
592+
},
593+
source2: {
594+
connected: false,
595+
error:
596+
'Testing source connections is not supported in your RDI version. Please upgrade to version 1.6.0 or later.',
597+
},
598+
},
599+
});
600+
601+
expect(mockedAxios.post).toHaveBeenCalledTimes(3);
602+
});
510603
});
511604

512605
describe('getPipelineStatus', () => {

redisinsight/api/src/modules/rdi/client/api.rdi.client.ts

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -225,25 +225,41 @@ export class ApiRdiClient extends RdiClient {
225225
throw wrapRdiPipelineError(error);
226226
}
227227

228-
try {
229-
const sourceConfigs = Object.keys(config.sources || {});
230-
231-
if (sourceConfigs.length) {
232-
await Promise.all(
233-
sourceConfigs.map(async (source) => {
234-
const response = await this.client.post(
235-
RdiUrl.TestSourcesConnections,
236-
{ ...config.sources[source] },
237-
);
238-
sources[source] = response.data;
239-
}),
240-
);
241-
}
242-
} catch (error) {
243-
// failing is expected on RDI version below 1.6.0 (1.4.3 for example)
244-
this.logger.error('Failed to fetch sources', error);
228+
const sourceConfigs = Object.keys(config.sources || {});
229+
230+
if (sourceConfigs.length === 0) {
231+
return { targets, sources };
245232
}
246233

234+
await Promise.all(
235+
sourceConfigs.map(async (source) => {
236+
try {
237+
const response = await this.client.post(
238+
RdiUrl.TestSourcesConnections,
239+
{ ...config.sources[source] },
240+
);
241+
sources[source] = response.data;
242+
} catch (error: any) {
243+
// Older versions of RDI (below 1.6.0) don't support testing sources connections
244+
// RDI returns 405 Method Not Allowed for non existing endpoints
245+
const status = error?.status;
246+
if (status === 405) {
247+
sources[source] = {
248+
connected: false,
249+
error:
250+
'Testing source connections is not supported in your RDI version. Please upgrade to version 1.6.0 or later.',
251+
};
252+
} else {
253+
// Something went wrong with testing source connection
254+
sources[source] = {
255+
connected: false,
256+
error: 'Failed to test source connection.',
257+
};
258+
}
259+
}
260+
}),
261+
);
262+
247263
return { targets, sources };
248264
}
249265

0 commit comments

Comments
 (0)