Skip to content

Commit 22127b1

Browse files
authored
Merge pull request #1889 from RedisInsight/fe/feature/decompress-brotli
#RI-4146 - add Brotli decompression
2 parents bb072ea + c062504 commit 22127b1

File tree

8 files changed

+78
-8
lines changed

8 files changed

+78
-8
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@
222222
"@reduxjs/toolkit": "^1.6.2",
223223
"@stablelib/snappy": "^1.0.2",
224224
"axios": "^0.25.0",
225+
"brotli-unicode": "^1.0.2",
225226
"buffer": "^6.0.3",
226227
"classnames": "^2.3.1",
227228
"connection-string": "^4.3.2",

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export enum Compressor {
3131
ZSTD = 'ZSTD',
3232
LZ4 = 'LZ4',
3333
SNAPPY = 'SNAPPY',
34+
Brotli = 'Brotli',
3435
}
3536

3637
@Entity('database_instance')

redisinsight/ui/src/constants/keys.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ export enum KeyValueCompressor {
186186
ZSTD = 'ZSTD',
187187
LZ4 = 'LZ4',
188188
SNAPPY = 'SNAPPY',
189-
// Brotli = 'Brotli',
189+
Brotli = 'Brotli',
190190
// PHPGZCompress = 'PHPGZCompress',
191191
}
192192

@@ -195,6 +195,7 @@ export const COMPRESSOR_MAGIC_SYMBOLS: ICompressorMagicSymbols = Object.freeze({
195195
[KeyValueCompressor.ZSTD]: '40,181,47,253', // 28 b5 2f fd hex
196196
[KeyValueCompressor.LZ4]: '4,34,77,24', // 04 22 4d 18 hex
197197
[KeyValueCompressor.SNAPPY]: '', // no magic symbols
198+
[KeyValueCompressor.Brotli]: '', // no magic symbols
198199
})
199200

200201
export type ICompressorMagicSymbols = {

redisinsight/ui/src/pages/home/components/AddInstanceForm/InstanceForm/form-components/DbCompressor.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ const DbCompressor = (props: Props) => {
4646
value: KeyValueCompressor.ZSTD,
4747
inputDisplay: 'ZSTD',
4848
},
49+
{
50+
value: KeyValueCompressor.Brotli,
51+
inputDisplay: 'Brotli'
52+
}
4953
]
5054

