Skip to content

Commit f2460b3

Browse files
authored
Merge branch 'master' into master
2 parents 89256c6 + a402c55 commit f2460b3

File tree

7 files changed

+231
-23
lines changed

7 files changed

+231
-23
lines changed

.github/actions/run-tests/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ runs:
2525
2626
# Mapping of redis version to redis testing containers
2727
declare -A redis_version_mapping=(
28-
["8.0-M03"]="8.0-M04-pre"
28+
["8.0-M05"]="8.0-M05-pre"
2929
["7.4.2"]="rs-7.4.0-v2"
3030
["7.2.7"]="rs-7.2.0-v14"
3131
)

.github/workflows/build.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
fail-fast: false
1919
matrix:
2020
redis-version:
21-
- "8.0-M03" # 8.0 milestone 4
21+
- "8.0-M05" # 8.0 milestone 5
2222
- "7.4.2" # should use redis stack 7.4
2323
go-version:
2424
- "1.23.x"
@@ -43,7 +43,7 @@ jobs:
4343
4444
# Mapping of redis version to redis testing containers
4545
declare -A redis_version_mapping=(
46-
["8.0-M03"]="8.0-M04-pre"
46+
["8.0-M05"]="8.0-M05-pre"
4747
["7.4.2"]="rs-7.4.0-v2"
4848
)
4949
if [[ -v redis_version_mapping[$REDIS_VERSION] ]]; then
@@ -72,7 +72,7 @@ jobs:
7272
fail-fast: false
7373
matrix:
7474
redis-version:
75-
- "8.0-M03" # 8.0 milestone 4
75+
- "8.0-M05" # 8.0 milestone 5
7676
- "7.4.2" # should use redis stack 7.4
7777
- "7.2.7" # should redis stack 7.2
7878
go-version:

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ test.ci:
1717
(cd "$${dir}" && \
1818
go mod tidy -compat=1.18 && \
1919
go vet && \
20-
go test -coverprofile=coverage.txt -covermode=atomic ./... -race); \
20+
go test -v -coverprofile=coverage.txt -covermode=atomic ./... -race); \
2121
done
2222
cd internal/customvet && go build .
2323
go vet -vettool ./internal/customvet/customvet

docker-compose.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
services:
44
redis:
55
image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:rs-7.4.0-v2}
6+
platform: linux/amd64
67
container_name: redis-standalone
78
environment:
89
- TLS_ENABLED=yes
@@ -23,6 +24,7 @@ services:
2324

2425
osscluster:
2526
image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:rs-7.4.0-v2}
27+
platform: linux/amd64
2628
container_name: redis-osscluster
2729
environment:
2830
- NODES=6
@@ -39,6 +41,7 @@ services:
3941

4042
sentinel-cluster:
4143
image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:rs-7.4.0-v2}
44+
platform: linux/amd64
4245
container_name: redis-sentinel-cluster
4346
network_mode: "host"
4447
environment:
@@ -58,6 +61,7 @@ services:
5861

5962
sentinel:
6063
image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:rs-7.4.0-v2}
64+
platform: linux/amd64
6165
container_name: redis-sentinel
6266
depends_on:
6367
- sentinel-cluster
@@ -81,6 +85,7 @@ services:
8185

8286
ring-cluster:
8387
image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:rs-7.4.0-v2}
88+
platform: linux/amd64
8489
container_name: redis-ring-cluster
8590
environment:
8691
- NODES=3

extra/rediscmd/rediscmd.go

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ func CmdString(cmd redis.Cmder) string {
1717
}
1818

