Skip to content

Commit c55fd92

Browse files
Merge pull request #3447 from RedisInsight/feature/RI-5767_update-key-details
Feature/ri 5767 update key details
2 parents 2ebcfde + 4b26432 commit c55fd92

File tree

124 files changed

+3196
-1433
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

124 files changed

+3196
-1433
lines changed

redisinsight/api/src/__mocks__/redis-client.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ export class MockRedisClient extends RedisClient {
4444

4545
public disconnect = jest.fn().mockResolvedValue(undefined);
4646

47+
public isFeatureSupported = jest.fn().mockResolvedValue(undefined);
48+
49+
public getInfo = jest.fn().mockResolvedValue(undefined);
50+
4751
public quit = jest.fn().mockResolvedValue(undefined); // todo: should return commands results
4852

4953
public getCurrentDbIndex = jest.fn().mockResolvedValue(0);

redisinsight/api/src/modules/browser/__mocks__/hash.ts

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import {
2-
AddFieldsToHashDto,
2+
AddFieldsToHashDto, CreateHashWithExpireDto,
33
DeleteFieldsFromHashDto,
44
GetHashFieldsDto,
55
GetHashFieldsResponse,
6-
HashFieldDto,
6+
HashFieldDto, HashFieldTtlDto, UpdateHashFieldsTtlDto,
77
} from 'src/modules/browser/hash/dto';
88
import { mockKeyDto } from 'src/modules/browser/__mocks__/keys';
99
import { flatMap } from 'lodash';
@@ -12,10 +12,59 @@ export const mockHashField: HashFieldDto = {
1212
field: Buffer.from('field1'),
1313
value: Buffer.from('value'),
1414
};
15+
16+
export const mockHashFieldWithExpire: HashFieldDto = {
17+
field: Buffer.from('field-exp1'),
18+
value: Buffer.from('value-exp1'),
19+
expire: 111,
20+
};
21+
export const mockHashFieldWithExpire2: HashFieldDto = {
22+
field: Buffer.from('field-exp2'),
23+
value: Buffer.from('value-exp2'),
24+
expire: 222,
25+
};
26+
1527
export const mockAddFieldsDto: AddFieldsToHashDto = {
1628
keyName: mockKeyDto.keyName,
1729
fields: [mockHashField],
1830
};
31+
32+
export const mockAddFieldsWithExpirationDto: CreateHashWithExpireDto = {
33+
keyName: mockKeyDto.keyName,
34+
fields: [mockHashField, mockHashFieldWithExpire, mockHashFieldWithExpire2],
35+
};
36+
37+
export const mockHashFieldTtlDto = Object.assign(new HashFieldTtlDto(), {
38+
field: Buffer.from('field-ttl'),
39+
expire: -1,
40+
});
41+
42+
export const mockHashFieldTtlDto2 = Object.assign(new HashFieldTtlDto(), {
43+
field: Buffer.from('field-ttl2'),
44+
expire: 0,
45+
});
46+
47+
export const mockHashFieldTtlDto3 = Object.assign(new HashFieldTtlDto(), {
48+
field: Buffer.from('field-ttl3'),
49+
expire: 123123,
50+
});
51+
52+
export const mockUpdateHashFieldsTtlDto: UpdateHashFieldsTtlDto = Object.assign(new UpdateHashFieldsTtlDto(), {
53+
keyName: mockKeyDto.keyName,
54+
fields: [mockHashFieldTtlDto, mockHashFieldTtlDto2, mockHashFieldTtlDto3],
55+
});
56+
57+
export const mockCreateHashWithExpireDto: CreateHashWithExpireDto = {
58+
keyName: mockKeyDto.keyName,
59+
fields: [mockHashField],
60+
expire: 3000,
61+
};
62+
63+
export const mockCreateHashWithExpireAndFieldsExpireDto: CreateHashWithExpireDto = {
64+
...mockAddFieldsWithExpirationDto,
65+
expire: 3000,
66+
};
67+
1968
export const mockDeleteFieldsDto: DeleteFieldsFromHashDto = {
2069
keyName: mockAddFieldsDto.keyName,
2170
fields: mockAddFieldsDto.fields.map((item) => item.field),
@@ -32,7 +81,24 @@ export const mockGetFieldsResponse: GetHashFieldsResponse = {
3281
total: mockAddFieldsDto.fields.length,
3382
fields: mockAddFieldsDto.fields,
3483
};
84+
export const mockGetFieldsWithTtlResponse: GetHashFieldsResponse = {
85+
keyName: mockGetFieldsDto.keyName,
86+
nextCursor: 0,
87+
total: mockCreateHashWithExpireAndFieldsExpireDto.fields.length,
88+
fields: mockCreateHashWithExpireAndFieldsExpireDto.fields.map((field) => ({
89+
...field,
90+
expire: field.expire || -1,
91+
})),
92+
};
3593
export const mockRedisHScanResponse = [
3694
0,
3795
flatMap(mockAddFieldsDto.fields, ({ field, value }: HashFieldDto) => [field, value]),
3896
];
97+
export const mockRedisHScanWithFieldsExpireResponse = [
98+
0,
99+
flatMap(mockCreateHashWithExpireAndFieldsExpireDto.fields, ({ field, value }: HashFieldDto) => [field, value]),
100+
];
101+
export const mockRedisHTtlResponse = flatMap(
102+
mockCreateHashWithExpireAndFieldsExpireDto.fields,
103+
({ expire }: HashFieldDto) => [expire || -1],
104+
);

redisinsight/api/src/modules/browser/constants/browser-tool-commands.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ export enum BrowserToolHashCommands {
2424
HLen = 'hlen',
2525
HScan = 'hscan',
2626
HDel = 'hdel',
27+
HExpire = 'hexpire',
28+
HPersist = 'hpersist',
29+
HTtl = 'httl',
2730
}
2831

2932
export enum BrowserToolListCommands {
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { ApiProperty, PickType } from '@nestjs/swagger';
2+
import { IsInt, IsNotEmpty, Max } from 'class-validator';
3+
import { MAX_TTL_NUMBER } from 'src/constants';
4+
import { HashFieldDto } from 'src/modules/browser/hash/dto/hash-field.dto';
5+
6+
export class HashFieldTtlDto extends PickType(HashFieldDto, ['field'] as const) {
7+
@ApiProperty({
8+
type: Number,
9+
description:
10+
'Set a timeout on key in seconds. After the timeout has expired, the field will automatically be deleted. '
11+
+ 'If the property has value of -1, then the field timeout will be removed.',
12+
maximum: MAX_TTL_NUMBER,
13+
})
14+
@IsNotEmpty()
15+
@IsInt({ always: true })
16+
@Max(MAX_TTL_NUMBER)
17+
expire: number;
18+
}

redisinsight/api/src/modules/browser/hash/dto/hash-field.dto.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
import { ApiProperty } from '@nestjs/swagger';
2-
import { IsDefined } from 'class-validator';
1+
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
2+
import {
3+
IsDefined, IsInt, IsOptional, Max, Min,
4+
} from 'class-validator';
35
import { IsRedisString, RedisStringType } from 'src/common/decorators';
46
import { RedisString } from 'src/common/constants';
7+
import { MAX_TTL_NUMBER } from 'src/constants';
58

69
export class HashFieldDto {
710
@ApiProperty({
@@ -21,4 +24,17 @@ export class HashFieldDto {
2124
@IsRedisString()
2225
@RedisStringType()
2326
value: RedisString;
27+
28+
@ApiPropertyOptional({
29+
type: Number,
30+
description:
31+
'Set timeout on field in seconds',
32+
minimum: 1,
33+
maximum: MAX_TTL_NUMBER,
34+
})
35+
@IsOptional()
36+
@IsInt({ always: true })
37+
@Min(1)
38+
@Max(MAX_TTL_NUMBER)
39+
expire?: number;
2440
}

redisinsight/api/src/modules/browser/hash/dto/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
export * from './hash-field.dto';
2+
export * from './hash-field-ttl.dto';
3+
export * from './update.hash-fields-ttl.dto';
24
export * from './add.fields-to-hash.dto';
35
export * from './create.hash-with-expire.dto';
46
export * from './delete.fields-from-hash.dto';
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { KeyDto } from 'src/modules/browser/keys/dto';
2+
import { ApiProperty } from '@nestjs/swagger';
3+
import {
4+
ArrayNotEmpty, IsArray, IsDefined, ValidateNested,
5+
} from 'class-validator';
6+
import { Type } from 'class-transformer';
7+
import { HashFieldTtlDto } from 'src/modules/browser/hash/dto';
8+
9+
export class UpdateHashFieldsTtlDto extends KeyDto {
10+
@ApiProperty({
11+
description: 'Hash fields',
12+
isArray: true,
13+
type: HashFieldTtlDto,
14+
})
15+
@IsDefined()
16+
@IsArray()
17+
@ArrayNotEmpty()
18+
@ValidateNested()
19+
@Type(() => HashFieldTtlDto)
20+
fields: HashFieldTtlDto[];
21+
}

redisinsight/api/src/modules/browser/hash/hash.controller.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {
22
Body,
33
Controller,
44
Delete,
5-
HttpCode,
5+
HttpCode, Patch,
66
Post,
77
Put,
88
UseInterceptors,
@@ -23,7 +23,7 @@ import {
2323
DeleteFieldsFromHashDto,
2424
DeleteFieldsFromHashResponse,
2525
GetHashFieldsDto,
26-
GetHashFieldsResponse,
26+
GetHashFieldsResponse, UpdateHashFieldsTtlDto,
2727
} from 'src/modules/browser/hash/dto';
2828
import { HashService } from 'src/modules/browser/hash/hash.service';
2929

@@ -80,6 +80,20 @@ export class HashController {
8080
return await this.hashService.addFields(clientMetadata, dto);
8181
}
8282

83+
@Patch('/ttl')
84+
@ApiOperation({
85+
description: 'Update hash fields ttl',
86+
})
87+
@ApiRedisParams()
88+
@ApiBody({ type: UpdateHashFieldsTtlDto })
89+
@ApiQueryRedisStringEncoding()
90+
async updateTtl(
91+
@BrowserClientMetadata() clientMetadata: ClientMetadata,
92+
@Body() dto: UpdateHashFieldsTtlDto,
93+
): Promise<void> {
94+
return await this.hashService.updateTtl(clientMetadata, dto);
95+
}
96+
8397
@Delete('/fields')
8498
@ApiOperation({
8599
description: 'Remove the specified fields from the Hash stored at key',

0 commit comments

Comments
 (0)