Skip to content

Commit 99a2ad8

Browse files
committed
#RI-4145 - Decompress SNAPPY, compressor switcher
1 parent fe7807f commit 99a2ad8

File tree

23 files changed

+239
-59
lines changed

23 files changed

+239
-59
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { MigrationInterface, QueryRunner } from "typeorm";
2+
3+
export class databaseCompressor1678182722874 implements MigrationInterface {
4+
name = 'databaseCompressor1678182722874'
5+
6+
public async up(queryRunner: QueryRunner): Promise<void> {
7+
await queryRunner.query(`CREATE TABLE "temporary_database_instance" ("id" varchar PRIMARY KEY NOT NULL, "host" varchar NOT NULL, "port" integer NOT NULL, "name" varchar NOT NULL, "username" varchar, "password" varchar, "tls" boolean, "verifyServerCert" boolean, "lastConnection" datetime, "caCertId" varchar, "clientCertId" varchar, "connectionType" varchar NOT NULL DEFAULT ('STANDALONE'), "nodes" varchar DEFAULT ('[]'), "nameFromProvider" varchar, "sentinelMasterName" varchar, "sentinelMasterUsername" varchar, "sentinelMasterPassword" varchar, "provider" varchar DEFAULT ('UNKNOWN'), "modules" varchar NOT NULL DEFAULT ('[]'), "db" integer, "encryption" varchar, "tlsServername" varchar, "new" boolean, "ssh" boolean, "timeout" integer, "compressor" varchar NOT NULL DEFAULT ('NONE'), CONSTRAINT "FK_d1bc747b5938e22b4b708d8e9a5" FOREIGN KEY ("caCertId") REFERENCES "ca_certificate" ("id") ON DELETE SET NULL ON UPDATE NO ACTION, CONSTRAINT "FK_3b9b625266c00feb2d66a9f36e4" FOREIGN KEY ("clientCertId") REFERENCES "client_certificate" ("id") ON DELETE SET NULL ON UPDATE NO ACTION)`);
8+
await queryRunner.query(`INSERT INTO "temporary_database_instance"("id", "host", "port", "name", "username", "password", "tls", "verifyServerCert", "lastConnection", "caCertId", "clientCertId", "connectionType", "nodes", "nameFromProvider", "sentinelMasterName", "sentinelMasterUsername", "sentinelMasterPassword", "provider", "modules", "db", "encryption", "tlsServername", "new", "ssh", "timeout") SELECT "id", "host", "port", "name", "username", "password", "tls", "verifyServerCert", "lastConnection", "caCertId", "clientCertId", "connectionType", "nodes", "nameFromProvider", "sentinelMasterName", "sentinelMasterUsername", "sentinelMasterPassword", "provider", "modules", "db", "encryption", "tlsServername", "new", "ssh", "timeout" FROM "database_instance"`);
9+
await queryRunner.query(`DROP TABLE "database_instance"`);
10+
await queryRunner.query(`ALTER TABLE "temporary_database_instance" RENAME TO "database_instance"`);
11+
}
12+
13+
public async down(queryRunner: QueryRunner): Promise<void> {
14+
await queryRunner.query(`ALTER TABLE "database_instance" RENAME TO "temporary_database_instance"`);
15+
await queryRunner.query(`CREATE TABLE "database_instance" ("id" varchar PRIMARY KEY NOT NULL, "host" varchar NOT NULL, "port" integer NOT NULL, "name" varchar NOT NULL, "username" varchar, "password" varchar, "tls" boolean, "verifyServerCert" boolean, "lastConnection" datetime, "caCertId" varchar, "clientCertId" varchar, "connectionType" varchar NOT NULL DEFAULT ('STANDALONE'), "nodes" varchar DEFAULT ('[]'), "nameFromProvider" varchar, "sentinelMasterName" varchar, "sentinelMasterUsername" varchar, "sentinelMasterPassword" varchar, "provider" varchar DEFAULT ('UNKNOWN'), "modules" varchar NOT NULL DEFAULT ('[]'), "db" integer, "encryption" varchar, "tlsServername" varchar, "new" boolean, "ssh" boolean, "timeout" integer, CONSTRAINT "FK_d1bc747b5938e22b4b708d8e9a5" FOREIGN KEY ("caCertId") REFERENCES "ca_certificate" ("id") ON DELETE SET NULL ON UPDATE NO ACTION, CONSTRAINT "FK_3b9b625266c00feb2d66a9f36e4" FOREIGN KEY ("clientCertId") REFERENCES "client_certificate" ("id") ON DELETE SET NULL ON UPDATE NO ACTION)`);
16+
await queryRunner.query(`INSERT INTO "database_instance"("id", "host", "port", "name", "username", "password", "tls", "verifyServerCert", "lastConnection", "caCertId", "clientCertId", "connectionType", "nodes", "nameFromProvider", "sentinelMasterName", "sentinelMasterUsername", "sentinelMasterPassword", "provider", "modules", "db", "encryption", "tlsServername", "new", "ssh", "timeout") SELECT "id", "host", "port", "name", "username", "password", "tls", "verifyServerCert", "lastConnection", "caCertId", "clientCertId", "connectionType", "nodes", "nameFromProvider", "sentinelMasterName", "sentinelMasterUsername", "sentinelMasterPassword", "provider", "modules", "db", "encryption", "tlsServername", "new", "ssh", "timeout" FROM "temporary_database_instance"`);
17+
await queryRunner.query(`DROP TABLE "temporary_database_instance"`);
18+
}
19+
20+
}

