Skip to content

Commit 21bfba8

Browse files
authored
Merge pull request #2843 from RedisInsight/feature/browser-vector-type-viz
Browser: Add support for vector 32bit and 64bit
2 parents 851decc + f8273f0 commit 21bfba8

File tree

8 files changed

+128
-8
lines changed

8 files changed

+128
-8
lines changed

redisinsight/ui/src/constants/keys.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ export enum KeyValueFormat {
146146
JAVA = 'Java serialized',
147147
Protobuf = 'Protobuf',
148148
Pickle = 'Pickle',
149+
Vector32Bit = 'Vector 32-bit',
150+
Vector64Bit = 'Vector 64-bit',
149151
}
150152

151153
export enum KeyValueCompressor {

redisinsight/ui/src/pages/browser/modules/key-details-header/components/key-details-header-formatter/KeyDetailsHeaderFormatter.spec.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ describe('KeyValueFormatter', () => {
2525
'Protobuf',
2626
'PHP serialized',
2727
'Java serialized',
28+
'Vector 32-bit',
29+
'Vector 64-bit',
2830
]
2931
render(<KeyDetailsHeaderFormatter {...mockedProps} />)
3032

redisinsight/ui/src/pages/browser/modules/key-details-header/components/key-details-header-formatter/constants.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@ export const KEY_VALUE_FORMATTER_OPTIONS = [
4141
text: 'Java serialized',
4242
value: KeyValueFormat.JAVA,
4343
},
44+
{
45+
text: 'Vector 32-bit',
46+
value: KeyValueFormat.Vector32Bit,
47+
},
48+
{
49+
text: 'Vector 64-bit',
50+
value: KeyValueFormat.Vector64Bit,
51+
},
4452
]
4553

4654
export const KEY_VALUE_JSON_FORMATTER_OPTIONS = []

redisinsight/ui/src/utils/formatters/bufferFormatters.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,29 @@ const ASCIIToBuffer = (strInit: string) => {
107107
return anyToBuffer(Array.from(Buffer.from(result, 'hex')))
108108
}
109109

110+
const bufferToFloat32Array = (data: Uint8Array) => {
111+
const buffer = new Uint8Array(data).buffer
112+
const dataView = new DataView(buffer)
113+
let vector = []
114+
115+
for(let i = 0; i < dataView.byteLength; i += 4) {
116+
vector.push(dataView.getFloat32(i, true))
117+
}
118+
return new Float32Array(vector)
119+
}
120+
121+
const bufferToFloat64Array = (data: Uint8Array) => {
122+
const buffer = new Uint8Array(data).buffer
123+
const dataView = new DataView(buffer)
124+
const vector = []
125+
126+
for (let i = 0; i < dataView.byteLength; i += 8) {
127+
vector.push(dataView.getFloat64(i, true))
128+
}
129+
return new Float64Array(vector)
130+
}
131+
132+
110133
const bufferToUint8Array = (reply: RedisResponseBuffer): Uint8Array => new Uint8Array(reply.data)
111134
const bufferToUTF8 = (reply: RedisResponseBuffer): string => decoder.decode(bufferToUint8Array(reply))
112135

@@ -186,7 +209,9 @@ export {
186209
anyToBuffer,
187210
bufferToBinary,
188211
binaryToBuffer,
189-
bufferToJava
212+
bufferToJava,
213+
bufferToFloat32Array,
214+
bufferToFloat64Array,
190215
}
191216

192217
window.ri = {

redisinsight/ui/src/utils/formatters/valueFormatters.tsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import {
2121
stringToBuffer,
2222
binaryToBuffer,
2323
Maybe,
24+
bufferToFloat64Array,
25+
bufferToFloat32Array,
2426
} from 'uiSrc/utils'
2527
import { reSerializeJSON } from 'uiSrc/utils/formatters/json'
2628

@@ -39,6 +41,8 @@ const isFormatEditable = (format: KeyValueFormat) => ![
3941
KeyValueFormat.Protobuf,
4042
KeyValueFormat.JAVA,
4143
KeyValueFormat.Pickle,
44+
KeyValueFormat.Vector32Bit,
45+
KeyValueFormat.Vector64Bit,
4246
].includes(format)
4347

4448
const isFullStringLoaded = (currentLength: Maybe<number>, fullLength: Maybe<number>) => currentLength === fullLength
@@ -100,6 +104,25 @@ const formattingBuffer = (
100104
return { value: bufferToUTF8(reply), isValid: false }
101105
}
102106
}
107+
case KeyValueFormat.Vector32Bit: {
108+
try {
109+
const vector = Array.from(bufferToFloat32Array(reply.data))
110+
const value = JSONBigInt.stringify(vector)
111+
return JSONViewer({ value, ...props })
112+
} catch (e) {
113+
return { value: bufferToUTF8(reply), isValid: false }
114+
}
115+
}
116+
case KeyValueFormat.Vector64Bit: {
117+
try {
118+
const vector = Array.from(bufferToFloat64Array(reply.data))
119+
const value = JSONBigInt.stringify(vector)
120+
121+
return JSONViewer({ value, ...props })
122+
} catch (e) {
123+
return { value: bufferToUTF8(reply), isValid: false }
124+
}
125+
}
103126
case KeyValueFormat.Protobuf: {
104127
try {
105128
const decoded = getData(Buffer.from(reply.data))
@@ -141,6 +164,8 @@ const bufferToSerializedFormat = (
141164
case KeyValueFormat.HEX: return bufferToHex(value)
142165
case KeyValueFormat.Binary: return bufferToBinary(value)
143166
case KeyValueFormat.JSON: return reSerializeJSON(bufferToUTF8(value), space)
167+
case KeyValueFormat.Vector32Bit: return bufferToFloat32Array(value.data)
168+
case KeyValueFormat.Vector64Bit: return bufferToFloat64Array(value.data)
144169
case KeyValueFormat.Msgpack: {
145170
try {
146171
const decoded = decode(Uint8Array.from(value.data))

redisinsight/ui/src/utils/tests/formatters/valueFormatters.spec.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,54 @@ describe('bufferToSerializedFormat', () => {
2222
})
2323
})
2424

25+
describe(KeyValueFormat.Vector32Bit, () => {
26+
describe('should properly serialize', () => {
27+
const testValues = [new Float32Array([1.0, 2.0]), new Float32Array([12.12, 13.41])].map((v) => ({
28+
input: anyToBuffer(v.buffer),
29+
expected: JSON.stringify(v),
30+
}))
31+
32+
test.each(testValues)('test %j', ({input, expected }) => {
33+
expect(JSON.stringify(bufferToSerializedFormat(KeyValueFormat.Vector32Bit, input))).toEqual(expected)
34+
})
35+
})
36+
37+
describe('should properly return value with invalid values', () => {
38+
const testValues = [new Float32Array(['test'])].map((v) => ({
39+
input: anyToBuffer(v.buffer),
40+
expected: JSON.stringify(v),
41+
}))
42+
43+
test.each(testValues)('test %j', ({input, expected }) => {
44+
expect(JSON.stringify(bufferToSerializedFormat(KeyValueFormat.Vector32Bit, input))).toEqual(expected)
45+
})
46+
})
47+
})
48+
49+
describe(KeyValueFormat.Vector64Bit, () => {
50+
describe('should properly serialize', () => {
51+
const testValues = [new Float64Array([1.0, 2.0]), new Float64Array([12.12, 13.41])].map((v) => ({
52+
input: anyToBuffer(v.buffer),
53+
expected: JSON.stringify(v),
54+
}))
55+
56+
test.each(testValues)('test %j', ({input, expected }) => {
57+
expect(JSON.stringify(bufferToSerializedFormat(KeyValueFormat.Vector64Bit, input))).toEqual(expected)
58+
})
59+
})
60+
61+
describe('should properly return value with invalid values', () => {
62+
const testValues = [new Float64Array(['test'])].map((v) => ({
63+
input: anyToBuffer(v.buffer),
64+
expected: JSON.stringify(v),
65+
}))
66+
67+
test.each(testValues)('test %j', ({input, expected }) => {
68+
expect(JSON.stringify(bufferToSerializedFormat(KeyValueFormat.Vector64Bit, input))).toEqual(expected)
69+
})
70+
})
71+
})
72+
2573
describe(KeyValueFormat.Msgpack, () => {
2674
describe('should properly serialize', () => {
2775
const testValues = [{}, '""', 6677, true, { a: { b: [1, 2, '3'] } }].map((v) => ({

tests/e2e/test-data/formatters-data.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,16 @@ export const formatters = [{
5555
format: 'Pickle',
5656
fromHexText: '286470300a5327617272270a70310a286c70320a49310a6149320a617353276f626a270a70330a286470340a532761270a70350a532762270a70360a7373532748656c6c6f270a70370a5327776f726c64270a70380a732e',
5757
formattedText: '{ "arr": [ 1, 2 ], "obj": { "a": "b" }, "Hello": "world" }'
58+
},
59+
{
60+
format: 'Vector 32-bit',
61+
fromHexText: '0000803f0000004000004040',
62+
formattedText: '[ 1, 2, 3 ]',
63+
},
64+
{
65+
format: 'Vector 64-bit',
66+
fromHexText: '000000000000f03f00000000000000400000000000000840',
67+
formattedText: '[ 1, 2, 3 ]',
5868
}];
5969

6070
/**

tests/e2e/tests/web/critical-path/browser/formatters.e2e.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ const keysData = keyTypes.map(object => ({ ...object })).filter((v, i) => i <= 6
1616
keysData.forEach(key => key.keyName = `${key.keyName}` + '-' + `${Common.generateWord(keyLength)}`);
1717
const binaryFormattersSet = [formatters[5], formatters[6], formatters[7]];
1818
const formattersHighlightedSet = [formatters[0], formatters[3]];
19-
const fromBinaryFormattersSet = [formatters[1], formatters[2], formatters[4], formatters[8]];
19+
const fromBinaryFormattersSet = [formatters[1], formatters[2], formatters[4], formatters[8], formatters[9], formatters[10]];
2020
const formattersForEditSet = [formatters[0], formatters[1], formatters[3]];
21-
const formattersWithTooltipSet = [formatters[0], formatters[1], formatters[2], formatters[3], formatters[4], formatters[8]];
22-
const notEditableFormattersSet = [formatters[2], formatters[4], formatters[8]];
21+
const formattersWithTooltipSet = [formatters[0], formatters[1], formatters[2], formatters[3], formatters[4], formatters[8], formatters[9], formatters[10]];
22+
const notEditableFormattersSet = [formatters[2], formatters[4], formatters[8], formatters[9], formatters[10]];
2323
const defaultFormatter = 'Unicode';
2424

2525
fixture `Formatters`
@@ -69,7 +69,7 @@ formattersHighlightedSet.forEach(formatter => {
6969
});
7070
fromBinaryFormattersSet.forEach(formatter => {
7171
test(`Verify that user can see highlighted key details in ${formatter.format} format`, async t => {
72-
// Verify for Msgpack, Protobuf, Java serialized, Pickle formats
72+
// Verify for Msgpack, Protobuf, Java serialized, Pickle, Vector 32-bit, Vector 64-bit formats
7373
// Open Hash key details
7474
await browserPage.openKeyDetailsByKeyName(keysData[0].keyName);
7575
// Add valid value in HEX format for convertion
@@ -112,8 +112,8 @@ formattersForEditSet.forEach(formatter => {
112112
});
113113
});
114114
formattersWithTooltipSet.forEach(formatter => {
115-
test(`Verify that user can see tooltip with convertion failed message on hover when data is not valid ${formatter.format}`, async t => {
116-
// Verify for JSON, Msgpack, Protobuf, PHP serialized, Java serialized object, Pickle formatters
115+
test(` ${formatter.format}`, async t => {
116+
// Verify for JSON, Msgpack, Protobuf, PHP serialized, Java serialized object, Pickle, Vector 32-bit, Vector 64-bit formatters
117117
const failedMessage = `Failed to convert to ${formatter.format}`;
118118
for (let i = 0; i < keysData.length; i++) {
119119
const valueSelector = Selector(`[data-testid^=${keysData[i].keyName.split('-')[0]}-][data-testid*=${keysData[i].data}]`);
@@ -190,7 +190,7 @@ test('Verify that user can format different data types of PHP serialized', async
190190
});
191191
notEditableFormattersSet.forEach(formatter => {
192192
test(`Verify that user see edit icon disabled for all keys when ${formatter.format} selected`, async t => {
193-
// Verify for Protobuf, Java serialized, Pickle
193+
// Verify for Protobuf, Java serialized, Pickle, Vector 32-bit, Vector 64-bit
194194
// Verify for Hash, List, ZSet, String keys
195195
for (const key of keysData) {
196196
if (key.textType === 'Hash' || key.textType === 'List' || key.textType === 'String') {

0 commit comments

Comments
 (0)