Skip to content

Commit 9018324

Browse files
Merge branch 'main' of https://github.com/RedisInsight/RedisInsight into feature/RI-3527_lua_scripts
2 parents 9fdf092 + c6ff61c commit 9018324

File tree

101 files changed

+2381
-763
lines changed

Some content is hidden

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

101 files changed

+2381
-763
lines changed

redisinsight/api/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"start:prod": "cross-env NODE_ENV=production node dist/src/main",
2828
"test": "cross-env NODE_ENV=test ./node_modules/.bin/jest -w 1",
2929
"test:watch": "cross-env NODE_ENV=test jest --watch -w 1",
30-
"test:cov": "cross-env NODE_ENV=test ./node_modules/.bin/jest --coverage -w 1",
30+
"test:cov": "cross-env NODE_ENV=test ./node_modules/.bin/jest --forceExit --coverage -w 1",
3131
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand -w 1",
3232
"test:e2e": "jest --config ./test/jest-e2e.json -w 1",
3333
"typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js -d ./config/ormconfig.ts",

redisinsight/api/src/__mocks__/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ export * from './server';
1717
export * from './redis-enterprise';
1818
export * from './redis-sentinel';
1919
export * from './database-import';
20+
export * from './redis-client';
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { IRedisClientInstance, RedisService } from 'src/modules/redis/redis.service';
2+
import { mockCommonClientMetadata } from 'src/__mocks__/common';
3+
import { mockIORedisClient } from 'src/__mocks__/redis';
4+
import { ClientMetadata } from 'src/common/models';
5+
6+
export const mockRedisClientInstance: IRedisClientInstance = {
7+
id: RedisService.generateId(mockCommonClientMetadata),
8+
clientMetadata: mockCommonClientMetadata,
9+
client: mockIORedisClient,
10+
lastTimeUsed: 1619791508019,
11+
};
12+
13+
export const generateMockRedisClientInstance = (clientMetadata: Partial<ClientMetadata>): IRedisClientInstance => ({
14+
id: RedisService.generateId(clientMetadata as ClientMetadata),
15+
clientMetadata: clientMetadata as ClientMetadata,
16+
client: mockIORedisClient,
17+
lastTimeUsed: Date.now(),
18+
});

redisinsight/api/src/__mocks__/redis.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,18 @@ export const mockRedisService = jest.fn(() => ({
6868
getClientInstance: jest.fn().mockResolvedValue({
6969
client: mockIORedisClient,
7070
}),
71-
setClientInstance: jest.fn(),
71+
setClientInstance: jest.fn().mockReturnValue({
72+
client: mockIORedisClient,
73+
}),
7274
isClientConnected: jest.fn().mockReturnValue(true),
73-
connectToDatabaseInstance: jest.fn().mockResolvedValue(mockIORedisClient),
74-
createStandaloneClient: jest.fn().mockResolvedValue(mockIORedisClient),
75-
createSentinelClient: jest.fn().mockResolvedValue(mockIORedisSentinel),
76-
createClusterClient: jest.fn().mockResolvedValue(mockIORedisCluster),
7775
removeClientInstance: jest.fn(),
76+
removeClientInstances: jest.fn(),
77+
findClientInstances: jest.fn(),
78+
}));
79+
80+
export const mockRedisConnectionFactory = jest.fn(() => ({
81+
createRedisConnection: jest.fn().mockResolvedValue(mockIORedisClient),
82+
createStandaloneConnection: jest.fn().mockResolvedValue(mockIORedisClient),
83+
createSentinelConnection: jest.fn().mockResolvedValue(mockIORedisSentinel),
84+
createClusterConnection: jest.fn().mockResolvedValue(mockIORedisCluster),
7885
}));
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export const API_PARAM_DATABASE_ID = 'dbInstance';
2+
export const API_HEADER_DATABASE_INDEX = 'ri-db-index';
23
export const API_PARAM_CLI_CLIENT_ID = 'uuid';

redisinsight/api/src/common/decorators/client-metadata/client-metadata.decorator.ts

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,43 +3,40 @@ import { plainToClass } from 'class-transformer';
33
import { ClientContext, ClientMetadata } from 'src/common/models';
44
import { sessionFromRequestFactory } from 'src/common/decorators';
55
import { Validator } from 'class-validator';
6-
import { API_PARAM_DATABASE_ID } from 'src/common/constants';
6+
import { API_HEADER_DATABASE_INDEX, API_PARAM_DATABASE_ID } from 'src/common/constants';
7+
import { ApiHeader, ApiParam } from '@nestjs/swagger';
78