redisinsight/api/migration/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import { workbenchAndAnalysisDbIndex1673934231410 } from './1673934231410-workbe
2727
import { browserHistory1674539211397 } from './1674539211397-browser-history';
2828
import { databaseAnalysisRecommendations1674660306971 } from './1674660306971-database-analysis-recommendations';
2929
import { databaseTimeout1675398140189 } from './1675398140189-database-timeout';
30+
import { databaseCompressor1678182722874 } from './1678182722874-database-compressor';
3031

3132
export default [
3233
initialMigration1614164490968,
@@ -58,4 +59,5 @@ export default [
5859
databaseAnalysisRecommendations1674660306971,
5960
browserHistory1674539211397,
6061
databaseTimeout1675398140189,
62+
databaseCompressor1678182722874,
6163
];

redisinsight/api/src/modules/database/database.analytics.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ export class DatabaseAnalytics extends TelemetryBaseService {
6767
numberOfModules: instance.modules?.length || 0,
6868
timeout: instance.timeout / 1_000, // milliseconds to seconds
6969
databaseIndex: instance.db || 0,
70+
useCompressor: instance.compressor || null,
7071
...modulesSummary,
7172
},
7273
);

redisinsight/api/src/modules/database/dto/create.database.dto.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import { sshOptionsTransformer } from 'src/modules/ssh/transformers/ssh-options.
2323
)
2424
export class CreateDatabaseDto extends PickType(Database, [
2525
'host', 'port', 'name', 'db', 'username', 'password', 'timeout', 'nameFromProvider', 'provider',
26-
'tls', 'tlsServername', 'verifyServerCert', 'sentinelMaster', 'ssh',
26+
'tls', 'tlsServername', 'verifyServerCert', 'sentinelMaster', 'ssh', 'compressor',
2727
] as const) {
2828
@ApiPropertyOptional({
2929
description: 'CA Certificate',

redisinsight/api/src/modules/database/dto/update.database.dto.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { ApiPropertyOptional, getSchemaPath } from '@nestjs/swagger';
22
import {
33
IsBoolean,
4+
IsEnum,
45
IsInt, IsNotEmpty, IsNotEmptyObject, IsOptional, IsString, MaxLength, Min, ValidateIf, ValidateNested,
56
} from 'class-validator';
67
import { CreateCaCertificateDto } from 'src/modules/certificate/dto/create.ca-certificate.dto';
@@ -16,6 +17,7 @@ import { CreateDatabaseDto } from 'src/modules/database/dto/create.database.dto'
1617
import { CreateBasicSshOptionsDto } from 'src/modules/ssh/dto/create.basic-ssh-options.dto';
1718
import { CreateCertSshOptionsDto } from 'src/modules/ssh/dto/create.cert-ssh-options.dto';
1819
import { sshOptionsTransformer } from 'src/modules/ssh/transformers/ssh-options.transformer';
20+
import { Compressor } from '../entities/database.entity';
1921

2022
export class UpdateDatabaseDto extends CreateDatabaseDto {
2123
@ValidateIf((object, value) => value !== undefined)
@@ -157,4 +159,14 @@ export class UpdateDatabaseDto extends CreateDatabaseDto {
157159
@ValidateNested()
158160
@Default(null)
159161
sshOptions?: CreateBasicSshOptionsDto | CreateCertSshOptionsDto;
162+
163+
@ApiPropertyOptional({
164+
description: 'Database compressor',
165+
default: Compressor.NONE,
166+
enum: Compressor,
167+
})
168+
@Expose()
169+
@IsEnum(Compressor)
170+
@IsOptional()
171+
compressor?: Compressor = Compressor.NONE;
160172
}

redisinsight/api/src/modules/database/entities/database.entity.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@ export enum ConnectionType {
2525
NOT_CONNECTED = 'NOT CONNECTED',
2626
}
2727

28+
export enum Compressor {
29+
NONE = 'NONE',
30+
GZIP = 'GZIP',
31+
ZSTD = 'ZSTD',
32+
LZ4 = 'LZ4',
33+
SNAPPY = 'SNAPPY',
34+
}
35+
2836
@Entity('database_instance')
2937
export class DatabaseEntity {
3038
@Expose()
@@ -184,4 +192,11 @@ export class DatabaseEntity {
184192
)
185193
@Type(() => SshOptionsEntity)
186194
sshOptions: SshOptionsEntity;
195+
196+
@Expose()
197+
@Column({
198+
nullable: false,
199+
default: Compressor.NONE,
200+
})
201+
compressor: Compressor;
187202
}

redisinsight/api/src/modules/database/models/database.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Expose, Type } from 'class-transformer';
33
import config from 'src/utils/config';
44
import { CaCertificate } from 'src/modules/certificate/models/ca-certificate';
55
import { ClientCertificate } from 'src/modules/certificate/models/client-certificate';
6-
import { ConnectionType, HostingProvider } from 'src/modules/database/entities/database.entity';
6+
import { Compressor, ConnectionType, HostingProvider } from 'src/modules/database/entities/database.entity';
77
import {
88
IsBoolean, IsEnum,
99
IsInt,
@@ -255,4 +255,14 @@ export class Database {
255255
@Type(() => SshOptions)
256256
@ValidateNested()
257257
sshOptions?: SshOptions;
258+
259+
@ApiPropertyOptional({
260+
description: 'Database compressor',
261+
default: Compressor.NONE,
262+
enum: Compressor,
263+
})
264+
@Expose()
265+
@IsEnum(Compressor)
266+
@IsOptional()
267+
compressor?: Compressor = Compressor.NONE;
258268
}

redisinsight/ui/src/pages/browser/components/hash-details/HashDetails.tsx

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ import {
5555
stringToSerializedBufferFormat
5656
} from 'uiSrc/utils'
5757
import { stringToBuffer } from 'uiSrc/utils/formatters/bufferFormatters'
58-
import { decompressingBuffer, getCompressor } from 'uiSrc/utils/decompressors'
58+
import { decompressingBuffer } from 'uiSrc/utils/decompressors'
5959
import { AddFieldsToHashDto, GetHashFieldsResponse, HashFieldDto, } from 'apiSrc/modules/browser/dto/hash.dto'
6060

6161
import PopoverDelete from '../popover-delete/PopoverDelete'
@@ -88,7 +88,7 @@ const HashDetails = (props: Props) => {
8888
} = useSelector(hashDataSelector)
8989
const { loading } = useSelector(hashSelector)
9090
const { viewType } = useSelector(keysSelector)
91-
const { id: instanceId } = useSelector(connectedInstanceSelector)
91+
const { id: instanceId, compressor = null } = useSelector(connectedInstanceSelector)
9292
const { viewFormat: viewFormatProp } = useSelector(selectedKeySelector)
9393
const { name: key, length } = useSelector(selectedKeyDataSelector) ?? { name: '' }
9494
const { loading: updateLoading } = useSelector(updateHashValueStateSelector)
@@ -295,7 +295,7 @@ const HashDetails = (props: Props) => {
295295
className: 'value-table-separate-border',
296296
headerClassName: 'value-table-separate-border',
297297
render: (_name: string, { field: fieldItem }: HashFieldDto, expanded?: boolean) => {
298-
const { value: decompressedItem } = decompressingBuffer(fieldItem)
298+
const { value: decompressedItem } = decompressingBuffer(fieldItem, compressor)
299299
const field = bufferToString(fieldItem) || ''
300300
// Better to cut the long string, because it could affect virtual scroll performance
301301
const tooltipContent = formatLongName(field)
@@ -333,8 +333,8 @@ const HashDetails = (props: Props) => {
333333
expanded?: boolean,
334334
rowIndex = 0
335335
) {
336-
const { value: decompressedFieldItem } = decompressingBuffer(fieldItem)
337-
const { value: decompressedValueItem } = decompressingBuffer(valueItem)
336+
const { value: decompressedFieldItem } = decompressingBuffer(fieldItem, compressor)
337+
const { value: decompressedValueItem } = decompressingBuffer(valueItem, compressor)
338338
const value = bufferToString(valueItem)
339339
const field = bufferToString(decompressedFieldItem)
340340
// Better to cut the long string, because it could affect virtual scroll performance
@@ -434,7 +434,6 @@ const HashDetails = (props: Props) => {
434434
minWidth: 95,
435435
maxWidth: 95,
436436
render: function Actions(_act: any, { field: fieldItem, value: valueItem }: HashFieldDto, _, rowIndex?: number) {
437-
const compressor = getCompressor(valueItem)
438437
const field = bufferToString(fieldItem, viewFormat)
439438
const isEditable = !compressor && isFormatEditable(viewFormat)
440439
const tooltipContent = compressor ? TEXT_DISABLED_COMPRESSED_VALUE : TEXT_DISABLED_FORMATTER_EDITING

redisinsight/ui/src/pages/browser/components/key-details-header/KeyDetailsHeader.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,10 @@ const KeyDetailsHeader = ({
9494
nameString: keyProp,
9595
name: keyBuffer,
9696
} = useSelector(selectedKeyDataSelector) ?? initialKeyInfo
97-
const { id: instanceId } = useSelector(connectedInstanceSelector)
97+
const { id: instanceId, compressor = null } = useSelector(connectedInstanceSelector)
9898
const { viewType } = useSelector(keysSelector)
9999
const { viewType: streamViewType } = useSelector(streamSelector)
100-
const { viewFormat: viewFormatProp, compressor } = useSelector(selectedKeySelector)
100+
const { viewFormat: viewFormatProp } = useSelector(selectedKeySelector)
101101

102102
const [isPopoverDeleteOpen, setIsPopoverDeleteOpen] = useState(false)
103103

redisinsight/ui/src/pages/browser/components/list-details/ListDetails.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ import VirtualTable from 'uiSrc/components/virtual-table/VirtualTable'
5454
import InlineItemEditor from 'uiSrc/components/inline-item-editor/InlineItemEditor'
5555
import { StopPropagation } from 'uiSrc/components/virtual-table'
5656
import { getColumnWidth } from 'uiSrc/components/virtual-grid'
57-
import { decompressingBuffer, getCompressor } from 'uiSrc/utils/decompressors'
57+
import { decompressingBuffer } from 'uiSrc/utils/decompressors'
5858

5959
import {
6060
SetListElementDto,
@@ -87,7 +87,7 @@ const ListDetails = (props: Props) => {
8787
listDataSelector
8888
)
8989
const { name: key } = useSelector(selectedKeyDataSelector) ?? { name: '' }
90-
const { id: instanceId } = useSelector(connectedInstanceSelector)
90+
const { id: instanceId, compressor = null } = useSelector(connectedInstanceSelector)
9191
const { viewType } = useSelector(keysSelector)
9292
const { viewFormat: viewFormatProp } = useSelector(selectedKeySelector)
9393
const { [KeyTypes.List]: listSizes } = useSelector(appContextBrowserKeyDetails)
@@ -280,7 +280,7 @@ const ListDetails = (props: Props) => {
280280
expanded: boolean = false,
281281
rowIndex = 0
282282
) {
283-
const { value: decompressedElementItem } = decompressingBuffer(elementItem)
283+
const { value: decompressedElementItem } = decompressingBuffer(elementItem, compressor)
284284
const element = bufferToString(elementItem)
285285
const tooltipContent = formatLongName(element)
286286
const { value, isValid } = formattingBuffer(decompressedElementItem, viewFormatProp, { expanded })
@@ -379,7 +379,6 @@ const ListDetails = (props: Props) => {
379379
maxWidth: 60,
380380
absoluteWidth: 60,
381381
render: function Actions(_element: any, { index, element }: IListElement) {
382-
const compressor = getCompressor(element)
383382
const isEditable = !compressor && isFormatEditable(viewFormat)
384383
const tooltipContent = compressor ? TEXT_DISABLED_COMPRESSED_VALUE : TEXT_DISABLED_FORMATTER_EDITING
385384
return (

0 commit comments

Comments
 (0)