Skip to content

Commit 47fb92a

Browse files
author
arthosofteq
authored
Merge pull request #2215 from RedisInsight/be/bugfix/RI-4658-cloud-discovery-timeout
#RI-4658 fix connection issue + set up cloud timeouts
2 parents 8a71fc9 + 8f70dc0 commit 47fb92a

File tree

6 files changed

+27
-6
lines changed

6 files changed

+27
-6
lines changed

redisinsight/api/config/default.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ export default {
7474
},
7575
redis_cloud: {
7676
url: process.env.REDIS_CLOUD_URL || 'https://api-cloudapi.qa.redislabs.com/v1',
77+
cloudDiscoveryTimeout: parseInt(process.env.RI_CLOUD_DISCOVERY_TIMEOUT, 10) || 60 * 1000, // 1 min
78+
cloudDatabaseConnectionTimeout: parseInt(process.env.RI_CLOUD_DATABASE_CONNECTION_TIMEOUT, 10) || 30 * 1000,
7779
},
7880
redis_clients: {
7981
idleSyncInterval: parseInt(process.env.CLIENTS_IDLE_SYNC_INTERVAL, 10) || 1000 * 60 * 60, // 1hr

redisinsight/api/src/common/interceptors/timeout.interceptor.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,16 @@ export class TimeoutInterceptor implements NestInterceptor {
1818

1919
private readonly message: string;
2020

21-
constructor(message: string = 'Request timeout') {
21+
private readonly timeout: number;
22+
23+
constructor(message: string = 'Request timeout', timeoutMs?: number) {
2224
this.message = message;
25+
this.timeout = timeoutMs ?? serverConfig.requestTimeout;
2326
}
2427

2528
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
2629
return next.handle().pipe(
27-
timeout(serverConfig.requestTimeout),
30+
timeout(this.timeout),
2831
catchError((err) => {
2932
if (err instanceof TimeoutError) {
3033
const { method, url } = context.switchToHttp().getRequest();

redisinsight/api/src/constants/error-messages.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export default {
1515
WRONG_DATABASE_TYPE: 'Wrong database type.',
1616
CONNECTION_TIMEOUT:
1717
'The connection has timed out, please check the connection details.',
18+
SERVER_CLOSED_CONNECTION: 'Server closed the connection.',
1819
AUTHENTICATION_FAILED: () => 'Failed to authenticate, please check the username or password.',
1920
INCORRECT_DATABASE_URL: (url) => `Could not connect to ${url}, please check the connection details.`,
2021
INCORRECT_CERTIFICATES: (url) => `Could not connect to ${url}, please check the CA or Client certificate.`,

redisinsight/api/src/modules/cloud/autodiscovery/cloud-autodiscovery.service.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,7 @@ export class CloudAutodiscoveryService {
306306
password,
307307
provider: HostingProvider.RE_CLOUD,
308308
cloudDetails: database?.cloudDetails,
309+
timeout: this.config.cloudDatabaseConnectionTimeout,
309310
});
310311

311312
return {

redisinsight/api/src/modules/cloud/autodiscovery/cloud.autodiscovery.controller.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ import {
2222
GetCloudDatabasesDto,
2323
} from 'src/modules/cloud/autodiscovery/dto';
2424
import { CloudAuthHeaders } from 'src/modules/cloud/autodiscovery/decorators/cloud-auth.decorator';
25+
import config from 'src/utils/config';
26+
27+
const cloudConf = config.get('redis_cloud');
2528

2629
@ApiTags('Cloud Autodiscovery')
2730
@ApiHeaders([{
@@ -30,12 +33,12 @@ import { CloudAuthHeaders } from 'src/modules/cloud/autodiscovery/decorators/clo
3033
name: 'x-cloud-api-secret',
3134
}])
3235
@UsePipes(new ValidationPipe({ transform: true }))
36+
@UseInterceptors(new TimeoutInterceptor(undefined, cloudConf.cloudDiscoveryTimeout))
3337
@Controller('cloud/autodiscovery')
3438
export class CloudAutodiscoveryController {
3539
constructor(private service: CloudAutodiscoveryService) {}
3640

3741
@Get('account')
38-
@UseInterceptors(new TimeoutInterceptor())
3942
@ApiEndpoint({
4043
description: 'Get current account',
4144
statusCode: 200,
@@ -53,7 +56,6 @@ export class CloudAutodiscoveryController {
5356
}
5457

5558
@Get('subscriptions')
56-
@UseInterceptors(new TimeoutInterceptor())
5759
@ApiEndpoint({
5860
description: 'Get information about current account’s subscriptions.',
5961
statusCode: 200,
@@ -107,7 +109,6 @@ export class CloudAutodiscoveryController {
107109
},
108110
],
109111
})
110-
@UsePipes(new ValidationPipe({ transform: true }))
111112
async addRedisCloudDatabases(
112113
@CloudAuthHeaders() authDto: CloudAuthDto,
113114
@Body() dto: AddCloudDatabasesDto,

redisinsight/api/src/modules/redis/redis-connection.factory.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import Redis, { Cluster, RedisOptions } from 'ioredis';
2-
import { Injectable, Logger } from '@nestjs/common';
2+
import { Injectable, InternalServerErrorException, Logger } from '@nestjs/common';
33
import { Database } from 'src/modules/database/models/database';
44
import apiConfig from 'src/utils/config';
55
import { ConnectionOptions } from 'tls';
@@ -10,6 +10,7 @@ import { ClientMetadata } from 'src/common/models';
1010
import { ClusterOptions } from 'ioredis/built/cluster/ClusterOptions';
1111
import { SshTunnelProvider } from 'src/modules/ssh/ssh-tunnel.provider';
1212
import { TunnelConnectionLostException } from 'src/modules/ssh/exceptions';
13+
import ERROR_MESSAGES from 'src/constants/error-messages';
1314

1415
const REDIS_CLIENTS_CONFIG = apiConfig.get('redis_clients');
1516

@@ -195,6 +196,10 @@ export class RedisConnectionFactory {
195196
this.logger.error('Failed connection to the redis database.', e);
196197
reject(e);
197198
});
199+
connection.on('end', (): void => {
200+
this.logger.error(ERROR_MESSAGES.SERVER_CLOSED_CONNECTION);
201+
reject(new InternalServerErrorException(ERROR_MESSAGES.SERVER_CLOSED_CONNECTION));
202+
});
198203
connection.on('ready', (): void => {
199204
this.logger.log('Successfully connected to the redis database');
200205
resolve(connection);
@@ -241,6 +246,10 @@ export class RedisConnectionFactory {
241246
this.logger.error('Failed connection to the redis oss cluster', e);
242247
reject(!isEmpty(e.lastNodeError) ? e.lastNodeError : e);
243248
});
249+
cluster.on('end', (): void => {
250+
this.logger.error(ERROR_MESSAGES.SERVER_CLOSED_CONNECTION);
251+
reject(new InternalServerErrorException(ERROR_MESSAGES.SERVER_CLOSED_CONNECTION));
252+
});
244253
cluster.on('ready', (): void => {
245254
this.logger.log('Successfully connected to the redis oss cluster.');
246255
resolve(cluster);
@@ -271,6 +280,10 @@ export class RedisConnectionFactory {
271280
this.logger.error('Failed connection to the redis oss sentinel', e);
272281
reject(e);
273282
});
283+
client.on('end', (): void => {
284+
this.logger.error(ERROR_MESSAGES.SERVER_CLOSED_CONNECTION);
285+
reject(new InternalServerErrorException(ERROR_MESSAGES.SERVER_CLOSED_CONNECTION));
286+
});
274287
client.on('ready', (): void => {
275288
this.logger.log('Successfully connected to the redis oss sentinel.');
276289
resolve(client);

0 commit comments

Comments
 (0)