89
const validator = new Validator();
910

1011
export interface IClientMetadataParamOptions {
1112
databaseIdParam?: string,
1213
uniqueIdParam?: string,
1314
context?: ClientContext,
15+
ignoreDbIndex?: boolean,
1416
}
1517

1618
export const clientMetadataParamFactory = (
1719
options: IClientMetadataParamOptions,
1820
ctx: ExecutionContext,
1921
): ClientMetadata => {
20-
const opts: IClientMetadataParamOptions = {
21-
context: ClientContext.Common,
22-
databaseIdParam: API_PARAM_DATABASE_ID,
23-
...options,
24-
};
25-
2622
const req = ctx.switchToHttp().getRequest();
2723

2824
let databaseId;
29-
if (opts?.databaseIdParam) {
30-
databaseId = req.params?.[opts.databaseIdParam];
25+
if (options?.databaseIdParam) {
26+
databaseId = req.params?.[options.databaseIdParam];
3127
}
3228

3329
let uniqueId;
34-
if (opts?.uniqueIdParam) {
35-
uniqueId = req.params?.[opts.uniqueIdParam];
30+
if (options?.uniqueIdParam) {
31+
uniqueId = req.params?.[options.uniqueIdParam];
3632
}
3733

3834
const clientMetadata = plainToClass(ClientMetadata, {
3935
session: sessionFromRequestFactory(undefined, ctx),
4036
databaseId,
4137
uniqueId,
42-
context: opts?.context || ClientContext.Common,
38+
context: options?.context || ClientContext.Common,
39+
db: options?.ignoreDbIndex ? undefined : req?.headers?.[API_HEADER_DATABASE_INDEX],
4340
});
4441

4542
const errors = validator.validateSync(clientMetadata, {
@@ -53,4 +50,35 @@ export const clientMetadataParamFactory = (
5350
return clientMetadata;
5451
};
5552

56-
export const ClientMetadataParam = createParamDecorator(clientMetadataParamFactory);
53+
export const ClientMetadataParam = (
54+
options?: IClientMetadataParamOptions,
55+
) => {
56+
const opts: IClientMetadataParamOptions = {
57+
context: ClientContext.Common,
58+
databaseIdParam: API_PARAM_DATABASE_ID,
59+
ignoreDbIndex: false,
60+
...options,
61+
};
62+
63+
return createParamDecorator(clientMetadataParamFactory, [
64+
(target: any, key: string) => {
65+
// Here it is. Use the `@ApiQuery` decorator purely as a function to define the meta only once here.
66+
ApiParam({
67+
name: opts.databaseIdParam,
68+
schema: { type: 'string' },
69+
required: true,
70+
})(target, key, Object.getOwnPropertyDescriptor(target, key));
71+
if (!opts.ignoreDbIndex) {
72+
ApiHeader({
73+
name: API_HEADER_DATABASE_INDEX,
74+
schema: {
75+
default: undefined,
76+
type: 'number',
77+
minimum: 0,
78+
},
79+
required: false,
80+
})(target, key, Object.getOwnPropertyDescriptor(target, key));
81+
}
82+
},
83+
])(opts);
84+
};

redisinsight/api/src/common/models/client-metadata.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Session } from 'src/common/models/session';
22
import { Type } from 'class-transformer';
33
import {
4-
IsEnum, IsNotEmpty, IsOptional, IsString,
4+
IsEnum, IsNotEmpty, IsNumber, IsOptional, IsString, Max, Min,
55
} from 'class-validator';
66

77
export enum ClientContext {
@@ -27,4 +27,11 @@ export class ClientMetadata {
2727
@IsOptional()
2828
@IsString()
2929
uniqueId?: string;
30+
31+
@IsOptional()
32+
@IsNumber()
33+
@Type(() => Number)
34+
@Min(0)
35+
@Max(2147483647)
36+
db?: number;
3037
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { PickType } from '@nestjs/swagger';
2+
import { ClientMetadata } from 'src/common/models/client-metadata';
3+
4+
export class DatabaseIndex extends PickType(ClientMetadata, ['db'] as const) {}

redisinsight/api/src/common/models/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ export * from './common';
22
export * from './endpoint';
33
export * from './session';
44
export * from './client-metadata';
5+
export * from './database-index';
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { ArgumentMetadata, ValidationPipe } from '@nestjs/common';
2+
3+
export class DbIndexValidationPipe extends ValidationPipe {
4+
async transform(db, metadata: ArgumentMetadata) {
5+
return super.transform({ db }, metadata);
6+
}
7+
}

0 commit comments

Comments
 (0)