Skip to content

Commit d9eb141

Browse files
#RI-3973 - update rts recommendation
1 parent 9018324 commit d9eb141

File tree

5 files changed

+67
-25
lines changed

5 files changed

+67
-25
lines changed

redisinsight/api/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
"body-parser": "^1.19.0",
5454
"class-transformer": "^0.2.3",
5555
"class-validator": "^0.12.2",
56+
"date-fns": "^2.29.3",
5657
"dotenv": "^16.0.0",
5758
"express": "^4.17.1",
5859
"fs-extra": "^10.0.0",
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export const ARG_IN_QUOTATION_MARKS_REGEX = /"[^"]*|'[^']*'|"+/g;
22
export const IS_INTEGER_NUMBER_REGEX = /^\d+$/;
3+
export const IS_NUMBER_REGEX = /^-?\d*(\.\d+)?$/;
34
export const IS_NON_PRINTABLE_ASCII_CHARACTER = /[^ -~\u0007\b\t\n\r]/;
45
export const IP_ADDRESS_REGEX = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
56
export const PRIVATE_IP_ADDRESS_REGEX = /(^127\.)|(^10\.)|(^172\.1[6-9]\.)|(^172\.2[0-9]\.)|(^172\.3[0-1]\.)|(^192\.168\.)/;
6-
export const IS_TIMESTAMP = /^\d{10,}$/;
7+
export const IS_TIMESTAMP = /^(\d{10}|\d{13}|\d{16}|\d{19})$/;

