Skip to content

Commit 5ddbd2e

Browse files
committed
msgpack: add optional msgpack.v5 support
The msgpack.v5 code located in msgpack_v5.go and msgpack_v5_helper_test.go for tests. It is the same logic for submodules. An user can use msgpack.v5 with a build tag: go_tarantool_msgpack_v5 Part of #124
1 parent 8ab808c commit 5ddbd2e

26 files changed

+453
-29
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ CI and documentation.
4444
- queue-utube handling (#85)
4545
- Master discovery (#113)
4646
- SQL support (#62)
47+
- Optional msgpack.v5 usage (#124)
4748

4849
### Changed
4950

README.md

+34-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ faster than other packages according to public benchmarks.
2626
* [Documentation](#documentation)
2727
* [API reference](#api-reference)
2828
* [Walking\-through example](#walking-through-example)
29+
* [msgpack.v5 migration](#msgpackv5-migration)
2930
* [Contributing](#contributing)
3031
* [Alternative connectors](#alternative-connectors)
3132

@@ -68,7 +69,15 @@ This allows us to introduce new features without losing backward compatibility.
6869
go_tarantool_call_17
6970
```
7071
**Note:** In future releases, `Call17` may be used as default `Call` behavior.
71-
3. To run fuzz tests with decimals, you can use the build tag:
72+
3. To replace usage of `msgpack.v2` with `msgpack.v5`, you can use the build
73+
tag:
74+
```
75+
go_tarantool_msgpack_v5
76+
```
77+
**Note:** In future releases, `msgpack.v5` may be used by default. We recommend
78+
to read [msgpack.v5 migration notes](#msgpackv5-migration) and try to
79+
use msgpack.v5 before the changes.
80+
4. To run fuzz tests with decimals, you can use the build tag:
7281
```
7382
go_tarantool_decimal_fuzzing
7483
```
@@ -144,6 +153,30 @@ There are two parameters:
144153
* a space number (it could just as easily have been a space name), and
145154
* a tuple.
146155

156+
### msgpack.v5 migration
157+
158+
Most function names and argument types in `msgpack.v5` and `msgpack.v2`
159+
have not changed (except at least `EncodeInt`, `EncodeUint` and `RegisterExt`).
160+
But there are a lot of changes in a logic of encoding and deconding. On the plus
161+
side the migration seems easy, but on the minus side you need to be very
162+
careful.
163+
164+
First of all, `EncodeInt8`, `EncodeInt16`, `EncodeInt32`, `EncodeInt64`
165+
and `EncodeUint*` analogues at `msgpack.v5` encode numbers as is without loss of
166+
type. In `msgpack.v2` the type of a number is reduced to a value.
167+
168+
Secondly, a base decoding function does not convert numbers to `int64` or
169+
`uint64`. The change makes manual type conversions much more difficult and can
170+
lead to runtime erros with an old code. We recommend not use type conversions
171+
and give preference to `*Typed` functions (besides, it's faster).
172+
173+
There are also changes in the logic that can lead to errors in the old code,
174+
[as example](https://github.com/vmihailenco/msgpack/issues/327). Although in
175+
`msgpack.v5` has added some functions for the logic tuning see
176+
[UseLooseInterfaceDecoding](https://pkg.go.dev/github.com/vmihailenco/msgpack/v5#Decoder.UseLooseInterfaceDecoding), [UseCompactInts](https://pkg.go.dev/github.com/vmihailenco/msgpack/v5#Encoder.UseCompactInts) etc, but it is still impossible
177+
to achieve full compliance of behavior between `msgpack.v5` and `msgpack.v2`. So
178+
we don't go this way. We use standart settings if it possible.
179+
147180
## Contributing
148181

149182
See [the contributing guide](CONTRIBUTING.md) for detailed instructions on how

datetime/datetime_test.go

+11-7
Original file line numberDiff line numberDiff line change
@@ -64,17 +64,17 @@ func assertDatetimeIsEqual(t *testing.T, tuples []interface{}, tm time.Time) {
6464
if len(tpl) != 2 {
6565
t.Fatalf("Unexpected return value body (tuple len = %d)", len(tpl))
6666
}
67-
if val, ok := tpl[dtIndex].(Datetime); !ok || !val.ToTime().Equal(tm) {
67+
if val, ok := toDatetime(tpl[dtIndex]); !ok || !val.ToTime().Equal(tm) {
6868
t.Fatalf("Unexpected tuple %d field %v, expected %v",
6969
dtIndex,
70-
val.ToTime(),
70+
val,
7171
tm)
7272
}
7373
}
7474
}
7575

7676
func tupleInsertSelectDelete(t *testing.T, conn *Connection, tm time.Time) {
77-
t.Helper()
77+
//t.Helper()
7878

7979
dt, err := NewDatetime(tm)
8080
if err != nil {
@@ -324,7 +324,11 @@ func (ev *Event) decodeMsgpackImpl(d *Decoder) error {
324324
if err != nil {
325325
return err
326326
}
327-
ev.Datetime = res.(Datetime)
327+
dt, ok := toDatetime(res)
328+
if !ok {
329+
return fmt.Errorf("datetime doesn't match")
330+
}
331+
ev.Datetime = dt
328332
return nil
329333
}
330334

@@ -428,8 +432,8 @@ func TestCustomEncodeDecodeTuple1(t *testing.T) {
428432
}
429433

430434
for i, tv := range []time.Time{tm1, tm2} {
431-
dt := events[i].([]interface{})[1].(Datetime)
432-
if !dt.ToTime().Equal(tv) {
435+
dt, ok := toDatetime(events[i].([]interface{})[1])
436+
if !ok || !dt.ToTime().Equal(tv) {
433437
t.Fatalf("%v != %v", dt.ToTime(), tv)
434438
}
435439
}
@@ -501,7 +505,7 @@ func TestCustomEncodeDecodeTuple5(t *testing.T) {
501505
if tpl, ok := resp.Data[0].([]interface{}); !ok {
502506
t.Errorf("Unexpected body of Select")
503507
} else {
504-
if val, ok := tpl[0].(Datetime); !ok || !val.ToTime().Equal(tm) {
508+
if val, ok := toDatetime(tpl[0]); !ok || !val.ToTime().Equal(tm) {
505509
t.Fatalf("Unexpected body of Select")
506510
}
507511
}

datetime/msgpack.go

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
//go:build !go_tarantool_msgpack_v5
2+
// +build !go_tarantool_msgpack_v5
3+
14
package datetime
25

36
import (

datetime/msgpack_helper_test.go

+9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
//go:build !go_tarantool_msgpack_v5
2+
// +build !go_tarantool_msgpack_v5
3+
14
package datetime_test
25

36
import (
47
. "github.com/tarantool/go-tarantool"
8+
. "github.com/tarantool/go-tarantool/datetime"
59
"gopkg.in/vmihailenco/msgpack.v2"
610
)
711

@@ -29,6 +33,11 @@ func (c *Tuple2) DecodeMsgpack(d *msgpack.Decoder) error {
2933
return c.decodeMsgpackImpl(&Decoder{Decoder: d})
3034
}
3135

36+
func toDatetime(i interface{}) (dt Datetime, ok bool) {
37+
dt, ok = i.(Datetime)
38+
return
39+
}
40+
3241
func marshal(v interface{}) ([]byte, error) {
3342
return msgpack.Marshal(v)
3443
}

datetime/msgpack_v5.go

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//go:build go_tarantool_msgpack_v5
2+
// +build go_tarantool_msgpack_v5
3+
4+
package datetime
5+
6+
import (
7+
"github.com/vmihailenco/msgpack/v5"
8+
)
9+
10+
func init() {
11+
msgpack.RegisterExt(datetime_extId, (*Datetime)(nil))
12+
}

datetime/msgpack_v5_helper_test.go

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//go:build go_tarantool_msgpack_v5
2+
// +build go_tarantool_msgpack_v5
3+
4+
package datetime_test
5+
6+
import (
7+
. "github.com/tarantool/go-tarantool"
8+
. "github.com/tarantool/go-tarantool/datetime"
9+
"github.com/vmihailenco/msgpack/v5"
10+
)
11+
12+
func (t *Tuple1) EncodeMsgpack(e *msgpack.Encoder) error {
13+
return t.encodeMsgpackImpl(&Encoder{Encoder: e})
14+
}
15+
16+
func (t *Tuple1) DecodeMsgpack(d *msgpack.Decoder) error {
17+
return t.decodeMsgpackImpl(&Decoder{Decoder: d})
18+
}
19+
20+
func (ev *Event) EncodeMsgpack(e *msgpack.Encoder) error {
21+
return ev.encodeMsgpackImpl(&Encoder{Encoder: e})
22+
}
23+
24+
func (ev *Event) DecodeMsgpack(d *msgpack.Decoder) error {
25+
return ev.decodeMsgpackImpl(&Decoder{Decoder: d})
26+
}
27+
28+
func (c *Tuple2) EncodeMsgpack(e *msgpack.Encoder) error {
29+
return c.encodeMsgpackImpl(&Encoder{Encoder: e})
30+
}
31+
32+
func (c *Tuple2) DecodeMsgpack(d *msgpack.Decoder) error {
33+
return c.decodeMsgpackImpl(&Decoder{Decoder: d})
34+
}
35+
36+
func marshal(v interface{}) ([]byte, error) {
37+
return msgpack.Marshal(v)
38+
}
39+
40+
func unmarshal(data []byte, v interface{}) error {
41+
return msgpack.Unmarshal(data, v)
42+
}
43+
44+
func toDatetime(i interface{}) (dt Datetime, ok bool) {
45+
var ptr *Datetime
46+
if ptr, ok = i.(*Datetime); ok {
47+
dt = *ptr
48+
}
49+
return
50+
}

decimal/decimal_test.go

+10-4
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,11 @@ func (t *TupleDecimal) decodeMsgpackImpl(d *Decoder) error {
6060
if err != nil {
6161
return err
6262
}
63-
t.number = res.(Decimal)
64-
63+
dec, ok := toDecimal(res)
64+
if !ok {
65+
return fmt.Errorf("decimal doesn't match")
66+
}
67+
t.number = dec
6568
return nil
6669
}
6770

@@ -347,7 +350,7 @@ func tupleValueIsDecimal(t *testing.T, tuples []interface{}, number decimal.Deci
347350
if len(tpl) != 1 {
348351
t.Fatalf("Unexpected return value body (tuple len)")
349352
}
350-
if val, ok := tpl[0].(Decimal); !ok || !val.Equal(number) {
353+
if val, ok := toDecimal(tpl[0]); !ok || !val.Equal(number) {
351354
t.Fatalf("Unexpected return value body (tuple 0 field)")
352355
}
353356
}
@@ -445,7 +448,10 @@ func TestMPDecode(t *testing.T) {
445448
if err != nil {
446449
t.Fatalf("Unmarshalling failed: %s", err.Error())
447450
}
448-
decActual := v.(Decimal)
451+
decActual, ok := toDecimal(v)
452+
if !ok {
453+
t.Fatalf("Unable to convert to Decimal")
454+
}
449455

450456
decExpected, err := decimal.NewFromString(testcase.numString)
451457
if err != nil {

decimal/msgpack.go

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
//go:build !go_tarantool_msgpack_v5
2+
// +build !go_tarantool_msgpack_v5
3+
14
package decimal
25

36
import (

decimal/msgpack_helper_test.go

+8
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
//go:build !go_tarantool_msgpack_v5
2+
// +build !go_tarantool_msgpack_v5
3+
14
package decimal_test
25

36
import (
@@ -14,6 +17,11 @@ func (t *TupleDecimal) DecodeMsgpack(d *msgpack.Decoder) error {
1417
return t.decodeMsgpackImpl(&Decoder{Decoder: d})
1518
}
1619

20+
func toDecimal(i interface{}) (dec Decimal, ok bool) {
21+
dec, ok = i.(Decimal)
22+
return
23+
}
24+
1725
func marshal(v interface{}) ([]byte, error) {
1826
return msgpack.Marshal(v)
1927
}

decimal/msgpack_v5.go

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//go:build go_tarantool_msgpack_v5
2+
// +build go_tarantool_msgpack_v5
3+
4+
package decimal
5+
6+
import (
7+
"github.com/vmihailenco/msgpack/v5"
8+
)
9+
10+
func init() {
11+
msgpack.RegisterExt(decimalExtID, (*Decimal)(nil))
12+
}

decimal/msgpack_v5_helper_test.go

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//go:build go_tarantool_msgpack_v5
2+
// +build go_tarantool_msgpack_v5
3+
4+
package decimal_test
5+
6+
import (
7+
. "github.com/tarantool/go-tarantool"
8+
. "github.com/tarantool/go-tarantool/decimal"
9+
"github.com/vmihailenco/msgpack/v5"
10+
)
11+
12+
func (t *TupleDecimal) EncodeMsgpack(e *msgpack.Encoder) error {
13+
return t.encodeMsgpackImpl(&Encoder{Encoder: e})
14+
}
15+
16+
func (t *TupleDecimal) DecodeMsgpack(d *msgpack.Decoder) error {
17+
return t.decodeMsgpackImpl(&Decoder{Decoder: d})
18+
}
19+
20+
func toDecimal(i interface{}) (dec Decimal, ok bool) {
21+
var ptr *Decimal
22+
if ptr, ok = i.(*Decimal); ok {
23+
dec = *ptr
24+
}
25+
return
26+
}
27+
28+
func marshal(v interface{}) ([]byte, error) {
29+
return msgpack.Marshal(v)
30+
}
31+
32+
func unmarshal(data []byte, v interface{}) error {
33+
return msgpack.Unmarshal(data, v)
34+
}

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@ require (
1414
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
1515
gopkg.in/vmihailenco/msgpack.v2 v2.9.2
1616
gotest.tools/v3 v3.2.0 // indirect
17+
github.com/vmihailenco/msgpack/v5 v5.3.5
1718
)

go.sum

+5
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,15 @@ github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+
2424
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc=
2525
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
2626
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
27+
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
2728
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
2829
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
2930
github.com/tarantool/go-openssl v0.0.8-0.20220419150948-be4921aa2f87 h1:JGzuBxNBq5saVtPUcuu5Y4+kbJON6H02//OT+RNqGts=
3031
github.com/tarantool/go-openssl v0.0.8-0.20220419150948-be4921aa2f87/go.mod h1:M7H4xYSbzqpW/ZRBMyH0eyqQBsnhAMfsYk5mv0yid7A=
32+
github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU=
33+
github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc=
34+
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
35+
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
3136
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
3237
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
3338
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=

0 commit comments

Comments
 (0)