5155
const handleChangeDbCompressorCheckbox = (e: ChangeEvent<HTMLInputElement>): void => {

redisinsight/ui/src/utils/decompressors/decompressors.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,18 @@ import { unzip } from 'gzip-js'
33
import { decompress as decompressFzstd } from 'fzstd'
44
import { decompress as decompressLz4 } from 'lz4js'
55
import { decompress as decompressSnappy } from '@stablelib/snappy'
6+
import { decompress as decompressBrotli } from 'brotli-unicode/js'
67
import { COMPRESSOR_MAGIC_SYMBOLS, ICompressorMagicSymbols, KeyValueCompressor } from 'uiSrc/constants'
78
import { RedisResponseBuffer, RedisString } from 'uiSrc/slices/interfaces'
8-
import { anyToBuffer, isEqualBuffers, Nullable } from 'uiSrc/utils'
9+
import { anyToBuffer, bufferToString, isEqualBuffers, Nullable } from 'uiSrc/utils'
910

1011
const decompressingBuffer = (
1112
reply: RedisResponseBuffer,
1213
compressorInit: Nullable<KeyValueCompressor> = null,
1314
): { value: RedisString, compressor: Nullable<KeyValueCompressor>, isCompressed: boolean } => {
1415
const compressorByValue: Nullable<KeyValueCompressor> = getCompressor(reply)
1516
const compressor = compressorInit === compressorByValue
16-
|| (!compressorByValue && compressorInit === KeyValueCompressor.SNAPPY)
17+
|| (!compressorByValue && compressorInit)
1718
? compressorInit
1819
: null
1920

@@ -56,6 +57,15 @@ const decompressingBuffer = (
5657
isCompressed: !isEqualBuffers(value, reply),
5758
}
5859
}
60+
case KeyValueCompressor.Brotli: {
61+
const value = anyToBuffer(decompressBrotli(bufferToString(reply)))
62+
63+
return {
64+
value,
65+
compressor,
66+
isCompressed: !isEqualBuffers(value, reply),
67+
}
68+
}
5969
default: {
6070
return { value: reply, compressor: null, isCompressed: false }
6171
}
@@ -73,10 +83,9 @@ const getCompressor = (reply: RedisResponseBuffer): Nullable<KeyValueCompressor>
7383
COMPRESSOR_MAGIC_SYMBOLS,
7484
(magicSymbols: string, compressorName: string) => {
7585
if (
76-
replyStart.startsWith(magicSymbols)
86+
magicSymbols
87+
&& replyStart.startsWith(magicSymbols)
7788
&& replyStart.length > magicSymbols.length
78-
// no magic symbols for SNAPPY
79-
&& compressorName !== KeyValueCompressor.SNAPPY
8089
) {
8190
compressor = compressorName as KeyValueCompressor
8291
return false // break loop

redisinsight/ui/src/utils/tests/decompressors/constants.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,6 @@ export const LZ4_COMPRESSED_VALUE_2 = [4, 34, 77, 24, 64, 112, 223, 1, 0, 0, 128
1818

1919
export const SNAPPY_COMPRESSED_VALUE_1 = [1, 0, 49]
2020
export const SNAPPY_COMPRESSED_VALUE_2 = [1, 0, 50]
21+
22+
export const BROTLI_COMPRESSED_VALUE_1 = [49, 65, 76, 231, 187, 141, 68]
23+
export const BROTLI_COMPRESSED_VALUE_2 = [49, 65, 76, 231, 191, 141, 68]

redisinsight/ui/src/utils/tests/decompressors/decompressors.spec.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import {
1616
LZ4_COMPRESSED_VALUE_2,
1717
SNAPPY_COMPRESSED_VALUE_2,
1818
SNAPPY_COMPRESSED_VALUE_1,
19+
BROTLI_COMPRESSED_VALUE_1,
20+
BROTLI_COMPRESSED_VALUE_2,
1921
} from './constants'
2022

2123
const defaultValues = [
@@ -111,6 +113,22 @@ const defaultValues = [
111113
outputStr: DECOMPRESSED_VALUE_STR_1,
112114
isCompressed: false,
113115
},
116+
{
117+
input: BROTLI_COMPRESSED_VALUE_1,
118+
compressor: KeyValueCompressor.Brotli,
119+
compressorInit: KeyValueCompressor.Brotli,
120+
output: DECOMPRESSED_VALUE_1,
121+
outputStr: DECOMPRESSED_VALUE_STR_1,
122+
isCompressed: true,
123+
},
124+
{
125+
input: BROTLI_COMPRESSED_VALUE_2,
126+
compressor: KeyValueCompressor.Brotli,
127+
compressorInit: KeyValueCompressor.Brotli,
128+
output: DECOMPRESSED_VALUE_2,
129+
outputStr: DECOMPRESSED_VALUE_STR_2,
130+
isCompressed: true,
131+
},
114132
].map((value) => ({
115133
...value,
116134
input: anyToBuffer(value.input)
@@ -121,7 +139,7 @@ describe('getCompressor', () => {
121139
let expected = compressorByValue || compressor
122140

123141
// SNAPPY doesn't have magic symbols
124-
if (compressor === KeyValueCompressor.SNAPPY) {
142+
if (compressor === KeyValueCompressor.SNAPPY || compressor === KeyValueCompressor.Brotli) {
125143
expected = null
126144
}
127145

yarn.lock

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2659,6 +2659,11 @@
26592659
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.43.tgz#555e5a743f76b6b897d47f945305b618525ddbe6"
26602660
integrity sha512-GqWykok+3uocgfAJM8imbozrqLnPyTrpFlrryURQlw1EesPUCx5XxTiucWDSFF9/NUEXDuD4bnvHm8xfVGWTpQ==
26612661

2662+
"@types/node@^17.0.40":
2663+
version "17.0.45"
2664+
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190"
2665+
integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==
2666+
26622667
"@types/normalize-package-data@^2.4.0":
26632668
version "2.4.1"
26642669
resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301"
@@ -4169,6 +4174,13 @@ balanced-match@^1.0.0:
41694174
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
41704175
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
41714176

4177+
base-unicode@^1.0.0:
4178+
version "1.0.0"
4179+
resolved "https://registry.yarnpkg.com/base-unicode/-/base-unicode-1.0.0.tgz#44b61fd4460b18f6d47ae6f5ea95a45b16a4885a"
4180+
integrity sha512-9y/0iVN7k3NyH0E4oYD/1qZceUVE180YcRRqhsQVNzazPcuRjr67SjUzl/wdhLaVmzjIMEjE5pDH7xb6X9kBFA==
4181+
dependencies:
4182+
buffer "^6.0.3"
4183+
41724184
base64-arraybuffer@~1.0.1:
41734185
version "1.0.1"
41744186
resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-1.0.1.tgz#87bd13525626db4a9838e00a508c2b73efcf348c"
@@ -4343,6 +4355,27 @@ brorand@^1.0.1, brorand@^1.1.0:
43434355
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
43444356
integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=
43454357

4358+
brotli-compress@^1.3.3:
4359+
version "1.3.3"
4360+
resolved "https://registry.yarnpkg.com/brotli-compress/-/brotli-compress-1.3.3.tgz#fe3b50b6234bfbc8e26a137bffff2a07e2a4efe9"
4361+
integrity sha512-cwKOmzEuKqUmRxXDdZimiNoXRRr7AQKMSubJSbYA9FXk+LTPT3fBGpHU8VZRZZctAJ5OCeXGK9PzPpZ1vD0pDA==
4362+
dependencies:
4363+
"@types/node" "^17.0.40"
4364+
brotli-wasm "1.2.0"
4365+
4366+
brotli-unicode@^1.0.2:
4367+
version "1.0.2"
4368+
resolved "https://registry.yarnpkg.com/brotli-unicode/-/brotli-unicode-1.0.2.tgz#25e53a7fdc543337768e90fd59a94b6eb55ea6cc"
4369+
integrity sha512-eqO2kauz48Raqi0I8c4WOhvfr5GAtpHhCvegHRTY00zyn6pEP8jo5nHrwtAJKO68j1ZFi4zel6JrwBz60Z5d3g==
4370+
dependencies:
4371+
base-unicode "^1.0.0"
4372+
brotli-compress "^1.3.3"
4373+
4374+
4375+
version "1.2.0"
4376+
resolved "https://registry.yarnpkg.com/brotli-wasm/-/brotli-wasm-1.2.0.tgz#0f99b97b0020c8152308c277388aecf2a06b6e32"
4377+
integrity sha512-PdDi7awF36zFujZyFJb9UNrP1l+If7iCgXhLKE1SpwqFQSK2yc7w2dysOmME7p325yQaZNvae7ruzypB3YhFxA==
4378+
43464379
browser-process-hrtime@^1.0.0:
43474380
version "1.0.0"
43484381
resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626"
@@ -11495,7 +11528,7 @@ [email protected]:
1149511528
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
1149611529
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
1149711530

11498-
minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6:
11531+
minimist@^1.2.0, minimist@^1.2.6:
1149911532
version "1.2.8"
1150011533
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
1150111534
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==

0 commit comments

Comments
 (0)