1919
func CmdsString(cmds []redis.Cmder) (string, string) {
20-
const numCmdLimit = 100
2120
const numNameLimit = 10
2221

2322
seen := make(map[string]struct{}, numNameLimit)
@@ -26,10 +25,6 @@ func CmdsString(cmds []redis.Cmder) (string, string) {
2625
b := make([]byte, 0, 32*len(cmds))
2726

2827
for i, cmd := range cmds {
29-
if i > numCmdLimit {
30-
break
31-
}
32-
3328
if i > 0 {
3429
b = append(b, '\n')
3530
}
@@ -51,12 +46,7 @@ func CmdsString(cmds []redis.Cmder) (string, string) {
5146
}
5247

5348
func AppendCmd(b []byte, cmd redis.Cmder) []byte {
54-
const numArgLimit = 32
55-
5649
for i, arg := range cmd.Args() {
57-
if i > numArgLimit {
58-
break
59-
}
6050
if i > 0 {
6151
b = append(b, ' ')
6252
}
@@ -72,20 +62,12 @@ func AppendCmd(b []byte, cmd redis.Cmder) []byte {
7262
}
7363

7464
func appendArg(b []byte, v interface{}) []byte {
75-
const argLenLimit = 64
76-
7765
switch v := v.(type) {
7866
case nil:
7967
return append(b, "<nil>"...)
8068
case string:
81-
if len(v) > argLenLimit {
82-
v = v[:argLenLimit]
83-
}
8469
return appendUTF8String(b, Bytes(v))
8570
case []byte:
86-
if len(v) > argLenLimit {
87-
v = v[:argLenLimit]
88-
}
8971
return appendUTF8String(b, v)
9072
case int:
9173
return strconv.AppendInt(b, int64(v), 10)

extra/redisotel/tracing_test.go

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"fmt"
66
"net"
7+
"strings"
78
"testing"
89

910
"go.opentelemetry.io/otel/attribute"
@@ -222,6 +223,169 @@ func TestTracingHook_ProcessPipelineHook(t *testing.T) {
222223
}
223224
}
224225

226+
func TestTracingHook_ProcessHook_LongCommand(t *testing.T) {
227+
imsb := tracetest.NewInMemoryExporter()
228+
provider := sdktrace.NewTracerProvider(sdktrace.WithSyncer(imsb))
229+
hook := newTracingHook(
230+
"redis://localhost:6379",
231+
WithTracerProvider(provider),
232+
)
233+
longValue := strings.Repeat("a", 102400)
234+
235+
tests := []struct {
236+
name string
237+
cmd redis.Cmder
238+
expected string
239+
}{
240+
{
241+
name: "short command",
242+
cmd: redis.NewCmd(context.Background(), "SET", "key", "value"),
243+
expected: "SET key value",
244+
},
245+
{
246+
name: "set command with long key",
247+
cmd: redis.NewCmd(context.Background(), "SET", longValue, "value"),
248+
expected: "SET " + longValue + " value",
249+
},
250+
{
251+
name: "set command with long value",
252+
cmd: redis.NewCmd(context.Background(), "SET", "key", longValue),
253+
expected: "SET key " + longValue,
254+
},
255+
{
256+
name: "set command with long key and value",
257+
cmd: redis.NewCmd(context.Background(), "SET", longValue, longValue),
258+
expected: "SET " + longValue + " " + longValue,
259+
},
260+
{
261+
name: "short command with many arguments",
262+
cmd: redis.NewCmd(context.Background(), "MSET", "key1", "value1", "key2", "value2", "key3", "value3", "key4", "value4", "key5", "value5"),
263+
expected: "MSET key1 value1 key2 value2 key3 value3 key4 value4 key5 value5",
264+
},
265+
{
266+
name: "long command",
267+
cmd: redis.NewCmd(context.Background(), longValue, "key", "value"),
268+
expected: longValue + " key value",
269+
},
270+
}
271+
272+
for _, tt := range tests {
273+
t.Run(tt.name, func(t *testing.T) {
274+
defer imsb.Reset()
275+
276+
processHook := hook.ProcessHook(func(ctx context.Context, cmd redis.Cmder) error {
277+
return nil
278+
})
279+
280+
if err := processHook(context.Background(), tt.cmd); err != nil {
281+
t.Fatal(err)
282+
}
283+
284+
assertEqual(t, 1, len(imsb.GetSpans()))
285+
286+
spanData := imsb.GetSpans()[0]
287+
288+
var dbStatement string
289+
for _, attr := range spanData.Attributes {
290+
if attr.Key == semconv.DBStatementKey {
291+
dbStatement = attr.Value.AsString()
292+
break
293+
}
294+
}
295+
296+
if dbStatement != tt.expected {
297+
t.Errorf("Expected DB statement: %q\nGot: %q", tt.expected, dbStatement)
298+
}
299+
})
300+
}
301+
}
302+
303+
func TestTracingHook_ProcessPipelineHook_LongCommands(t *testing.T) {
304+
imsb := tracetest.NewInMemoryExporter()
305+
provider := sdktrace.NewTracerProvider(sdktrace.WithSyncer(imsb))
306+
hook := newTracingHook(
307+
"redis://localhost:6379",
308+
WithTracerProvider(provider),
309+
)
310+
311+
tests := []struct {
312+
name string
313+
cmds []redis.Cmder
314+
expected string
315+
}{
316+
{
317+
name: "multiple short commands",
318+
cmds: []redis.Cmder{
319+
redis.NewCmd(context.Background(), "SET", "key1", "value1"),
320+
redis.NewCmd(context.Background(), "SET", "key2", "value2"),
321+
},
322+
expected: "SET key1 value1\nSET key2 value2",
323+
},
324+
{
325+
name: "multiple short commands with long key",
326+
cmds: []redis.Cmder{
327+
redis.NewCmd(context.Background(), "SET", strings.Repeat("a", 102400), "value1"),
328+
redis.NewCmd(context.Background(), "SET", strings.Repeat("b", 102400), "value2"),
329+
},
330+
expected: "SET " + strings.Repeat("a", 102400) + " value1\nSET " + strings.Repeat("b", 102400) + " value2",
331+
},
332+
{
333+
name: "multiple short commands with long value",
334+
cmds: []redis.Cmder{
335+
redis.NewCmd(context.Background(), "SET", "key1", strings.Repeat("a", 102400)),
336+
redis.NewCmd(context.Background(), "SET", "key2", strings.Repeat("b", 102400)),
337+
},
338+
expected: "SET key1 " + strings.Repeat("a", 102400) + "\nSET key2 " + strings.Repeat("b", 102400),
339+
},
340+
{
341+
name: "multiple short commands with long key and value",
342+
cmds: []redis.Cmder{
343+
redis.NewCmd(context.Background(), "SET", strings.Repeat("a", 102400), strings.Repeat("b", 102400)),
344+
redis.NewCmd(context.Background(), "SET", strings.Repeat("c", 102400), strings.Repeat("d", 102400)),
345+
},
346+
expected: "SET " + strings.Repeat("a", 102400) + " " + strings.Repeat("b", 102400) + "\nSET " + strings.Repeat("c", 102400) + " " + strings.Repeat("d", 102400),
347+
},
348+
{
349+
name: "multiple long commands",
350+
cmds: []redis.Cmder{
351+
redis.NewCmd(context.Background(), strings.Repeat("a", 102400), "key1", "value1"),
352+
redis.NewCmd(context.Background(), strings.Repeat("a", 102400), "key2", "value2"),
353+
},
354+
expected: strings.Repeat("a", 102400) + " key1 value1\n" + strings.Repeat("a", 102400) + " key2 value2",
355+
},
356+
}
357+
358+
for _, tt := range tests {
359+
t.Run(tt.name, func(t *testing.T) {
360+
defer imsb.Reset()
361+
362+
processHook := hook.ProcessPipelineHook(func(ctx context.Context, cmds []redis.Cmder) error {
363+
return nil
364+
})
365+
366+
if err := processHook(context.Background(), tt.cmds); err != nil {
367+
t.Fatal(err)
368+
}
369+
370+
assertEqual(t, 1, len(imsb.GetSpans()))
371+
372+
spanData := imsb.GetSpans()[0]
373+
374+
var dbStatement string
375+
for _, attr := range spanData.Attributes {
376+
if attr.Key == semconv.DBStatementKey {
377+
dbStatement = attr.Value.AsString()
378+
break
379+
}
380+
}
381+
382+
if dbStatement != tt.expected {
383+
t.Errorf("Expected DB statement:\n%q\nGot:\n%q", tt.expected, dbStatement)
384+
}
385+
})
386+
}
387+
}
388+
225389
func assertEqual(t *testing.T, expected, actual interface{}) {
226390
t.Helper()
227391
if expected != actual {

search_test.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1626,6 +1626,63 @@ var _ = Describe("RediSearch commands Resp 2", Label("search"), func() {
16261626
Expect(res.Docs[0].ID).To(BeEquivalentTo("property:1"))
16271627
Expect(res.Docs[1].ID).To(BeEquivalentTo("property:2"))
16281628
})
1629+
1630+
It("should FTCreate VECTOR with int8 and uint8 types", Label("search", "ftcreate"), func() {
1631+
SkipBeforeRedisVersion(7.9, "doesn't work with older redis")
1632+
// Define INT8 vector field
1633+
hnswOptionsInt8 := &redis.FTHNSWOptions{
1634+
Type: "INT8",
1635+
Dim: 2,
1636+
DistanceMetric: "L2",
1637+
}
1638+
1639+
// Define UINT8 vector field
1640+
hnswOptionsUint8 := &redis.FTHNSWOptions{
1641+
Type: "UINT8",
1642+
Dim: 2,
1643+
DistanceMetric: "L2",
1644+
}
1645+
1646+
// Create index with INT8 and UINT8 vector fields
1647+
val, err := client.FTCreate(ctx, "idx1",
1648+
&redis.FTCreateOptions{},
1649+
&redis.FieldSchema{FieldName: "int8_vector", FieldType: redis.SearchFieldTypeVector, VectorArgs: &redis.FTVectorArgs{HNSWOptions: hnswOptionsInt8}},
1650+
&redis.FieldSchema{FieldName: "uint8_vector", FieldType: redis.SearchFieldTypeVector, VectorArgs: &redis.FTVectorArgs{HNSWOptions: hnswOptionsUint8}},
1651+
).Result()
1652+
1653+
Expect(err).NotTo(HaveOccurred())
1654+
Expect(val).To(BeEquivalentTo("OK"))
1655+
WaitForIndexing(client, "idx1")
1656+
1657+
// Insert vectors in int8 and uint8 format
1658+
client.HSet(ctx, "doc1", "int8_vector", "\x01\x02", "uint8_vector", "\x01\x02")
1659+
client.HSet(ctx, "doc2", "int8_vector", "\x03\x04", "uint8_vector", "\x03\x04")
1660+
1661+
// Perform KNN search on INT8 vector
1662+
searchOptionsInt8 := &redis.FTSearchOptions{
1663+
Return: []redis.FTSearchReturn{{FieldName: "int8_vector"}},
1664+
SortBy: []redis.FTSearchSortBy{{FieldName: "int8_vector", Asc: true}},
1665+
DialectVersion: 2,
1666+
Params: map[string]interface{}{"vec": "\x01\x02"},
1667+
}
1668+
1669+
resInt8, err := client.FTSearchWithArgs(ctx, "idx1", "*=>[KNN 1 @int8_vector $vec]", searchOptionsInt8).Result()
1670+
Expect(err).NotTo(HaveOccurred())
1671+
Expect(resInt8.Docs[0].ID).To(BeEquivalentTo("doc1"))
1672+
1673+
// Perform KNN search on UINT8 vector
1674+
searchOptionsUint8 := &redis.FTSearchOptions{
1675+
Return: []redis.FTSearchReturn{{FieldName: "uint8_vector"}},
1676+
SortBy: []redis.FTSearchSortBy{{FieldName: "uint8_vector", Asc: true}},
1677+
DialectVersion: 2,
1678+
Params: map[string]interface{}{"vec": "\x01\x02"},
1679+
}
1680+
1681+
resUint8, err := client.FTSearchWithArgs(ctx, "idx1", "*=>[KNN 1 @uint8_vector $vec]", searchOptionsUint8).Result()
1682+
Expect(err).NotTo(HaveOccurred())
1683+
Expect(resUint8.Docs[0].ID).To(BeEquivalentTo("doc1"))
1684+
})
1685+
16291686
})
16301687

16311688
func _assert_geosearch_result(result *redis.FTSearchResult, expectedDocIDs []string) {

0 commit comments

Comments
 (0)