Skip to content

Commit deb4e21

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 634d095 commit deb4e21

26 files changed

+457
-29
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
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

Lines changed: 34 additions & 1 deletion
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

Lines changed: 11 additions & 7 deletions
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

Lines changed: 3 additions & 0 deletions
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

Lines changed: 9 additions & 0 deletions
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

Lines changed: 12 additions & 0 deletions
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

Lines changed: 50 additions & 0 deletions
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

Lines changed: 10 additions & 4 deletions
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

Lines changed: 3 additions & 0 deletions
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

Lines changed: 8 additions & 0 deletions
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
}

0 commit comments

Comments
 (0)