Skip to content

Commit 3c969a7

Browse files
authored
Merge pull request #1427 from RedisInsight/bugfix/regresion-fixes
Bugfix/regresion fixes
2 parents 70d6e4f + 028f47f commit 3c969a7

35 files changed

+444
-199
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export class TimeoutInterceptor implements NestInterceptor {
1818

1919
private readonly message: string;
2020

21-
constructor(message?: string) {
21+
constructor(message: string = 'Request timeout') {
2222
this.message = message;
2323
}
2424

redisinsight/api/src/constants/telemetry-events.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,5 @@ export enum CommandType {
6161
Core = 'core',
6262
Module = 'module',
6363
}
64+
65+
export const unknownCommand = 'unknown';

redisinsight/api/src/modules/analytics/telemetry.base.service.spec.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ describe('TelemetryBaseService', () => {
3333

3434
describe('sendEvent', () => {
3535
it('should emit event', () => {
36-
service.sendEvent(TelemetryEvents.RedisInstanceAdded, { data: 'Some data' });
36+
service.sendEvent(TelemetryEvents.RedisInstanceAdded, { data: 'Some data', command: 'lowercase' });
3737

3838
expect(eventEmitter.emit).toHaveBeenCalledWith(AppAnalyticsEvents.Track, {
3939
event: TelemetryEvents.RedisInstanceAdded,
40-
eventData: { data: 'Some data' },
40+
eventData: { data: 'Some data', command: 'LOWERCASE' },
4141
});
4242
});
4343
it('should emit event with empty event data', () => {
@@ -87,13 +87,18 @@ describe('TelemetryBaseService', () => {
8787
});
8888
});
8989
it('should emit event with additional event data', () => {
90-
service.sendFailedEvent(TelemetryEvents.RedisInstanceAddFailed, httpException, { data: 'Some data' });
90+
service.sendFailedEvent(
91+
TelemetryEvents.RedisInstanceAddFailed,
92+
httpException,
93+
{ data: 'Some data', command: 'lowercase' },
94+
);
9195

9296
expect(eventEmitter.emit).toHaveBeenCalledWith(AppAnalyticsEvents.Track, {
9397
event: TelemetryEvents.RedisInstanceAddFailed,
9498
eventData: {
9599
error: 'Internal Server Error',
96100
data: 'Some data',
101+
command: 'LOWERCASE',
97102
},
98103
});
99104
});

redisinsight/api/src/modules/analytics/telemetry.base.service.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { isString } from 'lodash';
12
import { EventEmitter2 } from '@nestjs/event-emitter';
23
import { HttpException } from '@nestjs/common';
34
import { AppAnalyticsEvents } from 'src/constants';
@@ -13,7 +14,10 @@ export abstract class TelemetryBaseService {
1314
try {
1415
this.eventEmitter.emit(AppAnalyticsEvents.Track, {
1516
event,
16-
eventData,
17+
eventData: {
18+
...eventData,
19+
command: isString(eventData['command']) ? eventData['command'].toUpperCase() : eventData['command'],
20+
},
1721
});
1822
} catch (e) {
1923
// continue regardless of error
@@ -27,6 +31,7 @@ export abstract class TelemetryBaseService {
2731
eventData: {
2832
error: exception.getResponse()['error'] || exception.message,
2933
...eventData,
34+
command: isString(eventData['command']) ? eventData['command'].toUpperCase() : eventData['command'],
3035
},
3136
});
3237
} catch (e) {

redisinsight/api/src/modules/browser/services/keys-business/scanner/strategies/cluster.strategy.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -943,7 +943,7 @@ describe('Cluster Scanner Strategy', () => {
943943
scanned: 10,
944944
},
945945
]);
946-
expect(strategy.getKeyInfo).toHaveBeenCalledWith(clusterClient, key);
946+
expect(strategy.getKeyInfo).toHaveBeenCalledWith(clusterClient, Buffer.from(key));
947947
expect(strategy.scanNodes).not.toHaveBeenCalled();
948948
});
949949
it('should find exact key when match is escaped glob patter', async () => {
@@ -973,7 +973,7 @@ describe('Cluster Scanner Strategy', () => {
973973
scanned: 10,
974974
},
975975
]);
976-
expect(strategy.getKeyInfo).toHaveBeenCalledWith(clusterClient, searchPattern);
976+
expect(strategy.getKeyInfo).toHaveBeenCalledWith(clusterClient, Buffer.from(searchPattern));
977977
expect(strategy.scanNodes).not.toHaveBeenCalled();
978978
});
979979
it('should find exact key with correct type', async () => {

redisinsight/api/src/modules/browser/services/keys-business/scanner/strategies/cluster.strategy.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export class ClusterStrategy extends AbstractStrategy {
4949
await this.calculateNodesTotalKeys(clientOptions, currentDbIndex, nodes);
5050

5151
if (!isGlob(match, { strict: false })) {
52-
const keyName = unescapeGlob(match);
52+
const keyName = Buffer.from(unescapeGlob(match));
5353
nodes.forEach((node) => {
5454
// eslint-disable-next-line no-param-reassign
5555
node.cursor = 0;

redisinsight/api/src/modules/browser/services/keys-business/scanner/strategies/standalone.strategy.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ describe('Standalone Scanner Strategy', () => {
476476
},
477477
]);
478478
expect(strategy.getKeysInfo).toHaveBeenCalledWith(nodeClient, [
479-
key,
479+
Buffer.from(key),
480480
]);
481481
expect(strategy.scan).not.toHaveBeenCalled();
482482
});
@@ -497,7 +497,7 @@ describe('Standalone Scanner Strategy', () => {
497497
keys: [{ ...getKeyInfoResponse, name: mockSearchPattern }],
498498
},
499499
]);
500-
expect(strategy.getKeysInfo).toHaveBeenCalledWith(nodeClient, [mockSearchPattern]);
500+
expect(strategy.getKeysInfo).toHaveBeenCalledWith(nodeClient, [Buffer.from(mockSearchPattern)]);
501501
expect(strategy.scan).not.toHaveBeenCalled();
502502
});
503503
it('should find exact key with correct type', async () => {

redisinsight/api/src/modules/browser/services/keys-business/scanner/strategies/standalone.strategy.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export class StandaloneStrategy extends AbstractStrategy {
6262
}
6363

6464
if (!isGlob(match, { strict: false })) {
65-
const keyName = unescapeGlob(match);
65+
const keyName = Buffer.from(unescapeGlob(match));
6666
node.cursor = 0;
6767
node.scanned = isNull(node.total) ? 1 : node.total;
6868
node.keys = await this.getKeysInfo(client, [keyName]);

redisinsight/api/src/modules/browser/services/redisearch/redisearch.service.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ describe('RedisearchService', () => {
240240
'LIMIT', `${mockSearchRedisearchDto.offset}`, `${mockSearchRedisearchDto.limit}`,
241241
],
242242
}));
243-
expect(nodeClient.sendCommand).toHaveBeenCalledWith(jasmine.objectContaining( {
243+
expect(nodeClient.sendCommand).toHaveBeenCalledWith(jasmine.objectContaining({
244244
name: 'FT.CONFIG',
245245
args: [
246246
'GET',
@@ -277,7 +277,7 @@ describe('RedisearchService', () => {
277277
'LIMIT', `${mockSearchRedisearchDto.offset}`, `${mockSearchRedisearchDto.limit}`,
278278
],
279279
}));
280-
expect(clusterClient.sendCommand).toHaveBeenCalledWith(jasmine.objectContaining( {
280+
expect(clusterClient.sendCommand).toHaveBeenCalledWith(jasmine.objectContaining({
281281
name: 'FT.CONFIG',
282282
args: [
283283
'GET',

redisinsight/api/src/modules/browser/services/redisearch/redisearch.service.ts

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { toNumber, uniq } from 'lodash';
33
import {
44
BadRequestException,
55
ConflictException,
6+
HttpException,
67
Injectable,
78
Logger,
89
} from '@nestjs/common';
@@ -147,11 +148,6 @@ export class RedisearchService {
147148

148149
const client = await this.browserTool.getRedisClient(clientOptions);
149150

150-
const [total, ...keyNames] = await client.sendCommand(
151-
new Command('FT.SEARCH', [index, query, 'NOCONTENT', 'LIMIT', offset, limit]),
152-
);
153-
154-
155151
try {
156152
const [[, maxSearchResults]] = await client.sendCommand(
157153
// response: [ [ 'MAXSEARCHRESULTS', '10000' ] ]
@@ -165,19 +161,34 @@ export class RedisearchService {
165161
maxResults = null;
166162
}
167163

164+
// Workaround: recalculate limit to not query more then MAXSEARCHRESULTS
165+
let safeLimit = limit;
166+
if (maxResults && offset + limit > maxResults) {
167+
safeLimit = offset <= maxResults ? maxResults - offset : limit;
168+
}
169+
170+
const [total, ...keyNames] = await client.sendCommand(
171+
new Command('FT.SEARCH', [index, query, 'NOCONTENT', 'LIMIT', offset, safeLimit]),
172+
);
173+
168174
return plainToClass(GetKeysWithDetailsResponse, {
169175
cursor: limit + offset,
170176
total,
171177
scanned: keyNames.length + offset,
172178
keys: keyNames.map((name) => ({ name })),
173179
maxResults,
174180
});
175-
} catch (error) {
176-
this.logger.error('Failed to search keys using redisearch index', error);
177-
if (error.message?.includes(RedisErrorCodes.RedisearchLimit)) {
181+
} catch (e) {
182+
this.logger.error('Failed to search keys using redisearch index', e);
183+
184+
if (e instanceof HttpException) {
185+
throw e;
186+
}
187+
188+
if (e.message?.includes(RedisErrorCodes.RedisearchLimit)) {
178189
throw new BadRequestException(ERROR_MESSAGES.INCREASE_MINIMUM_LIMIT(numberWithSpaces(dto.limit)));
179190
}
180-
throw catchAclError(error);
191+
throw catchAclError(e);
181192
}
182193
}
183194

0 commit comments

Comments
 (0)