Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions redisinsight/api/src/__mocks__/redis-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ export class MockRedisClient extends RedisClient {

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

public isFeatureSupported = jest.fn().mockResolvedValue(undefined);

public getInfo = jest.fn().mockResolvedValue(undefined);

public quit = jest.fn().mockResolvedValue(undefined); // todo: should return commands results

public getCurrentDbIndex = jest.fn().mockResolvedValue(0);
Expand Down
70 changes: 68 additions & 2 deletions redisinsight/api/src/modules/browser/__mocks__/hash.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {
AddFieldsToHashDto,
AddFieldsToHashDto, CreateHashWithExpireDto,
DeleteFieldsFromHashDto,
GetHashFieldsDto,
GetHashFieldsResponse,
HashFieldDto,
HashFieldDto, HashFieldTtlDto, UpdateHashFieldsTtlDto,
} from 'src/modules/browser/hash/dto';
import { mockKeyDto } from 'src/modules/browser/__mocks__/keys';
import { flatMap } from 'lodash';
Expand All @@ -12,10 +12,59 @@ export const mockHashField: HashFieldDto = {
field: Buffer.from('field1'),
value: Buffer.from('value'),
};

export const mockHashFieldWithExpire: HashFieldDto = {
field: Buffer.from('field-exp1'),
value: Buffer.from('value-exp1'),
expire: 111,
};
export const mockHashFieldWithExpire2: HashFieldDto = {
field: Buffer.from('field-exp2'),
value: Buffer.from('value-exp2'),
expire: 222,
};

export const mockAddFieldsDto: AddFieldsToHashDto = {
keyName: mockKeyDto.keyName,
fields: [mockHashField],
};

export const mockAddFieldsWithExpirationDto: CreateHashWithExpireDto = {
keyName: mockKeyDto.keyName,
fields: [mockHashField, mockHashFieldWithExpire, mockHashFieldWithExpire2],
};

export const mockHashFieldTtlDto = Object.assign(new HashFieldTtlDto(), {
field: Buffer.from('field-ttl'),
expire: -1,
});

export const mockHashFieldTtlDto2 = Object.assign(new HashFieldTtlDto(), {
field: Buffer.from('field-ttl2'),
expire: 0,
});

export const mockHashFieldTtlDto3 = Object.assign(new HashFieldTtlDto(), {
field: Buffer.from('field-ttl3'),
expire: 123123,
});

export const mockUpdateHashFieldsTtlDto: UpdateHashFieldsTtlDto = Object.assign(new UpdateHashFieldsTtlDto(), {
keyName: mockKeyDto.keyName,
fields: [mockHashFieldTtlDto, mockHashFieldTtlDto2, mockHashFieldTtlDto3],
});

export const mockCreateHashWithExpireDto: CreateHashWithExpireDto = {
keyName: mockKeyDto.keyName,
fields: [mockHashField],
expire: 3000,
};

export const mockCreateHashWithExpireAndFieldsExpireDto: CreateHashWithExpireDto = {
...mockAddFieldsWithExpirationDto,
expire: 3000,
};

export const mockDeleteFieldsDto: DeleteFieldsFromHashDto = {
keyName: mockAddFieldsDto.keyName,
fields: mockAddFieldsDto.fields.map((item) => item.field),
Expand All @@ -32,7 +81,24 @@ export const mockGetFieldsResponse: GetHashFieldsResponse = {
total: mockAddFieldsDto.fields.length,
fields: mockAddFieldsDto.fields,
};
export const mockGetFieldsWithTtlResponse: GetHashFieldsResponse = {
keyName: mockGetFieldsDto.keyName,
nextCursor: 0,
total: mockCreateHashWithExpireAndFieldsExpireDto.fields.length,
fields: mockCreateHashWithExpireAndFieldsExpireDto.fields.map((field) => ({
...field,
expire: field.expire || -1,
})),
};
export const mockRedisHScanResponse = [
0,
flatMap(mockAddFieldsDto.fields, ({ field, value }: HashFieldDto) => [field, value]),
];
export const mockRedisHScanWithFieldsExpireResponse = [
0,
flatMap(mockCreateHashWithExpireAndFieldsExpireDto.fields, ({ field, value }: HashFieldDto) => [field, value]),
];
export const mockRedisHTtlResponse = flatMap(
mockCreateHashWithExpireAndFieldsExpireDto.fields,
({ expire }: HashFieldDto) => [expire || -1],
);
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ export enum BrowserToolHashCommands {
HLen = 'hlen',
HScan = 'hscan',
HDel = 'hdel',
HExpire = 'hexpire',
HPersist = 'hpersist',
HTtl = 'httl',
}

export enum BrowserToolListCommands {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { ApiProperty, PickType } from '@nestjs/swagger';
import { IsInt, IsNotEmpty, Max } from 'class-validator';
import { MAX_TTL_NUMBER } from 'src/constants';
import { HashFieldDto } from 'src/modules/browser/hash/dto/hash-field.dto';

export class HashFieldTtlDto extends PickType(HashFieldDto, ['field'] as const) {
@ApiProperty({
type: Number,
description:
'Set a timeout on key in seconds. After the timeout has expired, the field will automatically be deleted. '
+ 'If the property has value of -1, then the field timeout will be removed.',
maximum: MAX_TTL_NUMBER,
})
@IsNotEmpty()
@IsInt({ always: true })
@Max(MAX_TTL_NUMBER)
expire: number;
}
20 changes: 18 additions & 2 deletions redisinsight/api/src/modules/browser/hash/dto/hash-field.dto.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsDefined } from 'class-validator';
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import {
IsDefined, IsInt, IsOptional, Max, Min,
} from 'class-validator';
import { IsRedisString, RedisStringType } from 'src/common/decorators';
import { RedisString } from 'src/common/constants';
import { MAX_TTL_NUMBER } from 'src/constants';

export class HashFieldDto {
@ApiProperty({
Expand All @@ -21,4 +24,17 @@ export class HashFieldDto {
@IsRedisString()
@RedisStringType()
value: RedisString;

@ApiPropertyOptional({
type: Number,
description:
'Set timeout on field in seconds',
minimum: 1,
maximum: MAX_TTL_NUMBER,
})
@IsOptional()
@IsInt({ always: true })
@Min(1)
@Max(MAX_TTL_NUMBER)
expire?: number;
}
2 changes: 2 additions & 0 deletions redisinsight/api/src/modules/browser/hash/dto/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export * from './hash-field.dto';
export * from './hash-field-ttl.dto';
export * from './update.hash-fields-ttl.dto';
export * from './add.fields-to-hash.dto';
export * from './create.hash-with-expire.dto';
export * from './delete.fields-from-hash.dto';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { KeyDto } from 'src/modules/browser/keys/dto';
import { ApiProperty } from '@nestjs/swagger';
import {
ArrayNotEmpty, IsArray, IsDefined, ValidateNested,
} from 'class-validator';
import { Type } from 'class-transformer';
import { HashFieldTtlDto } from 'src/modules/browser/hash/dto';

export class UpdateHashFieldsTtlDto extends KeyDto {
@ApiProperty({
description: 'Hash fields',
isArray: true,
type: HashFieldTtlDto,
})
@IsDefined()
@IsArray()
@ArrayNotEmpty()
@ValidateNested()
@Type(() => HashFieldTtlDto)
fields: HashFieldTtlDto[];
}
18 changes: 16 additions & 2 deletions redisinsight/api/src/modules/browser/hash/hash.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
Body,
Controller,
Delete,
HttpCode,
HttpCode, Patch,
Post,
Put,
UseInterceptors,
Expand All @@ -23,7 +23,7 @@ import {
DeleteFieldsFromHashDto,
DeleteFieldsFromHashResponse,
GetHashFieldsDto,
GetHashFieldsResponse,
GetHashFieldsResponse, UpdateHashFieldsTtlDto,
} from 'src/modules/browser/hash/dto';
import { HashService } from 'src/modules/browser/hash/hash.service';

Expand Down Expand Up @@ -80,6 +80,20 @@ export class HashController {
return await this.hashService.addFields(clientMetadata, dto);
}

@Patch('/ttl')
@ApiOperation({
description: 'Update hash fields ttl',
})
@ApiRedisParams()
@ApiBody({ type: UpdateHashFieldsTtlDto })
@ApiQueryRedisStringEncoding()
async updateTtl(
@BrowserClientMetadata() clientMetadata: ClientMetadata,
@Body() dto: UpdateHashFieldsTtlDto,
): Promise<void> {
return await this.hashService.updateTtl(clientMetadata, dto);
}

@Delete('/fields')
@ApiOperation({
description: 'Remove the specified fields from the Hash stored at key',
Expand Down
Loading