redisinsight/api/src/modules/recommendation/providers/recommendation.provider.spec.ts

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,39 @@ const mockRedisAclListResponse_2: string[] = [
3737
const mockFTListResponse_1 = [];
3838
const mockFTListResponse_2 = ['idx'];
3939

40+
const generateRTSRecommendationTests = [
41+
{ input: ['0', ['123', 123]], expected: null },
42+
{ input: ['0', ['1234567891', 3]], expected: { name: RECOMMENDATION_NAMES.RTS } },
43+
{ input: ['0', ['1234567891', 1234567891]], expected: { name: RECOMMENDATION_NAMES.RTS } },
44+
{ input: ['0', ['123', 1234567891]], expected: { name: RECOMMENDATION_NAMES.RTS } },
45+
{ input: ['0', ['123', 12345678911]], expected: null },
46+
{ input: ['0', ['123', 1234567891234]], expected: { name: RECOMMENDATION_NAMES.RTS } },
47+
{ input: ['0', ['123', 12345678912345]], expected: null },
48+
{ input: ['0', ['123', 1234567891234567]], expected: { name: RECOMMENDATION_NAMES.RTS } },
49+
{ input: ['0', ['12345678912345678', 1]], expected: null },
50+
{ input: ['0', ['1234567891234567891', 1]], expected: { name: RECOMMENDATION_NAMES.RTS } },
51+
{ input: ['0', ['1', 1234567891.2]], expected: { name: RECOMMENDATION_NAMES.RTS } },
52+
{ input: ['0', ['1234567891.2', 1]], expected: { name: RECOMMENDATION_NAMES.RTS } },
53+
{ input: ['0', ['1234567891:12', 1]], expected: { name: RECOMMENDATION_NAMES.RTS } },
54+
{ input: ['0', ['1234567891a12', 1]], expected: { name: RECOMMENDATION_NAMES.RTS } },
55+
{ input: ['0', ['1234567891.2.2', 1]], expected: null },
56+
{ input: ['0', ['1234567891asd', 1]], expected: null },
57+
{ input: ['0', ['10-10-2020', 1]], expected: { name: RECOMMENDATION_NAMES.RTS } },
58+
{ input: ['0', ['', 1]], expected: null },
59+
{ input: ['0', ['1', -12]], expected: null },
60+
{ input: ['0', ['1', -1234567891]], expected: null },
61+
{ input: ['0', ['1', -1234567891.123]], expected: null },
62+
{ input: ['0', ['1', -1234567891.123]], expected: null },
63+
{ input: ['0', ['1234567891.-123', 1]], expected: null },
64+
];
65+
4066
const mockZScanResponse_1 = [
4167
'0',
42-
[123456789, 123456789, 12345678910, 12345678910],
68+
['1', 1, '12345678910', 12345678910],
4369
];
4470
const mockZScanResponse_2 = [
4571
'0',
46-
[12345678910, 12345678910, 1, 1],
72+
['12345678910', 12345678910, 1, 1],
4773
];
4874

4975
const mockKeys = [
@@ -489,28 +515,14 @@ describe('RecommendationProvider', () => {
489515
});
490516

491517
describe('determineRTSRecommendation', () => {
492-
it('should not return RTS recommendation', async () => {
518+
test.each(generateRTSRecommendationTests)('%j', async ({ input, expected }) => {
493519
when(nodeClient.sendCommand)
494520
.calledWith(jasmine.objectContaining({ name: 'zscan' }))
495-
.mockResolvedValue(mockZScanResponse_1);
521+
.mockResolvedValue(input);
496522

497523
const RTSRecommendation = await service
498524
.determineRTSRecommendation(nodeClient, mockKeys);
499-
expect(RTSRecommendation).toEqual(null);
500-
});
501-
502-
it('should return RTS recommendation', async () => {
503-
when(nodeClient.sendCommand)
504-
.calledWith(jasmine.objectContaining({ name: 'zscan' }))
505-
.mockResolvedValueOnce(mockZScanResponse_1);
506-
507-
when(nodeClient.sendCommand)
508-
.calledWith(jasmine.objectContaining({ name: 'zscan' }))
509-
.mockResolvedValue(mockZScanResponse_2);
510-
511-
const RTSRecommendation = await service
512-
.determineRTSRecommendation(nodeClient, mockSortedSets);
513-
expect(RTSRecommendation).toEqual({ name: RECOMMENDATION_NAMES.RTS });
525+
expect(RTSRecommendation).toEqual(expected);
514526
});
515527

516528
it('should not return RTS recommendation when only 101 sorted set contain timestamp', async () => {

redisinsight/api/src/modules/recommendation/providers/recommendation.provider.ts

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import { Injectable, Logger } from '@nestjs/common';
22
import { Redis, Cluster, Command } from 'ioredis';
3-
import { get } from 'lodash';
3+
import { get, isNumber } from 'lodash';
4+
import { isValid } from 'date-fns';
45
import * as semverCompare from 'node-version-compare';
5-
import { convertRedisInfoReplyToObject, convertBulkStringsToObject, convertStringsArrayToObject } from 'src/utils';
6-
import { RECOMMENDATION_NAMES, IS_TIMESTAMP } from 'src/constants';
6+
import { convertRedisInfoReplyToObject, convertBulkStringsToObject } from 'src/utils';
7+
import {
8+
RECOMMENDATION_NAMES, IS_TIMESTAMP, IS_INTEGER_NUMBER_REGEX, IS_NUMBER_REGEX,
9+
} from 'src/constants';
710
import { RedisDataType } from 'src/modules/browser/dto';
811
import { Recommendation } from 'src/modules/database-analysis/models/recommendation';
912
import { Key } from 'src/modules/database-analysis/models';
@@ -311,8 +314,7 @@ export class RecommendationProvider {
311314
// get first member-score pair
312315
new Command('zscan', [keys[processedKeysNumber].name, '0', 'COUNT', 2], { replyEncoding: 'utf8' }),
313316
) as string[];
314-
// check is pair member-score is timestamp
315-
if (IS_TIMESTAMP.test(membersArray[0]) && IS_TIMESTAMP.test(membersArray[1])) {
317+
if (this.checkTimestamp(membersArray[0]) || this.checkTimestamp(membersArray[1])) {
316318
isTimeSeries = true;
317319
}
318320
processedKeysNumber += 1;
@@ -421,4 +423,25 @@ export class RecommendationProvider {
421423
}
422424
return false;
423425
}
426+
427+
private checkTimestamp(value: string): boolean {
428+
try {
429+
if (!IS_NUMBER_REGEX.test(value) && isValid(new Date(value))) {
430+
return true;
431+
}
432+
const integerPart = parseInt(value, 10);
433+
if (!IS_TIMESTAMP.test(integerPart.toString())) {
434+
return false;
435+
}
436+
if (isNumber(value) || integerPart.toString().length === value.length) {
437+
return true;
438+
}
439+
// check part after separator
440+
const subPart = value.replace(integerPart.toString(), '');
441+
return IS_INTEGER_NUMBER_REGEX.test(subPart.substring(1, subPart.length));
442+
} catch (err) {
443+
// ignore errors
444+
return false;
445+
}
446+
}
424447
}

redisinsight/api/yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2626,6 +2626,11 @@ date-fns@^2.28.0:
26262626
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.2.tgz#0d4b3d0f3dff0f920820a070920f0d9662c51931"
26272627
integrity sha512-0VNbwmWJDS/G3ySwFSJA3ayhbURMTJLtwM2DTxf9CWondCnh6DTNlO9JgRSq6ibf4eD0lfMJNBxUdEAHHix+bA==
26282628

2629+
date-fns@^2.29.3:
2630+
version "2.29.3"
2631+
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.3.tgz#27402d2fc67eb442b511b70bbdf98e6411cd68a8"
2632+
integrity sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==
2633+
26292634
[email protected], debug@^2.2.0, debug@^2.3.3, debug@^2.6.9:
26302635
version "2.6.9"
26312636
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"

0 commit comments

Comments
 (0)