diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 7d90fa892..6745870a2 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -99,21 +99,6 @@ jobs: make test make testrace - - name: Run regression tests with call_17 - run: | - make test TAGS="go_tarantool_call_17" - make testrace TAGS="go_tarantool_call_17" - - - name: Run regression tests with msgpack.v5 - run: | - make test TAGS="go_tarantool_msgpack_v5" - make testrace TAGS="go_tarantool_msgpack_v5" - - - name: Run regression tests with msgpack.v5 and call_17 - run: | - make test TAGS="go_tarantool_msgpack_v5,go_tarantool_call_17" - make testrace TAGS="go_tarantool_msgpack_v5,go_tarantool_call_17" - - name: Run fuzzing tests if: ${{ matrix.fuzzing }} run: make fuzzing TAGS="go_tarantool_decimal_fuzzing" @@ -199,30 +184,6 @@ jobs: env: TEST_TNT_SSL: ${{matrix.ssl}} - - name: Run regression tests with call_17 - run: | - source tarantool-enterprise/env.sh - make test TAGS="go_tarantool_call_17" - make testrace TAGS="go_tarantool_call_17" - env: - TEST_TNT_SSL: ${{matrix.ssl}} - - - name: Run regression tests with msgpack.v5 - run: | - source tarantool-enterprise/env.sh - make test TAGS="go_tarantool_msgpack_v5" - make testrace TAGS="go_tarantool_msgpack_v5" - env: - TEST_TNT_SSL: ${{matrix.ssl}} - - - name: Run regression tests with msgpack.v5 and call_17 - run: | - source tarantool-enterprise/env.sh - make test TAGS="go_tarantool_msgpack_v5,go_tarantool_call_17" - make testrace TAGS="go_tarantool_msgpack_v5,go_tarantool_call_17" - env: - TEST_TNT_SSL: ${{matrix.ssl}} - - name: Run fuzzing tests if: ${{ matrix.fuzzing }} run: make fuzzing TAGS="go_tarantool_decimal_fuzzing" @@ -389,24 +350,6 @@ jobs: make test make testrace - - name: Run regression tests with call_17 - run: | - cd "${SRCDIR}" - make test TAGS="go_tarantool_call_17" - make testrace TAGS="go_tarantool_call_17" - - - name: Run regression tests with msgpack.v5 - run: | - cd "${SRCDIR}" - make test TAGS="go_tarantool_msgpack_v5" - make testrace TAGS="go_tarantool_msgpack_v5" - - - name: Run regression tests with msgpack.v5 and call_17 - run: | - cd "${SRCDIR}" - make test TAGS="go_tarantool_msgpack_v5,go_tarantool_call_17" - make testrace TAGS="go_tarantool_msgpack_v5,go_tarantool_call_17" - - name: Run fuzzing tests if: ${{ matrix.fuzzing }} run: | diff --git a/CHANGELOG.md b/CHANGELOG.md index 0332f376f..759dc43c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,8 +10,25 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release. ### Added +- Type() method to the Request interface (#158) +- Enumeration types for RLimitAction/iterators (#158) + ### Changed +- connection_pool renamed to pool (#239) +- Use msgpack/v5 instead of msgpack.v2 (#236) +- Call/NewCallRequest = Call17/NewCall17Request (#235) + +### Removed + +- multi subpackage (#240) +- msgpack.v2 support (#236) +- pool/RoundRobinStrategy (#158) +- DeadlineIO (#158) +- UUID_extId (#158) +- IPROTO constants (#158) +- Code() method from the Request interface (#158) + ### Fixed ## [1.12.0] - 2023-06-07 diff --git a/Makefile b/Makefile index cc689dae7..f48b789cc 100644 --- a/Makefile +++ b/Makefile @@ -57,11 +57,11 @@ testrace: go clean -testcache go test -race -tags "$(TAGS)" ./... -v -p 1 -.PHONY: test-connection-pool -test-connection-pool: - @echo "Running tests in connection_pool package" +.PHONY: test-pool +test-pool: + @echo "Running tests in pool package" go clean -testcache - go test -tags "$(TAGS)" ./connection_pool/ -v -p 1 + go test -tags "$(TAGS)" ./pool/ -v -p 1 .PHONY: test-datetime test-datetime: @@ -75,12 +75,6 @@ test-decimal: go clean -testcache go test -tags "$(TAGS)" ./decimal/ -v -p 1 -.PHONY: test-multi -test-multi: - @echo "Running tests in multiconnection package" - go clean -testcache - go test -tags "$(TAGS)" ./multi/ -v -p 1 - .PHONY: test-queue test-queue: @echo "Running tests in queue package" diff --git a/README.md b/README.md index 7fcf96d1b..8d67db1b2 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,13 @@ faster than other packages according to public benchmarks. * [Documentation](#documentation) * [API reference](#api-reference) * [Walking\-through example](#walking-through-example) - * [msgpack.v5 migration](#msgpackv5-migration) + * [Migration to v2](#migration-to-v2) + * [multi package](#multi-package) + * [pool package](#pool-package) + * [msgpack.v5](#msgpackv5) + * [Call = Call17](#call--call17) + * [IPROTO constants](#iproto-constants) + * [Request interface](#request-interface) * [Contributing](#contributing) * [Alternative connectors](#alternative-connectors) @@ -45,7 +51,7 @@ The package `go-tarantool` is located in [tarantool/go-tarantool][go-tarantool] repository. To download and install, say: ``` -$ go get github.com/tarantool/go-tarantool +$ go get github.com/tarantool/go-tarantool/v2 ``` This should put the source and binary files in subdirectories of @@ -63,21 +69,7 @@ This allows us to introduce new features without losing backward compatibility. ``` go_tarantool_ssl_disable ``` -2. To change the default `Call` behavior from `Call16` to `Call17`, you can use - the build tag: - ``` - go_tarantool_call_17 - ``` - **Note:** In future releases, `Call17` may be used as default `Call` behavior. -3. To replace usage of `msgpack.v2` with `msgpack.v5`, you can use the build - tag: - ``` - go_tarantool_msgpack_v5 - ``` - **Note:** In future releases, `msgpack.v5` may be used by default. We recommend - to read [msgpack.v5 migration notes](#msgpackv5-migration) and try to - use msgpack.v5 before the changes. -4. To run fuzz tests with decimals, you can use the build tag: +2. To run fuzz tests with decimals, you can use the build tag: ``` go_tarantool_decimal_fuzzing ``` @@ -112,7 +104,7 @@ package tarantool import ( "fmt" - "github.com/tarantool/go-tarantool" + "github.com/tarantool/go-tarantool/v2" ) func main() { @@ -129,7 +121,7 @@ func main() { } ``` -**Observation 1:** The line "`github.com/tarantool/go-tarantool`" in the +**Observation 1:** The line "`github.com/tarantool/go-tarantool/v2`" in the `import(...)` section brings in all Tarantool-related functions and structures. **Observation 2:** The line starting with "`Opts :=`" sets up the options for @@ -153,7 +145,22 @@ There are two parameters: * a space number (it could just as easily have been a space name), and * a tuple. -### msgpack.v5 migration +### Migration to v2 + +The article describes migration from go-tarantool to go-tarantool/v2. + +#### multi package + +The subpackage has been deleted. You could use `pool` instead. + +#### pool package + +The logic has not changed, but there are a few renames: + +* The `connection_pool` subpackage has been renamed to `pool`. +* The type `PoolOpts` has been renamed to `Opts`. + +#### msgpack.v5 Most function names and argument types in `msgpack.v5` and `msgpack.v2` have not changed (in our code, we noticed changes in `EncodeInt`, `EncodeUint` @@ -178,6 +185,21 @@ There are also changes in the logic that can lead to errors in the old code, to achieve full compliance of behavior between `msgpack.v5` and `msgpack.v2`. So we don't go this way. We use standard settings if it possible. +#### Call = Call17 + +Call requests uses `IPROTO_CALL` instead of `IPROTO_CALL_16`. + +So now `Call` = `Call17` and `NewCallRequest` = `NewCall17Request`. A result +of the requests is an array instead of array of arrays. + +#### IPROTO constants + +IPROTO constants have been moved to a separate package [go-iproto](https://github.com/tarantool/go-iproto). + +#### Request interface + +* The method `Code() uint32` replaced by the `Type() iproto.Type`. + ## Contributing See [the contributing guide](CONTRIBUTING.md) for detailed instructions on how diff --git a/auth_test.go b/auth_test.go index 6964f2552..712226d63 100644 --- a/auth_test.go +++ b/auth_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" - . "github.com/tarantool/go-tarantool" + . "github.com/tarantool/go-tarantool/v2" ) func TestAuth_String(t *testing.T) { diff --git a/box_error.go b/box_error.go index ab8981b0b..3d76a942c 100644 --- a/box_error.go +++ b/box_error.go @@ -3,6 +3,8 @@ package tarantool import ( "bytes" "fmt" + + "github.com/vmihailenco/msgpack/v5" ) const errorExtID = 3 @@ -69,7 +71,7 @@ func (e *BoxError) Depth() int { return depth } -func decodeBoxError(d *decoder) (*BoxError, error) { +func decodeBoxError(d *msgpack.Decoder) (*BoxError, error) { var l, larr, l1, l2 int var errorStack []BoxError var err error @@ -169,7 +171,7 @@ func decodeBoxError(d *decoder) (*BoxError, error) { return &errorStack[0], nil } -func encodeBoxError(enc *encoder, boxError *BoxError) error { +func encodeBoxError(enc *msgpack.Encoder, boxError *BoxError) error { if boxError == nil { return fmt.Errorf("msgpack: unexpected nil BoxError on encode") } @@ -177,7 +179,7 @@ func encodeBoxError(enc *encoder, boxError *BoxError) error { if err := enc.EncodeMapLen(1); err != nil { return err } - if err := encodeUint(enc, keyErrorStack); err != nil { + if err := enc.EncodeUint(keyErrorStack); err != nil { return err } @@ -199,42 +201,42 @@ func encodeBoxError(enc *encoder, boxError *BoxError) error { } } - if err := encodeUint(enc, keyErrorType); err != nil { + if err := enc.EncodeUint(keyErrorType); err != nil { return err } if err := enc.EncodeString(boxError.Type); err != nil { return err } - if err := encodeUint(enc, keyErrorFile); err != nil { + if err := enc.EncodeUint(keyErrorFile); err != nil { return err } if err := enc.EncodeString(boxError.File); err != nil { return err } - if err := encodeUint(enc, keyErrorLine); err != nil { + if err := enc.EncodeUint(keyErrorLine); err != nil { return err } if err := enc.EncodeUint64(boxError.Line); err != nil { return err } - if err := encodeUint(enc, keyErrorMessage); err != nil { + if err := enc.EncodeUint(keyErrorMessage); err != nil { return err } if err := enc.EncodeString(boxError.Msg); err != nil { return err } - if err := encodeUint(enc, keyErrorErrno); err != nil { + if err := enc.EncodeUint(keyErrorErrno); err != nil { return err } if err := enc.EncodeUint64(boxError.Errno); err != nil { return err } - if err := encodeUint(enc, keyErrorErrcode); err != nil { + if err := enc.EncodeUint(keyErrorErrcode); err != nil { return err } if err := enc.EncodeUint64(boxError.Code); err != nil { @@ -242,7 +244,7 @@ func encodeBoxError(enc *encoder, boxError *BoxError) error { } if fieldsLen > 0 { - if err := encodeUint(enc, keyErrorFields); err != nil { + if err := enc.EncodeUint(keyErrorFields); err != nil { return err } @@ -276,7 +278,7 @@ func (e *BoxError) UnmarshalMsgpack(b []byte) error { } buf := bytes.NewBuffer(b) - dec := newDecoder(buf) + dec := msgpack.NewDecoder(buf) if val, err := decodeBoxError(dec); err != nil { return err @@ -290,10 +292,14 @@ func (e *BoxError) UnmarshalMsgpack(b []byte) error { func (e *BoxError) MarshalMsgpack() ([]byte, error) { var buf bytes.Buffer - enc := newEncoder(&buf) + enc := msgpack.NewEncoder(&buf) if err := encodeBoxError(enc, e); err != nil { return nil, err } return buf.Bytes(), nil } + +func init() { + msgpack.RegisterExt(errorExtID, (*BoxError)(nil)) +} diff --git a/box_error_test.go b/box_error_test.go index 276ca2cf8..d8ff5b11f 100644 --- a/box_error_test.go +++ b/box_error_test.go @@ -6,8 +6,10 @@ import ( "testing" "github.com/stretchr/testify/require" - . "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/test_helpers" + "github.com/vmihailenco/msgpack/v5" + + . "github.com/tarantool/go-tarantool/v2" + "github.com/tarantool/go-tarantool/v2/test_helpers" ) var samples = map[string]BoxError{ @@ -217,7 +219,7 @@ type TupleBoxError struct { val BoxError } -func (t *TupleBoxError) EncodeMsgpack(e *encoder) error { +func (t *TupleBoxError) EncodeMsgpack(e *msgpack.Encoder) error { if err := e.EncodeArrayLen(2); err != nil { return err } @@ -229,7 +231,7 @@ func (t *TupleBoxError) EncodeMsgpack(e *encoder) error { return e.Encode(&t.val) } -func (t *TupleBoxError) DecodeMsgpack(d *decoder) error { +func (t *TupleBoxError) DecodeMsgpack(d *msgpack.Decoder) error { var err error var l int if l, err = d.DecodeArrayLen(); err != nil { @@ -278,11 +280,11 @@ var tupleCases = map[string]struct { func TestErrorTypeMPEncodeDecode(t *testing.T) { for name, testcase := range tupleCases { t.Run(name, func(t *testing.T) { - buf, err := marshal(&testcase.tuple) + buf, err := msgpack.Marshal(&testcase.tuple) require.Nil(t, err) var res TupleBoxError - err = unmarshal(buf, &res) + err = msgpack.Unmarshal(buf, &res) require.Nil(t, err) require.Equal(t, testcase.tuple, res) @@ -302,9 +304,9 @@ func TestErrorTypeEval(t *testing.T) { require.Nil(t, err) require.NotNil(t, resp.Data) require.Equal(t, len(resp.Data), 1) - actual, ok := toBoxError(resp.Data[0]) + actual, ok := resp.Data[0].(*BoxError) require.Truef(t, ok, "Response data has valid type") - require.Equal(t, testcase.tuple.val, actual) + require.Equal(t, testcase.tuple.val, *actual) }) } } @@ -440,14 +442,13 @@ func TestErrorTypeSelect(t *testing.T) { tpl, ok := resp.Data[0].([]interface{}) require.Truef(t, ok, "Tuple has valid type") require.Equal(t, testcase.tuple.pk, tpl[0]) - var actual BoxError - actual, ok = toBoxError(tpl[1]) + actual, ok := tpl[1].(*BoxError) require.Truef(t, ok, "BoxError tuple field has valid type") // In fact, CheckEqualBoxErrors does not check than File and Line // of connector BoxError are equal to the Tarantool ones // since they may differ between different Tarantool versions // and editions. - test_helpers.CheckEqualBoxErrors(t, testcase.tuple.val, actual) + test_helpers.CheckEqualBoxErrors(t, testcase.tuple.val, *actual) }) } } diff --git a/call_16_test.go b/call_16_test.go deleted file mode 100644 index f23f0f783..000000000 --- a/call_16_test.go +++ /dev/null @@ -1,54 +0,0 @@ -//go:build !go_tarantool_call_17 -// +build !go_tarantool_call_17 - -package tarantool_test - -import ( - "testing" - - . "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/test_helpers" -) - -func TestConnection_Call(t *testing.T) { - var resp *Response - var err error - - conn := test_helpers.ConnectWithValidation(t, server, opts) - defer conn.Close() - - // Call16 - resp, err = conn.Call("simple_concat", []interface{}{"1"}) - if err != nil { - t.Errorf("Failed to use Call") - } - if val, ok := resp.Data[0].([]interface{})[0].(string); !ok || val != "11" { - t.Errorf("result is not {{1}} : %v", resp.Data) - } -} - -func TestCallRequest(t *testing.T) { - var resp *Response - var err error - - conn := test_helpers.ConnectWithValidation(t, server, opts) - defer conn.Close() - - req := NewCallRequest("simple_concat").Args([]interface{}{"1"}) - resp, err = conn.Do(req).Get() - if err != nil { - t.Errorf("Failed to use Call") - } - if val, ok := resp.Data[0].([]interface{})[0].(string); !ok || val != "11" { - t.Errorf("result is not {{1}} : %v", resp.Data) - } -} - -func TestCallRequestCode(t *testing.T) { - req := NewCallRequest("simple_concat") - code := req.Code() - expected := Call16RequestCode - if code != int32(expected) { - t.Errorf("CallRequest actual code %v != %v", code, expected) - } -} diff --git a/call_17_test.go b/call_17_test.go deleted file mode 100644 index 824ed850b..000000000 --- a/call_17_test.go +++ /dev/null @@ -1,54 +0,0 @@ -//go:build go_tarantool_call_17 -// +build go_tarantool_call_17 - -package tarantool_test - -import ( - "testing" - - . "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/test_helpers" -) - -func TestConnection_Call(t *testing.T) { - var resp *Response - var err error - - conn := test_helpers.ConnectWithValidation(t, server, opts) - defer conn.Close() - - // Call17 - resp, err = conn.Call17("simple_concat", []interface{}{"1"}) - if err != nil { - t.Errorf("Failed to use Call") - } - if val, ok := resp.Data[0].(string); !ok || val != "11" { - t.Errorf("result is not {{1}} : %v", resp.Data) - } -} - -func TestCallRequest(t *testing.T) { - var resp *Response - var err error - - conn := test_helpers.ConnectWithValidation(t, server, opts) - defer conn.Close() - - req := NewCallRequest("simple_concat").Args([]interface{}{"1"}) - resp, err = conn.Do(req).Get() - if err != nil { - t.Errorf("Failed to use Call") - } - if val, ok := resp.Data[0].(string); !ok || val != "11" { - t.Errorf("result is not {{1}} : %v", resp.Data) - } -} - -func TestCallRequestCode(t *testing.T) { - req := NewCallRequest("simple_concat") - code := req.Code() - expected := Call17RequestCode - if code != int32(expected) { - t.Errorf("CallRequest actual code %v != %v", code, expected) - } -} diff --git a/client_tools.go b/client_tools.go index 9c439ec21..159f3d0ce 100644 --- a/client_tools.go +++ b/client_tools.go @@ -1,14 +1,18 @@ package tarantool +import ( + "github.com/vmihailenco/msgpack/v5" +) + // IntKey is utility type for passing integer key to Select*, Update*, // Delete* and GetTyped. It serializes to array with single integer element. type IntKey struct { I int } -func (k IntKey) EncodeMsgpack(enc *encoder) error { +func (k IntKey) EncodeMsgpack(enc *msgpack.Encoder) error { enc.EncodeArrayLen(1) - encodeInt(enc, int64(k.I)) + enc.EncodeInt(int64(k.I)) return nil } @@ -19,9 +23,9 @@ type UintKey struct { I uint } -func (k UintKey) EncodeMsgpack(enc *encoder) error { +func (k UintKey) EncodeMsgpack(enc *msgpack.Encoder) error { enc.EncodeArrayLen(1) - encodeUint(enc, uint64(k.I)) + enc.EncodeUint(uint64(k.I)) return nil } @@ -31,7 +35,7 @@ type StringKey struct { S string } -func (k StringKey) EncodeMsgpack(enc *encoder) error { +func (k StringKey) EncodeMsgpack(enc *msgpack.Encoder) error { enc.EncodeArrayLen(1) enc.EncodeString(k.S) return nil @@ -43,10 +47,10 @@ type IntIntKey struct { I1, I2 int } -func (k IntIntKey) EncodeMsgpack(enc *encoder) error { +func (k IntIntKey) EncodeMsgpack(enc *msgpack.Encoder) error { enc.EncodeArrayLen(2) - encodeInt(enc, int64(k.I1)) - encodeInt(enc, int64(k.I2)) + enc.EncodeInt(int64(k.I1)) + enc.EncodeInt(int64(k.I2)) return nil } @@ -57,10 +61,10 @@ type Op struct { Arg interface{} } -func (o Op) EncodeMsgpack(enc *encoder) error { +func (o Op) EncodeMsgpack(enc *msgpack.Encoder) error { enc.EncodeArrayLen(3) enc.EncodeString(o.Op) - encodeInt(enc, int64(o.Field)) + enc.EncodeInt(int64(o.Field)) return enc.Encode(o.Arg) } @@ -145,12 +149,12 @@ type OpSplice struct { Replace string } -func (o OpSplice) EncodeMsgpack(enc *encoder) error { +func (o OpSplice) EncodeMsgpack(enc *msgpack.Encoder) error { enc.EncodeArrayLen(5) enc.EncodeString(o.Op) - encodeInt(enc, int64(o.Field)) - encodeInt(enc, int64(o.Pos)) - encodeInt(enc, int64(o.Len)) + enc.EncodeInt(int64(o.Field)) + enc.EncodeInt(int64(o.Pos)) + enc.EncodeInt(int64(o.Len)) enc.EncodeString(o.Replace) return nil } diff --git a/connection.go b/connection.go index 055941e78..ea7f236fe 100644 --- a/connection.go +++ b/connection.go @@ -14,6 +14,9 @@ import ( "sync" "sync/atomic" "time" + + "github.com/tarantool/go-iproto" + "github.com/vmihailenco/msgpack/v5" ) const requestsMap = 128 @@ -164,8 +167,8 @@ type Connection struct { rlimit chan struct{} opts Opts state uint32 - dec *decoder - lenbuf [PacketLengthBytes]byte + dec *msgpack.Decoder + lenbuf [packetLengthBytes]byte lastStreamId uint64 @@ -230,9 +233,22 @@ type connShard struct { requestsWithCtx [requestsMap]futureList bufmut sync.Mutex buf smallWBuf - enc *encoder + enc *msgpack.Encoder } +// RLimitActions is an enumeration type for an action to do when a rate limit +// is reached. +type RLimitAction int + +const ( + // RLimitDrop immediately aborts the request. + RLimitDrop RLimitAction = iota + // RLimitWait waits during timeout period for some request to be answered. + // If no request answered during timeout period, this request is aborted. + // If no timeout period is set, it will wait forever. + RLimitWait +) + // Opts is a way to configure Connection type Opts struct { // Auth is an authentication method. @@ -271,14 +287,9 @@ type Opts struct { // It is disabled by default. // See RLimitAction for possible actions when RateLimit.reached. RateLimit uint - // RLimitAction tells what to do when RateLimit reached: - // RLimitDrop - immediately abort request, - // RLimitWait - wait during timeout period for some request to be answered. - // If no request answered during timeout period, this request - // is aborted. - // If no timeout period is set, it will wait forever. + // RLimitAction tells what to do when RateLimit is reached. // It is required if RateLimit is specified. - RLimitAction uint + RLimitAction RLimitAction // Concurrency is amount of separate mutexes for request // queues and buffers inside of connection. // It is rounded up to nearest power of 2. @@ -364,7 +375,7 @@ func Connect(addr string, opts Opts) (conn *Connection, err error) { Greeting: &Greeting{}, control: make(chan struct{}), opts: opts.Clone(), - dec: newDecoder(&smallBuf{}), + dec: msgpack.NewDecoder(&smallBuf{}), } maxprocs := uint32(runtime.GOMAXPROCS(-1)) if conn.opts.Concurrency == 0 || conn.opts.Concurrency > maxprocs*128 { @@ -408,8 +419,8 @@ func Connect(addr string, opts Opts) (conn *Connection, err error) { ter, ok := err.(Error) if conn.opts.Reconnect <= 0 { return nil, err - } else if ok && (ter.Code == ErrNoSuchUser || - ter.Code == ErrPasswordMismatch) { + } else if ok && (ter.Code == iproto.ER_NO_SUCH_USER || + ter.Code == iproto.ER_CREDS_MISMATCH) { // Reported auth errors immediately. return nil, err } else { @@ -579,7 +590,7 @@ func (conn *Connection) dial() (err error) { return } -func pack(h *smallWBuf, enc *encoder, reqid uint32, +func pack(h *smallWBuf, enc *msgpack.Encoder, reqid uint32, req Request, streamId uint64, res SchemaResolver) (err error) { const uint32Code = 0xce const uint64Code = 0xcf @@ -593,7 +604,7 @@ func pack(h *smallWBuf, enc *encoder, reqid uint32, hMapLen := byte(0x82) // 2 element map. if streamId != ignoreStreamId { hMapLen = byte(0x83) // 3 element map. - streamBytes[0] = KeyStreamId + streamBytes[0] = byte(iproto.IPROTO_STREAM_ID) if streamId > math.MaxUint32 { streamBytesLen = streamBytesLenUint64 streamBytes[1] = uint64Code @@ -608,8 +619,8 @@ func pack(h *smallWBuf, enc *encoder, reqid uint32, hBytes := append([]byte{ uint32Code, 0, 0, 0, 0, // Length. hMapLen, - KeyCode, byte(req.Code()), // Request code. - KeySync, uint32Code, + byte(iproto.IPROTO_REQUEST_TYPE), byte(req.Type()), // Request type. + byte(iproto.IPROTO_SYNC), uint32Code, byte(reqid >> 24), byte(reqid >> 16), byte(reqid >> 8), byte(reqid), }, streamBytes[:streamBytesLen]...) @@ -798,7 +809,7 @@ func (conn *Connection) writer(w writeFlusher, c Conn) { func readWatchEvent(reader io.Reader) (connWatchEvent, error) { keyExist := false event := connWatchEvent{} - d := newDecoder(reader) + d := msgpack.NewDecoder(reader) l, err := d.DecodeMapLen() if err != nil { @@ -811,13 +822,13 @@ func readWatchEvent(reader io.Reader) (connWatchEvent, error) { return event, err } - switch cd { - case KeyEvent: + switch iproto.Key(cd) { + case iproto.IPROTO_EVENT_KEY: if event.key, err = d.DecodeString(); err != nil { return event, err } keyExist = true - case KeyEventData: + case iproto.IPROTO_EVENT_DATA: if event.value, err = d.DecodeInterface(); err != nil { return event, err } @@ -855,7 +866,7 @@ func (conn *Connection) reader(r io.Reader, c Conn) { } var fut *Future = nil - if resp.Code == EventCode { + if iproto.Type(resp.Code) == iproto.IPROTO_EVENT { if event, err := readWatchEvent(&resp.buf); err == nil { events <- event } else { @@ -1048,7 +1059,7 @@ func (conn *Connection) putFuture(fut *Future, req Request, streamId uint64) { firstWritten := shard.buf.Len() == 0 if shard.buf.Cap() == 0 { shard.buf.b = make([]byte, 0, 128) - shard.enc = newEncoder(&shard.buf) + shard.enc = msgpack.NewEncoder(&shard.buf) } blen := shard.buf.Len() reqid := fut.requestId diff --git a/connection_pool/call_16_test.go b/connection_pool/call_16_test.go deleted file mode 100644 index bf2ab2eb7..000000000 --- a/connection_pool/call_16_test.go +++ /dev/null @@ -1,69 +0,0 @@ -//go:build !go_tarantool_call_17 -// +build !go_tarantool_call_17 - -package connection_pool_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - "github.com/tarantool/go-tarantool/connection_pool" - "github.com/tarantool/go-tarantool/test_helpers" -) - -func TestCall(t *testing.T) { - roles := []bool{false, true, false, false, true} - - err := test_helpers.SetClusterRO(servers, connOpts, roles) - require.Nilf(t, err, "fail to set roles for cluster") - - connPool, err := connection_pool.Connect(servers, connOpts) - require.Nilf(t, err, "failed to connect") - require.NotNilf(t, connPool, "conn is nil after Connect") - - defer connPool.Close() - - // PreferRO - resp, err := connPool.Call("box.info", []interface{}{}, connection_pool.PreferRO) - require.Nilf(t, err, "failed to Call") - require.NotNilf(t, resp, "response is nil after Call") - require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Call") - - val := resp.Data[0].([]interface{})[0].(map[interface{}]interface{})["ro"] - ro, ok := val.(bool) - require.Truef(t, ok, "expected `true` with mode `PreferRO`") - require.Truef(t, ro, "expected `true` with mode `PreferRO`") - - // PreferRW - resp, err = connPool.Call("box.info", []interface{}{}, connection_pool.PreferRW) - require.Nilf(t, err, "failed to Call") - require.NotNilf(t, resp, "response is nil after Call") - require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Call") - - val = resp.Data[0].([]interface{})[0].(map[interface{}]interface{})["ro"] - ro, ok = val.(bool) - require.Truef(t, ok, "expected `false` with mode `PreferRW`") - require.Falsef(t, ro, "expected `false` with mode `PreferRW`") - - // RO - resp, err = connPool.Call("box.info", []interface{}{}, connection_pool.RO) - require.Nilf(t, err, "failed to Call") - require.NotNilf(t, resp, "response is nil after Call") - require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Call") - - val = resp.Data[0].([]interface{})[0].(map[interface{}]interface{})["ro"] - ro, ok = val.(bool) - require.Truef(t, ok, "expected `true` with mode `RO`") - require.Truef(t, ro, "expected `true` with mode `RO`") - - // RW - resp, err = connPool.Call("box.info", []interface{}{}, connection_pool.RW) - require.Nilf(t, err, "failed to Call") - require.NotNilf(t, resp, "response is nil after Call") - require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Call") - - val = resp.Data[0].([]interface{})[0].(map[interface{}]interface{})["ro"] - ro, ok = val.(bool) - require.Truef(t, ok, "expected `false` with mode `RW`") - require.Falsef(t, ro, "expected `false` with mode `RW`") -} diff --git a/connection_pool/call_17_test.go b/connection_pool/call_17_test.go deleted file mode 100644 index 94e5bb888..000000000 --- a/connection_pool/call_17_test.go +++ /dev/null @@ -1,69 +0,0 @@ -//go:build go_tarantool_call_17 -// +build go_tarantool_call_17 - -package connection_pool_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - "github.com/tarantool/go-tarantool/connection_pool" - "github.com/tarantool/go-tarantool/test_helpers" -) - -func TestCall(t *testing.T) { - roles := []bool{false, true, false, false, true} - - err := test_helpers.SetClusterRO(servers, connOpts, roles) - require.Nilf(t, err, "fail to set roles for cluster") - - connPool, err := connection_pool.Connect(servers, connOpts) - require.Nilf(t, err, "failed to connect") - require.NotNilf(t, connPool, "conn is nil after Connect") - - defer connPool.Close() - - // PreferRO - resp, err := connPool.Call("box.info", []interface{}{}, connection_pool.PreferRO) - require.Nilf(t, err, "failed to Call") - require.NotNilf(t, resp, "response is nil after Call") - require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Call") - - val := resp.Data[0].(map[interface{}]interface{})["ro"] - ro, ok := val.(bool) - require.Truef(t, ok, "expected `true` with mode `PreferRO`") - require.Truef(t, ro, "expected `true` with mode `PreferRO`") - - // PreferRW - resp, err = connPool.Call("box.info", []interface{}{}, connection_pool.PreferRW) - require.Nilf(t, err, "failed to Call") - require.NotNilf(t, resp, "response is nil after Call") - require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Call") - - val = resp.Data[0].(map[interface{}]interface{})["ro"] - ro, ok = val.(bool) - require.Truef(t, ok, "expected `false` with mode `PreferRW`") - require.Falsef(t, ro, "expected `false` with mode `PreferRW`") - - // RO - resp, err = connPool.Call("box.info", []interface{}{}, connection_pool.RO) - require.Nilf(t, err, "failed to Call") - require.NotNilf(t, resp, "response is nil after Call") - require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Call") - - val = resp.Data[0].(map[interface{}]interface{})["ro"] - ro, ok = val.(bool) - require.Truef(t, ok, "expected `true` with mode `RO`") - require.Truef(t, ro, "expected `true` with mode `RO`") - - // RW - resp, err = connPool.Call("box.info", []interface{}{}, connection_pool.RW) - require.Nilf(t, err, "failed to Call") - require.NotNilf(t, resp, "response is nil after Call") - require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Call") - - val = resp.Data[0].(map[interface{}]interface{})["ro"] - ro, ok = val.(bool) - require.Truef(t, ok, "expected `false` with mode `RW`") - require.Falsef(t, ro, "expected `false` with mode `RW`") -} diff --git a/connection_pool/msgpack_helper_test.go b/connection_pool/msgpack_helper_test.go deleted file mode 100644 index d60c7d84d..000000000 --- a/connection_pool/msgpack_helper_test.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build !go_tarantool_msgpack_v5 -// +build !go_tarantool_msgpack_v5 - -package connection_pool_test - -import ( - "gopkg.in/vmihailenco/msgpack.v2" -) - -type decoder = msgpack.Decoder diff --git a/connection_pool/msgpack_v5_helper_test.go b/connection_pool/msgpack_v5_helper_test.go deleted file mode 100644 index 7c449bec5..000000000 --- a/connection_pool/msgpack_v5_helper_test.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build go_tarantool_msgpack_v5 -// +build go_tarantool_msgpack_v5 - -package connection_pool_test - -import ( - "github.com/vmihailenco/msgpack/v5" -) - -type decoder = msgpack.Decoder diff --git a/connection_test.go b/connection_test.go index 05f29b093..3e7be1966 100644 --- a/connection_test.go +++ b/connection_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/require" - . "github.com/tarantool/go-tarantool" + . "github.com/tarantool/go-tarantool/v2" ) func TestOptsClonePreservesRequiredProtocolFeatures(t *testing.T) { diff --git a/connector.go b/connector.go index d93c69ec8..3aa2f9542 100644 --- a/connector.go +++ b/connector.go @@ -8,7 +8,7 @@ type Connector interface { Ping() (resp *Response, err error) ConfiguredTimeout() time.Duration - Select(space, index interface{}, offset, limit, iterator uint32, key interface{}) (resp *Response, err error) + Select(space, index interface{}, offset, limit uint32, iterator Iter, key interface{}) (resp *Response, err error) Insert(space interface{}, tuple interface{}) (resp *Response, err error) Replace(space interface{}, tuple interface{}) (resp *Response, err error) Delete(space, index interface{}, key interface{}) (resp *Response, err error) @@ -21,7 +21,7 @@ type Connector interface { Execute(expr string, args interface{}) (resp *Response, err error) GetTyped(space, index interface{}, key interface{}, result interface{}) (err error) - SelectTyped(space, index interface{}, offset, limit, iterator uint32, key interface{}, result interface{}) (err error) + SelectTyped(space, index interface{}, offset, limit uint32, iterator Iter, key interface{}, result interface{}) (err error) InsertTyped(space interface{}, tuple interface{}, result interface{}) (err error) ReplaceTyped(space interface{}, tuple interface{}, result interface{}) (err error) DeleteTyped(space, index interface{}, key interface{}, result interface{}) (err error) @@ -32,7 +32,7 @@ type Connector interface { EvalTyped(expr string, args interface{}, result interface{}) (err error) ExecuteTyped(expr string, args interface{}, result interface{}) (SQLInfo, []ColumnMetaData, error) - SelectAsync(space, index interface{}, offset, limit, iterator uint32, key interface{}) *Future + SelectAsync(space, index interface{}, offset, limit uint32, iterator Iter, key interface{}) *Future InsertAsync(space interface{}, tuple interface{}) *Future ReplaceAsync(space interface{}, tuple interface{}) *Future DeleteAsync(space, index interface{}, key interface{}) *Future diff --git a/const.go b/const.go index 4b6458645..62650b5be 100644 --- a/const.go +++ b/const.go @@ -1,94 +1,14 @@ package tarantool -const ( - SelectRequestCode = 1 - InsertRequestCode = 2 - ReplaceRequestCode = 3 - UpdateRequestCode = 4 - DeleteRequestCode = 5 - Call16RequestCode = 6 /* call in 1.6 format */ - AuthRequestCode = 7 - EvalRequestCode = 8 - UpsertRequestCode = 9 - Call17RequestCode = 10 /* call in >= 1.7 format */ - ExecuteRequestCode = 11 - PrepareRequestCode = 13 - BeginRequestCode = 14 - CommitRequestCode = 15 - RollbackRequestCode = 16 - PingRequestCode = 64 - SubscribeRequestCode = 66 - IdRequestCode = 73 - WatchRequestCode = 74 - UnwatchRequestCode = 75 - - KeyCode = 0x00 - KeySync = 0x01 - KeyStreamId = 0x0a - KeySpaceNo = 0x10 - KeyIndexNo = 0x11 - KeyLimit = 0x12 - KeyOffset = 0x13 - KeyIterator = 0x14 - KeyFetchPos = 0x1f - KeyKey = 0x20 - KeyTuple = 0x21 - KeyFunctionName = 0x22 - KeyUserName = 0x23 - KeyExpression = 0x27 - KeyAfterPos = 0x2e - KeyAfterTuple = 0x2f - KeyDefTuple = 0x28 - KeyData = 0x30 - KeyError24 = 0x31 /* Error in pre-2.4 format. */ - KeyMetaData = 0x32 - KeyBindCount = 0x34 - KeyPos = 0x35 - KeySQLText = 0x40 - KeySQLBind = 0x41 - KeySQLInfo = 0x42 - KeyStmtID = 0x43 - KeyError = 0x52 /* Extended error in >= 2.4 format. */ - KeyVersion = 0x54 - KeyFeatures = 0x55 - KeyTimeout = 0x56 - KeyEvent = 0x57 - KeyEventData = 0x58 - KeyTxnIsolation = 0x59 - KeyAuthType = 0x5b - - KeyFieldName = 0x00 - KeyFieldType = 0x01 - KeyFieldColl = 0x02 - KeyFieldIsNullable = 0x03 - KeyIsAutoincrement = 0x04 - KeyFieldSpan = 0x05 - KeySQLInfoRowCount = 0x00 - KeySQLInfoAutoincrementIds = 0x01 - - // https://github.com/fl00r/go-tarantool-1.6/issues/2 - - IterEq = uint32(0) // key == x ASC order - IterReq = uint32(1) // key == x DESC order - IterAll = uint32(2) // all tuples - IterLt = uint32(3) // key < x - IterLe = uint32(4) // key <= x - IterGe = uint32(5) // key >= x - IterGt = uint32(6) // key > x - IterBitsAllSet = uint32(7) // all bits from x are set in key - IterBitsAnySet = uint32(8) // at least one x's bit is set - IterBitsAllNotSet = uint32(9) // all bits are not set - IterOverlaps = uint32(10) // key overlaps x - IterNeighbor = uint32(11) // tuples in distance ascending order from specified point +import ( + "github.com/tarantool/go-iproto" +) - RLimitDrop = 1 - RLimitWait = 2 +const ( + packetLengthBytes = 5 +) - OkCode = uint32(0) - EventCode = uint32(0x4c) - PushCode = uint32(0x80) - ErrorCodeBit = 0x8000 - PacketLengthBytes = 5 - ErSpaceExistsCode = 0xa - IteratorCode = 0x14 +const ( + OkCode = uint32(iproto.IPROTO_OK) + PushCode = uint32(iproto.IPROTO_CHUNK) ) diff --git a/const_call_16.go b/const_call_16.go deleted file mode 100644 index 7d80cc631..000000000 --- a/const_call_16.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build !go_tarantool_call_17 -// +build !go_tarantool_call_17 - -package tarantool - -const ( - CallRequestCode = Call16RequestCode -) diff --git a/const_call_17.go b/const_call_17.go deleted file mode 100644 index d50d8f1c1..000000000 --- a/const_call_17.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build go_tarantool_call_17 -// +build go_tarantool_call_17 - -package tarantool - -const ( - CallRequestCode = Call17RequestCode -) diff --git a/crud/common.go b/crud/common.go index 2c4a3030c..7a6f9e03b 100644 --- a/crud/common.go +++ b/crud/common.go @@ -56,7 +56,9 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/tarantool/go-iproto" + + "github.com/tarantool/go-tarantool/v2" ) type baseRequest struct { @@ -67,9 +69,9 @@ func newCall(method string) *tarantool.CallRequest { return tarantool.NewCall17Request(method) } -// Code returns IPROTO code for CRUD request. -func (req baseRequest) Code() int32 { - return req.impl.Code() +// Type returns IPROTO type for CRUD request. +func (req baseRequest) Type() iproto.Type { + return req.impl.Type() } // Ctx returns a context of CRUD request. diff --git a/crud/count.go b/crud/count.go index 68e29f9fb..dc89f916e 100644 --- a/crud/count.go +++ b/crud/count.go @@ -3,7 +3,9 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/vmihailenco/msgpack/v5" + + "github.com/tarantool/go-tarantool/v2" ) // CountResult describes result for `crud.count` method. @@ -39,7 +41,7 @@ type CountOpts struct { } // EncodeMsgpack provides custom msgpack encoder. -func (opts CountOpts) EncodeMsgpack(enc *encoder) error { +func (opts CountOpts) EncodeMsgpack(enc *msgpack.Encoder) error { const optsCnt = 9 names := [optsCnt]string{timeoutOptName, vshardRouterOptName, @@ -101,7 +103,7 @@ func (req CountRequest) Opts(opts CountOpts) CountRequest { } // Body fills an encoder with the call request body. -func (req CountRequest) Body(res tarantool.SchemaResolver, enc *encoder) error { +func (req CountRequest) Body(res tarantool.SchemaResolver, enc *msgpack.Encoder) error { args := countArgs{Space: req.space, Conditions: req.conditions, Opts: req.opts} req.impl = req.impl.Args(args) return req.impl.Body(res, enc) diff --git a/crud/delete.go b/crud/delete.go index 5859d3d6b..f37da7ac5 100644 --- a/crud/delete.go +++ b/crud/delete.go @@ -3,7 +3,9 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/vmihailenco/msgpack/v5" + + "github.com/tarantool/go-tarantool/v2" ) // DeleteOpts describes options for `crud.delete` method. @@ -48,7 +50,7 @@ func (req DeleteRequest) Opts(opts DeleteOpts) DeleteRequest { } // Body fills an encoder with the call request body. -func (req DeleteRequest) Body(res tarantool.SchemaResolver, enc *encoder) error { +func (req DeleteRequest) Body(res tarantool.SchemaResolver, enc *msgpack.Encoder) error { if req.key == nil { req.key = []interface{}{} } diff --git a/crud/error.go b/crud/error.go index 12d416cfd..d7c36a333 100644 --- a/crud/error.go +++ b/crud/error.go @@ -1,6 +1,10 @@ package crud -import "strings" +import ( + "strings" + + "github.com/vmihailenco/msgpack/v5" +) // Error describes CRUD error object. type Error struct { @@ -20,7 +24,7 @@ type Error struct { } // DecodeMsgpack provides custom msgpack decoder. -func (e *Error) DecodeMsgpack(d *decoder) error { +func (e *Error) DecodeMsgpack(d *msgpack.Decoder) error { l, err := d.DecodeMapLen() if err != nil { return err @@ -76,7 +80,7 @@ type ErrorMany struct { } // DecodeMsgpack provides custom msgpack decoder. -func (e *ErrorMany) DecodeMsgpack(d *decoder) error { +func (e *ErrorMany) DecodeMsgpack(d *msgpack.Decoder) error { l, err := d.DecodeArrayLen() if err != nil { return err diff --git a/crud/error_test.go b/crud/error_test.go index 8bd973399..a3db035bf 100644 --- a/crud/error_test.go +++ b/crud/error_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/stretchr/testify/require" - "github.com/tarantool/go-tarantool/crud" + "github.com/tarantool/go-tarantool/v2/crud" ) func TestErrorMany(t *testing.T) { diff --git a/crud/example_test.go b/crud/example_test.go index 2b80212ca..3cd5e7bad 100644 --- a/crud/example_test.go +++ b/crud/example_test.go @@ -5,8 +5,8 @@ import ( "reflect" "time" - "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/crud" + "github.com/tarantool/go-tarantool/v2" + "github.com/tarantool/go-tarantool/v2/crud" ) const ( diff --git a/crud/get.go b/crud/get.go index 9f65a34fd..e1855f35c 100644 --- a/crud/get.go +++ b/crud/get.go @@ -3,7 +3,9 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/vmihailenco/msgpack/v5" + + "github.com/tarantool/go-tarantool/v2" ) // GetOpts describes options for `crud.get` method. @@ -30,7 +32,7 @@ type GetOpts struct { } // EncodeMsgpack provides custom msgpack encoder. -func (opts GetOpts) EncodeMsgpack(enc *encoder) error { +func (opts GetOpts) EncodeMsgpack(enc *msgpack.Encoder) error { const optsCnt = 7 names := [optsCnt]string{timeoutOptName, vshardRouterOptName, @@ -87,7 +89,7 @@ func (req GetRequest) Opts(opts GetOpts) GetRequest { } // Body fills an encoder with the call request body. -func (req GetRequest) Body(res tarantool.SchemaResolver, enc *encoder) error { +func (req GetRequest) Body(res tarantool.SchemaResolver, enc *msgpack.Encoder) error { if req.key == nil { req.key = []interface{}{} } diff --git a/crud/insert.go b/crud/insert.go index b8c34c9bd..c696d201f 100644 --- a/crud/insert.go +++ b/crud/insert.go @@ -3,7 +3,9 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/vmihailenco/msgpack/v5" + + "github.com/tarantool/go-tarantool/v2" ) // InsertOpts describes options for `crud.insert` method. @@ -48,7 +50,7 @@ func (req InsertRequest) Opts(opts InsertOpts) InsertRequest { } // Body fills an encoder with the call request body. -func (req InsertRequest) Body(res tarantool.SchemaResolver, enc *encoder) error { +func (req InsertRequest) Body(res tarantool.SchemaResolver, enc *msgpack.Encoder) error { if req.tuple == nil { req.tuple = []interface{}{} } @@ -106,7 +108,7 @@ func (req InsertObjectRequest) Opts(opts InsertObjectOpts) InsertObjectRequest { } // Body fills an encoder with the call request body. -func (req InsertObjectRequest) Body(res tarantool.SchemaResolver, enc *encoder) error { +func (req InsertObjectRequest) Body(res tarantool.SchemaResolver, enc *msgpack.Encoder) error { if req.object == nil { req.object = MapObject{} } diff --git a/crud/insert_many.go b/crud/insert_many.go index 9d2194642..602e210d5 100644 --- a/crud/insert_many.go +++ b/crud/insert_many.go @@ -3,7 +3,9 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/vmihailenco/msgpack/v5" + + "github.com/tarantool/go-tarantool/v2" ) // InsertManyOpts describes options for `crud.insert_many` method. @@ -48,7 +50,7 @@ func (req InsertManyRequest) Opts(opts InsertManyOpts) InsertManyRequest { } // Body fills an encoder with the call request body. -func (req InsertManyRequest) Body(res tarantool.SchemaResolver, enc *encoder) error { +func (req InsertManyRequest) Body(res tarantool.SchemaResolver, enc *msgpack.Encoder) error { if req.tuples == nil { req.tuples = []Tuple{} } @@ -106,7 +108,7 @@ func (req InsertObjectManyRequest) Opts(opts InsertObjectManyOpts) InsertObjectM } // Body fills an encoder with the call request body. -func (req InsertObjectManyRequest) Body(res tarantool.SchemaResolver, enc *encoder) error { +func (req InsertObjectManyRequest) Body(res tarantool.SchemaResolver, enc *msgpack.Encoder) error { if req.objects == nil { req.objects = []Object{} } diff --git a/crud/len.go b/crud/len.go index 8ebea253c..5fef700d7 100644 --- a/crud/len.go +++ b/crud/len.go @@ -3,7 +3,9 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/vmihailenco/msgpack/v5" + + "github.com/tarantool/go-tarantool/v2" ) // LenResult describes result for `crud.len` method. @@ -42,7 +44,7 @@ func (req LenRequest) Opts(opts LenOpts) LenRequest { } // Body fills an encoder with the call request body. -func (req LenRequest) Body(res tarantool.SchemaResolver, enc *encoder) error { +func (req LenRequest) Body(res tarantool.SchemaResolver, enc *msgpack.Encoder) error { args := lenArgs{Space: req.space, Opts: req.opts} req.impl = req.impl.Args(args) return req.impl.Body(res, enc) diff --git a/crud/max.go b/crud/max.go index fda960040..727a17ac5 100644 --- a/crud/max.go +++ b/crud/max.go @@ -3,7 +3,9 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/vmihailenco/msgpack/v5" + + "github.com/tarantool/go-tarantool/v2" ) // MaxOpts describes options for `crud.max` method. @@ -48,7 +50,7 @@ func (req MaxRequest) Opts(opts MaxOpts) MaxRequest { } // Body fills an encoder with the call request body. -func (req MaxRequest) Body(res tarantool.SchemaResolver, enc *encoder) error { +func (req MaxRequest) Body(res tarantool.SchemaResolver, enc *msgpack.Encoder) error { args := maxArgs{Space: req.space, Index: req.index, Opts: req.opts} req.impl = req.impl.Args(args) return req.impl.Body(res, enc) diff --git a/crud/min.go b/crud/min.go index 53794b21e..ab3bcfe07 100644 --- a/crud/min.go +++ b/crud/min.go @@ -3,7 +3,9 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/vmihailenco/msgpack/v5" + + "github.com/tarantool/go-tarantool/v2" ) // MinOpts describes options for `crud.min` method. @@ -48,7 +50,7 @@ func (req MinRequest) Opts(opts MinOpts) MinRequest { } // Body fills an encoder with the call request body. -func (req MinRequest) Body(res tarantool.SchemaResolver, enc *encoder) error { +func (req MinRequest) Body(res tarantool.SchemaResolver, enc *msgpack.Encoder) error { args := minArgs{Space: req.space, Index: req.index, Opts: req.opts} req.impl = req.impl.Args(args) return req.impl.Body(res, enc) diff --git a/crud/msgpack.go b/crud/msgpack.go deleted file mode 100644 index b9696b15e..000000000 --- a/crud/msgpack.go +++ /dev/null @@ -1,29 +0,0 @@ -//go:build !go_tarantool_msgpack_v5 -// +build !go_tarantool_msgpack_v5 - -package crud - -import ( - "gopkg.in/vmihailenco/msgpack.v2" - msgpcode "gopkg.in/vmihailenco/msgpack.v2/codes" -) - -type encoder = msgpack.Encoder -type decoder = msgpack.Decoder - -// Object is an interface to describe object for CRUD methods. -type Object interface { - EncodeMsgpack(enc *encoder) -} - -// MapObject is a type to describe object as a map. -type MapObject map[string]interface{} - -func (o MapObject) EncodeMsgpack(enc *encoder) { - enc.Encode(o) -} - -func msgpackIsArray(code byte) bool { - return code == msgpcode.Array16 || code == msgpcode.Array32 || - msgpcode.IsFixedArray(code) -} diff --git a/crud/msgpack_helper_test.go b/crud/msgpack_helper_test.go deleted file mode 100644 index 7d3998fc6..000000000 --- a/crud/msgpack_helper_test.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build !go_tarantool_msgpack_v5 -// +build !go_tarantool_msgpack_v5 - -package crud_test - -import ( - "gopkg.in/vmihailenco/msgpack.v2" -) - -var newEncoder = msgpack.NewEncoder diff --git a/crud/msgpack_v5.go b/crud/msgpack_v5.go deleted file mode 100644 index 393e359c3..000000000 --- a/crud/msgpack_v5.go +++ /dev/null @@ -1,29 +0,0 @@ -//go:build go_tarantool_msgpack_v5 -// +build go_tarantool_msgpack_v5 - -package crud - -import ( - "github.com/vmihailenco/msgpack/v5" - "github.com/vmihailenco/msgpack/v5/msgpcode" -) - -type encoder = msgpack.Encoder -type decoder = msgpack.Decoder - -// Object is an interface to describe object for CRUD methods. -type Object interface { - EncodeMsgpack(enc *encoder) -} - -// MapObject is a type to describe object as a map. -type MapObject map[string]interface{} - -func (o MapObject) EncodeMsgpack(enc *encoder) { - enc.Encode(o) -} - -func msgpackIsArray(code byte) bool { - return code == msgpcode.Array16 || code == msgpcode.Array32 || - msgpcode.IsFixedArray(code) -} diff --git a/crud/msgpack_v5_helper_test.go b/crud/msgpack_v5_helper_test.go deleted file mode 100644 index f3700bebc..000000000 --- a/crud/msgpack_v5_helper_test.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build go_tarantool_msgpack_v5 -// +build go_tarantool_msgpack_v5 - -package crud_test - -import ( - "github.com/vmihailenco/msgpack/v5" -) - -var newEncoder = msgpack.NewEncoder diff --git a/crud/object.go b/crud/object.go new file mode 100644 index 000000000..3f266a7ee --- /dev/null +++ b/crud/object.go @@ -0,0 +1,17 @@ +package crud + +import ( + "github.com/vmihailenco/msgpack/v5" +) + +// Object is an interface to describe object for CRUD methods. +type Object interface { + EncodeMsgpack(enc *msgpack.Encoder) +} + +// MapObject is a type to describe object as a map. +type MapObject map[string]interface{} + +func (o MapObject) EncodeMsgpack(enc *msgpack.Encoder) { + enc.Encode(o) +} diff --git a/crud/options.go b/crud/options.go index 9bec34754..c073b7222 100644 --- a/crud/options.go +++ b/crud/options.go @@ -1,5 +1,9 @@ package crud +import ( + "github.com/vmihailenco/msgpack/v5" +) + const ( timeoutOptName = "timeout" vshardRouterOptName = "vshard_router" @@ -121,7 +125,7 @@ type BaseOpts struct { } // EncodeMsgpack provides custom msgpack encoder. -func (opts BaseOpts) EncodeMsgpack(enc *encoder) error { +func (opts BaseOpts) EncodeMsgpack(enc *msgpack.Encoder) error { const optsCnt = 2 names := [optsCnt]string{timeoutOptName, vshardRouterOptName} @@ -148,7 +152,7 @@ type SimpleOperationOpts struct { } // EncodeMsgpack provides custom msgpack encoder. -func (opts SimpleOperationOpts) EncodeMsgpack(enc *encoder) error { +func (opts SimpleOperationOpts) EncodeMsgpack(enc *msgpack.Encoder) error { const optsCnt = 4 names := [optsCnt]string{timeoutOptName, vshardRouterOptName, @@ -182,7 +186,7 @@ type SimpleOperationObjectOpts struct { } // EncodeMsgpack provides custom msgpack encoder. -func (opts SimpleOperationObjectOpts) EncodeMsgpack(enc *encoder) error { +func (opts SimpleOperationObjectOpts) EncodeMsgpack(enc *msgpack.Encoder) error { const optsCnt = 5 names := [optsCnt]string{timeoutOptName, vshardRouterOptName, @@ -218,7 +222,7 @@ type OperationManyOpts struct { } // EncodeMsgpack provides custom msgpack encoder. -func (opts OperationManyOpts) EncodeMsgpack(enc *encoder) error { +func (opts OperationManyOpts) EncodeMsgpack(enc *msgpack.Encoder) error { const optsCnt = 5 names := [optsCnt]string{timeoutOptName, vshardRouterOptName, @@ -258,7 +262,7 @@ type OperationObjectManyOpts struct { } // EncodeMsgpack provides custom msgpack encoder. -func (opts OperationObjectManyOpts) EncodeMsgpack(enc *encoder) error { +func (opts OperationObjectManyOpts) EncodeMsgpack(enc *msgpack.Encoder) error { const optsCnt = 6 names := [optsCnt]string{timeoutOptName, vshardRouterOptName, @@ -289,7 +293,7 @@ type BorderOpts struct { } // EncodeMsgpack provides custom msgpack encoder. -func (opts BorderOpts) EncodeMsgpack(enc *encoder) error { +func (opts BorderOpts) EncodeMsgpack(enc *msgpack.Encoder) error { const optsCnt = 3 names := [optsCnt]string{timeoutOptName, vshardRouterOptName, fieldsOptName} @@ -302,7 +306,8 @@ func (opts BorderOpts) EncodeMsgpack(enc *encoder) error { return encodeOptions(enc, names[:], values[:], exists[:]) } -func encodeOptions(enc *encoder, names []string, values []interface{}, exists []bool) error { +func encodeOptions(enc *msgpack.Encoder, + names []string, values []interface{}, exists []bool) error { mapLen := 0 for _, exist := range exists { diff --git a/crud/replace.go b/crud/replace.go index 378a1ae22..8231c9aa5 100644 --- a/crud/replace.go +++ b/crud/replace.go @@ -3,7 +3,9 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/vmihailenco/msgpack/v5" + + "github.com/tarantool/go-tarantool/v2" ) // ReplaceOpts describes options for `crud.replace` method. @@ -48,7 +50,7 @@ func (req ReplaceRequest) Opts(opts ReplaceOpts) ReplaceRequest { } // Body fills an encoder with the call request body. -func (req ReplaceRequest) Body(res tarantool.SchemaResolver, enc *encoder) error { +func (req ReplaceRequest) Body(res tarantool.SchemaResolver, enc *msgpack.Encoder) error { if req.tuple == nil { req.tuple = []interface{}{} } @@ -106,7 +108,7 @@ func (req ReplaceObjectRequest) Opts(opts ReplaceObjectOpts) ReplaceObjectReques } // Body fills an encoder with the call request body. -func (req ReplaceObjectRequest) Body(res tarantool.SchemaResolver, enc *encoder) error { +func (req ReplaceObjectRequest) Body(res tarantool.SchemaResolver, enc *msgpack.Encoder) error { if req.object == nil { req.object = MapObject{} } diff --git a/crud/replace_many.go b/crud/replace_many.go index 511d60575..77c947718 100644 --- a/crud/replace_many.go +++ b/crud/replace_many.go @@ -3,7 +3,9 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/vmihailenco/msgpack/v5" + + "github.com/tarantool/go-tarantool/v2" ) // ReplaceManyOpts describes options for `crud.replace_many` method. @@ -48,7 +50,7 @@ func (req ReplaceManyRequest) Opts(opts ReplaceManyOpts) ReplaceManyRequest { } // Body fills an encoder with the call request body. -func (req ReplaceManyRequest) Body(res tarantool.SchemaResolver, enc *encoder) error { +func (req ReplaceManyRequest) Body(res tarantool.SchemaResolver, enc *msgpack.Encoder) error { if req.tuples == nil { req.tuples = []Tuple{} } @@ -106,7 +108,7 @@ func (req ReplaceObjectManyRequest) Opts(opts ReplaceObjectManyOpts) ReplaceObje } // Body fills an encoder with the call request body. -func (req ReplaceObjectManyRequest) Body(res tarantool.SchemaResolver, enc *encoder) error { +func (req ReplaceObjectManyRequest) Body(res tarantool.SchemaResolver, enc *msgpack.Encoder) error { if req.objects == nil { req.objects = []Object{} } diff --git a/crud/request_test.go b/crud/request_test.go index 3198a39c0..d36d8a264 100644 --- a/crud/request_test.go +++ b/crud/request_test.go @@ -4,11 +4,14 @@ import ( "bytes" "context" "errors" + "fmt" "testing" - "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/crud" - "github.com/tarantool/go-tarantool/test_helpers" + "github.com/tarantool/go-iproto" + "github.com/vmihailenco/msgpack/v5" + + "github.com/tarantool/go-tarantool/v2" + "github.com/tarantool/go-tarantool/v2/crud" ) const invalidSpaceMsg = "invalid space" @@ -20,7 +23,7 @@ const validSpace = "test" // Any valid value != default. const defaultSpace = 0 // And valid too. const defaultIndex = 0 // And valid too. -const CrudRequestCode = tarantool.Call17RequestCode +const CrudRequestType = iproto.IPROTO_CALL var reqObject = crud.MapObject{ "id": uint(24), @@ -91,15 +94,28 @@ func (*ValidSchemeResolver) ResolveSpaceIndex(s, i interface{}) (spaceNo, indexN var resolver ValidSchemeResolver +func extractRequestBody(req tarantool.Request, + resolver tarantool.SchemaResolver) ([]byte, error) { + var reqBuf bytes.Buffer + reqEnc := msgpack.NewEncoder(&reqBuf) + + err := req.Body(resolver, reqEnc) + if err != nil { + return nil, fmt.Errorf("An unexpected Response.Body() error: %q", err.Error()) + } + + return reqBuf.Bytes(), nil +} + func assertBodyEqual(t testing.TB, reference tarantool.Request, req tarantool.Request) { t.Helper() - reqBody, err := test_helpers.ExtractRequestBody(req, &resolver, newEncoder) + reqBody, err := extractRequestBody(req, &resolver) if err != nil { t.Fatalf("An unexpected Response.Body() error: %q", err.Error()) } - refBody, err := test_helpers.ExtractRequestBody(reference, &resolver, newEncoder) + refBody, err := extractRequestBody(reference, &resolver) if err != nil { t.Fatalf("An unexpected Response.Body() error: %q", err.Error()) } @@ -112,7 +128,7 @@ func assertBodyEqual(t testing.TB, reference tarantool.Request, req tarantool.Re func BenchmarkLenRequest(b *testing.B) { buf := bytes.Buffer{} buf.Grow(512 * 1024 * 1024) // Avoid allocs in test. - enc := newEncoder(&buf) + enc := msgpack.NewEncoder(&buf) b.ResetTimer() @@ -131,7 +147,7 @@ func BenchmarkLenRequest(b *testing.B) { func BenchmarkSelectRequest(b *testing.B) { buf := bytes.Buffer{} buf.Grow(512 * 1024 * 1024) // Avoid allocs in test. - enc := newEncoder(&buf) + enc := msgpack.NewEncoder(&buf) b.ResetTimer() @@ -151,37 +167,37 @@ func BenchmarkSelectRequest(b *testing.B) { func TestRequestsCodes(t *testing.T) { tests := []struct { - req tarantool.Request - code int32 + req tarantool.Request + rtype iproto.Type }{ - {req: crud.MakeInsertRequest(validSpace), code: CrudRequestCode}, - {req: crud.MakeInsertObjectRequest(validSpace), code: CrudRequestCode}, - {req: crud.MakeInsertManyRequest(validSpace), code: CrudRequestCode}, - {req: crud.MakeInsertObjectManyRequest(validSpace), code: CrudRequestCode}, - {req: crud.MakeGetRequest(validSpace), code: CrudRequestCode}, - {req: crud.MakeUpdateRequest(validSpace), code: CrudRequestCode}, - {req: crud.MakeDeleteRequest(validSpace), code: CrudRequestCode}, - {req: crud.MakeReplaceRequest(validSpace), code: CrudRequestCode}, - {req: crud.MakeReplaceObjectRequest(validSpace), code: CrudRequestCode}, - {req: crud.MakeReplaceManyRequest(validSpace), code: CrudRequestCode}, - {req: crud.MakeReplaceObjectManyRequest(validSpace), code: CrudRequestCode}, - {req: crud.MakeUpsertRequest(validSpace), code: CrudRequestCode}, - {req: crud.MakeUpsertObjectRequest(validSpace), code: CrudRequestCode}, - {req: crud.MakeUpsertManyRequest(validSpace), code: CrudRequestCode}, - {req: crud.MakeUpsertObjectManyRequest(validSpace), code: CrudRequestCode}, - {req: crud.MakeMinRequest(validSpace), code: CrudRequestCode}, - {req: crud.MakeMaxRequest(validSpace), code: CrudRequestCode}, - {req: crud.MakeSelectRequest(validSpace), code: CrudRequestCode}, - {req: crud.MakeTruncateRequest(validSpace), code: CrudRequestCode}, - {req: crud.MakeLenRequest(validSpace), code: CrudRequestCode}, - {req: crud.MakeCountRequest(validSpace), code: CrudRequestCode}, - {req: crud.MakeStorageInfoRequest(), code: CrudRequestCode}, - {req: crud.MakeStatsRequest(), code: CrudRequestCode}, + {req: crud.MakeInsertRequest(validSpace), rtype: CrudRequestType}, + {req: crud.MakeInsertObjectRequest(validSpace), rtype: CrudRequestType}, + {req: crud.MakeInsertManyRequest(validSpace), rtype: CrudRequestType}, + {req: crud.MakeInsertObjectManyRequest(validSpace), rtype: CrudRequestType}, + {req: crud.MakeGetRequest(validSpace), rtype: CrudRequestType}, + {req: crud.MakeUpdateRequest(validSpace), rtype: CrudRequestType}, + {req: crud.MakeDeleteRequest(validSpace), rtype: CrudRequestType}, + {req: crud.MakeReplaceRequest(validSpace), rtype: CrudRequestType}, + {req: crud.MakeReplaceObjectRequest(validSpace), rtype: CrudRequestType}, + {req: crud.MakeReplaceManyRequest(validSpace), rtype: CrudRequestType}, + {req: crud.MakeReplaceObjectManyRequest(validSpace), rtype: CrudRequestType}, + {req: crud.MakeUpsertRequest(validSpace), rtype: CrudRequestType}, + {req: crud.MakeUpsertObjectRequest(validSpace), rtype: CrudRequestType}, + {req: crud.MakeUpsertManyRequest(validSpace), rtype: CrudRequestType}, + {req: crud.MakeUpsertObjectManyRequest(validSpace), rtype: CrudRequestType}, + {req: crud.MakeMinRequest(validSpace), rtype: CrudRequestType}, + {req: crud.MakeMaxRequest(validSpace), rtype: CrudRequestType}, + {req: crud.MakeSelectRequest(validSpace), rtype: CrudRequestType}, + {req: crud.MakeTruncateRequest(validSpace), rtype: CrudRequestType}, + {req: crud.MakeLenRequest(validSpace), rtype: CrudRequestType}, + {req: crud.MakeCountRequest(validSpace), rtype: CrudRequestType}, + {req: crud.MakeStorageInfoRequest(), rtype: CrudRequestType}, + {req: crud.MakeStatsRequest(), rtype: CrudRequestType}, } for _, test := range tests { - if code := test.req.Code(); code != test.code { - t.Errorf("An invalid request code 0x%x, expected 0x%x", code, test.code) + if rtype := test.req.Type(); rtype != test.rtype { + t.Errorf("An invalid request type 0x%x, expected 0x%x", rtype, test.rtype) } } } diff --git a/crud/result.go b/crud/result.go index 5ee556a5f..100ec2a95 100644 --- a/crud/result.go +++ b/crud/result.go @@ -3,6 +3,9 @@ package crud import ( "fmt" "reflect" + + "github.com/vmihailenco/msgpack/v5" + "github.com/vmihailenco/msgpack/v5/msgpcode" ) // FieldFormat contains field definition: {name='...',type='...'[,is_nullable=...]}. @@ -13,7 +16,7 @@ type FieldFormat struct { } // DecodeMsgpack provides custom msgpack decoder. -func (format *FieldFormat) DecodeMsgpack(d *decoder) error { +func (format *FieldFormat) DecodeMsgpack(d *msgpack.Decoder) error { l, err := d.DecodeMapLen() if err != nil { return err @@ -60,8 +63,13 @@ func MakeResult(rowType reflect.Type) Result { } } +func msgpackIsArray(code byte) bool { + return code == msgpcode.Array16 || code == msgpcode.Array32 || + msgpcode.IsFixedArray(code) +} + // DecodeMsgpack provides custom msgpack decoder. -func (r *Result) DecodeMsgpack(d *decoder) error { +func (r *Result) DecodeMsgpack(d *msgpack.Decoder) error { arrLen, err := d.DecodeArrayLen() if err != nil { return err @@ -162,7 +170,7 @@ type NumberResult struct { } // DecodeMsgpack provides custom msgpack decoder. -func (r *NumberResult) DecodeMsgpack(d *decoder) error { +func (r *NumberResult) DecodeMsgpack(d *msgpack.Decoder) error { arrLen, err := d.DecodeArrayLen() if err != nil { return err @@ -201,7 +209,7 @@ type BoolResult struct { } // DecodeMsgpack provides custom msgpack decoder. -func (r *BoolResult) DecodeMsgpack(d *decoder) error { +func (r *BoolResult) DecodeMsgpack(d *msgpack.Decoder) error { arrLen, err := d.DecodeArrayLen() if err != nil { return err diff --git a/crud/select.go b/crud/select.go index 97048a365..bdd0e9d42 100644 --- a/crud/select.go +++ b/crud/select.go @@ -3,7 +3,9 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/vmihailenco/msgpack/v5" + + "github.com/tarantool/go-tarantool/v2" ) // SelectOpts describes options for `crud.select` method. @@ -42,7 +44,7 @@ type SelectOpts struct { } // EncodeMsgpack provides custom msgpack encoder. -func (opts SelectOpts) EncodeMsgpack(enc *encoder) error { +func (opts SelectOpts) EncodeMsgpack(enc *msgpack.Encoder) error { const optsCnt = 12 names := [optsCnt]string{timeoutOptName, vshardRouterOptName, @@ -108,7 +110,7 @@ func (req SelectRequest) Opts(opts SelectOpts) SelectRequest { } // Body fills an encoder with the call request body. -func (req SelectRequest) Body(res tarantool.SchemaResolver, enc *encoder) error { +func (req SelectRequest) Body(res tarantool.SchemaResolver, enc *msgpack.Encoder) error { args := selectArgs{Space: req.space, Conditions: req.conditions, Opts: req.opts} req.impl = req.impl.Args(args) return req.impl.Body(res, enc) diff --git a/crud/stats.go b/crud/stats.go index aa4184746..47737f33a 100644 --- a/crud/stats.go +++ b/crud/stats.go @@ -3,7 +3,9 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/vmihailenco/msgpack/v5" + + "github.com/tarantool/go-tarantool/v2" ) // StatsRequest helps you to create request object to call `crud.stats` @@ -28,7 +30,7 @@ func (req StatsRequest) Space(space string) StatsRequest { } // Body fills an encoder with the call request body. -func (req StatsRequest) Body(res tarantool.SchemaResolver, enc *encoder) error { +func (req StatsRequest) Body(res tarantool.SchemaResolver, enc *msgpack.Encoder) error { if value, ok := req.space.Get(); ok { req.impl = req.impl.Args([]interface{}{value}) } else { diff --git a/crud/storage_info.go b/crud/storage_info.go index 625029b51..e2d67aadb 100644 --- a/crud/storage_info.go +++ b/crud/storage_info.go @@ -3,7 +3,9 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/vmihailenco/msgpack/v5" + + "github.com/tarantool/go-tarantool/v2" ) // StatusTable describes information for instance. @@ -14,7 +16,7 @@ type StatusTable struct { } // DecodeMsgpack provides custom msgpack decoder. -func (statusTable *StatusTable) DecodeMsgpack(d *decoder) error { +func (statusTable *StatusTable) DecodeMsgpack(d *msgpack.Decoder) error { l, err := d.DecodeMapLen() if err != nil { return err @@ -54,7 +56,7 @@ type StorageInfoResult struct { } // DecodeMsgpack provides custom msgpack decoder. -func (r *StorageInfoResult) DecodeMsgpack(d *decoder) error { +func (r *StorageInfoResult) DecodeMsgpack(d *msgpack.Decoder) error { _, err := d.DecodeArrayLen() if err != nil { return err @@ -116,7 +118,7 @@ func (req StorageInfoRequest) Opts(opts StorageInfoOpts) StorageInfoRequest { } // Body fills an encoder with the call request body. -func (req StorageInfoRequest) Body(res tarantool.SchemaResolver, enc *encoder) error { +func (req StorageInfoRequest) Body(res tarantool.SchemaResolver, enc *msgpack.Encoder) error { args := storageInfoArgs{Opts: req.opts} req.impl = req.impl.Args(args) return req.impl.Body(res, enc) diff --git a/crud/tarantool_test.go b/crud/tarantool_test.go index 0787c99e5..837fa2787 100644 --- a/crud/tarantool_test.go +++ b/crud/tarantool_test.go @@ -8,9 +8,11 @@ import ( "time" "github.com/stretchr/testify/require" - "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/crud" - "github.com/tarantool/go-tarantool/test_helpers" + "github.com/tarantool/go-iproto" + + "github.com/tarantool/go-tarantool/v2" + "github.com/tarantool/go-tarantool/v2/crud" + "github.com/tarantool/go-tarantool/v2/test_helpers" ) var server = "127.0.0.1:3013" @@ -399,9 +401,9 @@ func getCrudError(req tarantool.Request, crudError interface{}) (interface{}, er var err []interface{} var ok bool - code := req.Code() + rtype := req.Type() if crudError != nil { - if code == tarantool.Call17RequestCode { + if rtype == iproto.IPROTO_CALL { return crudError, nil } diff --git a/crud/truncate.go b/crud/truncate.go index 1cd343a4d..9f80063d1 100644 --- a/crud/truncate.go +++ b/crud/truncate.go @@ -3,7 +3,9 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/vmihailenco/msgpack/v5" + + "github.com/tarantool/go-tarantool/v2" ) // TruncateResult describes result for `crud.truncate` method. @@ -42,7 +44,7 @@ func (req TruncateRequest) Opts(opts TruncateOpts) TruncateRequest { } // Body fills an encoder with the call request body. -func (req TruncateRequest) Body(res tarantool.SchemaResolver, enc *encoder) error { +func (req TruncateRequest) Body(res tarantool.SchemaResolver, enc *msgpack.Encoder) error { args := truncateArgs{Space: req.space, Opts: req.opts} req.impl = req.impl.Args(args) return req.impl.Body(res, enc) diff --git a/crud/update.go b/crud/update.go index 40951c95a..41ebd2c09 100644 --- a/crud/update.go +++ b/crud/update.go @@ -3,7 +3,9 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/vmihailenco/msgpack/v5" + + "github.com/tarantool/go-tarantool/v2" ) // UpdateOpts describes options for `crud.update` method. @@ -58,7 +60,7 @@ func (req UpdateRequest) Opts(opts UpdateOpts) UpdateRequest { } // Body fills an encoder with the call request body. -func (req UpdateRequest) Body(res tarantool.SchemaResolver, enc *encoder) error { +func (req UpdateRequest) Body(res tarantool.SchemaResolver, enc *msgpack.Encoder) error { if req.key == nil { req.key = []interface{}{} } diff --git a/crud/upsert.go b/crud/upsert.go index c116bbca5..e44523d45 100644 --- a/crud/upsert.go +++ b/crud/upsert.go @@ -3,7 +3,9 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/vmihailenco/msgpack/v5" + + "github.com/tarantool/go-tarantool/v2" ) // UpsertOpts describes options for `crud.upsert` method. @@ -58,7 +60,7 @@ func (req UpsertRequest) Opts(opts UpsertOpts) UpsertRequest { } // Body fills an encoder with the call request body. -func (req UpsertRequest) Body(res tarantool.SchemaResolver, enc *encoder) error { +func (req UpsertRequest) Body(res tarantool.SchemaResolver, enc *msgpack.Encoder) error { if req.tuple == nil { req.tuple = []interface{}{} } @@ -127,7 +129,7 @@ func (req UpsertObjectRequest) Opts(opts UpsertObjectOpts) UpsertObjectRequest { } // Body fills an encoder with the call request body. -func (req UpsertObjectRequest) Body(res tarantool.SchemaResolver, enc *encoder) error { +func (req UpsertObjectRequest) Body(res tarantool.SchemaResolver, enc *msgpack.Encoder) error { if req.object == nil { req.object = MapObject{} } diff --git a/crud/upsert_many.go b/crud/upsert_many.go index a195f5efa..c7a54ba05 100644 --- a/crud/upsert_many.go +++ b/crud/upsert_many.go @@ -3,7 +3,9 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/vmihailenco/msgpack/v5" + + "github.com/tarantool/go-tarantool/v2" ) // UpsertManyOpts describes options for `crud.upsert_many` method. @@ -57,7 +59,7 @@ func (req UpsertManyRequest) Opts(opts UpsertManyOpts) UpsertManyRequest { } // Body fills an encoder with the call request body. -func (req UpsertManyRequest) Body(res tarantool.SchemaResolver, enc *encoder) error { +func (req UpsertManyRequest) Body(res tarantool.SchemaResolver, enc *msgpack.Encoder) error { args := upsertManyArgs{Space: req.space, TuplesOperationsData: req.tuplesOperationsData, Opts: req.opts} req.impl = req.impl.Args(args) @@ -123,7 +125,7 @@ func (req UpsertObjectManyRequest) Opts(opts UpsertObjectManyOpts) UpsertObjectM } // Body fills an encoder with the call request body. -func (req UpsertObjectManyRequest) Body(res tarantool.SchemaResolver, enc *encoder) error { +func (req UpsertObjectManyRequest) Body(res tarantool.SchemaResolver, enc *msgpack.Encoder) error { args := upsertObjectManyArgs{Space: req.space, ObjectsOperationsData: req.objectsOperationsData, Opts: req.opts} req.impl = req.impl.Args(args) diff --git a/datetime/datetime.go b/datetime/datetime.go index 105d2cca5..09e86ce46 100644 --- a/datetime/datetime.go +++ b/datetime/datetime.go @@ -13,6 +13,8 @@ import ( "encoding/binary" "fmt" "time" + + "github.com/vmihailenco/msgpack/v5" ) // Datetime MessagePack serialization schema is an MP_EXT extension, which @@ -319,3 +321,7 @@ func (tm *Datetime) UnmarshalMsgpack(b []byte) error { } return err } + +func init() { + msgpack.RegisterExt(datetime_extId, (*Datetime)(nil)) +} diff --git a/datetime/datetime_test.go b/datetime/datetime_test.go index f2d1a37c7..a47126049 100644 --- a/datetime/datetime_test.go +++ b/datetime/datetime_test.go @@ -9,9 +9,11 @@ import ( "testing" "time" - . "github.com/tarantool/go-tarantool" - . "github.com/tarantool/go-tarantool/datetime" - "github.com/tarantool/go-tarantool/test_helpers" + "github.com/vmihailenco/msgpack/v5" + + . "github.com/tarantool/go-tarantool/v2" + . "github.com/tarantool/go-tarantool/v2/datetime" + "github.com/tarantool/go-tarantool/v2/test_helpers" ) var noTimezoneLoc = time.FixedZone(NoTimezone, 0) @@ -431,7 +433,7 @@ func assertDatetimeIsEqual(t *testing.T, tuples []interface{}, tm time.Time) { if len(tpl) != 2 { t.Fatalf("Unexpected return value body (tuple len = %d)", len(tpl)) } - if val, ok := toDatetime(tpl[dtIndex]); !ok || !val.ToTime().Equal(tm) { + if val, ok := tpl[dtIndex].(*Datetime); !ok || !val.ToTime().Equal(tm) { t.Fatalf("Unexpected tuple %d field %v, expected %v", dtIndex, val, @@ -546,7 +548,7 @@ func TestCustomTimezone(t *testing.T) { assertDatetimeIsEqual(t, resp.Data, tm) tpl := resp.Data[0].([]interface{}) - if respDt, ok := toDatetime(tpl[0]); ok { + if respDt, ok := tpl[0].(*Datetime); ok { zone := respDt.ToTime().Location().String() _, offset := respDt.ToTime().Zone() if zone != customZone { @@ -776,7 +778,7 @@ type Tuple1 struct { Datetime Datetime } -func (t *Tuple1) EncodeMsgpack(e *encoder) error { +func (t *Tuple1) EncodeMsgpack(e *msgpack.Encoder) error { if err := e.EncodeArrayLen(2); err != nil { return err } @@ -786,7 +788,7 @@ func (t *Tuple1) EncodeMsgpack(e *encoder) error { return nil } -func (t *Tuple1) DecodeMsgpack(d *decoder) error { +func (t *Tuple1) DecodeMsgpack(d *msgpack.Decoder) error { var err error var l int if l, err = d.DecodeArrayLen(); err != nil { @@ -802,7 +804,7 @@ func (t *Tuple1) DecodeMsgpack(d *decoder) error { return nil } -func (ev *Event) EncodeMsgpack(e *encoder) error { +func (ev *Event) EncodeMsgpack(e *msgpack.Encoder) error { if err := e.EncodeArrayLen(2); err != nil { return err } @@ -815,7 +817,7 @@ func (ev *Event) EncodeMsgpack(e *encoder) error { return nil } -func (ev *Event) DecodeMsgpack(d *decoder) error { +func (ev *Event) DecodeMsgpack(d *msgpack.Decoder) error { var err error var l int if l, err = d.DecodeArrayLen(); err != nil { @@ -831,14 +833,16 @@ func (ev *Event) DecodeMsgpack(d *decoder) error { if err != nil { return err } - var ok bool - if ev.Datetime, ok = toDatetime(res); !ok { + + if dt, ok := res.(*Datetime); !ok { return fmt.Errorf("Datetime doesn't match") + } else { + ev.Datetime = *dt } return nil } -func (c *Tuple2) EncodeMsgpack(e *encoder) error { +func (c *Tuple2) EncodeMsgpack(e *msgpack.Encoder) error { if err := e.EncodeArrayLen(3); err != nil { return err } @@ -852,7 +856,7 @@ func (c *Tuple2) EncodeMsgpack(e *encoder) error { return nil } -func (c *Tuple2) DecodeMsgpack(d *decoder) error { +func (c *Tuple2) DecodeMsgpack(d *msgpack.Decoder) error { var err error var l int if l, err = d.DecodeArrayLen(); err != nil { @@ -938,7 +942,7 @@ func TestCustomEncodeDecodeTuple1(t *testing.T) { } for i, tv := range []time.Time{tm1, tm2} { - dt, ok := toDatetime(events[i].([]interface{})[1]) + dt, ok := events[i].([]interface{})[1].(*Datetime) if !ok || !dt.ToTime().Equal(tv) { t.Fatalf("%v != %v", dt.ToTime(), tv) } @@ -1011,7 +1015,7 @@ func TestCustomEncodeDecodeTuple5(t *testing.T) { if tpl, ok := resp.Data[0].([]interface{}); !ok { t.Errorf("Unexpected body of Select") } else { - if val, ok := toDatetime(tpl[0]); !ok || !val.ToTime().Equal(tm) { + if val, ok := tpl[0].(*Datetime); !ok || !val.ToTime().Equal(tm) { t.Fatalf("Unexpected body of Select") } } @@ -1043,7 +1047,7 @@ func TestMPEncode(t *testing.T) { if err != nil { t.Fatalf("Unable to create Datetime from %s: %s", tm, err) } - buf, err := marshal(dt) + buf, err := msgpack.Marshal(dt) if err != nil { t.Fatalf("Marshalling failed: %s", err.Error()) } @@ -1076,7 +1080,7 @@ func TestMPDecode(t *testing.T) { } buf, _ := hex.DecodeString(testcase.mpBuf) var v Datetime - err = unmarshal(buf, &v) + err = msgpack.Unmarshal(buf, &v) if err != nil { t.Fatalf("Unmarshalling failed: %s", err.Error()) } diff --git a/datetime/example_test.go b/datetime/example_test.go index 50725e6a3..1faa5b24d 100644 --- a/datetime/example_test.go +++ b/datetime/example_test.go @@ -12,8 +12,8 @@ import ( "fmt" "time" - "github.com/tarantool/go-tarantool" - . "github.com/tarantool/go-tarantool/datetime" + "github.com/tarantool/go-tarantool/v2" + . "github.com/tarantool/go-tarantool/v2/datetime" ) // Example demonstrates how to use tuples with datetime. To enable support of diff --git a/datetime/interval.go b/datetime/interval.go index eee6b2d97..ef378e405 100644 --- a/datetime/interval.go +++ b/datetime/interval.go @@ -1,8 +1,11 @@ package datetime import ( + "bytes" "fmt" "reflect" + + "github.com/vmihailenco/msgpack/v5" ) const interval_extId = 6 @@ -63,22 +66,22 @@ func (ival Interval) Sub(sub Interval) Interval { return ival } -func encodeIntervalValue(e *encoder, typ uint64, value int64) (err error) { +func encodeIntervalValue(e *msgpack.Encoder, typ uint64, value int64) (err error) { if value == 0 { return } - err = encodeUint(e, typ) + err = e.EncodeUint(typ) if err == nil { if value > 0 { - err = encodeUint(e, uint64(value)) + err = e.EncodeUint(uint64(value)) } else if value < 0 { - err = encodeInt(e, int64(value)) + err = e.EncodeInt(int64(value)) } } return } -func encodeInterval(e *encoder, v reflect.Value) (err error) { +func encodeInterval(e *msgpack.Encoder, v reflect.Value) (err error) { val := v.Interface().(Interval) var fieldNum uint64 @@ -89,7 +92,7 @@ func encodeInterval(e *encoder, v reflect.Value) (err error) { fieldNum++ } } - if err = encodeUint(e, fieldNum); err != nil { + if err = e.EncodeUint(fieldNum); err != nil { return } @@ -123,7 +126,7 @@ func encodeInterval(e *encoder, v reflect.Value) (err error) { return nil } -func decodeInterval(d *decoder, v reflect.Value) (err error) { +func decodeInterval(d *msgpack.Decoder, v reflect.Value) (err error) { var fieldNum uint if fieldNum, err = d.DecodeUint(); err != nil { return @@ -177,3 +180,21 @@ func decodeInterval(d *decoder, v reflect.Value) (err error) { v.Set(reflect.ValueOf(val)) return nil } + +func init() { + msgpack.RegisterExtEncoder(interval_extId, Interval{}, + func(e *msgpack.Encoder, v reflect.Value) (ret []byte, err error) { + var b bytes.Buffer + + enc := msgpack.NewEncoder(&b) + if err = encodeInterval(enc, v); err == nil { + ret = b.Bytes() + } + + return + }) + msgpack.RegisterExtDecoder(interval_extId, Interval{}, + func(d *msgpack.Decoder, v reflect.Value, extLen int) error { + return decodeInterval(d, v) + }) +} diff --git a/datetime/interval_test.go b/datetime/interval_test.go index 2d1ad41f9..aa43f2bab 100644 --- a/datetime/interval_test.go +++ b/datetime/interval_test.go @@ -5,8 +5,8 @@ import ( "reflect" "testing" - . "github.com/tarantool/go-tarantool/datetime" - "github.com/tarantool/go-tarantool/test_helpers" + . "github.com/tarantool/go-tarantool/v2/datetime" + "github.com/tarantool/go-tarantool/v2/test_helpers" ) func TestIntervalAdd(t *testing.T) { diff --git a/datetime/msgpack.go b/datetime/msgpack.go deleted file mode 100644 index b5bc0d7c5..000000000 --- a/datetime/msgpack.go +++ /dev/null @@ -1,28 +0,0 @@ -//go:build !go_tarantool_msgpack_v5 -// +build !go_tarantool_msgpack_v5 - -package datetime - -import ( - "reflect" - - "gopkg.in/vmihailenco/msgpack.v2" -) - -type encoder = msgpack.Encoder -type decoder = msgpack.Decoder - -func encodeUint(e *encoder, v uint64) error { - return e.EncodeUint(uint(v)) -} - -func encodeInt(e *encoder, v int64) error { - return e.EncodeInt(int(v)) -} - -func init() { - msgpack.RegisterExt(datetime_extId, &Datetime{}) - - msgpack.Register(reflect.TypeOf((*Interval)(nil)).Elem(), encodeInterval, decodeInterval) - msgpack.RegisterExt(interval_extId, (*Interval)(nil)) -} diff --git a/datetime/msgpack_helper_test.go b/datetime/msgpack_helper_test.go deleted file mode 100644 index 7af2ee6ad..000000000 --- a/datetime/msgpack_helper_test.go +++ /dev/null @@ -1,26 +0,0 @@ -//go:build !go_tarantool_msgpack_v5 -// +build !go_tarantool_msgpack_v5 - -package datetime_test - -import ( - . "github.com/tarantool/go-tarantool/datetime" - - "gopkg.in/vmihailenco/msgpack.v2" -) - -type encoder = msgpack.Encoder -type decoder = msgpack.Decoder - -func toDatetime(i interface{}) (dt Datetime, ok bool) { - dt, ok = i.(Datetime) - return -} - -func marshal(v interface{}) ([]byte, error) { - return msgpack.Marshal(v) -} - -func unmarshal(data []byte, v interface{}) error { - return msgpack.Unmarshal(data, v) -} diff --git a/datetime/msgpack_v5.go b/datetime/msgpack_v5.go deleted file mode 100644 index 69285576e..000000000 --- a/datetime/msgpack_v5.go +++ /dev/null @@ -1,42 +0,0 @@ -//go:build go_tarantool_msgpack_v5 -// +build go_tarantool_msgpack_v5 - -package datetime - -import ( - "bytes" - "reflect" - - "github.com/vmihailenco/msgpack/v5" -) - -type encoder = msgpack.Encoder -type decoder = msgpack.Decoder - -func encodeUint(e *encoder, v uint64) error { - return e.EncodeUint(v) -} - -func encodeInt(e *encoder, v int64) error { - return e.EncodeInt(v) -} - -func init() { - msgpack.RegisterExt(datetime_extId, (*Datetime)(nil)) - - msgpack.RegisterExtEncoder(interval_extId, Interval{}, - func(e *msgpack.Encoder, v reflect.Value) (ret []byte, err error) { - var b bytes.Buffer - - enc := msgpack.NewEncoder(&b) - if err = encodeInterval(enc, v); err == nil { - ret = b.Bytes() - } - - return - }) - msgpack.RegisterExtDecoder(interval_extId, Interval{}, - func(d *msgpack.Decoder, v reflect.Value, extLen int) error { - return decodeInterval(d, v) - }) -} diff --git a/datetime/msgpack_v5_helper_test.go b/datetime/msgpack_v5_helper_test.go deleted file mode 100644 index d750ef006..000000000 --- a/datetime/msgpack_v5_helper_test.go +++ /dev/null @@ -1,28 +0,0 @@ -//go:build go_tarantool_msgpack_v5 -// +build go_tarantool_msgpack_v5 - -package datetime_test - -import ( - . "github.com/tarantool/go-tarantool/datetime" - "github.com/vmihailenco/msgpack/v5" -) - -type encoder = msgpack.Encoder -type decoder = msgpack.Decoder - -func toDatetime(i interface{}) (dt Datetime, ok bool) { - var ptr *Datetime - if ptr, ok = i.(*Datetime); ok { - dt = *ptr - } - return -} - -func marshal(v interface{}) ([]byte, error) { - return msgpack.Marshal(v) -} - -func unmarshal(data []byte, v interface{}) error { - return msgpack.Unmarshal(data, v) -} diff --git a/deadline_io.go b/deadline_io.go index 3bda73ac8..da547f5e2 100644 --- a/deadline_io.go +++ b/deadline_io.go @@ -5,12 +5,12 @@ import ( "time" ) -type DeadlineIO struct { +type deadlineIO struct { to time.Duration c net.Conn } -func (d *DeadlineIO) Write(b []byte) (n int, err error) { +func (d *deadlineIO) Write(b []byte) (n int, err error) { if d.to > 0 { d.c.SetWriteDeadline(time.Now().Add(d.to)) } @@ -18,7 +18,7 @@ func (d *DeadlineIO) Write(b []byte) (n int, err error) { return } -func (d *DeadlineIO) Read(b []byte) (n int, err error) { +func (d *deadlineIO) Read(b []byte) (n int, err error) { if d.to > 0 { d.c.SetReadDeadline(time.Now().Add(d.to)) } diff --git a/decimal/decimal.go b/decimal/decimal.go index cda08c12e..6cca53404 100644 --- a/decimal/decimal.go +++ b/decimal/decimal.go @@ -19,6 +19,7 @@ import ( "fmt" "github.com/shopspring/decimal" + "github.com/vmihailenco/msgpack/v5" ) // Decimal numbers have 38 digits of precision, that is, the total @@ -98,3 +99,7 @@ func (decNum *Decimal) UnmarshalMsgpack(b []byte) error { return nil } + +func init() { + msgpack.RegisterExt(decimalExtID, (*Decimal)(nil)) +} diff --git a/decimal/decimal_test.go b/decimal/decimal_test.go index b4e95ebe1..372a06fce 100644 --- a/decimal/decimal_test.go +++ b/decimal/decimal_test.go @@ -10,9 +10,11 @@ import ( "time" "github.com/shopspring/decimal" - . "github.com/tarantool/go-tarantool" - . "github.com/tarantool/go-tarantool/decimal" - "github.com/tarantool/go-tarantool/test_helpers" + "github.com/vmihailenco/msgpack/v5" + + . "github.com/tarantool/go-tarantool/v2" + . "github.com/tarantool/go-tarantool/v2/decimal" + "github.com/tarantool/go-tarantool/v2/test_helpers" ) var isDecimalSupported = false @@ -39,14 +41,14 @@ type TupleDecimal struct { number Decimal } -func (t *TupleDecimal) EncodeMsgpack(e *encoder) error { +func (t *TupleDecimal) EncodeMsgpack(e *msgpack.Encoder) error { if err := e.EncodeArrayLen(1); err != nil { return err } return e.EncodeValue(reflect.ValueOf(&t.number)) } -func (t *TupleDecimal) DecodeMsgpack(d *decoder) error { +func (t *TupleDecimal) DecodeMsgpack(d *msgpack.Decoder) error { var err error var l int if l, err = d.DecodeArrayLen(); err != nil { @@ -60,9 +62,11 @@ func (t *TupleDecimal) DecodeMsgpack(d *decoder) error { if err != nil { return err } - var ok bool - if t.number, ok = toDecimal(res); !ok { + + if dec, ok := res.(*Decimal); !ok { return fmt.Errorf("decimal doesn't match") + } else { + t.number = *dec } return nil } @@ -145,11 +149,11 @@ func TestMPEncodeDecode(t *testing.T) { } var buf []byte tuple := TupleDecimal{number: *decNum} - if buf, err = marshal(&tuple); err != nil { - t.Fatalf("Failed to encode decimal number '%s' to a MessagePack buffer: %s", testcase.numString, err) + if buf, err = msgpack.Marshal(&tuple); err != nil { + t.Fatalf("Failed to msgpack.Encoder decimal number '%s' to a MessagePack buffer: %s", testcase.numString, err) } var v TupleDecimal - if err = unmarshal(buf, &v); err != nil { + if err = msgpack.Unmarshal(buf, &v); err != nil { t.Fatalf("Failed to decode MessagePack buffer '%x' to a decimal number: %s", buf, err) } if !decNum.Equal(v.number.Decimal) { @@ -248,12 +252,12 @@ func TestEncodeMaxNumber(t *testing.T) { referenceErrMsg := "msgpack: decimal number is bigger than maximum supported number (10^38 - 1)" decNum := decimal.New(1, DecimalPrecision) // // 10^DecimalPrecision tuple := TupleDecimal{number: *NewDecimal(decNum)} - _, err := marshal(&tuple) + _, err := msgpack.Marshal(&tuple) if err == nil { - t.Fatalf("It is possible to encode a number unsupported by Tarantool") + t.Fatalf("It is possible to msgpack.Encoder a number unsupported by Tarantool") } if err.Error() != referenceErrMsg { - t.Fatalf("Incorrect error message on attempt to encode number unsupported by Tarantool") + t.Fatalf("Incorrect error message on attempt to msgpack.Encoder number unsupported by Tarantool") } } @@ -262,14 +266,14 @@ func TestEncodeMinNumber(t *testing.T) { two := decimal.NewFromInt(2) decNum := decimal.New(1, DecimalPrecision).Neg().Sub(two) // -10^DecimalPrecision - 2 tuple := TupleDecimal{number: *NewDecimal(decNum)} - _, err := marshal(&tuple) + _, err := msgpack.Marshal(&tuple) if err == nil { - t.Fatalf("It is possible to encode a number unsupported by Tarantool") + t.Fatalf("It is possible to msgpack.Encoder a number unsupported by Tarantool") } if err.Error() != referenceErrMsg { fmt.Println("Actual message: ", err.Error()) fmt.Println("Expected message: ", referenceErrMsg) - t.Fatalf("Incorrect error message on attempt to encode number unsupported by Tarantool") + t.Fatalf("Incorrect error message on attempt to msgpack.Encoder number unsupported by Tarantool") } } @@ -281,10 +285,10 @@ func benchmarkMPEncodeDecode(b *testing.B, src decimal.Decimal, dst interface{}) var err error for i := 0; i < b.N; i++ { tuple := TupleDecimal{number: *NewDecimal(src)} - if buf, err = marshal(&tuple); err != nil { + if buf, err = msgpack.Marshal(&tuple); err != nil { b.Fatal(err) } - if err = unmarshal(buf, &v); err != nil { + if err = msgpack.Unmarshal(buf, &v); err != nil { b.Fatal(err) } } @@ -311,7 +315,7 @@ func BenchmarkMPEncodeDecimal(b *testing.B) { } b.ResetTimer() for i := 0; i < b.N; i++ { - marshal(decNum) + msgpack.Marshal(decNum) } }) } @@ -325,13 +329,13 @@ func BenchmarkMPDecodeDecimal(b *testing.B) { b.Fatal(err) } var buf []byte - if buf, err = marshal(decNum); err != nil { + if buf, err = msgpack.Marshal(decNum); err != nil { b.Fatal(err) } b.ResetTimer() var v TupleDecimal for i := 0; i < b.N; i++ { - unmarshal(buf, &v) + msgpack.Unmarshal(buf, &v) } }) @@ -349,7 +353,7 @@ func tupleValueIsDecimal(t *testing.T, tuples []interface{}, number decimal.Deci if len(tpl) != 1 { t.Fatalf("Unexpected return value body (tuple len)") } - if val, ok := toDecimal(tpl[0]); !ok || !val.Equal(number) { + if val, ok := tpl[0].(*Decimal); !ok || !val.Equal(number) { t.Fatalf("Unexpected return value body (tuple 0 field)") } } @@ -370,13 +374,13 @@ func TestEncodeStringToBCD(t *testing.T) { t.Run(testcase.numString, func(t *testing.T) { buf, err := EncodeStringToBCD(testcase.numString) if err != nil { - t.Fatalf("Failed to encode decimal '%s' to BCD: %s", testcase.numString, err) + t.Fatalf("Failed to msgpack.Encoder decimal '%s' to BCD: %s", testcase.numString, err) } b, _ := hex.DecodeString(testcase.mpBuf) bcdBuf := trimMPHeader(b, testcase.fixExt) if reflect.DeepEqual(buf, bcdBuf) != true { - t.Fatalf("Failed to encode decimal '%s' to BCD: expected '%x', actual '%x'", testcase.numString, bcdBuf, buf) + t.Fatalf("Failed to msgpack.Encoder decimal '%s' to BCD: expected '%x', actual '%x'", testcase.numString, bcdBuf, buf) } }) } @@ -396,11 +400,11 @@ func TestDecodeStringFromBCD(t *testing.T) { decActual, err := decimal.NewFromString(s) if err != nil { - t.Fatalf("Failed to encode string ('%s') to decimal", s) + t.Fatalf("Failed to msgpack.Encoder string ('%s') to decimal", s) } decExpected, err := decimal.NewFromString(testcase.numString) if err != nil { - t.Fatalf("Failed to encode string ('%s') to decimal", testcase.numString) + t.Fatalf("Failed to msgpack.Encoder string ('%s') to decimal", testcase.numString) } if !decExpected.Equal(decActual) { t.Fatalf("Decoded decimal from BCD ('%x') is incorrect: expected '%s', actual '%s'", bcdBuf, testcase.numString, s) @@ -418,13 +422,13 @@ func TestMPEncode(t *testing.T) { if err != nil { t.Fatalf("NewDecimalFromString() failed: %s", err.Error()) } - buf, err := marshal(dec) + buf, err := msgpack.Marshal(dec) if err != nil { t.Fatalf("Marshalling failed: %s", err.Error()) } refBuf, _ := hex.DecodeString(testcase.mpBuf) if reflect.DeepEqual(buf, refBuf) != true { - t.Fatalf("Failed to encode decimal '%s', actual %x, expected %x", + t.Fatalf("Failed to msgpack.Encoder decimal '%s', actual %x, expected %x", testcase.numString, buf, refBuf) @@ -443,11 +447,11 @@ func TestMPDecode(t *testing.T) { t.Fatalf("hex.DecodeString() failed: %s", err) } var v interface{} - err = unmarshal(mpBuf, &v) + err = msgpack.Unmarshal(mpBuf, &v) if err != nil { - t.Fatalf("Unmarshalling failed: %s", err.Error()) + t.Fatalf("Unmsgpack.Marshalling failed: %s", err.Error()) } - decActual, ok := toDecimal(v) + decActual, ok := v.(*Decimal) if !ok { t.Fatalf("Unable to convert to Decimal") } diff --git a/decimal/example_test.go b/decimal/example_test.go index 346419125..cfa43c166 100644 --- a/decimal/example_test.go +++ b/decimal/example_test.go @@ -12,8 +12,8 @@ import ( "log" "time" - "github.com/tarantool/go-tarantool" - . "github.com/tarantool/go-tarantool/decimal" + "github.com/tarantool/go-tarantool/v2" + . "github.com/tarantool/go-tarantool/v2/decimal" ) // To enable support of decimal in msgpack with diff --git a/decimal/fuzzing_test.go b/decimal/fuzzing_test.go index c69a68719..c7df2e080 100644 --- a/decimal/fuzzing_test.go +++ b/decimal/fuzzing_test.go @@ -7,7 +7,7 @@ import ( "testing" "github.com/shopspring/decimal" - . "github.com/tarantool/go-tarantool/decimal" + . "github.com/tarantool/go-tarantool/v2/decimal" ) func strToDecimal(t *testing.T, buf string) decimal.Decimal { diff --git a/decimal/msgpack.go b/decimal/msgpack.go deleted file mode 100644 index 5a455ae59..000000000 --- a/decimal/msgpack.go +++ /dev/null @@ -1,12 +0,0 @@ -//go:build !go_tarantool_msgpack_v5 -// +build !go_tarantool_msgpack_v5 - -package decimal - -import ( - "gopkg.in/vmihailenco/msgpack.v2" -) - -func init() { - msgpack.RegisterExt(decimalExtID, &Decimal{}) -} diff --git a/decimal/msgpack_helper_test.go b/decimal/msgpack_helper_test.go deleted file mode 100644 index 3824f70b8..000000000 --- a/decimal/msgpack_helper_test.go +++ /dev/null @@ -1,26 +0,0 @@ -//go:build !go_tarantool_msgpack_v5 -// +build !go_tarantool_msgpack_v5 - -package decimal_test - -import ( - . "github.com/tarantool/go-tarantool/decimal" - - "gopkg.in/vmihailenco/msgpack.v2" -) - -type encoder = msgpack.Encoder -type decoder = msgpack.Decoder - -func toDecimal(i interface{}) (dec Decimal, ok bool) { - dec, ok = i.(Decimal) - return -} - -func marshal(v interface{}) ([]byte, error) { - return msgpack.Marshal(v) -} - -func unmarshal(data []byte, v interface{}) error { - return msgpack.Unmarshal(data, v) -} diff --git a/decimal/msgpack_v5.go b/decimal/msgpack_v5.go deleted file mode 100644 index 59fa713d0..000000000 --- a/decimal/msgpack_v5.go +++ /dev/null @@ -1,12 +0,0 @@ -//go:build go_tarantool_msgpack_v5 -// +build go_tarantool_msgpack_v5 - -package decimal - -import ( - "github.com/vmihailenco/msgpack/v5" -) - -func init() { - msgpack.RegisterExt(decimalExtID, (*Decimal)(nil)) -} diff --git a/decimal/msgpack_v5_helper_test.go b/decimal/msgpack_v5_helper_test.go deleted file mode 100644 index 6bb78168a..000000000 --- a/decimal/msgpack_v5_helper_test.go +++ /dev/null @@ -1,28 +0,0 @@ -//go:build go_tarantool_msgpack_v5 -// +build go_tarantool_msgpack_v5 - -package decimal_test - -import ( - . "github.com/tarantool/go-tarantool/decimal" - "github.com/vmihailenco/msgpack/v5" -) - -type encoder = msgpack.Encoder -type decoder = msgpack.Decoder - -func toDecimal(i interface{}) (dec Decimal, ok bool) { - var ptr *Decimal - if ptr, ok = i.(*Decimal); ok { - dec = *ptr - } - return -} - -func marshal(v interface{}) ([]byte, error) { - return msgpack.Marshal(v) -} - -func unmarshal(data []byte, v interface{}) error { - return msgpack.Unmarshal(data, v) -} diff --git a/dial.go b/dial.go index abed85e1b..3ba493ac7 100644 --- a/dial.go +++ b/dial.go @@ -9,6 +9,9 @@ import ( "net" "strings" "time" + + "github.com/tarantool/go-iproto" + "github.com/vmihailenco/msgpack/v5" ) const ( @@ -109,7 +112,7 @@ func (t TtDialer) Dial(address string, opts DialOpts) (Conn, error) { return nil, fmt.Errorf("failed to dial: %w", err) } - dc := &DeadlineIO{to: opts.IoTimeout, c: conn.net} + dc := &deadlineIO{to: opts.IoTimeout, c: conn.net} conn.reader = bufio.NewReaderSize(dc, 128*1024) conn.writer = bufio.NewWriterSize(dc, 128*1024) @@ -259,7 +262,7 @@ func identify(w writeFlusher, r io.Reader) (ProtocolInfo, error) { resp, err := readResponse(r) if err != nil { - if resp.Code == ErrUnknownRequestType { + if iproto.Error(resp.Code) == iproto.ER_UNKNOWN_REQUEST_TYPE { // IPROTO_ID requests are not supported by server. return info, nil } @@ -350,7 +353,7 @@ func authenticate(c Conn, opts DialOpts, salt string) error { // writeRequest writes a request to the writer. func writeRequest(w writeFlusher, req Request) error { var packet smallWBuf - err := pack(&packet, newEncoder(&packet), 0, req, ignoreStreamId, nil) + err := pack(&packet, msgpack.NewEncoder(&packet), 0, req, ignoreStreamId, nil) if err != nil { return fmt.Errorf("pack error: %w", err) @@ -366,7 +369,7 @@ func writeRequest(w writeFlusher, req Request) error { // readResponse reads a response from the reader. func readResponse(r io.Reader) (Response, error) { - var lenbuf [PacketLengthBytes]byte + var lenbuf [packetLengthBytes]byte respBytes, err := read(r, lenbuf[:]) if err != nil { @@ -374,7 +377,7 @@ func readResponse(r io.Reader) (Response, error) { } resp := Response{buf: smallBuf{b: respBytes}} - err = resp.decodeHeader(newDecoder(&smallBuf{})) + err = resp.decodeHeader(msgpack.NewDecoder(&smallBuf{})) if err != nil { return resp, fmt.Errorf("decode response header error: %w", err) } diff --git a/dial_test.go b/dial_test.go index 182e9c866..ff8a50aab 100644 --- a/dial_test.go +++ b/dial_test.go @@ -11,7 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/tarantool/go-tarantool" + "github.com/tarantool/go-tarantool/v2" ) type mockErrorDialer struct { diff --git a/errors.go b/errors.go index 906184c24..ab40e4f63 100644 --- a/errors.go +++ b/errors.go @@ -1,10 +1,14 @@ package tarantool -import "fmt" +import ( + "fmt" + + "github.com/tarantool/go-iproto" +) // Error is wrapper around error returned by Tarantool. type Error struct { - Code uint32 + Code iproto.Error Msg string ExtendedInfo *BoxError } @@ -57,118 +61,3 @@ const ( ErrRateLimited = 0x4000 + iota ErrConnectionShutdown = 0x4000 + iota ) - -// Tarantool server error codes. -const ( - ErrUnknown = 0 // Unknown error - ErrIllegalParams = 1 // Illegal parameters, %s - ErrMemoryIssue = 2 // Failed to allocate %u bytes in %s for %s - ErrTupleFound = 3 // Duplicate key exists in unique index '%s' in space '%s' - ErrTupleNotFound = 4 // Tuple doesn't exist in index '%s' in space '%s' - ErrUnsupported = 5 // %s does not support %s - ErrNonmaster = 6 // Can't modify data on a replication slave. My master is: %s - ErrReadonly = 7 // Can't modify data because this server is in read-only mode. - ErrInjection = 8 // Error injection '%s' - ErrCreateSpace = 9 // Failed to create space '%s': %s - ErrSpaceExists = 10 // Space '%s' already exists - ErrDropSpace = 11 // Can't drop space '%s': %s - ErrAlterSpace = 12 // Can't modify space '%s': %s - ErrIndexType = 13 // Unsupported index type supplied for index '%s' in space '%s' - ErrModifyIndex = 14 // Can't create or modify index '%s' in space '%s': %s - ErrLastDrop = 15 // Can't drop the primary key in a system space, space '%s' - ErrTupleFormatLimit = 16 // Tuple format limit reached: %u - ErrDropPrimaryKey = 17 // Can't drop primary key in space '%s' while secondary keys exist - ErrKeyPartType = 18 // Supplied key type of part %u does not match index part type: expected %s - ErrExactMatch = 19 // Invalid key part count in an exact match (expected %u, got %u) - ErrInvalidMsgpack = 20 // Invalid MsgPack - %s - ErrProcRet = 21 // msgpack.encode: can not encode Lua type '%s' - ErrTupleNotArray = 22 // Tuple/Key must be MsgPack array - ErrFieldType = 23 // Tuple field %u type does not match one required by operation: expected %s - ErrFieldTypeMismatch = 24 // Ambiguous field type in index '%s', key part %u. Requested type is %s but the field has previously been defined as %s - ErrSplice = 25 // SPLICE error on field %u: %s - ErrArgType = 26 // Argument type in operation '%c' on field %u does not match field type: expected a %s - ErrTupleIsTooLong = 27 // Tuple is too long %u - ErrUnknownUpdateOp = 28 // Unknown UPDATE operation - ErrUpdateField = 29 // Field %u UPDATE error: %s - ErrFiberStack = 30 // Can not create a new fiber: recursion limit reached - ErrKeyPartCount = 31 // Invalid key part count (expected [0..%u], got %u) - ErrProcLua = 32 // %s - ErrNoSuchProc = 33 // Procedure '%.*s' is not defined - ErrNoSuchTrigger = 34 // Trigger is not found - ErrNoSuchIndex = 35 // No index #%u is defined in space '%s' - ErrNoSuchSpace = 36 // Space '%s' does not exist - ErrNoSuchField = 37 // Field %d was not found in the tuple - ErrSpaceFieldCount = 38 // Tuple field count %u does not match space '%s' field count %u - ErrIndexFieldCount = 39 // Tuple field count %u is less than required by a defined index (expected %u) - ErrWalIo = 40 // Failed to write to disk - ErrMoreThanOneTuple = 41 // More than one tuple found by get() - ErrAccessDenied = 42 // %s access denied for user '%s' - ErrCreateUser = 43 // Failed to create user '%s': %s - ErrDropUser = 44 // Failed to drop user '%s': %s - ErrNoSuchUser = 45 // User '%s' is not found - ErrUserExists = 46 // User '%s' already exists - ErrPasswordMismatch = 47 // Incorrect password supplied for user '%s' - ErrUnknownRequestType = 48 // Unknown request type %u - ErrUnknownSchemaObject = 49 // Unknown object type '%s' - ErrCreateFunction = 50 // Failed to create function '%s': %s - ErrNoSuchFunction = 51 // Function '%s' does not exist - ErrFunctionExists = 52 // Function '%s' already exists - ErrFunctionAccessDenied = 53 // %s access denied for user '%s' to function '%s' - ErrFunctionMax = 54 // A limit on the total number of functions has been reached: %u - ErrSpaceAccessDenied = 55 // %s access denied for user '%s' to space '%s' - ErrUserMax = 56 // A limit on the total number of users has been reached: %u - ErrNoSuchEngine = 57 // Space engine '%s' does not exist - ErrReloadCfg = 58 // Can't set option '%s' dynamically - ErrCfg = 59 // Incorrect value for option '%s': %s - ErrSophia = 60 // %s - ErrLocalServerIsNotActive = 61 // Local server is not active - ErrUnknownServer = 62 // Server %s is not registered with the cluster - ErrClusterIdMismatch = 63 // Cluster id of the replica %s doesn't match cluster id of the master %s - ErrInvalidUUID = 64 // Invalid UUID: %s - ErrClusterIdIsRo = 65 // Can't reset cluster id: it is already assigned - ErrReserved66 = 66 // Reserved66 - ErrServerIdIsReserved = 67 // Can't initialize server id with a reserved value %u - ErrInvalidOrder = 68 // Invalid LSN order for server %u: previous LSN = %llu, new lsn = %llu - ErrMissingRequestField = 69 // Missing mandatory field '%s' in request - ErrIdentifier = 70 // Invalid identifier '%s' (expected letters, digits or an underscore) - ErrDropFunction = 71 // Can't drop function %u: %s - ErrIteratorType = 72 // Unknown iterator type '%s' - ErrReplicaMax = 73 // Replica count limit reached: %u - ErrInvalidXlog = 74 // Failed to read xlog: %lld - ErrInvalidXlogName = 75 // Invalid xlog name: expected %lld got %lld - ErrInvalidXlogOrder = 76 // Invalid xlog order: %lld and %lld - ErrNoConnection = 77 // Connection is not established - ErrTimeout = 78 // Timeout exceeded - ErrActiveTransaction = 79 // Operation is not permitted when there is an active transaction - ErrNoActiveTransaction = 80 // Operation is not permitted when there is no active transaction - ErrCrossEngineTransaction = 81 // A multi-statement transaction can not use multiple storage engines - ErrNoSuchRole = 82 // Role '%s' is not found - ErrRoleExists = 83 // Role '%s' already exists - ErrCreateRole = 84 // Failed to create role '%s': %s - ErrIndexExists = 85 // Index '%s' already exists - ErrTupleRefOverflow = 86 // Tuple reference counter overflow - ErrRoleLoop = 87 // Granting role '%s' to role '%s' would create a loop - ErrGrant = 88 // Incorrect grant arguments: %s - ErrPrivGranted = 89 // User '%s' already has %s access on %s '%s' - ErrRoleGranted = 90 // User '%s' already has role '%s' - ErrPrivNotGranted = 91 // User '%s' does not have %s access on %s '%s' - ErrRoleNotGranted = 92 // User '%s' does not have role '%s' - ErrMissingSnapshot = 93 // Can't find snapshot - ErrCantUpdatePrimaryKey = 94 // Attempt to modify a tuple field which is part of index '%s' in space '%s' - ErrUpdateIntegerOverflow = 95 // Integer overflow when performing '%c' operation on field %u - ErrGuestUserPassword = 96 // Setting password for guest user has no effect - ErrTransactionConflict = 97 // Transaction has been aborted by conflict - ErrUnsupportedRolePriv = 98 // Unsupported role privilege '%s' - ErrLoadFunction = 99 // Failed to dynamically load function '%s': %s - ErrFunctionLanguage = 100 // Unsupported language '%s' specified for function '%s' - ErrRtreeRect = 101 // RTree: %s must be an array with %u (point) or %u (rectangle/box) numeric coordinates - ErrProcC = 102 // ??? - ErrUnknownRtreeIndexDistanceType = 103 //Unknown RTREE index distance type %s - ErrProtocol = 104 // %s - ErrUpsertUniqueSecondaryKey = 105 // Space %s has a unique secondary index and does not support UPSERT - ErrWrongIndexRecord = 106 // Wrong record in _index space: got {%s}, expected {%s} - ErrWrongIndexParts = 107 // Wrong index parts (field %u): %s; expected field1 id (number), field1 type (string), ... - ErrWrongIndexOptions = 108 // Wrong index options (field %u): %s - ErrWrongSchemaVaersion = 109 // Wrong schema version, current: %d, in request: %u - ErrSlabAllocMax = 110 // Failed to allocate %u bytes for tuple in the slab allocator: tuple is too large. Check 'slab_alloc_maximal' configuration option. -) diff --git a/example_custom_unpacking_test.go b/example_custom_unpacking_test.go index 26d19f3af..5bac7ae62 100644 --- a/example_custom_unpacking_test.go +++ b/example_custom_unpacking_test.go @@ -5,7 +5,9 @@ import ( "log" "time" - "github.com/tarantool/go-tarantool" + "github.com/vmihailenco/msgpack/v5" + + "github.com/tarantool/go-tarantool/v2" ) type Tuple2 struct { @@ -23,11 +25,11 @@ type Tuple3 struct { Members []Member } -func (c *Tuple2) EncodeMsgpack(e *encoder) error { +func (c *Tuple2) EncodeMsgpack(e *msgpack.Encoder) error { if err := e.EncodeArrayLen(3); err != nil { return err } - if err := encodeUint(e, uint64(c.Cid)); err != nil { + if err := e.EncodeUint(uint64(c.Cid)); err != nil { return err } if err := e.EncodeString(c.Orig); err != nil { @@ -37,7 +39,7 @@ func (c *Tuple2) EncodeMsgpack(e *encoder) error { return nil } -func (c *Tuple2) DecodeMsgpack(d *decoder) error { +func (c *Tuple2) DecodeMsgpack(d *msgpack.Decoder) error { var err error var l int if l, err = d.DecodeArrayLen(); err != nil { diff --git a/example_test.go b/example_test.go index e608d0f42..60106001e 100644 --- a/example_test.go +++ b/example_test.go @@ -5,8 +5,8 @@ import ( "fmt" "time" - "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/test_helpers" + "github.com/tarantool/go-tarantool/v2" + "github.com/tarantool/go-tarantool/v2/test_helpers" ) type Tuple struct { diff --git a/export_test.go b/export_test.go index 71886bb20..688d09059 100644 --- a/export_test.go +++ b/export_test.go @@ -1,9 +1,10 @@ package tarantool import ( - "io" "net" "time" + + "github.com/vmihailenco/msgpack/v5" ) func SslDialTimeout(network, address string, timeout time.Duration, @@ -17,107 +18,103 @@ func SslCreateContext(opts SslOpts) (ctx interface{}, err error) { // RefImplPingBody is reference implementation for filling of a ping // request's body. -func RefImplPingBody(enc *encoder) error { +func RefImplPingBody(enc *msgpack.Encoder) error { return fillPing(enc) } // RefImplSelectBody is reference implementation for filling of a select // request's body. -func RefImplSelectBody(enc *encoder, space, index, offset, limit, iterator uint32, +func RefImplSelectBody(enc *msgpack.Encoder, space, index, offset, limit uint32, iterator Iter, key, after interface{}, fetchPos bool) error { return fillSelect(enc, space, index, offset, limit, iterator, key, after, fetchPos) } // RefImplInsertBody is reference implementation for filling of an insert // request's body. -func RefImplInsertBody(enc *encoder, space uint32, tuple interface{}) error { +func RefImplInsertBody(enc *msgpack.Encoder, space uint32, tuple interface{}) error { return fillInsert(enc, space, tuple) } // RefImplReplaceBody is reference implementation for filling of a replace // request's body. -func RefImplReplaceBody(enc *encoder, space uint32, tuple interface{}) error { +func RefImplReplaceBody(enc *msgpack.Encoder, space uint32, tuple interface{}) error { return fillInsert(enc, space, tuple) } // RefImplDeleteBody is reference implementation for filling of a delete // request's body. -func RefImplDeleteBody(enc *encoder, space, index uint32, key interface{}) error { +func RefImplDeleteBody(enc *msgpack.Encoder, space, index uint32, key interface{}) error { return fillDelete(enc, space, index, key) } // RefImplUpdateBody is reference implementation for filling of an update // request's body. -func RefImplUpdateBody(enc *encoder, space, index uint32, key, ops interface{}) error { +func RefImplUpdateBody(enc *msgpack.Encoder, space, index uint32, key, ops interface{}) error { return fillUpdate(enc, space, index, key, ops) } // RefImplUpsertBody is reference implementation for filling of an upsert // request's body. -func RefImplUpsertBody(enc *encoder, space uint32, tuple, ops interface{}) error { +func RefImplUpsertBody(enc *msgpack.Encoder, space uint32, tuple, ops interface{}) error { return fillUpsert(enc, space, tuple, ops) } // RefImplCallBody is reference implementation for filling of a call or call17 // request's body. -func RefImplCallBody(enc *encoder, function string, args interface{}) error { +func RefImplCallBody(enc *msgpack.Encoder, function string, args interface{}) error { return fillCall(enc, function, args) } // RefImplEvalBody is reference implementation for filling of an eval // request's body. -func RefImplEvalBody(enc *encoder, expr string, args interface{}) error { +func RefImplEvalBody(enc *msgpack.Encoder, expr string, args interface{}) error { return fillEval(enc, expr, args) } // RefImplExecuteBody is reference implementation for filling of an execute // request's body. -func RefImplExecuteBody(enc *encoder, expr string, args interface{}) error { +func RefImplExecuteBody(enc *msgpack.Encoder, expr string, args interface{}) error { return fillExecute(enc, expr, args) } // RefImplPrepareBody is reference implementation for filling of an prepare // request's body. -func RefImplPrepareBody(enc *encoder, expr string) error { +func RefImplPrepareBody(enc *msgpack.Encoder, expr string) error { return fillPrepare(enc, expr) } // RefImplUnprepareBody is reference implementation for filling of an execute prepared // request's body. -func RefImplExecutePreparedBody(enc *encoder, stmt Prepared, args interface{}) error { +func RefImplExecutePreparedBody(enc *msgpack.Encoder, stmt Prepared, args interface{}) error { return fillExecutePrepared(enc, stmt, args) } // RefImplUnprepareBody is reference implementation for filling of an unprepare // request's body. -func RefImplUnprepareBody(enc *encoder, stmt Prepared) error { +func RefImplUnprepareBody(enc *msgpack.Encoder, stmt Prepared) error { return fillUnprepare(enc, stmt) } // RefImplBeginBody is reference implementation for filling of an begin // request's body. -func RefImplBeginBody(enc *encoder, txnIsolation TxnIsolationLevel, timeout time.Duration) error { +func RefImplBeginBody(enc *msgpack.Encoder, txnIsolation TxnIsolationLevel, timeout time.Duration) error { return fillBegin(enc, txnIsolation, timeout) } // RefImplCommitBody is reference implementation for filling of an commit // request's body. -func RefImplCommitBody(enc *encoder) error { +func RefImplCommitBody(enc *msgpack.Encoder) error { return fillCommit(enc) } // RefImplRollbackBody is reference implementation for filling of an rollback // request's body. -func RefImplRollbackBody(enc *encoder) error { +func RefImplRollbackBody(enc *msgpack.Encoder) error { return fillRollback(enc) } // RefImplIdBody is reference implementation for filling of an id // request's body. -func RefImplIdBody(enc *encoder, protocolInfo ProtocolInfo) error { +func RefImplIdBody(enc *msgpack.Encoder, protocolInfo ProtocolInfo) error { return fillId(enc, protocolInfo) } - -func NewEncoder(w io.Writer) *encoder { - return newEncoder(w) -} diff --git a/future_test.go b/future_test.go index e7e9ab507..274bee7d5 100644 --- a/future_test.go +++ b/future_test.go @@ -6,7 +6,7 @@ import ( "testing" "time" - . "github.com/tarantool/go-tarantool" + . "github.com/tarantool/go-tarantool/v2" ) func assertResponseIteratorValue(t testing.TB, it ResponseIterator, diff --git a/go.mod b/go.mod index ee97cb2a1..44bc63483 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/tarantool/go-tarantool +module github.com/tarantool/go-tarantool/v2 go 1.11 @@ -7,11 +7,9 @@ require ( github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect github.com/shopspring/decimal v1.3.1 github.com/stretchr/testify v1.7.1 + github.com/tarantool/go-iproto v0.1.0 github.com/tarantool/go-openssl v0.0.8-0.20230307065445-720eeb389195 github.com/vmihailenco/msgpack/v5 v5.3.5 - golang.org/x/net v0.0.0-20201021035429-f5854403a974 // indirect golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 // indirect - google.golang.org/appengine v1.6.7 // indirect gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect - gopkg.in/vmihailenco/msgpack.v2 v2.9.2 ) diff --git a/go.sum b/go.sum index 733f1f96e..d38645c63 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,5 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -21,34 +19,19 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/tarantool/go-iproto v0.1.0 h1:zHN9AA8LDawT+JBD0/Nxgr/bIsWkkpDzpcMuaNPSIAQ= +github.com/tarantool/go-iproto v0.1.0/go.mod h1:LNCtdyZxojUed8SbOiYHoc3v9NvaZTB7p96hUySMlIo= github.com/tarantool/go-openssl v0.0.8-0.20230307065445-720eeb389195 h1:/AN3eUPsTlvF6W+Ng/8ZjnSU6o7L0H4Wb9GMks6RkzU= github.com/tarantool/go-openssl v0.0.8-0.20230307065445-720eeb389195/go.mod h1:M7H4xYSbzqpW/ZRBMyH0eyqQBsnhAMfsYk5mv0yid7A= github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 h1:myAQVi0cGEoqQVR5POX+8RR2mrocKqNN1hmeMqhX27k= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/vmihailenco/msgpack.v2 v2.9.2 h1:gjPqo9orRVlSAH/065qw3MsFCDpH7fa1KpiizXyllY4= -gopkg.in/vmihailenco/msgpack.v2 v2.9.2/go.mod h1:/3Dn1Npt9+MYyLpYYXjInO/5jvMLamn+AEGwNEOatn8= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/iterator.go b/iterator.go new file mode 100644 index 000000000..128168d7b --- /dev/null +++ b/iterator.go @@ -0,0 +1,35 @@ +package tarantool + +import ( + "github.com/tarantool/go-iproto" +) + +// Iter is an enumeration type of a select iterator. +type Iter uint32 + +const ( + // Key == x ASC order. + IterEq Iter = Iter(iproto.ITER_EQ) + // Key == x DESC order. + IterReq Iter = Iter(iproto.ITER_REQ) + // All tuples. + IterAll Iter = Iter(iproto.ITER_ALL) + // Key < x. + IterLt Iter = Iter(iproto.ITER_LT) + // Key <= x. + IterLe Iter = Iter(iproto.ITER_LE) + // Key >= x. + IterGe Iter = Iter(iproto.ITER_GE) + // Key > x. + IterGt Iter = Iter(iproto.ITER_GT) + // All bits from x are set in key. + IterBitsAllSet Iter = Iter(iproto.ITER_BITS_ALL_SET) + // All bits are not set. + IterBitsAnySet Iter = Iter(iproto.ITER_BITS_ANY_SET) + // All bits are not set. + IterBitsAllNotSet Iter = Iter(iproto.ITER_BITS_ALL_NOT_SET) + // Key overlaps x. + IterOverlaps Iter = Iter(iproto.ITER_OVERLAPS) + // Tuples in distance ascending order from specified point. + IterNeighbor Iter = Iter(iproto.ITER_NEIGHBOR) +) diff --git a/msgpack.go b/msgpack.go deleted file mode 100644 index 9977e9399..000000000 --- a/msgpack.go +++ /dev/null @@ -1,54 +0,0 @@ -//go:build !go_tarantool_msgpack_v5 -// +build !go_tarantool_msgpack_v5 - -package tarantool - -import ( - "io" - - "gopkg.in/vmihailenco/msgpack.v2" - msgpcode "gopkg.in/vmihailenco/msgpack.v2/codes" -) - -type encoder = msgpack.Encoder -type decoder = msgpack.Decoder - -func newEncoder(w io.Writer) *encoder { - return msgpack.NewEncoder(w) -} - -func newDecoder(r io.Reader) *decoder { - return msgpack.NewDecoder(r) -} - -func encodeUint(e *encoder, v uint64) error { - return e.EncodeUint(uint(v)) -} - -func encodeInt(e *encoder, v int64) error { - return e.EncodeInt(int(v)) -} - -func msgpackIsUint(code byte) bool { - return code == msgpcode.Uint8 || code == msgpcode.Uint16 || - code == msgpcode.Uint32 || code == msgpcode.Uint64 || - msgpcode.IsFixedNum(code) -} - -func msgpackIsMap(code byte) bool { - return code == msgpcode.Map16 || code == msgpcode.Map32 || msgpcode.IsFixedMap(code) -} - -func msgpackIsArray(code byte) bool { - return code == msgpcode.Array16 || code == msgpcode.Array32 || - msgpcode.IsFixedArray(code) -} - -func msgpackIsString(code byte) bool { - return msgpcode.IsFixedString(code) || code == msgpcode.Str8 || - code == msgpcode.Str16 || code == msgpcode.Str32 -} - -func init() { - msgpack.RegisterExt(errorExtID, &BoxError{}) -} diff --git a/msgpack_helper_test.go b/msgpack_helper_test.go deleted file mode 100644 index 896c105d3..000000000 --- a/msgpack_helper_test.go +++ /dev/null @@ -1,29 +0,0 @@ -//go:build !go_tarantool_msgpack_v5 -// +build !go_tarantool_msgpack_v5 - -package tarantool_test - -import ( - "github.com/tarantool/go-tarantool" - "gopkg.in/vmihailenco/msgpack.v2" -) - -type encoder = msgpack.Encoder -type decoder = msgpack.Decoder - -func encodeUint(e *encoder, v uint64) error { - return e.EncodeUint(uint(v)) -} - -func toBoxError(i interface{}) (v tarantool.BoxError, ok bool) { - v, ok = i.(tarantool.BoxError) - return -} - -func marshal(v interface{}) ([]byte, error) { - return msgpack.Marshal(v) -} - -func unmarshal(data []byte, v interface{}) error { - return msgpack.Unmarshal(data, v) -} diff --git a/msgpack_v5.go b/msgpack_v5.go deleted file mode 100644 index e8cd9aa29..000000000 --- a/msgpack_v5.go +++ /dev/null @@ -1,58 +0,0 @@ -//go:build go_tarantool_msgpack_v5 -// +build go_tarantool_msgpack_v5 - -package tarantool - -import ( - "io" - - "github.com/vmihailenco/msgpack/v5" - "github.com/vmihailenco/msgpack/v5/msgpcode" -) - -type encoder = msgpack.Encoder -type decoder = msgpack.Decoder - -func newEncoder(w io.Writer) *encoder { - return msgpack.NewEncoder(w) -} - -func newDecoder(r io.Reader) *decoder { - dec := msgpack.NewDecoder(r) - dec.SetMapDecoder(func(dec *msgpack.Decoder) (interface{}, error) { - return dec.DecodeUntypedMap() - }) - return dec -} - -func encodeUint(e *encoder, v uint64) error { - return e.EncodeUint(v) -} - -func encodeInt(e *encoder, v int64) error { - return e.EncodeInt(v) -} - -func msgpackIsUint(code byte) bool { - return code == msgpcode.Uint8 || code == msgpcode.Uint16 || - code == msgpcode.Uint32 || code == msgpcode.Uint64 || - msgpcode.IsFixedNum(code) -} - -func msgpackIsMap(code byte) bool { - return code == msgpcode.Map16 || code == msgpcode.Map32 || msgpcode.IsFixedMap(code) -} - -func msgpackIsArray(code byte) bool { - return code == msgpcode.Array16 || code == msgpcode.Array32 || - msgpcode.IsFixedArray(code) -} - -func msgpackIsString(code byte) bool { - return msgpcode.IsFixedString(code) || code == msgpcode.Str8 || - code == msgpcode.Str16 || code == msgpcode.Str32 -} - -func init() { - msgpack.RegisterExt(errorExtID, (*BoxError)(nil)) -} diff --git a/msgpack_v5_helper_test.go b/msgpack_v5_helper_test.go deleted file mode 100644 index 88154c26f..000000000 --- a/msgpack_v5_helper_test.go +++ /dev/null @@ -1,32 +0,0 @@ -//go:build go_tarantool_msgpack_v5 -// +build go_tarantool_msgpack_v5 - -package tarantool_test - -import ( - "github.com/tarantool/go-tarantool" - "github.com/vmihailenco/msgpack/v5" -) - -type encoder = msgpack.Encoder -type decoder = msgpack.Decoder - -func encodeUint(e *encoder, v uint64) error { - return e.EncodeUint(v) -} - -func toBoxError(i interface{}) (v tarantool.BoxError, ok bool) { - var ptr *tarantool.BoxError - if ptr, ok = i.(*tarantool.BoxError); ok { - v = *ptr - } - return -} - -func marshal(v interface{}) ([]byte, error) { - return msgpack.Marshal(v) -} - -func unmarshal(data []byte, v interface{}) error { - return msgpack.Unmarshal(data, v) -} diff --git a/multi/call_16_test.go b/multi/call_16_test.go deleted file mode 100644 index 35bcd20fb..000000000 --- a/multi/call_16_test.go +++ /dev/null @@ -1,33 +0,0 @@ -//go:build !go_tarantool_call_17 -// +build !go_tarantool_call_17 - -package multi - -import ( - "testing" - - "github.com/tarantool/go-tarantool" -) - -func TestCall(t *testing.T) { - var resp *tarantool.Response - var err error - - multiConn, err := Connect([]string{server1, server2}, connOpts) - if err != nil { - t.Fatalf("Failed to connect: %s", err.Error()) - } - if multiConn == nil { - t.Fatalf("conn is nil after Connect") - } - defer multiConn.Close() - - // Call16 - resp, err = multiConn.Call("simple_concat", []interface{}{"t"}) - if err != nil { - t.Fatalf("Failed to use Call: %s", err.Error()) - } - if resp.Data[0].([]interface{})[0].(string) != "tt" { - t.Fatalf("result is not {{1}} : %v", resp.Data) - } -} diff --git a/multi/call_17_test.go b/multi/call_17_test.go deleted file mode 100644 index 378961fda..000000000 --- a/multi/call_17_test.go +++ /dev/null @@ -1,33 +0,0 @@ -//go:build go_tarantool_call_17 -// +build go_tarantool_call_17 - -package multi - -import ( - "testing" - - "github.com/tarantool/go-tarantool" -) - -func TestCall(t *testing.T) { - var resp *tarantool.Response - var err error - - multiConn, err := Connect([]string{server1, server2}, connOpts) - if err != nil { - t.Fatalf("Failed to connect: %s", err.Error()) - } - if multiConn == nil { - t.Fatalf("conn is nil after Connect") - } - defer multiConn.Close() - - // Call17 - resp, err = multiConn.Call("simple_concat", []interface{}{"t"}) - if err != nil { - t.Fatalf("Failed to use Call: %s", err.Error()) - } - if resp.Data[0].(string) != "tt" { - t.Fatalf("result is not {{1}} : %v", resp.Data) - } -} diff --git a/multi/config.lua b/multi/config.lua deleted file mode 100644 index 7364c0bd6..000000000 --- a/multi/config.lua +++ /dev/null @@ -1,49 +0,0 @@ -local nodes_load = require("config_load_nodes") - --- Do not set listen for now so connector won't be --- able to send requests until everything is configured. -box.cfg{ - work_dir = os.getenv("TEST_TNT_WORK_DIR"), - memtx_use_mvcc_engine = os.getenv("TEST_TNT_MEMTX_USE_MVCC_ENGINE") == 'true' or nil, -} - --- Function to call for getting address list, part of tarantool/multi API. -local get_cluster_nodes = nodes_load.get_cluster_nodes -rawset(_G, 'get_cluster_nodes', get_cluster_nodes) - -box.once("init", function() - local s = box.schema.space.create('test', { - id = 617, - if_not_exists = true, - }) - s:create_index('primary', {type = 'tree', parts = {1, 'string'}, if_not_exists = true}) - - box.schema.user.create('test', { password = 'test' }) - box.schema.user.grant('test', 'read,write,execute', 'universe') - - local sp = box.schema.space.create('SQL_TEST', { - id = 621, - if_not_exists = true, - format = { - {name = "NAME0", type = "unsigned"}, - {name = "NAME1", type = "string"}, - {name = "NAME2", type = "string"}, - } - }) - sp:create_index('primary', {type = 'tree', parts = {1, 'uint'}, if_not_exists = true}) - sp:insert{1, "test", "test"} - -- grants for sql tests - box.schema.user.grant('test', 'create,read,write,drop,alter', 'space') - box.schema.user.grant('test', 'create', 'sequence') -end) - -local function simple_concat(a) - return a .. a -end - -rawset(_G, 'simple_concat', simple_concat) - --- Set listen only when every other thing is configured. -box.cfg{ - listen = os.getenv("TEST_TNT_LISTEN"), -} diff --git a/multi/config_load_nodes.lua b/multi/config_load_nodes.lua deleted file mode 100644 index 4df87fc28..000000000 --- a/multi/config_load_nodes.lua +++ /dev/null @@ -1,7 +0,0 @@ -local function get_cluster_nodes() - return { 'localhost:3013', 'localhost:3014' } -end - -return { - get_cluster_nodes = get_cluster_nodes -} \ No newline at end of file diff --git a/multi/example_test.go b/multi/example_test.go deleted file mode 100644 index 1ef369e4c..000000000 --- a/multi/example_test.go +++ /dev/null @@ -1,39 +0,0 @@ -package multi - -import ( - "fmt" - "time" - - "github.com/tarantool/go-tarantool" -) - -func ExampleConnect() { - multiConn, err := Connect([]string{"127.0.0.1:3031", "127.0.0.1:3032"}, tarantool.Opts{ - Timeout: 5 * time.Second, - User: "test", - Pass: "test", - }) - if err != nil { - fmt.Printf("error in connect is %v", err) - } - fmt.Println(multiConn) -} - -func ExampleConnectWithOpts() { - multiConn, err := ConnectWithOpts([]string{"127.0.0.1:3301", "127.0.0.1:3302"}, tarantool.Opts{ - Timeout: 5 * time.Second, - User: "test", - Pass: "test", - }, OptsMulti{ - // Check for connection timeout every 1 second. - CheckTimeout: 1 * time.Second, - // Lua function name for getting address list. - NodesGetFunctionName: "get_cluster_nodes", - // Ask server for updated address list every 3 seconds. - ClusterDiscoveryTime: 3 * time.Second, - }) - if err != nil { - fmt.Printf("error in connect is %v", err) - } - fmt.Println(multiConn) -} diff --git a/multi/multi.go b/multi/multi.go deleted file mode 100644 index 6aba2a426..000000000 --- a/multi/multi.go +++ /dev/null @@ -1,534 +0,0 @@ -// Package with methods to work with a Tarantool cluster. -// -// Main features: -// -// - Check the active connection with a configurable time interval and switch -// to the next connection in the pool if there is a connection failure. -// -// - Get the address list from the server and reconfigure it for use in -// MultiConnection. -// -// Since: 1.5 -package multi - -import ( - "errors" - "fmt" - "sync" - "sync/atomic" - "time" - - "github.com/tarantool/go-tarantool" -) - -const ( - connConnected = iota - connClosed -) - -var ( - ErrEmptyAddrs = errors.New("addrs should not be empty") - ErrWrongCheckTimeout = errors.New("wrong check timeout, must be greater than 0") - ErrNoConnection = errors.New("no active connections") -) - -func indexOf(sstring string, data []string) int { - for i, v := range data { - if sstring == v { - return i - } - } - return -1 -} - -// ConnectionMulti is a handle with connections to a number of Tarantool instances. -// -// It is created and configured with Connect function, and could not be -// reconfigured later. -type ConnectionMulti struct { - addrs []string - connOpts tarantool.Opts - opts OptsMulti - - mutex sync.RWMutex - notify chan tarantool.ConnEvent - state uint32 - control chan struct{} - pool map[string]*tarantool.Connection - fallback *tarantool.Connection -} - -var _ = tarantool.Connector(&ConnectionMulti{}) // Check compatibility with connector interface. - -// OptsMulti is a way to configure Connection with multiconnect-specific options. -type OptsMulti struct { - // CheckTimeout is a time interval to check for connection timeout and try to - // switch connection. - CheckTimeout time.Duration - // Lua function name of the server called to retrieve the address list. - NodesGetFunctionName string - // Time interval to ask the server for an updated address list (works - // if NodesGetFunctionName is set). - ClusterDiscoveryTime time.Duration -} - -// Connect creates and configures new ConnectionMulti with multiconnection options. -func ConnectWithOpts(addrs []string, connOpts tarantool.Opts, opts OptsMulti) (connMulti *ConnectionMulti, err error) { - if len(addrs) == 0 { - return nil, ErrEmptyAddrs - } - if opts.CheckTimeout <= 0 { - return nil, ErrWrongCheckTimeout - } - if opts.ClusterDiscoveryTime <= 0 { - opts.ClusterDiscoveryTime = 60 * time.Second - } - - notify := make(chan tarantool.ConnEvent, 10*len(addrs)) // x10 to accept disconnected and closed event (with a margin). - connOpts.Notify = notify - connMulti = &ConnectionMulti{ - addrs: addrs, - connOpts: connOpts.Clone(), - opts: opts, - notify: notify, - control: make(chan struct{}), - pool: make(map[string]*tarantool.Connection), - } - somebodyAlive, _ := connMulti.warmUp() - if !somebodyAlive { - connMulti.Close() - return nil, ErrNoConnection - } - go connMulti.checker() - - return connMulti, nil -} - -// Connect creates and configures new ConnectionMulti. -func Connect(addrs []string, connOpts tarantool.Opts) (connMulti *ConnectionMulti, err error) { - opts := OptsMulti{ - CheckTimeout: 1 * time.Second, - } - return ConnectWithOpts(addrs, connOpts, opts) -} - -func (connMulti *ConnectionMulti) warmUp() (somebodyAlive bool, errs []error) { - errs = make([]error, len(connMulti.addrs)) - - for i, addr := range connMulti.addrs { - conn, err := tarantool.Connect(addr, connMulti.connOpts) - errs[i] = err - if conn != nil && err == nil { - if connMulti.fallback == nil { - connMulti.fallback = conn - } - connMulti.pool[addr] = conn - if conn.ConnectedNow() { - somebodyAlive = true - } - } - } - return -} - -func (connMulti *ConnectionMulti) getState() uint32 { - return atomic.LoadUint32(&connMulti.state) -} - -func (connMulti *ConnectionMulti) getConnectionFromPool(addr string) (*tarantool.Connection, bool) { - connMulti.mutex.RLock() - defer connMulti.mutex.RUnlock() - conn, ok := connMulti.pool[addr] - return conn, ok -} - -func (connMulti *ConnectionMulti) setConnectionToPool(addr string, conn *tarantool.Connection) { - connMulti.mutex.Lock() - defer connMulti.mutex.Unlock() - connMulti.pool[addr] = conn -} - -func (connMulti *ConnectionMulti) deleteConnectionFromPool(addr string) { - connMulti.mutex.Lock() - defer connMulti.mutex.Unlock() - delete(connMulti.pool, addr) -} - -func (connMulti *ConnectionMulti) checker() { - - refreshTimer := time.NewTicker(connMulti.opts.ClusterDiscoveryTime) - timer := time.NewTicker(connMulti.opts.CheckTimeout) - defer refreshTimer.Stop() - defer timer.Stop() - - for connMulti.getState() != connClosed { - - select { - case <-connMulti.control: - return - case e := <-connMulti.notify: - if connMulti.getState() == connClosed { - return - } - if e.Conn.ClosedNow() { - addr := e.Conn.Addr() - if _, ok := connMulti.getConnectionFromPool(addr); !ok { - continue - } - conn, _ := tarantool.Connect(addr, connMulti.connOpts) - if conn != nil { - connMulti.setConnectionToPool(addr, conn) - } else { - connMulti.deleteConnectionFromPool(addr) - } - } - case <-refreshTimer.C: - if connMulti.getState() == connClosed || connMulti.opts.NodesGetFunctionName == "" { - continue - } - var resp [][]string - err := connMulti.Call17Typed(connMulti.opts.NodesGetFunctionName, []interface{}{}, &resp) - if err != nil { - continue - } - if len(resp) > 0 && len(resp[0]) > 0 { - addrs := resp[0] - // Fill pool with new connections. - for _, v := range addrs { - if indexOf(v, connMulti.addrs) < 0 { - conn, _ := tarantool.Connect(v, connMulti.connOpts) - if conn != nil { - connMulti.setConnectionToPool(v, conn) - } - } - } - // Clear pool from obsolete connections. - for _, v := range connMulti.addrs { - if indexOf(v, addrs) < 0 { - con, ok := connMulti.getConnectionFromPool(v) - if con != nil && ok { - con.Close() - } - connMulti.deleteConnectionFromPool(v) - } - } - connMulti.mutex.Lock() - connMulti.addrs = addrs - connMulti.mutex.Unlock() - } - case <-timer.C: - for _, addr := range connMulti.addrs { - if connMulti.getState() == connClosed { - return - } - if conn, ok := connMulti.getConnectionFromPool(addr); ok { - if !conn.ClosedNow() { - continue - } - } - conn, _ := tarantool.Connect(addr, connMulti.connOpts) - if conn != nil { - connMulti.setConnectionToPool(addr, conn) - } - } - } - } -} - -func (connMulti *ConnectionMulti) getCurrentConnection() *tarantool.Connection { - connMulti.mutex.RLock() - defer connMulti.mutex.RUnlock() - - for _, addr := range connMulti.addrs { - conn := connMulti.pool[addr] - if conn != nil { - if conn.ConnectedNow() { - return conn - } - connMulti.fallback = conn - } - } - return connMulti.fallback -} - -// ConnectedNow reports if connection is established at the moment. -func (connMulti *ConnectionMulti) ConnectedNow() bool { - return connMulti.getState() == connConnected && connMulti.getCurrentConnection().ConnectedNow() -} - -// Close closes Connection. -// After this method called, there is no way to reopen this Connection. -func (connMulti *ConnectionMulti) Close() (err error) { - connMulti.mutex.Lock() - defer connMulti.mutex.Unlock() - - close(connMulti.control) - atomic.StoreUint32(&connMulti.state, connClosed) - - for _, conn := range connMulti.pool { - if err == nil { - err = conn.Close() - } else { - conn.Close() - } - } - if connMulti.fallback != nil { - connMulti.fallback.Close() - } - - return -} - -// Ping sends empty request to Tarantool to check connection. -func (connMulti *ConnectionMulti) Ping() (resp *tarantool.Response, err error) { - return connMulti.getCurrentConnection().Ping() -} - -// ConfiguredTimeout returns a timeout from connection config. -func (connMulti *ConnectionMulti) ConfiguredTimeout() time.Duration { - return connMulti.getCurrentConnection().ConfiguredTimeout() -} - -// Select performs select to box space. -func (connMulti *ConnectionMulti) Select(space, index interface{}, offset, limit, iterator uint32, key interface{}) (resp *tarantool.Response, err error) { - return connMulti.getCurrentConnection().Select(space, index, offset, limit, iterator, key) -} - -// Insert performs insertion to box space. -// Tarantool will reject Insert when tuple with same primary key exists. -func (connMulti *ConnectionMulti) Insert(space interface{}, tuple interface{}) (resp *tarantool.Response, err error) { - return connMulti.getCurrentConnection().Insert(space, tuple) -} - -// Replace performs "insert or replace" action to box space. -// If tuple with same primary key exists, it will be replaced. -func (connMulti *ConnectionMulti) Replace(space interface{}, tuple interface{}) (resp *tarantool.Response, err error) { - return connMulti.getCurrentConnection().Replace(space, tuple) -} - -// Delete performs deletion of a tuple by key. -// Result will contain array with deleted tuple. -func (connMulti *ConnectionMulti) Delete(space, index interface{}, key interface{}) (resp *tarantool.Response, err error) { - return connMulti.getCurrentConnection().Delete(space, index, key) -} - -// Update performs update of a tuple by key. -// Result will contain array with updated tuple. -func (connMulti *ConnectionMulti) Update(space, index interface{}, key, ops interface{}) (resp *tarantool.Response, err error) { - return connMulti.getCurrentConnection().Update(space, index, key, ops) -} - -// Upsert performs "update or insert" action of a tuple by key. -// Result will not contain any tuple. -func (connMulti *ConnectionMulti) Upsert(space interface{}, tuple, ops interface{}) (resp *tarantool.Response, err error) { - return connMulti.getCurrentConnection().Upsert(space, tuple, ops) -} - -// Call calls registered Tarantool function. -// It uses request code for Tarantool >= 1.7 if go-tarantool -// was build with go_tarantool_call_17 tag. -// Otherwise, uses request code for Tarantool 1.6. -func (connMulti *ConnectionMulti) Call(functionName string, args interface{}) (resp *tarantool.Response, err error) { - return connMulti.getCurrentConnection().Call(functionName, args) -} - -// Call16 calls registered Tarantool function. -// It uses request code for Tarantool 1.6, so result is converted to array of -// arrays. -// Deprecated since Tarantool 1.7.2. -func (connMulti *ConnectionMulti) Call16(functionName string, args interface{}) (resp *tarantool.Response, err error) { - return connMulti.getCurrentConnection().Call16(functionName, args) -} - -// Call17 calls registered Tarantool function. -// It uses request code for Tarantool >= 1.7, so result is not converted -// (though, keep in mind, result is always array). -func (connMulti *ConnectionMulti) Call17(functionName string, args interface{}) (resp *tarantool.Response, err error) { - return connMulti.getCurrentConnection().Call17(functionName, args) -} - -// Eval passes Lua expression for evaluation. -func (connMulti *ConnectionMulti) Eval(expr string, args interface{}) (resp *tarantool.Response, err error) { - return connMulti.getCurrentConnection().Eval(expr, args) -} - -// Execute passes sql expression to Tarantool for execution. -// -// Since 1.6.0 -func (connMulti *ConnectionMulti) Execute(expr string, args interface{}) (resp *tarantool.Response, err error) { - return connMulti.getCurrentConnection().Execute(expr, args) -} - -// GetTyped performs select (with limit = 1 and offset = 0) to box space and -// fills typed result. -func (connMulti *ConnectionMulti) GetTyped(space, index interface{}, key interface{}, result interface{}) (err error) { - return connMulti.getCurrentConnection().GetTyped(space, index, key, result) -} - -// SelectTyped performs select to box space and fills typed result. -func (connMulti *ConnectionMulti) SelectTyped(space, index interface{}, offset, limit, iterator uint32, key interface{}, result interface{}) (err error) { - return connMulti.getCurrentConnection().SelectTyped(space, index, offset, limit, iterator, key, result) -} - -// InsertTyped performs insertion to box space. -// Tarantool will reject Insert when tuple with same primary key exists. -func (connMulti *ConnectionMulti) InsertTyped(space interface{}, tuple interface{}, result interface{}) (err error) { - return connMulti.getCurrentConnection().InsertTyped(space, tuple, result) -} - -// ReplaceTyped performs "insert or replace" action to box space. -// If tuple with same primary key exists, it will be replaced. -func (connMulti *ConnectionMulti) ReplaceTyped(space interface{}, tuple interface{}, result interface{}) (err error) { - return connMulti.getCurrentConnection().ReplaceTyped(space, tuple, result) -} - -// DeleteTyped performs deletion of a tuple by key and fills result with -// deleted tuple. -func (connMulti *ConnectionMulti) DeleteTyped(space, index interface{}, key interface{}, result interface{}) (err error) { - return connMulti.getCurrentConnection().DeleteTyped(space, index, key, result) -} - -// UpdateTyped performs update of a tuple by key and fills result with updated -// tuple. -func (connMulti *ConnectionMulti) UpdateTyped(space, index interface{}, key, ops interface{}, result interface{}) (err error) { - return connMulti.getCurrentConnection().UpdateTyped(space, index, key, ops, result) -} - -// CallTyped calls registered function. -// It uses request code for Tarantool >= 1.7 if go-tarantool -// was build with go_tarantool_call_17 tag. -// Otherwise, uses request code for Tarantool 1.6. -func (connMulti *ConnectionMulti) CallTyped(functionName string, args interface{}, result interface{}) (err error) { - return connMulti.getCurrentConnection().CallTyped(functionName, args, result) -} - -// Call16Typed calls registered function. -// It uses request code for Tarantool 1.6, so result is converted to array of -// arrays. -// Deprecated since Tarantool 1.7.2. -func (connMulti *ConnectionMulti) Call16Typed(functionName string, args interface{}, result interface{}) (err error) { - return connMulti.getCurrentConnection().Call16Typed(functionName, args, result) -} - -// Call17Typed calls registered function. -// It uses request code for Tarantool >= 1.7, so result is not converted (though, -// keep in mind, result is always array) -func (connMulti *ConnectionMulti) Call17Typed(functionName string, args interface{}, result interface{}) (err error) { - return connMulti.getCurrentConnection().Call17Typed(functionName, args, result) -} - -// EvalTyped passes Lua expression for evaluation. -func (connMulti *ConnectionMulti) EvalTyped(expr string, args interface{}, result interface{}) (err error) { - return connMulti.getCurrentConnection().EvalTyped(expr, args, result) -} - -// ExecuteTyped passes sql expression to Tarantool for execution. -func (connMulti *ConnectionMulti) ExecuteTyped(expr string, args interface{}, result interface{}) (tarantool.SQLInfo, []tarantool.ColumnMetaData, error) { - return connMulti.getCurrentConnection().ExecuteTyped(expr, args, result) -} - -// SelectAsync sends select request to Tarantool and returns Future. -func (connMulti *ConnectionMulti) SelectAsync(space, index interface{}, offset, limit, iterator uint32, key interface{}) *tarantool.Future { - return connMulti.getCurrentConnection().SelectAsync(space, index, offset, limit, iterator, key) -} - -// InsertAsync sends insert action to Tarantool and returns Future. -// Tarantool will reject Insert when tuple with same primary key exists. -func (connMulti *ConnectionMulti) InsertAsync(space interface{}, tuple interface{}) *tarantool.Future { - return connMulti.getCurrentConnection().InsertAsync(space, tuple) -} - -// ReplaceAsync sends "insert or replace" action to Tarantool and returns Future. -// If tuple with same primary key exists, it will be replaced. -func (connMulti *ConnectionMulti) ReplaceAsync(space interface{}, tuple interface{}) *tarantool.Future { - return connMulti.getCurrentConnection().ReplaceAsync(space, tuple) -} - -// DeleteAsync sends deletion action to Tarantool and returns Future. -// Future's result will contain array with deleted tuple. -func (connMulti *ConnectionMulti) DeleteAsync(space, index interface{}, key interface{}) *tarantool.Future { - return connMulti.getCurrentConnection().DeleteAsync(space, index, key) -} - -// Update sends deletion of a tuple by key and returns Future. -// Future's result will contain array with updated tuple. -func (connMulti *ConnectionMulti) UpdateAsync(space, index interface{}, key, ops interface{}) *tarantool.Future { - return connMulti.getCurrentConnection().UpdateAsync(space, index, key, ops) -} - -// UpsertAsync sends "update or insert" action to Tarantool and returns Future. -// Future's sesult will not contain any tuple. -func (connMulti *ConnectionMulti) UpsertAsync(space interface{}, tuple interface{}, ops interface{}) *tarantool.Future { - return connMulti.getCurrentConnection().UpsertAsync(space, tuple, ops) -} - -// CallAsync sends a call to registered Tarantool function and returns Future. -// It uses request code for Tarantool >= 1.7 if go-tarantool -// was build with go_tarantool_call_17 tag. -// Otherwise, uses request code for Tarantool 1.6. -func (connMulti *ConnectionMulti) CallAsync(functionName string, args interface{}) *tarantool.Future { - return connMulti.getCurrentConnection().CallAsync(functionName, args) -} - -// Call16Async sends a call to registered Tarantool function and returns Future. -// It uses request code for Tarantool 1.6, so future's result is always array -// of arrays. -// Deprecated since Tarantool 1.7.2. -func (connMulti *ConnectionMulti) Call16Async(functionName string, args interface{}) *tarantool.Future { - return connMulti.getCurrentConnection().Call16Async(functionName, args) -} - -// Call17Async sends a call to registered Tarantool function and returns Future. -// It uses request code for Tarantool >= 1.7, so future's result will not be converted -// (though, keep in mind, result is always array). -func (connMulti *ConnectionMulti) Call17Async(functionName string, args interface{}) *tarantool.Future { - return connMulti.getCurrentConnection().Call17Async(functionName, args) -} - -// EvalAsync passes Lua expression for evaluation. -func (connMulti *ConnectionMulti) EvalAsync(expr string, args interface{}) *tarantool.Future { - return connMulti.getCurrentConnection().EvalAsync(expr, args) -} - -// ExecuteAsync passes sql expression to Tarantool for execution. -func (connMulti *ConnectionMulti) ExecuteAsync(expr string, args interface{}) *tarantool.Future { - return connMulti.getCurrentConnection().ExecuteAsync(expr, args) -} - -// NewPrepared passes a sql statement to Tarantool for preparation synchronously. -func (connMulti *ConnectionMulti) NewPrepared(expr string) (*tarantool.Prepared, error) { - return connMulti.getCurrentConnection().NewPrepared(expr) -} - -// NewStream creates new Stream object for connection. -// -// Since v. 2.10.0, Tarantool supports streams and interactive transactions over them. -// To use interactive transactions, memtx_use_mvcc_engine box option should be set to true. -// Since 1.7.0 -func (connMulti *ConnectionMulti) NewStream() (*tarantool.Stream, error) { - return connMulti.getCurrentConnection().NewStream() -} - -// NewWatcher does not supported by the ConnectionMulti. The ConnectionMulti is -// deprecated: use ConnectionPool instead. -// -// Since 1.10.0 -func (connMulti *ConnectionMulti) NewWatcher(key string, - callback tarantool.WatchCallback) (tarantool.Watcher, error) { - return nil, errors.New("ConnectionMulti is deprecated " + - "use ConnectionPool") -} - -// Do sends the request and returns a future. -func (connMulti *ConnectionMulti) Do(req tarantool.Request) *tarantool.Future { - if connectedReq, ok := req.(tarantool.ConnectedRequest); ok { - _, belongs := connMulti.getConnectionFromPool(connectedReq.Conn().Addr()) - if !belongs { - fut := tarantool.NewFuture() - fut.SetError(fmt.Errorf("the passed connected request doesn't belong to the current connection or connection pool")) - return fut - } - return connectedReq.Conn().Do(req) - } - return connMulti.getCurrentConnection().Do(req) -} diff --git a/multi/multi_test.go b/multi/multi_test.go deleted file mode 100644 index 88db98321..000000000 --- a/multi/multi_test.go +++ /dev/null @@ -1,647 +0,0 @@ -package multi - -import ( - "fmt" - "log" - "os" - "reflect" - "testing" - "time" - - "github.com/stretchr/testify/require" - - "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/test_helpers" -) - -var server1 = "127.0.0.1:3013" -var server2 = "127.0.0.1:3014" -var spaceNo = uint32(617) -var spaceName = "test" -var indexNo = uint32(0) -var connOpts = tarantool.Opts{ - Timeout: 5 * time.Second, - User: "test", - Pass: "test", -} - -var connOptsMulti = OptsMulti{ - CheckTimeout: 1 * time.Second, - NodesGetFunctionName: "get_cluster_nodes", - ClusterDiscoveryTime: 3 * time.Second, -} - -var instances []test_helpers.TarantoolInstance - -func TestConnError_IncorrectParams(t *testing.T) { - multiConn, err := Connect([]string{}, tarantool.Opts{}) - if err == nil { - t.Fatalf("err is nil with incorrect params") - } - if multiConn != nil { - t.Fatalf("conn is not nill with incorrect params") - } - if err.Error() != "addrs should not be empty" { - t.Errorf("incorrect error: %s", err.Error()) - } - - multiConn, err = ConnectWithOpts([]string{server1}, tarantool.Opts{}, OptsMulti{}) - if err == nil { - t.Fatal("err is nil with incorrect params") - } - if multiConn != nil { - t.Fatal("conn is not nill with incorrect params") - } - if err.Error() != "wrong check timeout, must be greater than 0" { - t.Errorf("incorrect error: %s", err.Error()) - } -} - -func TestConnError_Connection(t *testing.T) { - multiConn, err := Connect([]string{"err1", "err2"}, connOpts) - if err == nil { - t.Errorf("err is nil with incorrect params") - return - } - if multiConn != nil { - t.Errorf("conn is not nil with incorrect params") - return - } -} - -func TestConnSuccessfully(t *testing.T) { - multiConn, err := Connect([]string{"err", server1}, connOpts) - if err != nil { - t.Errorf("Failed to connect: %s", err.Error()) - return - } - if multiConn == nil { - t.Errorf("conn is nil after Connect") - return - } - defer multiConn.Close() - - if !multiConn.ConnectedNow() { - t.Errorf("conn has incorrect status") - return - } - if multiConn.getCurrentConnection().Addr() != server1 { - t.Errorf("conn has incorrect addr") - return - } -} - -func TestReconnect(t *testing.T) { - sleep := 100 * time.Millisecond - sleepCnt := 50 - servers := []string{server1, server2} - multiConn, _ := Connect(servers, connOpts) - if multiConn == nil { - t.Errorf("conn is nil after Connect") - return - } - test_helpers.StopTarantoolWithCleanup(instances[0]) - - for i := 0; i < sleepCnt; i++ { - _, ok := multiConn.getConnectionFromPool(servers[0]) - if !ok { - break - } - time.Sleep(sleep) - } - - _, ok := multiConn.getConnectionFromPool(servers[0]) - if ok { - t.Fatalf("failed to close conn") - } - - if multiConn.getCurrentConnection().Addr() == servers[0] { - t.Errorf("conn has incorrect addr: %s after disconnect server1", multiConn.getCurrentConnection().Addr()) - } - - err := test_helpers.RestartTarantool(&instances[0]) - if err != nil { - t.Fatalf("failed to restart Tarantool: %s", err) - } - - for i := 0; i < sleepCnt; i++ { - _, ok := multiConn.getConnectionFromPool(servers[0]) - if ok { - break - } - time.Sleep(sleep) - } - - _, ok = multiConn.getConnectionFromPool(servers[0]) - if !ok { - t.Fatalf("incorrect conn status after reconnecting") - } -} - -func TestDisconnectAll(t *testing.T) { - sleep := 100 * time.Millisecond - sleepCnt := int((time.Second / sleep) * 2) // Checkout time * 2. - - servers := []string{server1, server2} - multiConn, _ := Connect(servers, connOpts) - if multiConn == nil { - t.Errorf("conn is nil after Connect") - return - } - - for _, inst := range instances { - test_helpers.StopTarantoolWithCleanup(inst) - } - - for i := 0; i < sleepCnt && multiConn.ConnectedNow(); i++ { - time.Sleep(sleep) - } - - if multiConn.ConnectedNow() { - t.Errorf("incorrect status after desconnect all") - } - - for _, inst := range instances { - err := test_helpers.RestartTarantool(&inst) - if err != nil { - t.Fatalf("failed to restart Tarantool: %s", err) - } - } - - for i := 0; i < sleepCnt && !multiConn.ConnectedNow(); i++ { - time.Sleep(sleep) - } - - if !multiConn.ConnectedNow() { - t.Errorf("incorrect multiConn status after reconnecting") - } -} - -func TestClose(t *testing.T) { - multiConn, _ := Connect([]string{server1, server2}, connOpts) - if multiConn == nil { - t.Errorf("conn is nil after Connect") - return - } - timer := time.NewTimer(300 * time.Millisecond) - <-timer.C - - conn, _ := multiConn.getConnectionFromPool(server1) - if !conn.ConnectedNow() { - t.Errorf("incorrect conn server1 status") - } - conn, _ = multiConn.getConnectionFromPool(server2) - if !conn.ConnectedNow() { - t.Errorf("incorrect conn server2 status") - } - - multiConn.Close() - timer = time.NewTimer(100 * time.Millisecond) - <-timer.C - - if multiConn.ConnectedNow() { - t.Errorf("incorrect multiConn status after close") - } - conn, _ = multiConn.getConnectionFromPool(server1) - if conn.ConnectedNow() { - t.Errorf("incorrect server1 conn status after close") - } - conn, _ = multiConn.getConnectionFromPool(server2) - if conn.ConnectedNow() { - t.Errorf("incorrect server2 conn status after close") - } -} - -func TestRefresh(t *testing.T) { - - multiConn, _ := ConnectWithOpts([]string{server1, server2}, connOpts, connOptsMulti) - if multiConn == nil { - t.Errorf("conn is nil after Connect") - return - } - - multiConn.mutex.RLock() - curAddr := multiConn.addrs[0] - multiConn.mutex.RUnlock() - - // Wait for refresh timer. - // Scenario 1 nodeload, 1 refresh, 1 nodeload. - time.Sleep(10 * time.Second) - - multiConn.mutex.RLock() - newAddr := multiConn.addrs[0] - multiConn.mutex.RUnlock() - - if curAddr == newAddr { - t.Errorf("Expect address refresh") - } - - if !multiConn.ConnectedNow() { - t.Errorf("Expect connection to exist") - } - - _, err := multiConn.Call17(multiConn.opts.NodesGetFunctionName, []interface{}{}) - if err != nil { - t.Error("Expect to get data after reconnect") - } -} - -func TestCall17(t *testing.T) { - var resp *tarantool.Response - var err error - - multiConn, err := Connect([]string{server1, server2}, connOpts) - if err != nil { - t.Fatalf("Failed to connect: %s", err.Error()) - } - if multiConn == nil { - t.Fatalf("conn is nil after Connect") - } - defer multiConn.Close() - - // Call17 - resp, err = multiConn.Call17("simple_concat", []interface{}{"s"}) - if err != nil { - t.Fatalf("Failed to use Call: %s", err.Error()) - } - if resp.Data[0].(string) != "ss" { - t.Fatalf("result is not {{1}} : %v", resp.Data) - } -} - -func TestNewPrepared(t *testing.T) { - test_helpers.SkipIfSQLUnsupported(t) - - multiConn, err := Connect([]string{server1, server2}, connOpts) - if err != nil { - t.Fatalf("Failed to connect: %s", err.Error()) - } - if multiConn == nil { - t.Fatalf("conn is nil after Connect") - } - defer multiConn.Close() - - stmt, err := multiConn.NewPrepared("SELECT NAME0, NAME1 FROM SQL_TEST WHERE NAME0=:id AND NAME1=:name;") - require.Nilf(t, err, "fail to prepare statement: %v", err) - - executeReq := tarantool.NewExecutePreparedRequest(stmt) - unprepareReq := tarantool.NewUnprepareRequest(stmt) - - resp, err := multiConn.Do(executeReq.Args([]interface{}{1, "test"})).Get() - if err != nil { - t.Fatalf("failed to execute prepared: %v", err) - } - if resp == nil { - t.Fatalf("nil response") - } - if resp.Code != tarantool.OkCode { - t.Fatalf("failed to execute prepared: code %d", resp.Code) - } - if reflect.DeepEqual(resp.Data[0], []interface{}{1, "test"}) { - t.Error("Select with named arguments failed") - } - if resp.MetaData[0].FieldType != "unsigned" || - resp.MetaData[0].FieldName != "NAME0" || - resp.MetaData[1].FieldType != "string" || - resp.MetaData[1].FieldName != "NAME1" { - t.Error("Wrong metadata") - } - - // the second argument for unprepare request is unused - it already belongs to some connection - resp, err = multiConn.Do(unprepareReq).Get() - if err != nil { - t.Errorf("failed to unprepare prepared statement: %v", err) - } - if resp.Code != tarantool.OkCode { - t.Errorf("failed to unprepare prepared statement: code %d", resp.Code) - } - - _, err = multiConn.Do(unprepareReq).Get() - if err == nil { - t.Errorf("the statement must be already unprepared") - } - require.Contains(t, err.Error(), "Prepared statement with id") - - _, err = multiConn.Do(executeReq).Get() - if err == nil { - t.Errorf("the statement must be already unprepared") - } - require.Contains(t, err.Error(), "Prepared statement with id") -} - -func TestDoWithStrangerConn(t *testing.T) { - expectedErr := fmt.Errorf("the passed connected request doesn't belong to the current connection or connection pool") - - multiConn, err := Connect([]string{server1, server2}, connOpts) - if err != nil { - t.Fatalf("Failed to connect: %s", err.Error()) - } - if multiConn == nil { - t.Fatalf("conn is nil after Connect") - } - defer multiConn.Close() - - req := test_helpers.NewStrangerRequest() - - _, err = multiConn.Do(req).Get() - if err == nil { - t.Fatalf("nil error caught") - } - if err.Error() != expectedErr.Error() { - t.Fatalf("Unexpected error caught") - } -} - -func TestStream_Commit(t *testing.T) { - var req tarantool.Request - var resp *tarantool.Response - var err error - - test_helpers.SkipIfStreamsUnsupported(t) - - multiConn, err := Connect([]string{server1, server2}, connOpts) - if err != nil { - t.Fatalf("Failed to connect: %s", err.Error()) - } - if multiConn == nil { - t.Fatalf("conn is nil after Connect") - } - defer multiConn.Close() - - stream, _ := multiConn.NewStream() - - // Begin transaction - req = tarantool.NewBeginRequest() - resp, err = stream.Do(req).Get() - if err != nil { - t.Fatalf("Failed to Begin: %s", err.Error()) - } - if resp.Code != tarantool.OkCode { - t.Fatalf("Failed to Begin: wrong code returned %d", resp.Code) - } - - // Insert in stream - req = tarantool.NewInsertRequest(spaceName). - Tuple([]interface{}{"1001", "hello2", "world2"}) - resp, err = stream.Do(req).Get() - if err != nil { - t.Fatalf("Failed to Insert: %s", err.Error()) - } - if resp.Code != tarantool.OkCode { - t.Errorf("Failed to Insert: wrong code returned %d", resp.Code) - } - defer test_helpers.DeleteRecordByKey(t, multiConn, spaceNo, indexNo, []interface{}{"1001"}) - - // Select not related to the transaction - // while transaction is not committed - // result of select is empty - selectReq := tarantool.NewSelectRequest(spaceNo). - Index(indexNo). - Limit(1). - Iterator(tarantool.IterEq). - Key([]interface{}{"1001"}) - resp, err = multiConn.Do(selectReq).Get() - if err != nil { - t.Fatalf("Failed to Select: %s", err.Error()) - } - if resp == nil { - t.Fatalf("Response is nil after Select") - } - if len(resp.Data) != 0 { - t.Fatalf("Response Data len != 0") - } - - // Select in stream - resp, err = stream.Do(selectReq).Get() - if err != nil { - t.Fatalf("Failed to Select: %s", err.Error()) - } - if resp == nil { - t.Fatalf("Response is nil after Select") - } - if len(resp.Data) != 1 { - t.Fatalf("Response Data len != 1") - } - if tpl, ok := resp.Data[0].([]interface{}); !ok { - t.Fatalf("Unexpected body of Select") - } else { - if id, ok := tpl[0].(string); !ok || id != "1001" { - t.Fatalf("Unexpected body of Select (0)") - } - if h, ok := tpl[1].(string); !ok || h != "hello2" { - t.Fatalf("Unexpected body of Select (1)") - } - if h, ok := tpl[2].(string); !ok || h != "world2" { - t.Fatalf("Unexpected body of Select (2)") - } - } - - // Commit transaction - req = tarantool.NewCommitRequest() - resp, err = stream.Do(req).Get() - if err != nil { - t.Fatalf("Failed to Commit: %s", err.Error()) - } - if resp.Code != tarantool.OkCode { - t.Fatalf("Failed to Commit: wrong code returned %d", resp.Code) - } - - // Select outside of transaction - resp, err = multiConn.Do(selectReq).Get() - if err != nil { - t.Fatalf("Failed to Select: %s", err.Error()) - } - if resp == nil { - t.Fatalf("Response is nil after Select") - } - if len(resp.Data) != 1 { - t.Fatalf("Response Data len != 1") - } - if tpl, ok := resp.Data[0].([]interface{}); !ok { - t.Fatalf("Unexpected body of Select") - } else { - if id, ok := tpl[0].(string); !ok || id != "1001" { - t.Fatalf("Unexpected body of Select (0)") - } - if h, ok := tpl[1].(string); !ok || h != "hello2" { - t.Fatalf("Unexpected body of Select (1)") - } - if h, ok := tpl[2].(string); !ok || h != "world2" { - t.Fatalf("Unexpected body of Select (2)") - } - } -} - -func TestStream_Rollback(t *testing.T) { - var req tarantool.Request - var resp *tarantool.Response - var err error - - test_helpers.SkipIfStreamsUnsupported(t) - - multiConn, err := Connect([]string{server1, server2}, connOpts) - if err != nil { - t.Fatalf("Failed to connect: %s", err.Error()) - } - if multiConn == nil { - t.Fatalf("conn is nil after Connect") - } - defer multiConn.Close() - - stream, _ := multiConn.NewStream() - - // Begin transaction - req = tarantool.NewBeginRequest() - resp, err = stream.Do(req).Get() - if err != nil { - t.Fatalf("Failed to Begin: %s", err.Error()) - } - if resp.Code != tarantool.OkCode { - t.Fatalf("Failed to Begin: wrong code returned %d", resp.Code) - } - - // Insert in stream - req = tarantool.NewInsertRequest(spaceName). - Tuple([]interface{}{"1001", "hello2", "world2"}) - resp, err = stream.Do(req).Get() - if err != nil { - t.Fatalf("Failed to Insert: %s", err.Error()) - } - if resp.Code != tarantool.OkCode { - t.Errorf("Failed to Insert: wrong code returned %d", resp.Code) - } - defer test_helpers.DeleteRecordByKey(t, multiConn, spaceNo, indexNo, []interface{}{"1001"}) - - // Select not related to the transaction - // while transaction is not committed - // result of select is empty - selectReq := tarantool.NewSelectRequest(spaceNo). - Index(indexNo). - Limit(1). - Iterator(tarantool.IterEq). - Key([]interface{}{"1001"}) - resp, err = multiConn.Do(selectReq).Get() - if err != nil { - t.Fatalf("Failed to Select: %s", err.Error()) - } - if resp == nil { - t.Fatalf("Response is nil after Select") - } - if len(resp.Data) != 0 { - t.Fatalf("Response Data len != 0") - } - - // Select in stream - resp, err = stream.Do(selectReq).Get() - if err != nil { - t.Fatalf("Failed to Select: %s", err.Error()) - } - if resp == nil { - t.Fatalf("Response is nil after Select") - } - if len(resp.Data) != 1 { - t.Fatalf("Response Data len != 1") - } - if tpl, ok := resp.Data[0].([]interface{}); !ok { - t.Fatalf("Unexpected body of Select") - } else { - if id, ok := tpl[0].(string); !ok || id != "1001" { - t.Fatalf("Unexpected body of Select (0)") - } - if h, ok := tpl[1].(string); !ok || h != "hello2" { - t.Fatalf("Unexpected body of Select (1)") - } - if h, ok := tpl[2].(string); !ok || h != "world2" { - t.Fatalf("Unexpected body of Select (2)") - } - } - - // Rollback transaction - req = tarantool.NewRollbackRequest() - resp, err = stream.Do(req).Get() - if err != nil { - t.Fatalf("Failed to Rollback: %s", err.Error()) - } - if resp.Code != tarantool.OkCode { - t.Fatalf("Failed to Rollback: wrong code returned %d", resp.Code) - } - - // Select outside of transaction - resp, err = multiConn.Do(selectReq).Get() - if err != nil { - t.Fatalf("Failed to Select: %s", err.Error()) - } - if resp == nil { - t.Fatalf("Response is nil after Select") - } - if len(resp.Data) != 0 { - t.Fatalf("Response Data len != 0") - } -} - -func TestConnectionMulti_NewWatcher(t *testing.T) { - test_helpers.SkipIfStreamsUnsupported(t) - - multiConn, err := Connect([]string{server1, server2}, connOpts) - if err != nil { - t.Fatalf("Failed to connect: %s", err.Error()) - } - if multiConn == nil { - t.Fatalf("conn is nil after Connect") - } - defer multiConn.Close() - - watcher, err := multiConn.NewWatcher("foo", func(event tarantool.WatchEvent) {}) - if watcher != nil { - t.Errorf("Unexpected watcher") - } - if err == nil { - t.Fatalf("Unexpected success") - } - if err.Error() != "ConnectionMulti is deprecated use ConnectionPool" { - t.Fatalf("Unexpected error: %s", err) - } -} - -// runTestMain is a body of TestMain function -// (see https://pkg.go.dev/testing#hdr-Main). -// Using defer + os.Exit is not works so TestMain body -// is a separate function, see -// https://stackoverflow.com/questions/27629380/how-to-exit-a-go-program-honoring-deferred-calls -func runTestMain(m *testing.M) int { - initScript := "config.lua" - waitStart := 100 * time.Millisecond - connectRetry := 10 - retryTimeout := 500 * time.Millisecond - - // Tarantool supports streams and interactive transactions since version 2.10.0 - isStreamUnsupported, err := test_helpers.IsTarantoolVersionLess(2, 10, 0) - if err != nil { - log.Fatalf("Could not check the Tarantool version") - } - - servers := []string{server1, server2} - instances, err = test_helpers.StartTarantoolInstances(servers, nil, test_helpers.StartOpts{ - InitScript: initScript, - User: connOpts.User, - Pass: connOpts.Pass, - WaitStart: waitStart, - ConnectRetry: connectRetry, - RetryTimeout: retryTimeout, - MemtxUseMvccEngine: !isStreamUnsupported, - }) - - if err != nil { - log.Fatalf("Failed to prepare test tarantool: %s", err) - return -1 - } - - defer test_helpers.StopTarantoolInstances(instances) - - return m.Run() -} - -func TestMain(m *testing.M) { - code := runTestMain(m) - os.Exit(code) -} diff --git a/connection_pool/config.lua b/pool/config.lua similarity index 100% rename from connection_pool/config.lua rename to pool/config.lua diff --git a/connection_pool/connection_pool.go b/pool/connection_pool.go similarity index 94% rename from connection_pool/connection_pool.go rename to pool/connection_pool.go index 5113e9ea5..f2d85f445 100644 --- a/connection_pool/connection_pool.go +++ b/pool/connection_pool.go @@ -8,7 +8,7 @@ // - Automatic master discovery by mode parameter. // // Since: 1.6.0 -package connection_pool +package pool import ( "errors" @@ -17,7 +17,7 @@ import ( "sync" "time" - "github.com/tarantool/go-tarantool" + "github.com/tarantool/go-tarantool/v2" ) var ( @@ -59,8 +59,8 @@ type ConnectionHandler interface { Deactivated(conn *tarantool.Connection, role Role) error } -// OptsPool provides additional options (configurable via ConnectWithOpts). -type OptsPool struct { +// Opts provides additional options (configurable via ConnectWithOpts). +type Opts struct { // Timeout for timer to reopen connections that have been closed by some // events and to relocate connection between subpools if ro/rw role has // been updated. @@ -93,13 +93,13 @@ type ConnectionPool struct { addrsMutex sync.RWMutex connOpts tarantool.Opts - opts OptsPool + opts Opts state state done chan struct{} - roPool *RoundRobinStrategy - rwPool *RoundRobinStrategy - anyPool *RoundRobinStrategy + roPool *roundRobinStrategy + rwPool *roundRobinStrategy + anyPool *roundRobinStrategy poolsMutex sync.RWMutex watcherContainer watcherContainer } @@ -132,7 +132,7 @@ func newEndpoint(addr string) *endpoint { // ConnectWithOpts creates pool for instances with addresses addrs // with options opts. -func ConnectWithOpts(addrs []string, connOpts tarantool.Opts, opts OptsPool) (connPool *ConnectionPool, err error) { +func ConnectWithOpts(addrs []string, connOpts tarantool.Opts, opts Opts) (connPool *ConnectionPool, err error) { if len(addrs) == 0 { return nil, ErrEmptyAddrs } @@ -141,9 +141,9 @@ func ConnectWithOpts(addrs []string, connOpts tarantool.Opts, opts OptsPool) (co } size := len(addrs) - rwPool := NewEmptyRoundRobin(size) - roPool := NewEmptyRoundRobin(size) - anyPool := NewEmptyRoundRobin(size) + rwPool := newRoundRobinStrategy(size) + roPool := newRoundRobinStrategy(size) + anyPool := newRoundRobinStrategy(size) connPool = &ConnectionPool{ addrs: make(map[string]*endpoint), @@ -179,9 +179,9 @@ func ConnectWithOpts(addrs []string, connOpts tarantool.Opts, opts OptsPool) (co // // It is useless to set up tarantool.Opts.Reconnect value for a connection. // The connection pool has its own reconnection logic. See -// OptsPool.CheckTimeout description. +// Opts.CheckTimeout description. func Connect(addrs []string, connOpts tarantool.Opts) (connPool *ConnectionPool, err error) { - opts := OptsPool{ + opts := Opts{ CheckTimeout: 1 * time.Second, } return ConnectWithOpts(addrs, connOpts, opts) @@ -373,7 +373,9 @@ func (connPool *ConnectionPool) Ping(userMode Mode) (*tarantool.Response, error) } // Select performs select to box space. -func (connPool *ConnectionPool) Select(space, index interface{}, offset, limit, iterator uint32, key interface{}, userMode ...Mode) (resp *tarantool.Response, err error) { +func (connPool *ConnectionPool) Select(space, index interface{}, + offset, limit uint32, + iterator tarantool.Iter, key interface{}, userMode ...Mode) (resp *tarantool.Response, err error) { conn, err := connPool.getConnByMode(ANY, userMode) if err != nil { return nil, err @@ -437,10 +439,8 @@ func (connPool *ConnectionPool) Upsert(space interface{}, tuple, ops interface{} return conn.Upsert(space, tuple, ops) } -// Call16 calls registered Tarantool function. -// It uses request code for Tarantool >= 1.7 if go-tarantool -// was build with go_tarantool_call_17 tag. -// Otherwise, uses request code for Tarantool 1.6. +// Call calls registered Tarantool function. +// It uses request code for Tarantool >= 1.7, result is an array. func (connPool *ConnectionPool) Call(functionName string, args interface{}, userMode Mode) (resp *tarantool.Response, err error) { conn, err := connPool.getNextConnection(userMode) if err != nil { @@ -451,7 +451,7 @@ func (connPool *ConnectionPool) Call(functionName string, args interface{}, user } // Call16 calls registered Tarantool function. -// It uses request code for Tarantool 1.6, so result is converted to array of arrays. +// It uses request code for Tarantool 1.6, result is an array of arrays. // Deprecated since Tarantool 1.7.2. func (connPool *ConnectionPool) Call16(functionName string, args interface{}, userMode Mode) (resp *tarantool.Response, err error) { conn, err := connPool.getNextConnection(userMode) @@ -463,8 +463,7 @@ func (connPool *ConnectionPool) Call16(functionName string, args interface{}, us } // Call17 calls registered Tarantool function. -// It uses request code for Tarantool >= 1.7, so result is not converted -// (though, keep in mind, result is always array). +// It uses request code for Tarantool >= 1.7, result is an array. func (connPool *ConnectionPool) Call17(functionName string, args interface{}, userMode Mode) (resp *tarantool.Response, err error) { conn, err := connPool.getNextConnection(userMode) if err != nil { @@ -506,7 +505,9 @@ func (connPool *ConnectionPool) GetTyped(space, index interface{}, key interface } // SelectTyped performs select to box space and fills typed result. -func (connPool *ConnectionPool) SelectTyped(space, index interface{}, offset, limit, iterator uint32, key interface{}, result interface{}, userMode ...Mode) (err error) { +func (connPool *ConnectionPool) SelectTyped(space, index interface{}, + offset, limit uint32, + iterator tarantool.Iter, key interface{}, result interface{}, userMode ...Mode) (err error) { conn, err := connPool.getConnByMode(ANY, userMode) if err != nil { return err @@ -558,9 +559,7 @@ func (connPool *ConnectionPool) UpdateTyped(space, index interface{}, key, ops i } // CallTyped calls registered function. -// It uses request code for Tarantool >= 1.7 if go-tarantool -// was build with go_tarantool_call_17 tag. -// Otherwise, uses request code for Tarantool 1.6. +// It uses request code for Tarantool >= 1.7, result is an array. func (connPool *ConnectionPool) CallTyped(functionName string, args interface{}, result interface{}, userMode Mode) (err error) { conn, err := connPool.getNextConnection(userMode) if err != nil { @@ -571,7 +570,7 @@ func (connPool *ConnectionPool) CallTyped(functionName string, args interface{}, } // Call16Typed calls registered function. -// It uses request code for Tarantool 1.6, so result is converted to array of arrays. +// It uses request code for Tarantool 1.6, result is an array of arrays. // Deprecated since Tarantool 1.7.2. func (connPool *ConnectionPool) Call16Typed(functionName string, args interface{}, result interface{}, userMode Mode) (err error) { conn, err := connPool.getNextConnection(userMode) @@ -583,8 +582,7 @@ func (connPool *ConnectionPool) Call16Typed(functionName string, args interface{ } // Call17Typed calls registered function. -// It uses request code for Tarantool >= 1.7, so result is not converted -// (though, keep in mind, result is always array). +// It uses request code for Tarantool >= 1.7, result is an array. func (connPool *ConnectionPool) Call17Typed(functionName string, args interface{}, result interface{}, userMode Mode) (err error) { conn, err := connPool.getNextConnection(userMode) if err != nil { @@ -615,7 +613,9 @@ func (connPool *ConnectionPool) ExecuteTyped(expr string, args interface{}, resu } // SelectAsync sends select request to Tarantool and returns Future. -func (connPool *ConnectionPool) SelectAsync(space, index interface{}, offset, limit, iterator uint32, key interface{}, userMode ...Mode) *tarantool.Future { +func (connPool *ConnectionPool) SelectAsync(space, index interface{}, + offset, limit uint32, + iterator tarantool.Iter, key interface{}, userMode ...Mode) *tarantool.Future { conn, err := connPool.getConnByMode(ANY, userMode) if err != nil { return newErrorFuture(err) @@ -680,9 +680,7 @@ func (connPool *ConnectionPool) UpsertAsync(space interface{}, tuple interface{} } // CallAsync sends a call to registered Tarantool function and returns Future. -// It uses request code for Tarantool >= 1.7 if go-tarantool -// was build with go_tarantool_call_17 tag. -// Otherwise, uses request code for Tarantool 1.6. +// It uses request code for Tarantool >= 1.7, future's result is an array. func (connPool *ConnectionPool) CallAsync(functionName string, args interface{}, userMode Mode) *tarantool.Future { conn, err := connPool.getNextConnection(userMode) if err != nil { @@ -693,7 +691,7 @@ func (connPool *ConnectionPool) CallAsync(functionName string, args interface{}, } // Call16Async sends a call to registered Tarantool function and returns Future. -// It uses request code for Tarantool 1.6, so future's result is always array of arrays. +// It uses request code for Tarantool 1.6, so future's result is an array of arrays. // Deprecated since Tarantool 1.7.2. func (connPool *ConnectionPool) Call16Async(functionName string, args interface{}, userMode Mode) *tarantool.Future { conn, err := connPool.getNextConnection(userMode) @@ -705,8 +703,7 @@ func (connPool *ConnectionPool) Call16Async(functionName string, args interface{ } // Call17Async sends a call to registered Tarantool function and returns Future. -// It uses request code for Tarantool >= 1.7, so future's result will not be converted -// (though, keep in mind, result is always array). +// It uses request code for Tarantool >= 1.7, future's result is an array. func (connPool *ConnectionPool) Call17Async(functionName string, args interface{}, userMode Mode) *tarantool.Future { conn, err := connPool.getNextConnection(userMode) if err != nil { diff --git a/connection_pool/connection_pool_test.go b/pool/connection_pool_test.go similarity index 85% rename from connection_pool/connection_pool_test.go rename to pool/connection_pool_test.go index dde6815d9..eda8560e8 100644 --- a/connection_pool/connection_pool_test.go +++ b/pool/connection_pool_test.go @@ -1,4 +1,4 @@ -package connection_pool_test +package pool_test import ( "fmt" @@ -13,9 +13,11 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/connection_pool" - "github.com/tarantool/go-tarantool/test_helpers" + "github.com/vmihailenco/msgpack/v5" + + "github.com/tarantool/go-tarantool/v2" + "github.com/tarantool/go-tarantool/v2/pool" + "github.com/tarantool/go-tarantool/v2/test_helpers" ) var spaceNo = uint32(520) @@ -45,17 +47,17 @@ var defaultTimeoutRetry = 500 * time.Millisecond var instances []test_helpers.TarantoolInstance func TestConnError_IncorrectParams(t *testing.T) { - connPool, err := connection_pool.Connect([]string{}, tarantool.Opts{}) + connPool, err := pool.Connect([]string{}, tarantool.Opts{}) require.Nilf(t, connPool, "conn is not nil with incorrect param") require.NotNilf(t, err, "err is nil with incorrect params") require.Equal(t, "addrs (first argument) should not be empty", err.Error()) - connPool, err = connection_pool.Connect([]string{"err1", "err2"}, connOpts) + connPool, err = pool.Connect([]string{"err1", "err2"}, connOpts) require.Nilf(t, connPool, "conn is not nil with incorrect param") require.NotNilf(t, err, "err is nil with incorrect params") require.Equal(t, "no active connections", err.Error()) - connPool, err = connection_pool.ConnectWithOpts(servers, tarantool.Opts{}, connection_pool.OptsPool{}) + connPool, err = pool.ConnectWithOpts(servers, tarantool.Opts{}, pool.Opts{}) require.Nilf(t, connPool, "conn is not nil with incorrect param") require.NotNilf(t, err, "err is nil with incorrect params") require.Equal(t, "wrong check timeout, must be greater than 0", err.Error()) @@ -63,7 +65,7 @@ func TestConnError_IncorrectParams(t *testing.T) { func TestConnSuccessfully(t *testing.T) { server := servers[0] - connPool, err := connection_pool.Connect([]string{"err", server}, connOpts) + connPool, err := pool.Connect([]string{"err", server}, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -71,7 +73,7 @@ func TestConnSuccessfully(t *testing.T) { args := test_helpers.CheckStatusesArgs{ ConnPool: connPool, - Mode: connection_pool.ANY, + Mode: pool.ANY, Servers: []string{server}, ExpectedPoolStatus: true, ExpectedStatuses: map[string]bool{ @@ -85,7 +87,7 @@ func TestConnSuccessfully(t *testing.T) { func TestConnSuccessfullyDuplicates(t *testing.T) { server := servers[0] - connPool, err := connection_pool.Connect([]string{server, server, server, server}, connOpts) + connPool, err := pool.Connect([]string{server, server, server, server}, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -93,7 +95,7 @@ func TestConnSuccessfullyDuplicates(t *testing.T) { args := test_helpers.CheckStatusesArgs{ ConnPool: connPool, - Mode: connection_pool.ANY, + Mode: pool.ANY, Servers: []string{server}, ExpectedPoolStatus: true, ExpectedStatuses: map[string]bool{ @@ -111,7 +113,7 @@ func TestConnSuccessfullyDuplicates(t *testing.T) { func TestReconnect(t *testing.T) { server := servers[0] - connPool, err := connection_pool.Connect(servers, connOpts) + connPool, err := pool.Connect(servers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -121,7 +123,7 @@ func TestReconnect(t *testing.T) { args := test_helpers.CheckStatusesArgs{ ConnPool: connPool, - Mode: connection_pool.ANY, + Mode: pool.ANY, Servers: []string{server}, ExpectedPoolStatus: true, ExpectedStatuses: map[string]bool{ @@ -137,7 +139,7 @@ func TestReconnect(t *testing.T) { args = test_helpers.CheckStatusesArgs{ ConnPool: connPool, - Mode: connection_pool.ANY, + Mode: pool.ANY, Servers: []string{server}, ExpectedPoolStatus: true, ExpectedStatuses: map[string]bool{ @@ -155,7 +157,7 @@ func TestDisconnect_withReconnect(t *testing.T) { opts := connOpts opts.Reconnect = 10 * time.Second - connPool, err := connection_pool.Connect([]string{servers[serverId]}, opts) + connPool, err := pool.Connect([]string{servers[serverId]}, opts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -165,7 +167,7 @@ func TestDisconnect_withReconnect(t *testing.T) { test_helpers.StopTarantoolWithCleanup(instances[serverId]) args := test_helpers.CheckStatusesArgs{ ConnPool: connPool, - Mode: connection_pool.ANY, + Mode: pool.ANY, Servers: []string{servers[serverId]}, ExpectedPoolStatus: false, ExpectedStatuses: map[string]bool{ @@ -182,7 +184,7 @@ func TestDisconnect_withReconnect(t *testing.T) { args = test_helpers.CheckStatusesArgs{ ConnPool: connPool, - Mode: connection_pool.ANY, + Mode: pool.ANY, Servers: []string{servers[serverId]}, ExpectedPoolStatus: true, ExpectedStatuses: map[string]bool{ @@ -199,7 +201,7 @@ func TestDisconnectAll(t *testing.T) { server1 := servers[0] server2 := servers[1] - connPool, err := connection_pool.Connect([]string{server1, server2}, connOpts) + connPool, err := pool.Connect([]string{server1, server2}, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -210,7 +212,7 @@ func TestDisconnectAll(t *testing.T) { args := test_helpers.CheckStatusesArgs{ ConnPool: connPool, - Mode: connection_pool.ANY, + Mode: pool.ANY, Servers: []string{server1, server2}, ExpectedPoolStatus: false, ExpectedStatuses: map[string]bool{ @@ -230,7 +232,7 @@ func TestDisconnectAll(t *testing.T) { args = test_helpers.CheckStatusesArgs{ ConnPool: connPool, - Mode: connection_pool.ANY, + Mode: pool.ANY, Servers: []string{server1, server2}, ExpectedPoolStatus: true, ExpectedStatuses: map[string]bool{ @@ -244,7 +246,7 @@ func TestDisconnectAll(t *testing.T) { } func TestAdd(t *testing.T) { - connPool, err := connection_pool.Connect([]string{servers[0]}, connOpts) + connPool, err := pool.Connect([]string{servers[0]}, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -257,7 +259,7 @@ func TestAdd(t *testing.T) { args := test_helpers.CheckStatusesArgs{ ConnPool: connPool, - Mode: connection_pool.ANY, + Mode: pool.ANY, Servers: servers, ExpectedPoolStatus: true, ExpectedStatuses: map[string]bool{ @@ -275,18 +277,18 @@ func TestAdd(t *testing.T) { } func TestAdd_exist(t *testing.T) { - connPool, err := connection_pool.Connect([]string{servers[0]}, connOpts) + connPool, err := pool.Connect([]string{servers[0]}, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") defer connPool.Close() err = connPool.Add(servers[0]) - require.Equal(t, connection_pool.ErrExists, err) + require.Equal(t, pool.ErrExists, err) args := test_helpers.CheckStatusesArgs{ ConnPool: connPool, - Mode: connection_pool.ANY, + Mode: pool.ANY, Servers: servers, ExpectedPoolStatus: true, ExpectedStatuses: map[string]bool{ @@ -300,7 +302,7 @@ func TestAdd_exist(t *testing.T) { } func TestAdd_unreachable(t *testing.T) { - connPool, err := connection_pool.Connect([]string{servers[0]}, connOpts) + connPool, err := pool.Connect([]string{servers[0]}, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -312,7 +314,7 @@ func TestAdd_unreachable(t *testing.T) { args := test_helpers.CheckStatusesArgs{ ConnPool: connPool, - Mode: connection_pool.ANY, + Mode: pool.ANY, Servers: servers, ExpectedPoolStatus: true, ExpectedStatuses: map[string]bool{ @@ -326,17 +328,17 @@ func TestAdd_unreachable(t *testing.T) { } func TestAdd_afterClose(t *testing.T) { - connPool, err := connection_pool.Connect([]string{servers[0]}, connOpts) + connPool, err := pool.Connect([]string{servers[0]}, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") connPool.Close() err = connPool.Add(servers[0]) - assert.Equal(t, err, connection_pool.ErrClosed) + assert.Equal(t, err, pool.ErrClosed) } func TestAdd_Close_concurrent(t *testing.T) { - connPool, err := connection_pool.Connect([]string{servers[0]}, connOpts) + connPool, err := pool.Connect([]string{servers[0]}, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -347,7 +349,7 @@ func TestAdd_Close_concurrent(t *testing.T) { err = connPool.Add(servers[1]) if err != nil { - assert.Equal(t, connection_pool.ErrClosed, err) + assert.Equal(t, pool.ErrClosed, err) } }() @@ -357,7 +359,7 @@ func TestAdd_Close_concurrent(t *testing.T) { } func TestAdd_CloseGraceful_concurrent(t *testing.T) { - connPool, err := connection_pool.Connect([]string{servers[0]}, connOpts) + connPool, err := pool.Connect([]string{servers[0]}, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -368,7 +370,7 @@ func TestAdd_CloseGraceful_concurrent(t *testing.T) { err = connPool.Add(servers[1]) if err != nil { - assert.Equal(t, connection_pool.ErrClosed, err) + assert.Equal(t, pool.ErrClosed, err) } }() @@ -378,7 +380,7 @@ func TestAdd_CloseGraceful_concurrent(t *testing.T) { } func TestRemove(t *testing.T) { - connPool, err := connection_pool.Connect(servers, connOpts) + connPool, err := pool.Connect(servers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -391,7 +393,7 @@ func TestRemove(t *testing.T) { args := test_helpers.CheckStatusesArgs{ ConnPool: connPool, - Mode: connection_pool.ANY, + Mode: pool.ANY, Servers: servers, ExpectedPoolStatus: true, ExpectedStatuses: map[string]bool{ @@ -405,7 +407,7 @@ func TestRemove(t *testing.T) { } func TestRemove_double(t *testing.T) { - connPool, err := connection_pool.Connect([]string{servers[0], servers[1]}, connOpts) + connPool, err := pool.Connect([]string{servers[0], servers[1]}, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -418,7 +420,7 @@ func TestRemove_double(t *testing.T) { args := test_helpers.CheckStatusesArgs{ ConnPool: connPool, - Mode: connection_pool.ANY, + Mode: pool.ANY, Servers: servers, ExpectedPoolStatus: true, ExpectedStatuses: map[string]bool{ @@ -432,7 +434,7 @@ func TestRemove_double(t *testing.T) { } func TestRemove_unknown(t *testing.T) { - connPool, err := connection_pool.Connect([]string{servers[0], servers[1]}, connOpts) + connPool, err := pool.Connect([]string{servers[0], servers[1]}, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -443,7 +445,7 @@ func TestRemove_unknown(t *testing.T) { args := test_helpers.CheckStatusesArgs{ ConnPool: connPool, - Mode: connection_pool.ANY, + Mode: pool.ANY, Servers: servers, ExpectedPoolStatus: true, ExpectedStatuses: map[string]bool{ @@ -458,7 +460,7 @@ func TestRemove_unknown(t *testing.T) { } func TestRemove_concurrent(t *testing.T) { - connPool, err := connection_pool.Connect([]string{servers[0], servers[1]}, connOpts) + connPool, err := pool.Connect([]string{servers[0], servers[1]}, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -491,7 +493,7 @@ func TestRemove_concurrent(t *testing.T) { args := test_helpers.CheckStatusesArgs{ ConnPool: connPool, - Mode: connection_pool.ANY, + Mode: pool.ANY, Servers: servers, ExpectedPoolStatus: true, ExpectedStatuses: map[string]bool{ @@ -505,7 +507,7 @@ func TestRemove_concurrent(t *testing.T) { } func TestRemove_Close_concurrent(t *testing.T) { - connPool, err := connection_pool.Connect([]string{servers[0], servers[1]}, connOpts) + connPool, err := pool.Connect([]string{servers[0], servers[1]}, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -524,7 +526,7 @@ func TestRemove_Close_concurrent(t *testing.T) { } func TestRemove_CloseGraceful_concurrent(t *testing.T) { - connPool, err := connection_pool.Connect([]string{servers[0], servers[1]}, connOpts) + connPool, err := pool.Connect([]string{servers[0], servers[1]}, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -546,13 +548,13 @@ func TestClose(t *testing.T) { server1 := servers[0] server2 := servers[1] - connPool, err := connection_pool.Connect([]string{server1, server2}, connOpts) + connPool, err := pool.Connect([]string{server1, server2}, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") args := test_helpers.CheckStatusesArgs{ ConnPool: connPool, - Mode: connection_pool.ANY, + Mode: pool.ANY, Servers: []string{server1, server2}, ExpectedPoolStatus: true, ExpectedStatuses: map[string]bool{ @@ -568,7 +570,7 @@ func TestClose(t *testing.T) { args = test_helpers.CheckStatusesArgs{ ConnPool: connPool, - Mode: connection_pool.ANY, + Mode: pool.ANY, Servers: []string{server1, server2}, ExpectedPoolStatus: false, ExpectedStatuses: map[string]bool{ @@ -585,13 +587,13 @@ func TestCloseGraceful(t *testing.T) { server1 := servers[0] server2 := servers[1] - connPool, err := connection_pool.Connect([]string{server1, server2}, connOpts) + connPool, err := pool.Connect([]string{server1, server2}, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") args := test_helpers.CheckStatusesArgs{ ConnPool: connPool, - Mode: connection_pool.ANY, + Mode: pool.ANY, Servers: []string{server1, server2}, ExpectedPoolStatus: true, ExpectedStatuses: map[string]bool{ @@ -609,14 +611,14 @@ func TestCloseGraceful(t *testing.T) { ` evalSleep := 3 // In seconds. req := tarantool.NewEvalRequest(eval).Args([]interface{}{evalSleep}) - fut := connPool.Do(req, connection_pool.ANY) + fut := connPool.Do(req, pool.ANY) go func() { connPool.CloseGraceful() }() // Check that a request rejected if graceful shutdown in progress. time.Sleep((time.Duration(evalSleep) * time.Second) / 2) - _, err = connPool.Do(tarantool.NewPingRequest(), connection_pool.ANY).Get() + _, err = connPool.Do(tarantool.NewPingRequest(), pool.ANY).Get() require.ErrorContains(t, err, "can't find healthy instance in pool") // Check that a previous request was successful. @@ -626,7 +628,7 @@ func TestCloseGraceful(t *testing.T) { args = test_helpers.CheckStatusesArgs{ ConnPool: connPool, - Mode: connection_pool.ANY, + Mode: pool.ANY, Servers: []string{server1, server2}, ExpectedPoolStatus: false, ExpectedStatuses: map[string]bool{ @@ -649,7 +651,7 @@ func (h *testHandler) addErr(err error) { } func (h *testHandler) Discovered(conn *tarantool.Connection, - role connection_pool.Role) error { + role pool.Role) error { discovered := atomic.AddUint32(&h.discovered, 1) if conn == nil { @@ -661,17 +663,17 @@ func (h *testHandler) Discovered(conn *tarantool.Connection, // discovered >= 3 - update a connection after a role update addr := conn.Addr() if addr == servers[0] { - if discovered < 3 && role != connection_pool.MasterRole { + if discovered < 3 && role != pool.MasterRole { h.addErr(fmt.Errorf("unexpected init role %d for addr %s", role, addr)) } - if discovered >= 3 && role != connection_pool.ReplicaRole { + if discovered >= 3 && role != pool.ReplicaRole { h.addErr(fmt.Errorf("unexpected updated role %d for addr %s", role, addr)) } } else if addr == servers[1] { if discovered >= 3 { h.addErr(fmt.Errorf("unexpected discovery for addr %s", addr)) } - if role != connection_pool.ReplicaRole { + if role != pool.ReplicaRole { h.addErr(fmt.Errorf("unexpected role %d for addr %s", role, addr)) } } else { @@ -682,7 +684,7 @@ func (h *testHandler) Discovered(conn *tarantool.Connection, } func (h *testHandler) Deactivated(conn *tarantool.Connection, - role connection_pool.Role) error { + role pool.Role) error { deactivated := atomic.AddUint32(&h.deactivated, 1) if conn == nil { @@ -693,7 +695,7 @@ func (h *testHandler) Deactivated(conn *tarantool.Connection, addr := conn.Addr() if deactivated == 1 && addr == servers[0] { // A first close is a role update. - if role != connection_pool.MasterRole { + if role != pool.MasterRole { h.addErr(fmt.Errorf("unexpected removed role %d for addr %s", role, addr)) } return nil @@ -701,7 +703,7 @@ func (h *testHandler) Deactivated(conn *tarantool.Connection, if addr == servers[0] || addr == servers[1] { // Close. - if role != connection_pool.ReplicaRole { + if role != pool.ReplicaRole { h.addErr(fmt.Errorf("unexpected removed role %d for addr %s", role, addr)) } } else { @@ -719,17 +721,17 @@ func TestConnectionHandlerOpenUpdateClose(t *testing.T) { require.Nilf(t, err, "fail to set roles for cluster") h := &testHandler{} - poolOpts := connection_pool.OptsPool{ + poolOpts := pool.Opts{ CheckTimeout: 100 * time.Microsecond, ConnectionHandler: h, } - pool, err := connection_pool.ConnectWithOpts(poolServers, connOpts, poolOpts) + connPool, err := pool.ConnectWithOpts(poolServers, connOpts, poolOpts) require.Nilf(t, err, "failed to connect") - require.NotNilf(t, pool, "conn is nil after Connect") + require.NotNilf(t, connPool, "conn is nil after Connect") - _, err = pool.Call17("box.cfg", []interface{}{map[string]bool{ + _, err = connPool.Call17("box.cfg", []interface{}{map[string]bool{ "read_only": true, - }}, connection_pool.RW) + }}, pool.RW) require.Nilf(t, err, "failed to make ro") for i := 0; i < 100; i++ { @@ -748,7 +750,7 @@ func TestConnectionHandlerOpenUpdateClose(t *testing.T) { require.Equalf(t, uint32(1), deactivated, "updated not reported as deactivated") - pool.Close() + connPool.Close() for i := 0; i < 100; i++ { // Wait for close of all connections. @@ -761,7 +763,7 @@ func TestConnectionHandlerOpenUpdateClose(t *testing.T) { for _, err := range h.errs { t.Errorf("Unexpected error: %s", err) } - connected, err := pool.ConnectedNow(connection_pool.ANY) + connected, err := connPool.ConnectedNow(pool.ANY) require.Nilf(t, err, "failed to get connected state") require.Falsef(t, connected, "connection pool still be connected") @@ -778,13 +780,13 @@ type testAddErrorHandler struct { } func (h *testAddErrorHandler) Discovered(conn *tarantool.Connection, - role connection_pool.Role) error { + role pool.Role) error { h.discovered++ return fmt.Errorf("any error") } func (h *testAddErrorHandler) Deactivated(conn *tarantool.Connection, - role connection_pool.Role) error { + role pool.Role) error { h.deactivated++ return nil } @@ -793,11 +795,11 @@ func TestConnectionHandlerOpenError(t *testing.T) { poolServers := []string{servers[0], servers[1]} h := &testAddErrorHandler{} - poolOpts := connection_pool.OptsPool{ + poolOpts := pool.Opts{ CheckTimeout: 100 * time.Microsecond, ConnectionHandler: h, } - connPool, err := connection_pool.ConnectWithOpts(poolServers, connOpts, poolOpts) + connPool, err := pool.ConnectWithOpts(poolServers, connOpts, poolOpts) if err == nil { defer connPool.Close() } @@ -811,7 +813,7 @@ type testUpdateErrorHandler struct { } func (h *testUpdateErrorHandler) Discovered(conn *tarantool.Connection, - role connection_pool.Role) error { + role pool.Role) error { atomic.AddUint32(&h.discovered, 1) if atomic.LoadUint32(&h.deactivated) != 0 { @@ -822,7 +824,7 @@ func (h *testUpdateErrorHandler) Discovered(conn *tarantool.Connection, } func (h *testUpdateErrorHandler) Deactivated(conn *tarantool.Connection, - role connection_pool.Role) error { + role pool.Role) error { atomic.AddUint32(&h.deactivated, 1) return nil } @@ -835,42 +837,42 @@ func TestConnectionHandlerUpdateError(t *testing.T) { require.Nilf(t, err, "fail to set roles for cluster") h := &testUpdateErrorHandler{} - poolOpts := connection_pool.OptsPool{ + poolOpts := pool.Opts{ CheckTimeout: 100 * time.Microsecond, ConnectionHandler: h, } - connPool, err := connection_pool.ConnectWithOpts(poolServers, connOpts, poolOpts) + connPool, err := pool.ConnectWithOpts(poolServers, connOpts, poolOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") defer connPool.Close() - connected, err := connPool.ConnectedNow(connection_pool.ANY) + connected, err := connPool.ConnectedNow(pool.ANY) require.Nilf(t, err, "failed to get ConnectedNow()") require.Truef(t, connected, "should be connected") for i := 0; i < len(poolServers); i++ { _, err = connPool.Call17("box.cfg", []interface{}{map[string]bool{ "read_only": true, - }}, connection_pool.RW) + }}, pool.RW) require.Nilf(t, err, "failed to make ro") } for i := 0; i < 100; i++ { // Wait for updates done. - connected, err = connPool.ConnectedNow(connection_pool.ANY) + connected, err = connPool.ConnectedNow(pool.ANY) if !connected || err != nil { break } time.Sleep(poolOpts.CheckTimeout) } - connected, err = connPool.ConnectedNow(connection_pool.ANY) + connected, err = connPool.ConnectedNow(pool.ANY) require.Nilf(t, err, "failed to get ConnectedNow()") require.Falsef(t, connected, "should not be any active connection") connPool.Close() - connected, err = connPool.ConnectedNow(connection_pool.ANY) + connected, err = connPool.ConnectedNow(pool.ANY) require.Nilf(t, err, "failed to get ConnectedNow()") require.Falsef(t, connected, "should be deactivated") @@ -884,7 +886,7 @@ func TestRequestOnClosed(t *testing.T) { server1 := servers[0] server2 := servers[1] - connPool, err := connection_pool.Connect([]string{server1, server2}, connOpts) + connPool, err := pool.Connect([]string{server1, server2}, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -895,7 +897,7 @@ func TestRequestOnClosed(t *testing.T) { args := test_helpers.CheckStatusesArgs{ ConnPool: connPool, - Mode: connection_pool.ANY, + Mode: pool.ANY, Servers: []string{server1, server2}, ExpectedPoolStatus: false, ExpectedStatuses: map[string]bool{ @@ -906,7 +908,7 @@ func TestRequestOnClosed(t *testing.T) { err = test_helpers.Retry(test_helpers.CheckPoolStatuses, args, defaultCountRetry, defaultTimeoutRetry) require.Nil(t, err) - _, err = connPool.Ping(connection_pool.ANY) + _, err = connPool.Ping(pool.ANY) require.NotNilf(t, err, "err is nil after Ping") err = test_helpers.RestartTarantool(&instances[0]) @@ -922,7 +924,7 @@ func TestGetPoolInfo(t *testing.T) { srvs := []string{server1, server2} expected := []string{server1, server2} - connPool, err := connection_pool.Connect(srvs, connOpts) + connPool, err := pool.Connect(srvs, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -934,20 +936,134 @@ func TestGetPoolInfo(t *testing.T) { require.ElementsMatch(t, expected, connPool.GetAddrs()) } +func TestCall(t *testing.T) { + roles := []bool{false, true, false, false, true} + + err := test_helpers.SetClusterRO(servers, connOpts, roles) + require.Nilf(t, err, "fail to set roles for cluster") + + connPool, err := pool.Connect(servers, connOpts) + require.Nilf(t, err, "failed to connect") + require.NotNilf(t, connPool, "conn is nil after Connect") + + defer connPool.Close() + + // PreferRO + resp, err := connPool.Call("box.info", []interface{}{}, pool.PreferRO) + require.Nilf(t, err, "failed to Call") + require.NotNilf(t, resp, "response is nil after Call") + require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Call") + + val := resp.Data[0].(map[interface{}]interface{})["ro"] + ro, ok := val.(bool) + require.Truef(t, ok, "expected `true` with mode `PreferRO`") + require.Truef(t, ro, "expected `true` with mode `PreferRO`") + + // PreferRW + resp, err = connPool.Call("box.info", []interface{}{}, pool.PreferRW) + require.Nilf(t, err, "failed to Call") + require.NotNilf(t, resp, "response is nil after Call") + require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Call") + + val = resp.Data[0].(map[interface{}]interface{})["ro"] + ro, ok = val.(bool) + require.Truef(t, ok, "expected `false` with mode `PreferRW`") + require.Falsef(t, ro, "expected `false` with mode `PreferRW`") + + // RO + resp, err = connPool.Call("box.info", []interface{}{}, pool.RO) + require.Nilf(t, err, "failed to Call") + require.NotNilf(t, resp, "response is nil after Call") + require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Call") + + val = resp.Data[0].(map[interface{}]interface{})["ro"] + ro, ok = val.(bool) + require.Truef(t, ok, "expected `true` with mode `RO`") + require.Truef(t, ro, "expected `true` with mode `RO`") + + // RW + resp, err = connPool.Call("box.info", []interface{}{}, pool.RW) + require.Nilf(t, err, "failed to Call") + require.NotNilf(t, resp, "response is nil after Call") + require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Call") + + val = resp.Data[0].(map[interface{}]interface{})["ro"] + ro, ok = val.(bool) + require.Truef(t, ok, "expected `false` with mode `RW`") + require.Falsef(t, ro, "expected `false` with mode `RW`") +} + +func TestCall16(t *testing.T) { + roles := []bool{false, true, false, false, true} + + err := test_helpers.SetClusterRO(servers, connOpts, roles) + require.Nilf(t, err, "fail to set roles for cluster") + + connPool, err := pool.Connect(servers, connOpts) + require.Nilf(t, err, "failed to connect") + require.NotNilf(t, connPool, "conn is nil after Connect") + + defer connPool.Close() + + // PreferRO + resp, err := connPool.Call16("box.info", []interface{}{}, pool.PreferRO) + require.Nilf(t, err, "failed to Call") + require.NotNilf(t, resp, "response is nil after Call") + require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Call") + + val := resp.Data[0].([]interface{})[0].(map[interface{}]interface{})["ro"] + ro, ok := val.(bool) + require.Truef(t, ok, "expected `true` with mode `PreferRO`") + require.Truef(t, ro, "expected `true` with mode `PreferRO`") + + // PreferRW + resp, err = connPool.Call16("box.info", []interface{}{}, pool.PreferRW) + require.Nilf(t, err, "failed to Call") + require.NotNilf(t, resp, "response is nil after Call") + require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Call") + + val = resp.Data[0].([]interface{})[0].(map[interface{}]interface{})["ro"] + ro, ok = val.(bool) + require.Truef(t, ok, "expected `false` with mode `PreferRW`") + require.Falsef(t, ro, "expected `false` with mode `PreferRW`") + + // RO + resp, err = connPool.Call16("box.info", []interface{}{}, pool.RO) + require.Nilf(t, err, "failed to Call") + require.NotNilf(t, resp, "response is nil after Call") + require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Call") + + val = resp.Data[0].([]interface{})[0].(map[interface{}]interface{})["ro"] + ro, ok = val.(bool) + require.Truef(t, ok, "expected `true` with mode `RO`") + require.Truef(t, ro, "expected `true` with mode `RO`") + + // RW + resp, err = connPool.Call16("box.info", []interface{}{}, pool.RW) + require.Nilf(t, err, "failed to Call") + require.NotNilf(t, resp, "response is nil after Call") + require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Call") + + val = resp.Data[0].([]interface{})[0].(map[interface{}]interface{})["ro"] + ro, ok = val.(bool) + require.Truef(t, ok, "expected `false` with mode `RW`") + require.Falsef(t, ro, "expected `false` with mode `RW`") +} + func TestCall17(t *testing.T) { roles := []bool{false, true, false, false, true} err := test_helpers.SetClusterRO(servers, connOpts, roles) require.Nilf(t, err, "fail to set roles for cluster") - connPool, err := connection_pool.Connect(servers, connOpts) + connPool, err := pool.Connect(servers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") defer connPool.Close() // PreferRO - resp, err := connPool.Call17("box.info", []interface{}{}, connection_pool.PreferRO) + resp, err := connPool.Call17("box.info", []interface{}{}, pool.PreferRO) require.Nilf(t, err, "failed to Call") require.NotNilf(t, resp, "response is nil after Call") require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Call") @@ -958,7 +1074,7 @@ func TestCall17(t *testing.T) { require.Truef(t, ro, "expected `true` with mode `PreferRO`") // PreferRW - resp, err = connPool.Call17("box.info", []interface{}{}, connection_pool.PreferRW) + resp, err = connPool.Call17("box.info", []interface{}{}, pool.PreferRW) require.Nilf(t, err, "failed to Call") require.NotNilf(t, resp, "response is nil after Call") require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Call") @@ -969,7 +1085,7 @@ func TestCall17(t *testing.T) { require.Falsef(t, ro, "expected `false` with mode `PreferRW`") // RO - resp, err = connPool.Call17("box.info", []interface{}{}, connection_pool.RO) + resp, err = connPool.Call17("box.info", []interface{}{}, pool.RO) require.Nilf(t, err, "failed to Call") require.NotNilf(t, resp, "response is nil after Call") require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Call") @@ -980,7 +1096,7 @@ func TestCall17(t *testing.T) { require.Truef(t, ro, "expected `true` with mode `RO`") // RW - resp, err = connPool.Call17("box.info", []interface{}{}, connection_pool.RW) + resp, err = connPool.Call17("box.info", []interface{}{}, pool.RW) require.Nilf(t, err, "failed to Call") require.NotNilf(t, resp, "response is nil after Call") require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Call") @@ -997,14 +1113,14 @@ func TestEval(t *testing.T) { err := test_helpers.SetClusterRO(servers, connOpts, roles) require.Nilf(t, err, "fail to set roles for cluster") - connPool, err := connection_pool.Connect(servers, connOpts) + connPool, err := pool.Connect(servers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") defer connPool.Close() // PreferRO - resp, err := connPool.Eval("return box.info().ro", []interface{}{}, connection_pool.PreferRO) + resp, err := connPool.Eval("return box.info().ro", []interface{}{}, pool.PreferRO) require.Nilf(t, err, "failed to Eval") require.NotNilf(t, resp, "response is nil after Eval") require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Eval") @@ -1014,7 +1130,7 @@ func TestEval(t *testing.T) { require.Truef(t, val, "expected `true` with mode `PreferRO`") // PreferRW - resp, err = connPool.Eval("return box.info().ro", []interface{}{}, connection_pool.PreferRW) + resp, err = connPool.Eval("return box.info().ro", []interface{}{}, pool.PreferRW) require.Nilf(t, err, "failed to Eval") require.NotNilf(t, resp, "response is nil after Eval") require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Eval") @@ -1024,7 +1140,7 @@ func TestEval(t *testing.T) { require.Falsef(t, val, "expected `false` with mode `PreferRW`") // RO - resp, err = connPool.Eval("return box.info().ro", []interface{}{}, connection_pool.RO) + resp, err = connPool.Eval("return box.info().ro", []interface{}{}, pool.RO) require.Nilf(t, err, "failed to Eval") require.NotNilf(t, resp, "response is nil after Eval") require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Eval") @@ -1034,7 +1150,7 @@ func TestEval(t *testing.T) { require.Truef(t, val, "expected `true` with mode `RO`") // RW - resp, err = connPool.Eval("return box.info().ro", []interface{}{}, connection_pool.RW) + resp, err = connPool.Eval("return box.info().ro", []interface{}{}, pool.RW) require.Nilf(t, err, "failed to Eval") require.NotNilf(t, resp, "response is nil after Eval") require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Eval") @@ -1049,7 +1165,7 @@ type Member struct { val string } -func (m *Member) DecodeMsgpack(d *decoder) error { +func (m *Member) DecodeMsgpack(d *msgpack.Decoder) error { var err error var l int if l, err = d.DecodeArrayLen(); err != nil { @@ -1075,7 +1191,7 @@ func TestExecute(t *testing.T) { err := test_helpers.SetClusterRO(servers, connOpts, roles) require.Nilf(t, err, "fail to set roles for cluster") - connPool, err := connection_pool.Connect(servers, connOpts) + connPool, err := pool.Connect(servers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -1083,7 +1199,7 @@ func TestExecute(t *testing.T) { request := "SELECT NAME0, NAME1 FROM SQL_TEST WHERE NAME0 == 1;" // Execute - resp, err := connPool.Execute(request, []interface{}{}, connection_pool.ANY) + resp, err := connPool.Execute(request, []interface{}{}, pool.ANY) require.Nilf(t, err, "failed to Execute") require.NotNilf(t, resp, "response is nil after Execute") require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Execute") @@ -1091,13 +1207,13 @@ func TestExecute(t *testing.T) { // ExecuteTyped mem := []Member{} - info, _, err := connPool.ExecuteTyped(request, []interface{}{}, &mem, connection_pool.ANY) + info, _, err := connPool.ExecuteTyped(request, []interface{}{}, &mem, pool.ANY) require.Nilf(t, err, "failed to ExecuteTyped") require.Equalf(t, info.AffectedCount, uint64(0), "unexpected info.AffectedCount") require.Equalf(t, len(mem), 1, "wrong count of results") // ExecuteAsync - fut := connPool.ExecuteAsync(request, []interface{}{}, connection_pool.ANY) + fut := connPool.ExecuteAsync(request, []interface{}{}, pool.ANY) resp, err = fut.Get() require.Nilf(t, err, "failed to ExecuteAsync") require.NotNilf(t, resp, "response is nil after ExecuteAsync") @@ -1132,7 +1248,7 @@ func TestRoundRobinStrategy(t *testing.T) { err := test_helpers.SetClusterRO(servers, connOpts, roles) require.Nilf(t, err, "fail to set roles for cluster") - connPool, err := connection_pool.Connect(servers, connOpts) + connPool, err := pool.Connect(servers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -1143,7 +1259,7 @@ func TestRoundRobinStrategy(t *testing.T) { ServersNumber: serversNumber, ExpectedPorts: allPorts, ConnPool: connPool, - Mode: connection_pool.ANY, + Mode: pool.ANY, } err = test_helpers.ProcessListenOnInstance(args) @@ -1154,7 +1270,7 @@ func TestRoundRobinStrategy(t *testing.T) { ServersNumber: serversNumber, ExpectedPorts: masterPorts, ConnPool: connPool, - Mode: connection_pool.RW, + Mode: pool.RW, } err = test_helpers.ProcessListenOnInstance(args) @@ -1165,7 +1281,7 @@ func TestRoundRobinStrategy(t *testing.T) { ServersNumber: serversNumber, ExpectedPorts: replicaPorts, ConnPool: connPool, - Mode: connection_pool.RO, + Mode: pool.RO, } err = test_helpers.ProcessListenOnInstance(args) @@ -1176,7 +1292,7 @@ func TestRoundRobinStrategy(t *testing.T) { ServersNumber: serversNumber, ExpectedPorts: masterPorts, ConnPool: connPool, - Mode: connection_pool.PreferRW, + Mode: pool.PreferRW, } err = test_helpers.ProcessListenOnInstance(args) @@ -1187,7 +1303,7 @@ func TestRoundRobinStrategy(t *testing.T) { ServersNumber: serversNumber, ExpectedPorts: replicaPorts, ConnPool: connPool, - Mode: connection_pool.PreferRO, + Mode: pool.PreferRO, } err = test_helpers.ProcessListenOnInstance(args) @@ -1209,14 +1325,14 @@ func TestRoundRobinStrategy_NoReplica(t *testing.T) { err := test_helpers.SetClusterRO(servers, connOpts, roles) require.Nilf(t, err, "fail to set roles for cluster") - connPool, err := connection_pool.Connect(servers, connOpts) + connPool, err := pool.Connect(servers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") defer connPool.Close() // RO - _, err = connPool.Eval("return box.cfg.listen", []interface{}{}, connection_pool.RO) + _, err = connPool.Eval("return box.cfg.listen", []interface{}{}, pool.RO) require.NotNilf(t, err, "expected to fail after Eval, but error is nil") require.Equal(t, "can't find ro instance in pool", err.Error()) @@ -1225,7 +1341,7 @@ func TestRoundRobinStrategy_NoReplica(t *testing.T) { ServersNumber: serversNumber, ExpectedPorts: allPorts, ConnPool: connPool, - Mode: connection_pool.ANY, + Mode: pool.ANY, } err = test_helpers.ProcessListenOnInstance(args) @@ -1236,7 +1352,7 @@ func TestRoundRobinStrategy_NoReplica(t *testing.T) { ServersNumber: serversNumber, ExpectedPorts: allPorts, ConnPool: connPool, - Mode: connection_pool.RW, + Mode: pool.RW, } err = test_helpers.ProcessListenOnInstance(args) @@ -1247,7 +1363,7 @@ func TestRoundRobinStrategy_NoReplica(t *testing.T) { ServersNumber: serversNumber, ExpectedPorts: allPorts, ConnPool: connPool, - Mode: connection_pool.PreferRW, + Mode: pool.PreferRW, } err = test_helpers.ProcessListenOnInstance(args) @@ -1258,7 +1374,7 @@ func TestRoundRobinStrategy_NoReplica(t *testing.T) { ServersNumber: serversNumber, ExpectedPorts: allPorts, ConnPool: connPool, - Mode: connection_pool.PreferRO, + Mode: pool.PreferRO, } err = test_helpers.ProcessListenOnInstance(args) @@ -1280,14 +1396,14 @@ func TestRoundRobinStrategy_NoMaster(t *testing.T) { err := test_helpers.SetClusterRO(servers, connOpts, roles) require.Nilf(t, err, "fail to set roles for cluster") - connPool, err := connection_pool.Connect(servers, connOpts) + connPool, err := pool.Connect(servers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") defer connPool.Close() // RW - _, err = connPool.Eval("return box.cfg.listen", []interface{}{}, connection_pool.RW) + _, err = connPool.Eval("return box.cfg.listen", []interface{}{}, pool.RW) require.NotNilf(t, err, "expected to fail after Eval, but error is nil") require.Equal(t, "can't find rw instance in pool", err.Error()) @@ -1296,7 +1412,7 @@ func TestRoundRobinStrategy_NoMaster(t *testing.T) { ServersNumber: serversNumber, ExpectedPorts: allPorts, ConnPool: connPool, - Mode: connection_pool.ANY, + Mode: pool.ANY, } err = test_helpers.ProcessListenOnInstance(args) @@ -1307,7 +1423,7 @@ func TestRoundRobinStrategy_NoMaster(t *testing.T) { ServersNumber: serversNumber, ExpectedPorts: allPorts, ConnPool: connPool, - Mode: connection_pool.RO, + Mode: pool.RO, } err = test_helpers.ProcessListenOnInstance(args) @@ -1318,7 +1434,7 @@ func TestRoundRobinStrategy_NoMaster(t *testing.T) { ServersNumber: serversNumber, ExpectedPorts: allPorts, ConnPool: connPool, - Mode: connection_pool.PreferRW, + Mode: pool.PreferRW, } err = test_helpers.ProcessListenOnInstance(args) @@ -1329,7 +1445,7 @@ func TestRoundRobinStrategy_NoMaster(t *testing.T) { ServersNumber: serversNumber, ExpectedPorts: allPorts, ConnPool: connPool, - Mode: connection_pool.PreferRO, + Mode: pool.PreferRO, } err = test_helpers.ProcessListenOnInstance(args) @@ -1363,7 +1479,7 @@ func TestUpdateInstancesRoles(t *testing.T) { err := test_helpers.SetClusterRO(servers, connOpts, roles) require.Nilf(t, err, "fail to set roles for cluster") - connPool, err := connection_pool.Connect(servers, connOpts) + connPool, err := pool.Connect(servers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -1374,7 +1490,7 @@ func TestUpdateInstancesRoles(t *testing.T) { ServersNumber: serversNumber, ExpectedPorts: allPorts, ConnPool: connPool, - Mode: connection_pool.ANY, + Mode: pool.ANY, } err = test_helpers.ProcessListenOnInstance(args) @@ -1385,7 +1501,7 @@ func TestUpdateInstancesRoles(t *testing.T) { ServersNumber: serversNumber, ExpectedPorts: masterPorts, ConnPool: connPool, - Mode: connection_pool.RW, + Mode: pool.RW, } err = test_helpers.ProcessListenOnInstance(args) @@ -1396,7 +1512,7 @@ func TestUpdateInstancesRoles(t *testing.T) { ServersNumber: serversNumber, ExpectedPorts: replicaPorts, ConnPool: connPool, - Mode: connection_pool.RO, + Mode: pool.RO, } err = test_helpers.ProcessListenOnInstance(args) @@ -1407,7 +1523,7 @@ func TestUpdateInstancesRoles(t *testing.T) { ServersNumber: serversNumber, ExpectedPorts: masterPorts, ConnPool: connPool, - Mode: connection_pool.PreferRW, + Mode: pool.PreferRW, } err = test_helpers.ProcessListenOnInstance(args) @@ -1418,7 +1534,7 @@ func TestUpdateInstancesRoles(t *testing.T) { ServersNumber: serversNumber, ExpectedPorts: replicaPorts, ConnPool: connPool, - Mode: connection_pool.PreferRO, + Mode: pool.PreferRO, } err = test_helpers.ProcessListenOnInstance(args) @@ -1445,7 +1561,7 @@ func TestUpdateInstancesRoles(t *testing.T) { ServersNumber: serversNumber, ExpectedPorts: allPorts, ConnPool: connPool, - Mode: connection_pool.ANY, + Mode: pool.ANY, } err = test_helpers.Retry(test_helpers.ProcessListenOnInstance, args, defaultCountRetry, defaultTimeoutRetry) @@ -1456,7 +1572,7 @@ func TestUpdateInstancesRoles(t *testing.T) { ServersNumber: serversNumber, ExpectedPorts: masterPorts, ConnPool: connPool, - Mode: connection_pool.RW, + Mode: pool.RW, } err = test_helpers.Retry(test_helpers.ProcessListenOnInstance, args, defaultCountRetry, defaultTimeoutRetry) @@ -1467,7 +1583,7 @@ func TestUpdateInstancesRoles(t *testing.T) { ServersNumber: serversNumber, ExpectedPorts: replicaPorts, ConnPool: connPool, - Mode: connection_pool.RO, + Mode: pool.RO, } err = test_helpers.Retry(test_helpers.ProcessListenOnInstance, args, defaultCountRetry, defaultTimeoutRetry) @@ -1478,7 +1594,7 @@ func TestUpdateInstancesRoles(t *testing.T) { ServersNumber: serversNumber, ExpectedPorts: masterPorts, ConnPool: connPool, - Mode: connection_pool.PreferRW, + Mode: pool.PreferRW, } err = test_helpers.Retry(test_helpers.ProcessListenOnInstance, args, defaultCountRetry, defaultTimeoutRetry) @@ -1489,7 +1605,7 @@ func TestUpdateInstancesRoles(t *testing.T) { ServersNumber: serversNumber, ExpectedPorts: replicaPorts, ConnPool: connPool, - Mode: connection_pool.PreferRO, + Mode: pool.PreferRO, } err = test_helpers.Retry(test_helpers.ProcessListenOnInstance, args, defaultCountRetry, defaultTimeoutRetry) @@ -1502,7 +1618,7 @@ func TestInsert(t *testing.T) { err := test_helpers.SetClusterRO(servers, connOpts, roles) require.Nilf(t, err, "fail to set roles for cluster") - connPool, err := connection_pool.Connect(servers, connOpts) + connPool, err := pool.Connect(servers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -1590,7 +1706,7 @@ func TestDelete(t *testing.T) { err := test_helpers.SetClusterRO(servers, connOpts, roles) require.Nilf(t, err, "fail to set roles for cluster") - connPool, err := connection_pool.Connect(servers, connOpts) + connPool, err := pool.Connect(servers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -1648,7 +1764,7 @@ func TestUpsert(t *testing.T) { err := test_helpers.SetClusterRO(servers, connOpts, roles) require.Nilf(t, err, "fail to set roles for cluster") - connPool, err := connection_pool.Connect(servers, connOpts) + connPool, err := pool.Connect(servers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -1684,7 +1800,7 @@ func TestUpsert(t *testing.T) { // PreferRW resp, err = connPool.Upsert( spaceName, []interface{}{"upsert_key", "upsert_value"}, - []interface{}{[]interface{}{"=", 1, "new_value"}}, connection_pool.PreferRW) + []interface{}{[]interface{}{"=", 1, "new_value"}}, pool.PreferRW) require.Nilf(t, err, "failed to Upsert") require.NotNilf(t, resp, "response is nil after Upsert") @@ -1713,7 +1829,7 @@ func TestUpdate(t *testing.T) { err := test_helpers.SetClusterRO(servers, connOpts, roles) require.Nilf(t, err, "fail to set roles for cluster") - connPool, err := connection_pool.Connect(servers, connOpts) + connPool, err := pool.Connect(servers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -1766,7 +1882,7 @@ func TestUpdate(t *testing.T) { // PreferRW resp, err = connPool.Update( spaceName, indexNo, []interface{}{"update_key"}, - []interface{}{[]interface{}{"=", 1, "another_value"}}, connection_pool.PreferRW) + []interface{}{[]interface{}{"=", 1, "another_value"}}, pool.PreferRW) require.Nilf(t, err, "failed to Update") require.NotNilf(t, resp, "response is nil after Update") @@ -1795,7 +1911,7 @@ func TestReplace(t *testing.T) { err := test_helpers.SetClusterRO(servers, connOpts, roles) require.Nilf(t, err, "fail to set roles for cluster") - connPool, err := connection_pool.Connect(servers, connOpts) + connPool, err := pool.Connect(servers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -1846,7 +1962,7 @@ func TestReplace(t *testing.T) { require.Equalf(t, "new_value", value, "unexpected body of Select (1)") // PreferRW - resp, err = connPool.Replace(spaceNo, []interface{}{"new_key", "new_value"}, connection_pool.PreferRW) + resp, err = connPool.Replace(spaceNo, []interface{}{"new_key", "new_value"}, pool.PreferRW) require.Nilf(t, err, "failed to Replace") require.NotNilf(t, resp, "response is nil after Replace") @@ -1874,7 +1990,7 @@ func TestSelect(t *testing.T) { err := test_helpers.SetClusterRO(servers, connOpts, roles) require.Nilf(t, err, "fail to set roles for cluster") - connPool, err := connection_pool.Connect(servers, connOpts) + connPool, err := pool.Connect(servers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -1920,7 +2036,7 @@ func TestSelect(t *testing.T) { require.Equalf(t, "any_select_value", value, "unexpected body of Select (1)") // PreferRO - resp, err = connPool.Select(spaceNo, indexNo, 0, 1, tarantool.IterEq, roKey, connection_pool.PreferRO) + resp, err = connPool.Select(spaceNo, indexNo, 0, 1, tarantool.IterEq, roKey, pool.PreferRO) require.Nilf(t, err, "failed to Select") require.NotNilf(t, resp, "response is nil after Select") require.Equalf(t, len(resp.Data), 1, "response Body len != 1 after Select") @@ -1934,7 +2050,7 @@ func TestSelect(t *testing.T) { require.Equalf(t, "ro_select_key", key, "unexpected body of Select (0)") // PreferRW - resp, err = connPool.Select(spaceNo, indexNo, 0, 1, tarantool.IterEq, rwKey, connection_pool.PreferRW) + resp, err = connPool.Select(spaceNo, indexNo, 0, 1, tarantool.IterEq, rwKey, pool.PreferRW) require.Nilf(t, err, "failed to Select") require.NotNilf(t, resp, "response is nil after Select") require.Equalf(t, len(resp.Data), 1, "response Body len != 1 after Select") @@ -1952,7 +2068,7 @@ func TestSelect(t *testing.T) { require.Equalf(t, "rw_select_value", value, "unexpected body of Select (1)") // RO - resp, err = connPool.Select(spaceNo, indexNo, 0, 1, tarantool.IterEq, roKey, connection_pool.RO) + resp, err = connPool.Select(spaceNo, indexNo, 0, 1, tarantool.IterEq, roKey, pool.RO) require.Nilf(t, err, "failed to Select") require.NotNilf(t, resp, "response is nil after Select") require.Equalf(t, len(resp.Data), 1, "response Body len != 1 after Select") @@ -1970,7 +2086,7 @@ func TestSelect(t *testing.T) { require.Equalf(t, "ro_select_value", value, "unexpected body of Select (1)") // RW - resp, err = connPool.Select(spaceNo, indexNo, 0, 1, tarantool.IterEq, rwKey, connection_pool.RW) + resp, err = connPool.Select(spaceNo, indexNo, 0, 1, tarantool.IterEq, rwKey, pool.RW) require.Nilf(t, err, "failed to Select") require.NotNilf(t, resp, "response is nil after Select") require.Equalf(t, len(resp.Data), 1, "response Body len != 1 after Select") @@ -1994,34 +2110,34 @@ func TestPing(t *testing.T) { err := test_helpers.SetClusterRO(servers, connOpts, roles) require.Nilf(t, err, "fail to set roles for cluster") - connPool, err := connection_pool.Connect(servers, connOpts) + connPool, err := pool.Connect(servers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") defer connPool.Close() // ANY - resp, err := connPool.Ping(connection_pool.ANY) + resp, err := connPool.Ping(pool.ANY) require.Nilf(t, err, "failed to Ping") require.NotNilf(t, resp, "response is nil after Ping") // RW - resp, err = connPool.Ping(connection_pool.RW) + resp, err = connPool.Ping(pool.RW) require.Nilf(t, err, "failed to Ping") require.NotNilf(t, resp, "response is nil after Ping") // RO - resp, err = connPool.Ping(connection_pool.RO) + resp, err = connPool.Ping(pool.RO) require.Nilf(t, err, "failed to Ping") require.NotNilf(t, resp, "response is nil after Ping") // PreferRW - resp, err = connPool.Ping(connection_pool.PreferRW) + resp, err = connPool.Ping(pool.PreferRW) require.Nilf(t, err, "failed to Ping") require.NotNilf(t, resp, "response is nil after Ping") // PreferRO - resp, err = connPool.Ping(connection_pool.PreferRO) + resp, err = connPool.Ping(pool.PreferRO) require.Nilf(t, err, "failed to Ping") require.NotNilf(t, resp, "response is nil after Ping") } @@ -2032,7 +2148,7 @@ func TestDo(t *testing.T) { err := test_helpers.SetClusterRO(servers, connOpts, roles) require.Nilf(t, err, "fail to set roles for cluster") - connPool, err := connection_pool.Connect(servers, connOpts) + connPool, err := pool.Connect(servers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -2040,27 +2156,27 @@ func TestDo(t *testing.T) { req := tarantool.NewPingRequest() // ANY - resp, err := connPool.Do(req, connection_pool.ANY).Get() + resp, err := connPool.Do(req, pool.ANY).Get() require.Nilf(t, err, "failed to Ping") require.NotNilf(t, resp, "response is nil after Ping") // RW - resp, err = connPool.Do(req, connection_pool.RW).Get() + resp, err = connPool.Do(req, pool.RW).Get() require.Nilf(t, err, "failed to Ping") require.NotNilf(t, resp, "response is nil after Ping") // RO - resp, err = connPool.Do(req, connection_pool.RO).Get() + resp, err = connPool.Do(req, pool.RO).Get() require.Nilf(t, err, "failed to Ping") require.NotNilf(t, resp, "response is nil after Ping") // PreferRW - resp, err = connPool.Do(req, connection_pool.PreferRW).Get() + resp, err = connPool.Do(req, pool.PreferRW).Get() require.Nilf(t, err, "failed to Ping") require.NotNilf(t, resp, "response is nil after Ping") // PreferRO - resp, err = connPool.Do(req, connection_pool.PreferRO).Get() + resp, err = connPool.Do(req, pool.PreferRO).Get() require.Nilf(t, err, "failed to Ping") require.NotNilf(t, resp, "response is nil after Ping") } @@ -2073,23 +2189,23 @@ func TestNewPrepared(t *testing.T) { err := test_helpers.SetClusterRO(servers, connOpts, roles) require.Nilf(t, err, "fail to set roles for cluster") - connPool, err := connection_pool.Connect(servers, connOpts) + connPool, err := pool.Connect(servers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") defer connPool.Close() - stmt, err := connPool.NewPrepared("SELECT NAME0, NAME1 FROM SQL_TEST WHERE NAME0=:id AND NAME1=:name;", connection_pool.RO) + stmt, err := connPool.NewPrepared("SELECT NAME0, NAME1 FROM SQL_TEST WHERE NAME0=:id AND NAME1=:name;", pool.RO) require.Nilf(t, err, "fail to prepare statement: %v", err) - if connPool.GetPoolInfo()[stmt.Conn.Addr()].ConnRole != connection_pool.ReplicaRole { + if connPool.GetPoolInfo()[stmt.Conn.Addr()].ConnRole != pool.ReplicaRole { t.Errorf("wrong role for the statement's connection") } executeReq := tarantool.NewExecutePreparedRequest(stmt) unprepareReq := tarantool.NewUnprepareRequest(stmt) - resp, err := connPool.Do(executeReq.Args([]interface{}{1, "test"}), connection_pool.ANY).Get() + resp, err := connPool.Do(executeReq.Args([]interface{}{1, "test"}), pool.ANY).Get() if err != nil { t.Fatalf("failed to execute prepared: %v", err) } @@ -2110,7 +2226,7 @@ func TestNewPrepared(t *testing.T) { } // the second argument for unprepare request is unused - it already belongs to some connection - resp, err = connPool.Do(unprepareReq, connection_pool.ANY).Get() + resp, err = connPool.Do(unprepareReq, pool.ANY).Get() if err != nil { t.Errorf("failed to unprepare prepared statement: %v", err) } @@ -2118,13 +2234,13 @@ func TestNewPrepared(t *testing.T) { t.Errorf("failed to unprepare prepared statement: code %d", resp.Code) } - _, err = connPool.Do(unprepareReq, connection_pool.ANY).Get() + _, err = connPool.Do(unprepareReq, pool.ANY).Get() if err == nil { t.Errorf("the statement must be already unprepared") } require.Contains(t, err.Error(), "Prepared statement with id") - _, err = connPool.Do(executeReq, connection_pool.ANY).Get() + _, err = connPool.Do(executeReq, pool.ANY).Get() if err == nil { t.Errorf("the statement must be already unprepared") } @@ -2139,7 +2255,7 @@ func TestDoWithStrangerConn(t *testing.T) { err := test_helpers.SetClusterRO(servers, connOpts, roles) require.Nilf(t, err, "fail to set roles for cluster") - connPool, err := connection_pool.Connect(servers, connOpts) + connPool, err := pool.Connect(servers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") @@ -2147,7 +2263,7 @@ func TestDoWithStrangerConn(t *testing.T) { req := test_helpers.NewStrangerRequest() - _, err = connPool.Do(req, connection_pool.ANY).Get() + _, err = connPool.Do(req, pool.ANY).Get() if err == nil { t.Fatalf("nil error caught") } @@ -2168,12 +2284,12 @@ func TestStream_Commit(t *testing.T) { err = test_helpers.SetClusterRO(servers, connOpts, roles) require.Nilf(t, err, "fail to set roles for cluster") - connPool, err := connection_pool.Connect(servers, connOpts) + connPool, err := pool.Connect(servers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") defer connPool.Close() - stream, err := connPool.NewStream(connection_pool.PreferRW) + stream, err := connPool.NewStream(pool.PreferRW) require.Nilf(t, err, "failed to create stream") require.NotNilf(t, connPool, "stream is nil after NewStream") @@ -2267,12 +2383,12 @@ func TestStream_Rollback(t *testing.T) { err = test_helpers.SetClusterRO(servers, connOpts, roles) require.Nilf(t, err, "fail to set roles for cluster") - connPool, err := connection_pool.Connect(servers, connOpts) + connPool, err := pool.Connect(servers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") defer connPool.Close() - stream, err := connPool.NewStream(connection_pool.PreferRW) + stream, err := connPool.NewStream(pool.PreferRW) require.Nilf(t, err, "failed to create stream") require.NotNilf(t, connPool, "stream is nil after NewStream") @@ -2366,12 +2482,12 @@ func TestStream_TxnIsolationLevel(t *testing.T) { err = test_helpers.SetClusterRO(servers, connOpts, roles) require.Nilf(t, err, "fail to set roles for cluster") - connPool, err := connection_pool.Connect(servers, connOpts) + connPool, err := pool.Connect(servers, connOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, connPool, "conn is nil after Connect") defer connPool.Close() - stream, err := connPool.NewStream(connection_pool.PreferRW) + stream, err := connPool.NewStream(pool.PreferRW) require.Nilf(t, err, "failed to create stream") require.NotNilf(t, connPool, "stream is nil after NewStream") @@ -2460,13 +2576,13 @@ func TestConnectionPool_NewWatcher_noWatchersFeature(t *testing.T) { err := test_helpers.SetClusterRO(servers, opts, roles) require.Nilf(t, err, "fail to set roles for cluster") - pool, err := connection_pool.Connect(servers, opts) + connPool, err := pool.Connect(servers, opts) require.Nilf(t, err, "failed to connect") - require.NotNilf(t, pool, "conn is nil after Connect") - defer pool.Close() + require.NotNilf(t, connPool, "conn is nil after Connect") + defer connPool.Close() - watcher, err := pool.NewWatcher(key, - func(event tarantool.WatchEvent) {}, connection_pool.ANY) + watcher, err := connPool.NewWatcher(key, + func(event tarantool.WatchEvent) {}, pool.ANY) require.Nilf(t, watcher, "watcher must not be created") require.NotNilf(t, err, "an error is expected") expected := "the feature WatchersFeature must be required by connection " + @@ -2488,25 +2604,25 @@ func TestConnectionPool_NewWatcher_modes(t *testing.T) { err := test_helpers.SetClusterRO(servers, opts, roles) require.Nilf(t, err, "fail to set roles for cluster") - pool, err := connection_pool.Connect(servers, opts) + connPool, err := pool.Connect(servers, opts) require.Nilf(t, err, "failed to connect") - require.NotNilf(t, pool, "conn is nil after Connect") - defer pool.Close() + require.NotNilf(t, connPool, "conn is nil after Connect") + defer connPool.Close() - modes := []connection_pool.Mode{ - connection_pool.ANY, - connection_pool.RW, - connection_pool.RO, - connection_pool.PreferRW, - connection_pool.PreferRO, + modes := []pool.Mode{ + pool.ANY, + pool.RW, + pool.RO, + pool.PreferRW, + pool.PreferRO, } for _, mode := range modes { t.Run(fmt.Sprintf("%d", mode), func(t *testing.T) { expectedServers := []string{} for i, server := range servers { - if roles[i] && mode == connection_pool.RW { + if roles[i] && mode == pool.RW { continue - } else if !roles[i] && mode == connection_pool.RO { + } else if !roles[i] && mode == pool.RO { continue } expectedServers = append(expectedServers, server) @@ -2515,7 +2631,7 @@ func TestConnectionPool_NewWatcher_modes(t *testing.T) { events := make(chan tarantool.WatchEvent, 1024) defer close(events) - watcher, err := pool.NewWatcher(key, func(event tarantool.WatchEvent) { + watcher, err := connPool.NewWatcher(key, func(event tarantool.WatchEvent) { require.Equal(t, key, event.Key) require.Equal(t, nil, event.Value) events <- event @@ -2556,7 +2672,7 @@ func TestConnectionPool_NewWatcher_update(t *testing.T) { test_helpers.SkipIfWatchersUnsupported(t) const key = "TestConnectionPool_NewWatcher_update" - const mode = connection_pool.RW + const mode = pool.RW const initCnt = 2 roles := []bool{true, false, false, true, true} @@ -2567,10 +2683,10 @@ func TestConnectionPool_NewWatcher_update(t *testing.T) { err := test_helpers.SetClusterRO(servers, opts, roles) require.Nilf(t, err, "fail to set roles for cluster") - poolOpts := connection_pool.OptsPool{ + poolOpts := pool.Opts{ CheckTimeout: 500 * time.Millisecond, } - pool, err := connection_pool.ConnectWithOpts(servers, opts, poolOpts) + pool, err := pool.ConnectWithOpts(servers, opts, poolOpts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, pool, "conn is nil after Connect") @@ -2643,7 +2759,7 @@ func TestWatcher_Unregister(t *testing.T) { test_helpers.SkipIfWatchersUnsupported(t) const key = "TestWatcher_Unregister" - const mode = connection_pool.RW + const mode = pool.RW const expectedCnt = 2 roles := []bool{true, false, false, true, true} @@ -2654,7 +2770,7 @@ func TestWatcher_Unregister(t *testing.T) { err := test_helpers.SetClusterRO(servers, opts, roles) require.Nilf(t, err, "fail to set roles for cluster") - pool, err := connection_pool.Connect(servers, opts) + pool, err := pool.Connect(servers, opts) require.Nilf(t, err, "failed to connect") require.NotNilf(t, pool, "conn is nil after Connect") defer pool.Close() @@ -2713,21 +2829,21 @@ func TestConnectionPool_NewWatcher_concurrent(t *testing.T) { err := test_helpers.SetClusterRO(servers, opts, roles) require.Nilf(t, err, "fail to set roles for cluster") - pool, err := connection_pool.Connect(servers, opts) + connPool, err := pool.Connect(servers, opts) require.Nilf(t, err, "failed to connect") - require.NotNilf(t, pool, "conn is nil after Connect") - defer pool.Close() + require.NotNilf(t, connPool, "conn is nil after Connect") + defer connPool.Close() var wg sync.WaitGroup wg.Add(testConcurrency) - mode := connection_pool.ANY + mode := pool.ANY callback := func(event tarantool.WatchEvent) {} for i := 0; i < testConcurrency; i++ { go func(i int) { defer wg.Done() - watcher, err := pool.NewWatcher(key, callback, mode) + watcher, err := connPool.NewWatcher(key, callback, mode) if err != nil { t.Errorf("Failed to create a watcher: %s", err) } else { @@ -2753,13 +2869,13 @@ func TestWatcher_Unregister_concurrent(t *testing.T) { err := test_helpers.SetClusterRO(servers, opts, roles) require.Nilf(t, err, "fail to set roles for cluster") - pool, err := connection_pool.Connect(servers, opts) + connPool, err := pool.Connect(servers, opts) require.Nilf(t, err, "failed to connect") - require.NotNilf(t, pool, "conn is nil after Connect") - defer pool.Close() + require.NotNilf(t, connPool, "conn is nil after Connect") + defer connPool.Close() - mode := connection_pool.ANY - watcher, err := pool.NewWatcher(key, func(event tarantool.WatchEvent) { + mode := pool.ANY + watcher, err := connPool.NewWatcher(key, func(event tarantool.WatchEvent) { }, mode) require.Nilf(t, err, "failed to create a watcher") diff --git a/connection_pool/connector.go b/pool/connector.go similarity index 88% rename from connection_pool/connector.go rename to pool/connector.go index c108aba0b..852f47cee 100644 --- a/connection_pool/connector.go +++ b/pool/connector.go @@ -1,11 +1,11 @@ -package connection_pool +package pool import ( "errors" "fmt" "time" - "github.com/tarantool/go-tarantool" + "github.com/tarantool/go-tarantool/v2" ) // ConnectorAdapter allows to use Pooler as Connector. @@ -63,7 +63,7 @@ func (c *ConnectorAdapter) ConfiguredTimeout() time.Duration { // Select performs select to box space. func (c *ConnectorAdapter) Select(space, index interface{}, - offset, limit, iterator uint32, + offset, limit uint32, iterator tarantool.Iter, key interface{}) (*tarantool.Response, error) { return c.pool.Select(space, index, offset, limit, iterator, key, c.mode) } @@ -99,16 +99,14 @@ func (c *ConnectorAdapter) Upsert(space interface{}, } // Call calls registered Tarantool function. -// It uses request code for Tarantool >= 1.7 if go-tarantool -// was build with go_tarantool_call_17 tag. -// Otherwise, uses request code for Tarantool 1.6. +// It uses request code for Tarantool >= 1.7, result is an array. func (c *ConnectorAdapter) Call(functionName string, args interface{}) (*tarantool.Response, error) { return c.pool.Call(functionName, args, c.mode) } // Call16 calls registered Tarantool function. -// It uses request code for Tarantool 1.6, so result is converted to array of arrays +// It uses request code for Tarantool 1.6, result is an array of arrays. // Deprecated since Tarantool 1.7.2. func (c *ConnectorAdapter) Call16(functionName string, args interface{}) (*tarantool.Response, error) { @@ -116,8 +114,7 @@ func (c *ConnectorAdapter) Call16(functionName string, } // Call17 calls registered Tarantool function. -// It uses request code for Tarantool >= 1.7, so result is not converted -// (though, keep in mind, result is always array) +// It uses request code for Tarantool >= 1.7, result is an array. func (c *ConnectorAdapter) Call17(functionName string, args interface{}) (*tarantool.Response, error) { return c.pool.Call17(functionName, args, c.mode) @@ -144,7 +141,7 @@ func (c *ConnectorAdapter) GetTyped(space, index interface{}, // SelectTyped performs select to box space and fills typed result. func (c *ConnectorAdapter) SelectTyped(space, index interface{}, - offset, limit, iterator uint32, + offset, limit uint32, iterator tarantool.Iter, key interface{}, result interface{}) error { return c.pool.SelectTyped(space, index, offset, limit, iterator, key, result, c.mode) } @@ -174,16 +171,14 @@ func (c *ConnectorAdapter) UpdateTyped(space, index interface{}, } // CallTyped calls registered function. -// It uses request code for Tarantool >= 1.7 if go-tarantool -// was build with go_tarantool_call_17 tag. -// Otherwise, uses request code for Tarantool 1.6. +// It uses request code for Tarantool >= 1.7, result is an array. func (c *ConnectorAdapter) CallTyped(functionName string, args interface{}, result interface{}) error { return c.pool.CallTyped(functionName, args, result, c.mode) } // Call16Typed calls registered function. -// It uses request code for Tarantool 1.6, so result is converted to array of arrays +// It uses request code for Tarantool 1.6, result is an array of arrays. // Deprecated since Tarantool 1.7.2. func (c *ConnectorAdapter) Call16Typed(functionName string, args interface{}, result interface{}) error { @@ -191,8 +186,7 @@ func (c *ConnectorAdapter) Call16Typed(functionName string, } // Call17Typed calls registered function. -// It uses request code for Tarantool >= 1.7, so result is not converted -// (though, keep in mind, result is always array) +// It uses request code for Tarantool >= 1.7, result is an array. func (c *ConnectorAdapter) Call17Typed(functionName string, args interface{}, result interface{}) error { return c.pool.Call17Typed(functionName, args, result, c.mode) @@ -212,7 +206,7 @@ func (c *ConnectorAdapter) ExecuteTyped(expr string, args interface{}, // SelectAsync sends select request to Tarantool and returns Future. func (c *ConnectorAdapter) SelectAsync(space, index interface{}, - offset, limit, iterator uint32, key interface{}) *tarantool.Future { + offset, limit uint32, iterator tarantool.Iter, key interface{}) *tarantool.Future { return c.pool.SelectAsync(space, index, offset, limit, iterator, key, c.mode) } @@ -247,16 +241,14 @@ func (c *ConnectorAdapter) UpsertAsync(space interface{}, tuple interface{}, } // CallAsync sends a call to registered Tarantool function and returns Future. -// It uses request code for Tarantool >= 1.7 if go-tarantool -// was build with go_tarantool_call_17 tag. -// Otherwise, uses request code for Tarantool 1.6. +// It uses request code for Tarantool >= 1.7, future's result is an array. func (c *ConnectorAdapter) CallAsync(functionName string, args interface{}) *tarantool.Future { return c.pool.CallAsync(functionName, args, c.mode) } // Call16Async sends a call to registered Tarantool function and returns Future. -// It uses request code for Tarantool 1.6, so future's result is always array of arrays. +// It uses request code for Tarantool 1.6, so future's result is an array of arrays. // Deprecated since Tarantool 1.7.2. func (c *ConnectorAdapter) Call16Async(functionName string, args interface{}) *tarantool.Future { @@ -264,8 +256,7 @@ func (c *ConnectorAdapter) Call16Async(functionName string, } // Call17Async sends a call to registered Tarantool function and returns Future. -// It uses request code for Tarantool >= 1.7, so future's result will not be converted -// (though, keep in mind, result is always array) +// It uses request code for Tarantool >= 1.7, future's result is an array. func (c *ConnectorAdapter) Call17Async(functionName string, args interface{}) *tarantool.Future { return c.pool.Call17Async(functionName, args, c.mode) diff --git a/connection_pool/connector_test.go b/pool/connector_test.go similarity index 98% rename from connection_pool/connector_test.go rename to pool/connector_test.go index f53a05b22..8a954fa6e 100644 --- a/connection_pool/connector_test.go +++ b/pool/connector_test.go @@ -1,4 +1,4 @@ -package connection_pool_test +package pool_test import ( "errors" @@ -7,8 +7,8 @@ import ( "time" "github.com/stretchr/testify/require" - "github.com/tarantool/go-tarantool" - . "github.com/tarantool/go-tarantool/connection_pool" + "github.com/tarantool/go-tarantool/v2" + . "github.com/tarantool/go-tarantool/v2/pool" ) var testMode Mode = RW @@ -125,13 +125,14 @@ func TestConnectorConfiguredTimeoutWithError(t *testing.T) { type baseRequestMock struct { Pooler - called int - functionName string - offset, limit, iterator uint32 - space, index interface{} - args, tuple, key, ops interface{} - result interface{} - mode Mode + called int + functionName string + offset, limit uint32 + iterator tarantool.Iter + space, index interface{} + args, tuple, key, ops interface{} + result interface{} + mode Mode } var reqResp *tarantool.Response = &tarantool.Response{} @@ -141,7 +142,7 @@ var reqFuture *tarantool.Future = &tarantool.Future{} var reqFunctionName string = "any_name" var reqOffset uint32 = 1 var reqLimit uint32 = 2 -var reqIterator uint32 = 3 +var reqIterator tarantool.Iter = tarantool.IterLt var reqSpace interface{} = []interface{}{1} var reqIndex interface{} = []interface{}{2} var reqArgs interface{} = []interface{}{3} @@ -188,7 +189,7 @@ type selectMock struct { } func (m *selectMock) Select(space, index interface{}, - offset, limit, iterator uint32, key interface{}, + offset, limit uint32, iterator tarantool.Iter, key interface{}, mode ...Mode) (*tarantool.Response, error) { m.called++ m.space = space @@ -224,7 +225,7 @@ type selectTypedMock struct { } func (m *selectTypedMock) SelectTyped(space, index interface{}, - offset, limit, iterator uint32, key interface{}, + offset, limit uint32, iterator tarantool.Iter, key interface{}, result interface{}, mode ...Mode) error { m.called++ m.space = space @@ -262,7 +263,7 @@ type selectAsyncMock struct { } func (m *selectAsyncMock) SelectAsync(space, index interface{}, - offset, limit, iterator uint32, key interface{}, + offset, limit uint32, iterator tarantool.Iter, key interface{}, mode ...Mode) *tarantool.Future { m.called++ m.space = space diff --git a/connection_pool/const.go b/pool/const.go similarity index 97% rename from connection_pool/const.go rename to pool/const.go index 26b028f5a..7ec239f7d 100644 --- a/connection_pool/const.go +++ b/pool/const.go @@ -1,4 +1,4 @@ -package connection_pool +package pool /* Default mode for each request table: diff --git a/connection_pool/example_test.go b/pool/example_test.go similarity index 83% rename from connection_pool/example_test.go rename to pool/example_test.go index 4ed422375..f917668a6 100644 --- a/connection_pool/example_test.go +++ b/pool/example_test.go @@ -1,12 +1,12 @@ -package connection_pool_test +package pool_test import ( "fmt" "time" - "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/connection_pool" - "github.com/tarantool/go-tarantool/test_helpers" + "github.com/tarantool/go-tarantool/v2" + "github.com/tarantool/go-tarantool/v2/pool" + "github.com/tarantool/go-tarantool/v2/test_helpers" ) type Tuple struct { @@ -19,12 +19,12 @@ type Tuple struct { var testRoles = []bool{true, true, false, true, true} -func examplePool(roles []bool, connOpts tarantool.Opts) (*connection_pool.ConnectionPool, error) { +func examplePool(roles []bool, connOpts tarantool.Opts) (*pool.ConnectionPool, error) { err := test_helpers.SetClusterRO(servers, connOpts, roles) if err != nil { return nil, fmt.Errorf("ConnectionPool is not established") } - connPool, err := connection_pool.Connect(servers, connOpts) + connPool, err := pool.Connect(servers, connOpts) if err != nil || connPool == nil { return nil, fmt.Errorf("ConnectionPool is not established") } @@ -33,11 +33,11 @@ func examplePool(roles []bool, connOpts tarantool.Opts) (*connection_pool.Connec } func ExampleConnectionPool_Select() { - pool, err := examplePool(testRoles, connOpts) + connPool, err := examplePool(testRoles, connOpts) if err != nil { fmt.Println(err) } - defer pool.Close() + defer connPool.Close() // Connect to servers[2] to check if tuple // was inserted on RW instance @@ -60,17 +60,17 @@ func ExampleConnectionPool_Select() { return } - resp, err := pool.Select( + resp, err := connPool.Select( spaceNo, indexNo, 0, 100, tarantool.IterEq, - []interface{}{"key1"}, connection_pool.PreferRW) + []interface{}{"key1"}, pool.PreferRW) if err != nil { fmt.Printf("error in select is %v", err) return } fmt.Printf("response is %#v\n", resp.Data) - resp, err = pool.Select( + resp, err = connPool.Select( spaceNo, indexNo, 0, 100, tarantool.IterEq, - []interface{}{"key2"}, connection_pool.PreferRW) + []interface{}{"key2"}, pool.PreferRW) if err != nil { fmt.Printf("error in select is %v", err) return @@ -94,11 +94,11 @@ func ExampleConnectionPool_Select() { } func ExampleConnectionPool_SelectTyped() { - pool, err := examplePool(testRoles, connOpts) + connPool, err := examplePool(testRoles, connOpts) if err != nil { fmt.Println(err) } - defer pool.Close() + defer connPool.Close() // Connect to servers[2] to check if tuple // was inserted on RW instance @@ -122,17 +122,17 @@ func ExampleConnectionPool_SelectTyped() { } var res []Tuple - err = pool.SelectTyped( + err = connPool.SelectTyped( spaceNo, indexNo, 0, 100, tarantool.IterEq, - []interface{}{"key1"}, &res, connection_pool.PreferRW) + []interface{}{"key1"}, &res, pool.PreferRW) if err != nil { fmt.Printf("error in select is %v", err) return } fmt.Printf("response is %v\n", res) - err = pool.SelectTyped( + err = connPool.SelectTyped( spaceName, indexName, 0, 100, tarantool.IterEq, - []interface{}{"key2"}, &res, connection_pool.PreferRW) + []interface{}{"key2"}, &res, pool.PreferRW) if err != nil { fmt.Printf("error in select is %v", err) return @@ -156,11 +156,11 @@ func ExampleConnectionPool_SelectTyped() { } func ExampleConnectionPool_SelectAsync() { - pool, err := examplePool(testRoles, connOpts) + connPool, err := examplePool(testRoles, connOpts) if err != nil { fmt.Println(err) } - defer pool.Close() + defer connPool.Close() // Connect to servers[2] to check if tuple // was inserted on RW instance @@ -190,15 +190,15 @@ func ExampleConnectionPool_SelectAsync() { } var futs [3]*tarantool.Future - futs[0] = pool.SelectAsync( + futs[0] = connPool.SelectAsync( spaceName, indexName, 0, 2, tarantool.IterEq, - []interface{}{"key1"}, connection_pool.PreferRW) - futs[1] = pool.SelectAsync( + []interface{}{"key1"}, pool.PreferRW) + futs[1] = connPool.SelectAsync( spaceName, indexName, 0, 1, tarantool.IterEq, - []interface{}{"key2"}, connection_pool.RW) - futs[2] = pool.SelectAsync( + []interface{}{"key2"}, pool.RW) + futs[2] = connPool.SelectAsync( spaceName, indexName, 0, 1, tarantool.IterEq, - []interface{}{"key3"}, connection_pool.RW) + []interface{}{"key3"}, pool.RW) var t []Tuple err = futs[0].GetTyped(&t) fmt.Println("Future", 0, "Error", err) @@ -239,16 +239,16 @@ func ExampleConnectionPool_SelectAsync() { func ExampleConnectionPool_SelectAsync_err() { roles := []bool{true, true, true, true, true} - pool, err := examplePool(roles, connOpts) + connPool, err := examplePool(roles, connOpts) if err != nil { fmt.Println(err) } - defer pool.Close() + defer connPool.Close() var futs [3]*tarantool.Future - futs[0] = pool.SelectAsync( + futs[0] = connPool.SelectAsync( spaceName, indexName, 0, 2, tarantool.IterEq, - []interface{}{"key1"}, connection_pool.RW) + []interface{}{"key1"}, pool.RW) err = futs[0].Err() fmt.Println("Future", 0, "Error", err) @@ -258,14 +258,14 @@ func ExampleConnectionPool_SelectAsync_err() { } func ExampleConnectionPool_Ping() { - pool, err := examplePool(testRoles, connOpts) + connPool, err := examplePool(testRoles, connOpts) if err != nil { fmt.Println(err) } - defer pool.Close() + defer connPool.Close() // Ping a Tarantool instance to check connection. - resp, err := pool.Ping(connection_pool.ANY) + resp, err := connPool.Ping(pool.ANY) fmt.Println("Ping Code", resp.Code) fmt.Println("Ping Data", resp.Data) fmt.Println("Ping Error", err) @@ -276,20 +276,20 @@ func ExampleConnectionPool_Ping() { } func ExampleConnectionPool_Insert() { - pool, err := examplePool(testRoles, connOpts) + connPool, err := examplePool(testRoles, connOpts) if err != nil { fmt.Println(err) } - defer pool.Close() + defer connPool.Close() // Insert a new tuple {"key1", "value1"}. - resp, err := pool.Insert(spaceNo, []interface{}{"key1", "value1"}) + resp, err := connPool.Insert(spaceNo, []interface{}{"key1", "value1"}) fmt.Println("Insert key1") fmt.Println("Error", err) fmt.Println("Code", resp.Code) fmt.Println("Data", resp.Data) // Insert a new tuple {"key2", "value2"}. - resp, err = pool.Insert(spaceName, &Tuple{Key: "key2", Value: "value2"}, connection_pool.PreferRW) + resp, err = connPool.Insert(spaceName, &Tuple{Key: "key2", Value: "value2"}, pool.PreferRW) fmt.Println("Insert key2") fmt.Println("Error", err) fmt.Println("Code", resp.Code) @@ -325,11 +325,11 @@ func ExampleConnectionPool_Insert() { } func ExampleConnectionPool_Delete() { - pool, err := examplePool(testRoles, connOpts) + connPool, err := examplePool(testRoles, connOpts) if err != nil { fmt.Println(err) } - defer pool.Close() + defer connPool.Close() // Connect to servers[2] to check if tuple // was inserted on RW instance @@ -353,14 +353,14 @@ func ExampleConnectionPool_Delete() { } // Delete tuple with primary key {"key1"}. - resp, err := pool.Delete(spaceNo, indexNo, []interface{}{"key1"}) + resp, err := connPool.Delete(spaceNo, indexNo, []interface{}{"key1"}) fmt.Println("Delete key1") fmt.Println("Error", err) fmt.Println("Code", resp.Code) fmt.Println("Data", resp.Data) // Delete tuple with primary key { "key2" }. - resp, err = pool.Delete(spaceName, indexName, []interface{}{"key2"}, connection_pool.PreferRW) + resp, err = connPool.Delete(spaceName, indexName, []interface{}{"key2"}, pool.PreferRW) fmt.Println("Delete key2") fmt.Println("Error", err) fmt.Println("Code", resp.Code) @@ -377,11 +377,11 @@ func ExampleConnectionPool_Delete() { } func ExampleConnectionPool_Replace() { - pool, err := examplePool(testRoles, connOpts) + connPool, err := examplePool(testRoles, connOpts) if err != nil { fmt.Println(err) } - defer pool.Close() + defer connPool.Close() // Connect to servers[2] to check if tuple // was inserted on RW instance @@ -401,22 +401,22 @@ func ExampleConnectionPool_Replace() { // Replace a tuple with primary key ""key1. // Note, Tuple is defined within tests, and has EncdodeMsgpack and // DecodeMsgpack methods. - resp, err := pool.Replace(spaceNo, []interface{}{"key1", "new_value"}) + resp, err := connPool.Replace(spaceNo, []interface{}{"key1", "new_value"}) fmt.Println("Replace key1") fmt.Println("Error", err) fmt.Println("Code", resp.Code) fmt.Println("Data", resp.Data) - resp, err = pool.Replace(spaceName, []interface{}{"key1", "another_value"}) + resp, err = connPool.Replace(spaceName, []interface{}{"key1", "another_value"}) fmt.Println("Replace key1") fmt.Println("Error", err) fmt.Println("Code", resp.Code) fmt.Println("Data", resp.Data) - resp, err = pool.Replace(spaceName, &Tuple{Key: "key1", Value: "value2"}) + resp, err = connPool.Replace(spaceName, &Tuple{Key: "key1", Value: "value2"}) fmt.Println("Replace key1") fmt.Println("Error", err) fmt.Println("Code", resp.Code) fmt.Println("Data", resp.Data) - resp, err = pool.Replace(spaceName, &Tuple{Key: "key1", Value: "new_value2"}, connection_pool.PreferRW) + resp, err = connPool.Replace(spaceName, &Tuple{Key: "key1", Value: "new_value2"}, pool.PreferRW) fmt.Println("Replace key1") fmt.Println("Error", err) fmt.Println("Code", resp.Code) @@ -448,11 +448,11 @@ func ExampleConnectionPool_Replace() { } func ExampleConnectionPool_Update() { - pool, err := examplePool(testRoles, connOpts) + connPool, err := examplePool(testRoles, connOpts) if err != nil { fmt.Println(err) } - defer pool.Close() + defer connPool.Close() // Connect to servers[2] to check if tuple // was inserted on RW instance @@ -470,9 +470,9 @@ func ExampleConnectionPool_Update() { } // Update tuple with primary key { "key1" }. - resp, err := pool.Update( + resp, err := connPool.Update( spaceName, indexName, []interface{}{"key1"}, - []interface{}{[]interface{}{"=", 1, "new_value"}}, connection_pool.PreferRW) + []interface{}{[]interface{}{"=", 1, "new_value"}}, pool.PreferRW) fmt.Println("Update key1") fmt.Println("Error", err) fmt.Println("Code", resp.Code) @@ -492,14 +492,14 @@ func ExampleConnectionPool_Update() { } func ExampleConnectionPool_Call() { - pool, err := examplePool(testRoles, connOpts) + connPool, err := examplePool(testRoles, connOpts) if err != nil { fmt.Println(err) } - defer pool.Close() + defer connPool.Close() // Call a function 'simple_incr' with arguments. - resp, err := pool.Call17("simple_incr", []interface{}{1}, connection_pool.PreferRW) + resp, err := connPool.Call17("simple_incr", []interface{}{1}, pool.PreferRW) fmt.Println("Call simple_incr()") fmt.Println("Error", err) fmt.Println("Code", resp.Code) @@ -512,14 +512,14 @@ func ExampleConnectionPool_Call() { } func ExampleConnectionPool_Eval() { - pool, err := examplePool(testRoles, connOpts) + connPool, err := examplePool(testRoles, connOpts) if err != nil { fmt.Println(err) } - defer pool.Close() + defer connPool.Close() // Run raw Lua code. - resp, err := pool.Eval("return 1 + 2", []interface{}{}, connection_pool.PreferRW) + resp, err := connPool.Eval("return 1 + 2", []interface{}{}, pool.PreferRW) fmt.Println("Eval 'return 1 + 2'") fmt.Println("Error", err) fmt.Println("Code", resp.Code) @@ -532,15 +532,15 @@ func ExampleConnectionPool_Eval() { } func ExampleConnectionPool_Do() { - pool, err := examplePool(testRoles, connOpts) + connPool, err := examplePool(testRoles, connOpts) if err != nil { fmt.Println(err) } - defer pool.Close() + defer connPool.Close() // Ping a Tarantool instance to check connection. req := tarantool.NewPingRequest() - resp, err := pool.Do(req, connection_pool.ANY).Get() + resp, err := connPool.Do(req, pool.ANY).Get() fmt.Println("Ping Code", resp.Code) fmt.Println("Ping Data", resp.Data) fmt.Println("Ping Error", err) @@ -551,13 +551,13 @@ func ExampleConnectionPool_Do() { } func ExampleConnectionPool_NewPrepared() { - pool, err := examplePool(testRoles, connOpts) + connPool, err := examplePool(testRoles, connOpts) if err != nil { fmt.Println(err) } - defer pool.Close() + defer connPool.Close() - stmt, err := pool.NewPrepared("SELECT 1", connection_pool.ANY) + stmt, err := connPool.NewPrepared("SELECT 1", pool.ANY) if err != nil { fmt.Println(err) } @@ -565,11 +565,11 @@ func ExampleConnectionPool_NewPrepared() { executeReq := tarantool.NewExecutePreparedRequest(stmt) unprepareReq := tarantool.NewUnprepareRequest(stmt) - _, err = pool.Do(executeReq, connection_pool.ANY).Get() + _, err = connPool.Do(executeReq, pool.ANY).Get() if err != nil { fmt.Printf("Failed to execute prepared stmt") } - _, err = pool.Do(unprepareReq, connection_pool.ANY).Get() + _, err = connPool.Do(unprepareReq, pool.ANY).Get() if err != nil { fmt.Printf("Failed to prepare") } @@ -584,26 +584,26 @@ func ExampleConnectionPool_NewWatcher() { tarantool.WatchersFeature, } - pool, err := examplePool(testRoles, connOpts) + connPool, err := examplePool(testRoles, connOpts) if err != nil { fmt.Println(err) } - defer pool.Close() + defer connPool.Close() callback := func(event tarantool.WatchEvent) { fmt.Printf("event connection: %s\n", event.Conn.Addr()) fmt.Printf("event key: %s\n", event.Key) fmt.Printf("event value: %v\n", event.Value) } - mode := connection_pool.ANY - watcher, err := pool.NewWatcher(key, callback, mode) + mode := pool.ANY + watcher, err := connPool.NewWatcher(key, callback, mode) if err != nil { fmt.Printf("Unexpected error: %s\n", err) return } defer watcher.Unregister() - pool.Do(tarantool.NewBroadcastRequest(key).Value(value), mode).Get() + connPool.Do(tarantool.NewBroadcastRequest(key).Value(value), mode).Get() time.Sleep(time.Second) } @@ -613,14 +613,14 @@ func ExampleConnectionPool_NewWatcher_noWatchersFeature() { opts := connOpts.Clone() opts.RequiredProtocolInfo.Features = []tarantool.ProtocolFeature{} - pool, err := examplePool(testRoles, connOpts) + connPool, err := examplePool(testRoles, connOpts) if err != nil { fmt.Println(err) } - defer pool.Close() + defer connPool.Close() callback := func(event tarantool.WatchEvent) {} - watcher, err := pool.NewWatcher(key, callback, connection_pool.ANY) + watcher, err := connPool.NewWatcher(key, callback, pool.ANY) fmt.Println(watcher) fmt.Println(err) // Output: @@ -655,15 +655,15 @@ func ExampleCommitRequest() { } txnOpts := getTestTxnOpts() - pool, err := examplePool(testRoles, txnOpts) + connPool, err := examplePool(testRoles, txnOpts) if err != nil { fmt.Println(err) return } - defer pool.Close() + defer connPool.Close() // example pool has only one rw instance - stream, err := pool.NewStream(connection_pool.RW) + stream, err := connPool.NewStream(pool.RW) if err != nil { fmt.Println(err) return @@ -696,7 +696,7 @@ func ExampleCommitRequest() { Limit(1). Iterator(tarantool.IterEq). Key([]interface{}{"example_commit_key"}) - resp, err = pool.Do(selectReq, connection_pool.RW).Get() + resp, err = connPool.Do(selectReq, pool.RW).Get() if err != nil { fmt.Printf("Failed to Select: %s", err.Error()) return @@ -722,7 +722,7 @@ func ExampleCommitRequest() { // Select outside of transaction // example pool has only one rw instance - resp, err = pool.Do(selectReq, connection_pool.RW).Get() + resp, err = connPool.Do(selectReq, pool.RW).Get() if err != nil { fmt.Printf("Failed to Select: %s", err.Error()) return @@ -743,14 +743,14 @@ func ExampleRollbackRequest() { txnOpts := getTestTxnOpts() // example pool has only one rw instance - pool, err := examplePool(testRoles, txnOpts) + connPool, err := examplePool(testRoles, txnOpts) if err != nil { fmt.Println(err) return } - defer pool.Close() + defer connPool.Close() - stream, err := pool.NewStream(connection_pool.RW) + stream, err := connPool.NewStream(pool.RW) if err != nil { fmt.Println(err) return @@ -783,7 +783,7 @@ func ExampleRollbackRequest() { Limit(1). Iterator(tarantool.IterEq). Key([]interface{}{"example_rollback_key"}) - resp, err = pool.Do(selectReq, connection_pool.RW).Get() + resp, err = connPool.Do(selectReq, pool.RW).Get() if err != nil { fmt.Printf("Failed to Select: %s", err.Error()) return @@ -809,7 +809,7 @@ func ExampleRollbackRequest() { // Select outside of transaction // example pool has only one rw instance - resp, err = pool.Do(selectReq, connection_pool.RW).Get() + resp, err = connPool.Do(selectReq, pool.RW).Get() if err != nil { fmt.Printf("Failed to Select: %s", err.Error()) return @@ -830,14 +830,14 @@ func ExampleBeginRequest_TxnIsolation() { txnOpts := getTestTxnOpts() // example pool has only one rw instance - pool, err := examplePool(testRoles, txnOpts) + connPool, err := examplePool(testRoles, txnOpts) if err != nil { fmt.Println(err) return } - defer pool.Close() + defer connPool.Close() - stream, err := pool.NewStream(connection_pool.RW) + stream, err := connPool.NewStream(pool.RW) if err != nil { fmt.Println(err) return @@ -872,7 +872,7 @@ func ExampleBeginRequest_TxnIsolation() { Limit(1). Iterator(tarantool.IterEq). Key([]interface{}{"isolation_level_key"}) - resp, err = pool.Do(selectReq, connection_pool.RW).Get() + resp, err = connPool.Do(selectReq, pool.RW).Get() if err != nil { fmt.Printf("Failed to Select: %s", err.Error()) return @@ -898,7 +898,7 @@ func ExampleBeginRequest_TxnIsolation() { // Select outside of transaction // example pool has only one rw instance - resp, err = pool.Do(selectReq, connection_pool.RW).Get() + resp, err = connPool.Do(selectReq, pool.RW).Get() if err != nil { fmt.Printf("Failed to Select: %s", err.Error()) return @@ -907,13 +907,13 @@ func ExampleBeginRequest_TxnIsolation() { } func ExampleConnectorAdapter() { - pool, err := examplePool(testRoles, connOpts) + connPool, err := examplePool(testRoles, connOpts) if err != nil { fmt.Println(err) } - defer pool.Close() + defer connPool.Close() - adapter := connection_pool.NewConnectorAdapter(pool, connection_pool.RW) + adapter := pool.NewConnectorAdapter(connPool, pool.RW) var connector tarantool.Connector = adapter // Ping an RW instance to check connection. @@ -930,7 +930,7 @@ func ExampleConnectorAdapter() { // ExampleConnectionPool_CloseGraceful_force demonstrates how to force close // a connection pool with graceful close in progress after a while. func ExampleConnectionPool_CloseGraceful_force() { - pool, err := examplePool(testRoles, connOpts) + connPool, err := examplePool(testRoles, connOpts) if err != nil { fmt.Println(err) return @@ -941,11 +941,11 @@ func ExampleConnectionPool_CloseGraceful_force() { fiber.sleep(time) ` req := tarantool.NewEvalRequest(eval).Args([]interface{}{10}) - fut := pool.Do(req, connection_pool.ANY) + fut := connPool.Do(req, pool.ANY) done := make(chan struct{}) go func() { - pool.CloseGraceful() + connPool.CloseGraceful() fmt.Println("ConnectionPool.CloseGraceful() done!") close(done) }() @@ -954,7 +954,7 @@ func ExampleConnectionPool_CloseGraceful_force() { case <-done: case <-time.After(3 * time.Second): fmt.Println("Force ConnectionPool.Close()!") - pool.Close() + connPool.Close() } <-done diff --git a/connection_pool/pooler.go b/pool/pooler.go similarity index 91% rename from connection_pool/pooler.go rename to pool/pooler.go index 856f5d5be..a7cae8f95 100644 --- a/connection_pool/pooler.go +++ b/pool/pooler.go @@ -1,9 +1,9 @@ -package connection_pool +package pool import ( "time" - "github.com/tarantool/go-tarantool" + "github.com/tarantool/go-tarantool/v2" ) // Pooler is the interface that must be implemented by a connection pool. @@ -13,7 +13,7 @@ type Pooler interface { Ping(mode Mode) (*tarantool.Response, error) ConfiguredTimeout(mode Mode) (time.Duration, error) - Select(space, index interface{}, offset, limit, iterator uint32, + Select(space, index interface{}, offset, limit uint32, iterator tarantool.Iter, key interface{}, mode ...Mode) (*tarantool.Response, error) Insert(space interface{}, tuple interface{}, mode ...Mode) (*tarantool.Response, error) @@ -38,7 +38,7 @@ type Pooler interface { GetTyped(space, index interface{}, key interface{}, result interface{}, mode ...Mode) error - SelectTyped(space, index interface{}, offset, limit, iterator uint32, + SelectTyped(space, index interface{}, offset, limit uint32, iterator tarantool.Iter, key interface{}, result interface{}, mode ...Mode) error InsertTyped(space interface{}, tuple interface{}, result interface{}, mode ...Mode) error @@ -59,7 +59,7 @@ type Pooler interface { ExecuteTyped(expr string, args interface{}, result interface{}, mode Mode) (tarantool.SQLInfo, []tarantool.ColumnMetaData, error) - SelectAsync(space, index interface{}, offset, limit, iterator uint32, + SelectAsync(space, index interface{}, offset, limit uint32, iterator tarantool.Iter, key interface{}, mode ...Mode) *tarantool.Future InsertAsync(space interface{}, tuple interface{}, mode ...Mode) *tarantool.Future diff --git a/connection_pool/round_robin.go b/pool/round_robin.go similarity index 70% rename from connection_pool/round_robin.go rename to pool/round_robin.go index a7fb73e18..1c50b97d9 100644 --- a/connection_pool/round_robin.go +++ b/pool/round_robin.go @@ -1,12 +1,12 @@ -package connection_pool +package pool import ( "sync" - "github.com/tarantool/go-tarantool" + "github.com/tarantool/go-tarantool/v2" ) -type RoundRobinStrategy struct { +type roundRobinStrategy struct { conns []*tarantool.Connection indexByAddr map[string]uint mutex sync.RWMutex @@ -14,8 +14,8 @@ type RoundRobinStrategy struct { current uint } -func NewEmptyRoundRobin(size int) *RoundRobinStrategy { - return &RoundRobinStrategy{ +func newRoundRobinStrategy(size int) *roundRobinStrategy { + return &roundRobinStrategy{ conns: make([]*tarantool.Connection, 0, size), indexByAddr: make(map[string]uint), size: 0, @@ -23,7 +23,7 @@ func NewEmptyRoundRobin(size int) *RoundRobinStrategy { } } -func (r *RoundRobinStrategy) GetConnByAddr(addr string) *tarantool.Connection { +func (r *roundRobinStrategy) GetConnByAddr(addr string) *tarantool.Connection { r.mutex.RLock() defer r.mutex.RUnlock() @@ -35,7 +35,7 @@ func (r *RoundRobinStrategy) GetConnByAddr(addr string) *tarantool.Connection { return r.conns[index] } -func (r *RoundRobinStrategy) DeleteConnByAddr(addr string) *tarantool.Connection { +func (r *roundRobinStrategy) DeleteConnByAddr(addr string) *tarantool.Connection { r.mutex.Lock() defer r.mutex.Unlock() @@ -63,14 +63,14 @@ func (r *RoundRobinStrategy) DeleteConnByAddr(addr string) *tarantool.Connection return conn } -func (r *RoundRobinStrategy) IsEmpty() bool { +func (r *roundRobinStrategy) IsEmpty() bool { r.mutex.RLock() defer r.mutex.RUnlock() return r.size == 0 } -func (r *RoundRobinStrategy) GetNextConnection() *tarantool.Connection { +func (r *roundRobinStrategy) GetNextConnection() *tarantool.Connection { r.mutex.RLock() defer r.mutex.RUnlock() @@ -80,7 +80,7 @@ func (r *RoundRobinStrategy) GetNextConnection() *tarantool.Connection { return r.conns[r.nextIndex()] } -func (r *RoundRobinStrategy) GetConnections() []*tarantool.Connection { +func (r *roundRobinStrategy) GetConnections() []*tarantool.Connection { r.mutex.RLock() defer r.mutex.RUnlock() @@ -90,7 +90,7 @@ func (r *RoundRobinStrategy) GetConnections() []*tarantool.Connection { return ret } -func (r *RoundRobinStrategy) AddConn(addr string, conn *tarantool.Connection) { +func (r *roundRobinStrategy) AddConn(addr string, conn *tarantool.Connection) { r.mutex.Lock() defer r.mutex.Unlock() @@ -103,7 +103,7 @@ func (r *RoundRobinStrategy) AddConn(addr string, conn *tarantool.Connection) { } } -func (r *RoundRobinStrategy) nextIndex() uint { +func (r *roundRobinStrategy) nextIndex() uint { ret := r.current % r.size r.current++ return ret diff --git a/connection_pool/round_robin_test.go b/pool/round_robin_test.go similarity index 88% rename from connection_pool/round_robin_test.go rename to pool/round_robin_test.go index 03038eada..4aacb1a26 100644 --- a/connection_pool/round_robin_test.go +++ b/pool/round_robin_test.go @@ -1,10 +1,9 @@ -package connection_pool_test +package pool import ( "testing" - "github.com/tarantool/go-tarantool" - . "github.com/tarantool/go-tarantool/connection_pool" + "github.com/tarantool/go-tarantool/v2" ) const ( @@ -13,7 +12,7 @@ const ( ) func TestRoundRobinAddDelete(t *testing.T) { - rr := NewEmptyRoundRobin(10) + rr := newRoundRobinStrategy(10) addrs := []string{validAddr1, validAddr2} conns := []*tarantool.Connection{&tarantool.Connection{}, &tarantool.Connection{}} @@ -33,7 +32,7 @@ func TestRoundRobinAddDelete(t *testing.T) { } func TestRoundRobinAddDuplicateDelete(t *testing.T) { - rr := NewEmptyRoundRobin(10) + rr := newRoundRobinStrategy(10) conn1 := &tarantool.Connection{} conn2 := &tarantool.Connection{} @@ -53,7 +52,7 @@ func TestRoundRobinAddDuplicateDelete(t *testing.T) { } func TestRoundRobinGetNextConnection(t *testing.T) { - rr := NewEmptyRoundRobin(10) + rr := newRoundRobinStrategy(10) addrs := []string{validAddr1, validAddr2} conns := []*tarantool.Connection{&tarantool.Connection{}, &tarantool.Connection{}} @@ -71,7 +70,7 @@ func TestRoundRobinGetNextConnection(t *testing.T) { } func TestRoundRobinStrategy_GetConnections(t *testing.T) { - rr := NewEmptyRoundRobin(10) + rr := newRoundRobinStrategy(10) addrs := []string{validAddr1, validAddr2} conns := []*tarantool.Connection{&tarantool.Connection{}, &tarantool.Connection{}} diff --git a/connection_pool/state.go b/pool/state.go similarity index 94% rename from connection_pool/state.go rename to pool/state.go index 20cd070af..2af093e60 100644 --- a/connection_pool/state.go +++ b/pool/state.go @@ -1,4 +1,4 @@ -package connection_pool +package pool import ( "sync/atomic" diff --git a/connection_pool/watcher.go b/pool/watcher.go similarity index 98% rename from connection_pool/watcher.go rename to pool/watcher.go index d60cfa171..2d2b72e17 100644 --- a/connection_pool/watcher.go +++ b/pool/watcher.go @@ -1,9 +1,9 @@ -package connection_pool +package pool import ( "sync" - "github.com/tarantool/go-tarantool" + "github.com/tarantool/go-tarantool/v2" ) // watcherContainer is a very simple implementation of a thread-safe container diff --git a/prepared.go b/prepared.go index 9019a81f3..8f2d95519 100644 --- a/prepared.go +++ b/prepared.go @@ -3,6 +3,9 @@ package tarantool import ( "context" "fmt" + + "github.com/tarantool/go-iproto" + "github.com/vmihailenco/msgpack/v5" ) // PreparedID is a type for Prepared Statement ID @@ -18,23 +21,23 @@ type Prepared struct { Conn *Connection } -func fillPrepare(enc *encoder, expr string) error { +func fillPrepare(enc *msgpack.Encoder, expr string) error { enc.EncodeMapLen(1) - encodeUint(enc, KeySQLText) + enc.EncodeUint(uint64(iproto.IPROTO_SQL_TEXT)) return enc.EncodeString(expr) } -func fillUnprepare(enc *encoder, stmt Prepared) error { +func fillUnprepare(enc *msgpack.Encoder, stmt Prepared) error { enc.EncodeMapLen(1) - encodeUint(enc, KeyStmtID) - return encodeUint(enc, uint64(stmt.StatementID)) + enc.EncodeUint(uint64(iproto.IPROTO_STMT_ID)) + return enc.EncodeUint(uint64(stmt.StatementID)) } -func fillExecutePrepared(enc *encoder, stmt Prepared, args interface{}) error { +func fillExecutePrepared(enc *msgpack.Encoder, stmt Prepared, args interface{}) error { enc.EncodeMapLen(2) - encodeUint(enc, KeyStmtID) - encodeUint(enc, uint64(stmt.StatementID)) - encodeUint(enc, KeySQLBind) + enc.EncodeUint(uint64(iproto.IPROTO_STMT_ID)) + enc.EncodeUint(uint64(stmt.StatementID)) + enc.EncodeUint(uint64(iproto.IPROTO_SQL_BIND)) return encodeSQLBind(enc, args) } @@ -67,13 +70,13 @@ type PrepareRequest struct { // NewPrepareRequest returns a new empty PrepareRequest. func NewPrepareRequest(expr string) *PrepareRequest { req := new(PrepareRequest) - req.requestCode = PrepareRequestCode + req.rtype = iproto.IPROTO_PREPARE req.expr = expr return req } -// Body fills an encoder with the execute request body. -func (req *PrepareRequest) Body(res SchemaResolver, enc *encoder) error { +// Body fills an msgpack.Encoder with the execute request body. +func (req *PrepareRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error { return fillPrepare(enc, req.expr) } @@ -98,7 +101,7 @@ type UnprepareRequest struct { // NewUnprepareRequest returns a new empty UnprepareRequest. func NewUnprepareRequest(stmt *Prepared) *UnprepareRequest { req := new(UnprepareRequest) - req.requestCode = PrepareRequestCode + req.rtype = iproto.IPROTO_PREPARE req.stmt = stmt return req } @@ -108,8 +111,8 @@ func (req *UnprepareRequest) Conn() *Connection { return req.stmt.Conn } -// Body fills an encoder with the execute request body. -func (req *UnprepareRequest) Body(res SchemaResolver, enc *encoder) error { +// Body fills an msgpack.Encoder with the execute request body. +func (req *UnprepareRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error { return fillUnprepare(enc, *req.stmt) } @@ -135,7 +138,7 @@ type ExecutePreparedRequest struct { // NewExecutePreparedRequest returns a new empty preparedExecuteRequest. func NewExecutePreparedRequest(stmt *Prepared) *ExecutePreparedRequest { req := new(ExecutePreparedRequest) - req.requestCode = ExecuteRequestCode + req.rtype = iproto.IPROTO_EXECUTE req.stmt = stmt req.args = []interface{}{} return req @@ -153,8 +156,8 @@ func (req *ExecutePreparedRequest) Args(args interface{}) *ExecutePreparedReques return req } -// Body fills an encoder with the execute request body. -func (req *ExecutePreparedRequest) Body(res SchemaResolver, enc *encoder) error { +// Body fills an msgpack.Encoder with the execute request body. +func (req *ExecutePreparedRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error { return fillExecutePrepared(enc, *req.stmt, req.args) } diff --git a/protocol.go b/protocol.go index ae8dce306..63424283b 100644 --- a/protocol.go +++ b/protocol.go @@ -3,6 +3,9 @@ package tarantool import ( "context" "fmt" + + "github.com/tarantool/go-iproto" + "github.com/vmihailenco/msgpack/v5" ) // ProtocolVersion type stores Tarantool protocol version. @@ -101,15 +104,15 @@ type IdRequest struct { protocolInfo ProtocolInfo } -func fillId(enc *encoder, protocolInfo ProtocolInfo) error { +func fillId(enc *msgpack.Encoder, protocolInfo ProtocolInfo) error { enc.EncodeMapLen(2) - encodeUint(enc, KeyVersion) + enc.EncodeUint(uint64(iproto.IPROTO_VERSION)) if err := enc.Encode(protocolInfo.Version); err != nil { return err } - encodeUint(enc, KeyFeatures) + enc.EncodeUint(uint64(iproto.IPROTO_FEATURES)) t := len(protocolInfo.Features) if err := enc.EncodeArrayLen(t); err != nil { @@ -128,13 +131,13 @@ func fillId(enc *encoder, protocolInfo ProtocolInfo) error { // NewIdRequest returns a new IdRequest. func NewIdRequest(protocolInfo ProtocolInfo) *IdRequest { req := new(IdRequest) - req.requestCode = IdRequestCode + req.rtype = iproto.IPROTO_ID req.protocolInfo = protocolInfo.Clone() return req } -// Body fills an encoder with the id request body. -func (req *IdRequest) Body(res SchemaResolver, enc *encoder) error { +// Body fills an msgpack.Encoder with the id request body. +func (req *IdRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error { return fillId(enc, req.protocolInfo) } diff --git a/protocol_test.go b/protocol_test.go index c747d9bff..6aa94463b 100644 --- a/protocol_test.go +++ b/protocol_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/require" - . "github.com/tarantool/go-tarantool" + . "github.com/tarantool/go-tarantool/v2" ) func TestProtocolInfoClonePreservesFeatures(t *testing.T) { diff --git a/queue/example_connection_pool_test.go b/queue/example_connection_pool_test.go index 7e80110fd..51fb967a5 100644 --- a/queue/example_connection_pool_test.go +++ b/queue/example_connection_pool_test.go @@ -7,10 +7,10 @@ import ( "time" "github.com/google/uuid" - "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/connection_pool" - "github.com/tarantool/go-tarantool/queue" - "github.com/tarantool/go-tarantool/test_helpers" + "github.com/tarantool/go-tarantool/v2" + "github.com/tarantool/go-tarantool/v2/pool" + "github.com/tarantool/go-tarantool/v2/queue" + "github.com/tarantool/go-tarantool/v2/test_helpers" ) // QueueConnectionHandler handles new connections in a ConnectionPool. @@ -27,7 +27,7 @@ type QueueConnectionHandler struct { } // QueueConnectionHandler implements the ConnectionHandler interface. -var _ connection_pool.ConnectionHandler = &QueueConnectionHandler{} +var _ pool.ConnectionHandler = &QueueConnectionHandler{} // NewQueueConnectionHandler creates a QueueConnectionHandler object. func NewQueueConnectionHandler(name string, cfg queue.Cfg) *QueueConnectionHandler { @@ -44,7 +44,7 @@ func NewQueueConnectionHandler(name string, cfg queue.Cfg) *QueueConnectionHandl // NOTE: the Queue supports only a master-replica cluster configuration. It // does not support a master-master configuration. func (h *QueueConnectionHandler) Discovered(conn *tarantool.Connection, - role connection_pool.Role) error { + role pool.Role) error { h.mutex.Lock() defer h.mutex.Unlock() @@ -52,7 +52,7 @@ func (h *QueueConnectionHandler) Discovered(conn *tarantool.Connection, return h.err } - master := role == connection_pool.MasterRole + master := role == pool.MasterRole q := queue.New(conn, h.name) @@ -113,8 +113,8 @@ func (h *QueueConnectionHandler) Discovered(conn *tarantool.Connection, // Deactivated doesn't do anything useful for the example. func (h *QueueConnectionHandler) Deactivated(conn *tarantool.Connection, - role connection_pool.Role) error { - if role == connection_pool.MasterRole { + role pool.Role) error { + if role == pool.MasterRole { atomic.AddInt32(&h.masterCnt, -1) } return nil @@ -125,7 +125,7 @@ func (h *QueueConnectionHandler) Close() { close(h.updated) } -// Example demonstrates how to use the queue package with the connection_pool +// Example demonstrates how to use the queue package with the pool // package. First of all, you need to create a ConnectionHandler implementation // for the a ConnectionPool object to process new connections from // RW-instances. @@ -160,11 +160,11 @@ func Example_connectionPool() { User: "test", Pass: "test", } - poolOpts := connection_pool.OptsPool{ + poolOpts := pool.Opts{ CheckTimeout: 5 * time.Second, ConnectionHandler: h, } - connPool, err := connection_pool.ConnectWithOpts(servers, connOpts, poolOpts) + connPool, err := pool.ConnectWithOpts(servers, connOpts, poolOpts) if err != nil { fmt.Printf("Unable to connect to the pool: %s", err) return @@ -182,7 +182,7 @@ func Example_connectionPool() { // Create a Queue object from the ConnectionPool object via // a ConnectorAdapter. - rw := connection_pool.NewConnectorAdapter(connPool, connection_pool.RW) + rw := pool.NewConnectorAdapter(connPool, pool.RW) q := queue.New(rw, "test_queue") fmt.Println("A Queue object is ready to work.") @@ -229,7 +229,7 @@ func Example_connectionPool() { // Take a data from the new master instance. task, err := q.Take() - if err == connection_pool.ErrNoRwInstance { + if err == pool.ErrNoRwInstance { // It may be not registered yet by the pool. continue } else if err != nil { diff --git a/queue/example_msgpack_test.go b/queue/example_msgpack_test.go index 5b179f5c0..ff37c1879 100644 --- a/queue/example_msgpack_test.go +++ b/queue/example_msgpack_test.go @@ -13,15 +13,17 @@ import ( "log" "time" - "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/queue" + "github.com/vmihailenco/msgpack/v5" + + "github.com/tarantool/go-tarantool/v2" + "github.com/tarantool/go-tarantool/v2/queue" ) type dummyData struct { Dummy bool } -func (c *dummyData) DecodeMsgpack(d *decoder) error { +func (c *dummyData) DecodeMsgpack(d *msgpack.Decoder) error { var err error if c.Dummy, err = d.DecodeBool(); err != nil { return err @@ -29,7 +31,7 @@ func (c *dummyData) DecodeMsgpack(d *decoder) error { return nil } -func (c *dummyData) EncodeMsgpack(e *encoder) error { +func (c *dummyData) EncodeMsgpack(e *msgpack.Encoder) error { return e.EncodeBool(c.Dummy) } diff --git a/queue/example_test.go b/queue/example_test.go index d546b43d7..711ee31d4 100644 --- a/queue/example_test.go +++ b/queue/example_test.go @@ -12,8 +12,8 @@ import ( "fmt" "time" - "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/queue" + "github.com/tarantool/go-tarantool/v2" + "github.com/tarantool/go-tarantool/v2/queue" ) // Example demonstrates an operations like Put and Take with queue. diff --git a/queue/msgpack.go b/queue/msgpack.go deleted file mode 100644 index d9e0b58db..000000000 --- a/queue/msgpack.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build !go_tarantool_msgpack_v5 -// +build !go_tarantool_msgpack_v5 - -package queue - -import ( - "gopkg.in/vmihailenco/msgpack.v2" -) - -type decoder = msgpack.Decoder diff --git a/queue/msgpack_helper_test.go b/queue/msgpack_helper_test.go deleted file mode 100644 index 49b61240c..000000000 --- a/queue/msgpack_helper_test.go +++ /dev/null @@ -1,11 +0,0 @@ -//go:build !go_tarantool_msgpack_v5 -// +build !go_tarantool_msgpack_v5 - -package queue_test - -import ( - "gopkg.in/vmihailenco/msgpack.v2" -) - -type encoder = msgpack.Encoder -type decoder = msgpack.Decoder diff --git a/queue/msgpack_v5.go b/queue/msgpack_v5.go deleted file mode 100644 index b5037caaf..000000000 --- a/queue/msgpack_v5.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build go_tarantool_msgpack_v5 -// +build go_tarantool_msgpack_v5 - -package queue - -import ( - "github.com/vmihailenco/msgpack/v5" -) - -type decoder = msgpack.Decoder diff --git a/queue/msgpack_v5_helper_test.go b/queue/msgpack_v5_helper_test.go deleted file mode 100644 index ea2991f34..000000000 --- a/queue/msgpack_v5_helper_test.go +++ /dev/null @@ -1,11 +0,0 @@ -//go:build go_tarantool_msgpack_v5 -// +build go_tarantool_msgpack_v5 - -package queue_test - -import ( - "github.com/vmihailenco/msgpack/v5" -) - -type encoder = msgpack.Encoder -type decoder = msgpack.Decoder diff --git a/queue/queue.go b/queue/queue.go index 8d161b033..2407bad03 100644 --- a/queue/queue.go +++ b/queue/queue.go @@ -13,7 +13,9 @@ import ( "time" "github.com/google/uuid" - "github.com/tarantool/go-tarantool" + "github.com/vmihailenco/msgpack/v5" + + "github.com/tarantool/go-tarantool/v2" ) // Queue is a handle to Tarantool queue's tube. @@ -371,7 +373,7 @@ type kickResult struct { id uint64 } -func (r *kickResult) DecodeMsgpack(d *decoder) (err error) { +func (r *kickResult) DecodeMsgpack(d *msgpack.Decoder) (err error) { var l int if l, err = d.DecodeArrayLen(); err != nil { return err @@ -453,7 +455,7 @@ type queueData struct { result interface{} } -func (qd *queueData) DecodeMsgpack(d *decoder) error { +func (qd *queueData) DecodeMsgpack(d *msgpack.Decoder) error { var err error var l int if l, err = d.DecodeArrayLen(); err != nil { @@ -472,7 +474,7 @@ func (qd *queueData) DecodeMsgpack(d *decoder) error { } if qd.task.Data() == nil { - // It may happen if the decoder has a code.Nil value inside. As a + // It may happen if the msgpack.Decoder has a code.Nil value inside. As a // result, the task will not be decoded. qd.task = nil } diff --git a/queue/queue_test.go b/queue/queue_test.go index ffbf8feb5..313032f49 100644 --- a/queue/queue_test.go +++ b/queue/queue_test.go @@ -8,9 +8,11 @@ import ( "testing" "time" - . "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/queue" - "github.com/tarantool/go-tarantool/test_helpers" + "github.com/vmihailenco/msgpack/v5" + + . "github.com/tarantool/go-tarantool/v2" + "github.com/tarantool/go-tarantool/v2/queue" + "github.com/tarantool/go-tarantool/v2/test_helpers" ) var server = "127.0.0.1:3013" @@ -300,7 +302,7 @@ type customData struct { customField string } -func (c *customData) DecodeMsgpack(d *decoder) error { +func (c *customData) DecodeMsgpack(d *msgpack.Decoder) error { var err error var l int if l, err = d.DecodeArrayLen(); err != nil { @@ -315,7 +317,7 @@ func (c *customData) DecodeMsgpack(d *decoder) error { return nil } -func (c *customData) EncodeMsgpack(e *encoder) error { +func (c *customData) EncodeMsgpack(e *msgpack.Encoder) error { if err := e.EncodeArrayLen(1); err != nil { return err } diff --git a/queue/task.go b/queue/task.go index c1b0aad98..db970884e 100644 --- a/queue/task.go +++ b/queue/task.go @@ -3,6 +3,8 @@ package queue import ( "fmt" "time" + + "github.com/vmihailenco/msgpack/v5" ) // Task represents a task from Tarantool queue's tube. @@ -13,7 +15,7 @@ type Task struct { q *queue } -func (t *Task) DecodeMsgpack(d *decoder) error { +func (t *Task) DecodeMsgpack(d *msgpack.Decoder) error { var err error var l int if l, err = d.DecodeArrayLen(); err != nil { diff --git a/request.go b/request.go index 7c79c5863..adb4a7b31 100644 --- a/request.go +++ b/request.go @@ -7,63 +7,66 @@ import ( "reflect" "strings" "sync" + + "github.com/tarantool/go-iproto" + "github.com/vmihailenco/msgpack/v5" ) -func fillSearch(enc *encoder, spaceNo, indexNo uint32, key interface{}) error { - if err := encodeUint(enc, KeySpaceNo); err != nil { +func fillSearch(enc *msgpack.Encoder, spaceNo, indexNo uint32, key interface{}) error { + if err := enc.EncodeUint(uint64(iproto.IPROTO_SPACE_ID)); err != nil { return err } - if err := encodeUint(enc, uint64(spaceNo)); err != nil { + if err := enc.EncodeUint(uint64(spaceNo)); err != nil { return err } - if err := encodeUint(enc, KeyIndexNo); err != nil { + if err := enc.EncodeUint(uint64(iproto.IPROTO_INDEX_ID)); err != nil { return err } - if err := encodeUint(enc, uint64(indexNo)); err != nil { + if err := enc.EncodeUint(uint64(indexNo)); err != nil { return err } - if err := encodeUint(enc, KeyKey); err != nil { + if err := enc.EncodeUint(uint64(iproto.IPROTO_KEY)); err != nil { return err } return enc.Encode(key) } -func fillIterator(enc *encoder, offset, limit, iterator uint32) error { - if err := encodeUint(enc, KeyIterator); err != nil { +func fillIterator(enc *msgpack.Encoder, offset, limit uint32, iterator Iter) error { + if err := enc.EncodeUint(uint64(iproto.IPROTO_ITERATOR)); err != nil { return err } - if err := encodeUint(enc, uint64(iterator)); err != nil { + if err := enc.EncodeUint(uint64(iterator)); err != nil { return err } - if err := encodeUint(enc, KeyOffset); err != nil { + if err := enc.EncodeUint(uint64(iproto.IPROTO_OFFSET)); err != nil { return err } - if err := encodeUint(enc, uint64(offset)); err != nil { + if err := enc.EncodeUint(uint64(offset)); err != nil { return err } - if err := encodeUint(enc, KeyLimit); err != nil { + if err := enc.EncodeUint(uint64(iproto.IPROTO_LIMIT)); err != nil { return err } - return encodeUint(enc, uint64(limit)) + return enc.EncodeUint(uint64(limit)) } -func fillInsert(enc *encoder, spaceNo uint32, tuple interface{}) error { +func fillInsert(enc *msgpack.Encoder, spaceNo uint32, tuple interface{}) error { if err := enc.EncodeMapLen(2); err != nil { return err } - if err := encodeUint(enc, KeySpaceNo); err != nil { + if err := enc.EncodeUint(uint64(iproto.IPROTO_SPACE_ID)); err != nil { return err } - if err := encodeUint(enc, uint64(spaceNo)); err != nil { + if err := enc.EncodeUint(uint64(spaceNo)); err != nil { return err } - if err := encodeUint(enc, KeyTuple); err != nil { + if err := enc.EncodeUint(uint64(iproto.IPROTO_TUPLE)); err != nil { return err } return enc.Encode(tuple) } -func fillSelect(enc *encoder, spaceNo, indexNo, offset, limit, iterator uint32, +func fillSelect(enc *msgpack.Encoder, spaceNo, indexNo, offset, limit uint32, iterator Iter, key, after interface{}, fetchPos bool) error { mapLen := 6 if fetchPos { @@ -82,7 +85,7 @@ func fillSelect(enc *encoder, spaceNo, indexNo, offset, limit, iterator uint32, return err } if fetchPos { - if err := encodeUint(enc, KeyFetchPos); err != nil { + if err := enc.EncodeUint(uint64(iproto.IPROTO_FETCH_POSITION)); err != nil { return err } if err := enc.EncodeBool(fetchPos); err != nil { @@ -91,14 +94,14 @@ func fillSelect(enc *encoder, spaceNo, indexNo, offset, limit, iterator uint32, } if after != nil { if pos, ok := after.([]byte); ok { - if err := encodeUint(enc, KeyAfterPos); err != nil { + if err := enc.EncodeUint(uint64(iproto.IPROTO_AFTER_POSITION)); err != nil { return err } if err := enc.EncodeString(string(pos)); err != nil { return err } } else { - if err := encodeUint(enc, KeyAfterTuple); err != nil { + if err := enc.EncodeUint(uint64(iproto.IPROTO_AFTER_TUPLE)); err != nil { return err } if err := enc.Encode(after); err != nil { @@ -109,57 +112,57 @@ func fillSelect(enc *encoder, spaceNo, indexNo, offset, limit, iterator uint32, return nil } -func fillUpdate(enc *encoder, spaceNo, indexNo uint32, key, ops interface{}) error { +func fillUpdate(enc *msgpack.Encoder, spaceNo, indexNo uint32, key, ops interface{}) error { enc.EncodeMapLen(4) if err := fillSearch(enc, spaceNo, indexNo, key); err != nil { return err } - encodeUint(enc, KeyTuple) + enc.EncodeUint(uint64(iproto.IPROTO_TUPLE)) return enc.Encode(ops) } -func fillUpsert(enc *encoder, spaceNo uint32, tuple, ops interface{}) error { +func fillUpsert(enc *msgpack.Encoder, spaceNo uint32, tuple, ops interface{}) error { enc.EncodeMapLen(3) - encodeUint(enc, KeySpaceNo) - encodeUint(enc, uint64(spaceNo)) - encodeUint(enc, KeyTuple) + enc.EncodeUint(uint64(iproto.IPROTO_SPACE_ID)) + enc.EncodeUint(uint64(spaceNo)) + enc.EncodeUint(uint64(iproto.IPROTO_TUPLE)) if err := enc.Encode(tuple); err != nil { return err } - encodeUint(enc, KeyDefTuple) + enc.EncodeUint(uint64(iproto.IPROTO_OPS)) return enc.Encode(ops) } -func fillDelete(enc *encoder, spaceNo, indexNo uint32, key interface{}) error { +func fillDelete(enc *msgpack.Encoder, spaceNo, indexNo uint32, key interface{}) error { enc.EncodeMapLen(3) return fillSearch(enc, spaceNo, indexNo, key) } -func fillCall(enc *encoder, functionName string, args interface{}) error { +func fillCall(enc *msgpack.Encoder, functionName string, args interface{}) error { enc.EncodeMapLen(2) - encodeUint(enc, KeyFunctionName) + enc.EncodeUint(uint64(iproto.IPROTO_FUNCTION_NAME)) enc.EncodeString(functionName) - encodeUint(enc, KeyTuple) + enc.EncodeUint(uint64(iproto.IPROTO_TUPLE)) return enc.Encode(args) } -func fillEval(enc *encoder, expr string, args interface{}) error { +func fillEval(enc *msgpack.Encoder, expr string, args interface{}) error { enc.EncodeMapLen(2) - encodeUint(enc, KeyExpression) + enc.EncodeUint(uint64(iproto.IPROTO_EXPR)) enc.EncodeString(expr) - encodeUint(enc, KeyTuple) + enc.EncodeUint(uint64(iproto.IPROTO_TUPLE)) return enc.Encode(args) } -func fillExecute(enc *encoder, expr string, args interface{}) error { +func fillExecute(enc *msgpack.Encoder, expr string, args interface{}) error { enc.EncodeMapLen(2) - encodeUint(enc, KeySQLText) + enc.EncodeUint(uint64(iproto.IPROTO_SQL_TEXT)) enc.EncodeString(expr) - encodeUint(enc, KeySQLBind) + enc.EncodeUint(uint64(iproto.IPROTO_SQL_BIND)) return encodeSQLBind(enc, args) } -func fillPing(enc *encoder) error { +func fillPing(enc *msgpack.Encoder) error { return enc.EncodeMapLen(0) } @@ -171,7 +174,7 @@ func (conn *Connection) Ping() (resp *Response, err error) { // Select performs select to box space. // // It is equal to conn.SelectAsync(...).Get(). -func (conn *Connection) Select(space, index interface{}, offset, limit, iterator uint32, key interface{}) (resp *Response, err error) { +func (conn *Connection) Select(space, index interface{}, offset, limit uint32, iterator Iter, key interface{}) (resp *Response, err error) { return conn.SelectAsync(space, index, offset, limit, iterator, key).Get() } @@ -216,9 +219,7 @@ func (conn *Connection) Upsert(space interface{}, tuple, ops interface{}) (resp } // Call calls registered Tarantool function. -// It uses request code for Tarantool >= 1.7 if go-tarantool -// was build with go_tarantool_call_17 tag. -// Otherwise, uses request code for Tarantool 1.6. +// It uses request code for Tarantool >= 1.7, result is an array. // // It is equal to conn.CallAsync(functionName, args).Get(). func (conn *Connection) Call(functionName string, args interface{}) (resp *Response, err error) { @@ -226,7 +227,7 @@ func (conn *Connection) Call(functionName string, args interface{}) (resp *Respo } // Call16 calls registered Tarantool function. -// It uses request code for Tarantool 1.6, so result is converted to array of arrays +// It uses request code for Tarantool 1.6, result is an array of arrays. // Deprecated since Tarantool 1.7.2. // // It is equal to conn.Call16Async(functionName, args).Get(). @@ -235,8 +236,7 @@ func (conn *Connection) Call16(functionName string, args interface{}) (resp *Res } // Call17 calls registered Tarantool function. -// It uses request code for Tarantool >= 1.7, so result is not converted -// (though, keep in mind, result is always array) +// It uses request code for Tarantool >= 1.7, result is an array. // // It is equal to conn.Call17Async(functionName, args).Get(). func (conn *Connection) Call17(functionName string, args interface{}) (resp *Response, err error) { @@ -264,7 +264,7 @@ type single struct { found bool } -func (s *single) DecodeMsgpack(d *decoder) error { +func (s *single) DecodeMsgpack(d *msgpack.Decoder) error { var err error var len int if len, err = d.DecodeArrayLen(); err != nil { @@ -292,7 +292,7 @@ func (conn *Connection) GetTyped(space, index interface{}, key interface{}, resu // SelectTyped performs select to box space and fills typed result. // // It is equal to conn.SelectAsync(space, index, offset, limit, iterator, key).GetTyped(&result) -func (conn *Connection) SelectTyped(space, index interface{}, offset, limit, iterator uint32, key interface{}, result interface{}) (err error) { +func (conn *Connection) SelectTyped(space, index interface{}, offset, limit uint32, iterator Iter, key interface{}, result interface{}) (err error) { return conn.SelectAsync(space, index, offset, limit, iterator, key).GetTyped(result) } @@ -327,9 +327,7 @@ func (conn *Connection) UpdateTyped(space, index interface{}, key, ops interface } // CallTyped calls registered function. -// It uses request code for Tarantool >= 1.7 if go-tarantool -// was build with go_tarantool_call_17 tag. -// Otherwise, uses request code for Tarantool 1.6. +// It uses request code for Tarantool >= 1.7, result is an array. // // It is equal to conn.Call16Async(functionName, args).GetTyped(&result). func (conn *Connection) CallTyped(functionName string, args interface{}, result interface{}) (err error) { @@ -337,7 +335,7 @@ func (conn *Connection) CallTyped(functionName string, args interface{}, result } // Call16Typed calls registered function. -// It uses request code for Tarantool 1.6, so result is converted to array of arrays +// It uses request code for Tarantool 1.6, result is an array of arrays. // Deprecated since Tarantool 1.7.2. // // It is equal to conn.Call16Async(functionName, args).GetTyped(&result). @@ -346,8 +344,7 @@ func (conn *Connection) Call16Typed(functionName string, args interface{}, resul } // Call17Typed calls registered function. -// It uses request code for Tarantool >= 1.7, so result is not converted -// (though, keep in mind, result is always array) +// It uses request code for Tarantool >= 1.7, result is an array. // // It is equal to conn.Call17Async(functionName, args).GetTyped(&result). func (conn *Connection) Call17Typed(functionName string, args interface{}, result interface{}) (err error) { @@ -372,7 +369,7 @@ func (conn *Connection) ExecuteTyped(expr string, args interface{}, result inter } // SelectAsync sends select request to Tarantool and returns Future. -func (conn *Connection) SelectAsync(space, index interface{}, offset, limit, iterator uint32, key interface{}) *Future { +func (conn *Connection) SelectAsync(space, index interface{}, offset, limit uint32, iterator Iter, key interface{}) *Future { req := NewSelectRequest(space). Index(index). Offset(offset). @@ -420,16 +417,14 @@ func (conn *Connection) UpsertAsync(space interface{}, tuple interface{}, ops in } // CallAsync sends a call to registered Tarantool function and returns Future. -// It uses request code for Tarantool >= 1.7 if go-tarantool -// was build with go_tarantool_call_17 tag. -// Otherwise, uses request code for Tarantool 1.6. +// It uses request code for Tarantool >= 1.7, so future's result is an array. func (conn *Connection) CallAsync(functionName string, args interface{}) *Future { req := NewCallRequest(functionName).Args(args) return conn.Do(req) } // Call16Async sends a call to registered Tarantool function and returns Future. -// It uses request code for Tarantool 1.6, so future's result is always array of arrays. +// It uses request code for Tarantool 1.6, so future's result is an array of arrays. // Deprecated since Tarantool 1.7.2. func (conn *Connection) Call16Async(functionName string, args interface{}) *Future { req := NewCall16Request(functionName).Args(args) @@ -437,8 +432,7 @@ func (conn *Connection) Call16Async(functionName string, args interface{}) *Futu } // Call17Async sends a call to registered Tarantool function and returns Future. -// It uses request code for Tarantool >= 1.7, so future's result will not be converted -// (though, keep in mind, result is always array) +// It uses request code for Tarantool >= 1.7, so future's result is an array. func (conn *Connection) Call17Async(functionName string, args interface{}) *Future { req := NewCall17Request(functionName).Args(args) return conn.Do(req) @@ -471,7 +465,7 @@ type KeyValueBind struct { // to avoid extra allocations in heap by calling strings.ToLower() var lowerCaseNames sync.Map -func encodeSQLBind(enc *encoder, from interface{}) error { +func encodeSQLBind(enc *msgpack.Encoder, from interface{}) error { // internal function for encoding single map in msgpack encodeKeyInterface := func(key string, val interface{}) error { if err := enc.EncodeMapLen(1); err != nil { @@ -601,10 +595,10 @@ func encodeSQLBind(enc *encoder, from interface{}) error { // Request is an interface that provides the necessary data to create a request // that will be sent to a tarantool instance. type Request interface { - // Code returns a IPROTO code for the request. - Code() int32 - // Body fills an encoder with a request body. - Body(resolver SchemaResolver, enc *encoder) error + // Type returns a IPROTO type of the request. + Type() iproto.Type + // Body fills an msgpack.Encoder with a request body. + Body(resolver SchemaResolver, enc *msgpack.Encoder) error // Ctx returns a context of the request. Ctx() context.Context // Async returns true if the request does not expect response. @@ -620,14 +614,14 @@ type ConnectedRequest interface { } type baseRequest struct { - requestCode int32 - async bool - ctx context.Context + rtype iproto.Type + async bool + ctx context.Context } -// Code returns a IPROTO code for the request. -func (req *baseRequest) Code() int32 { - return req.requestCode +// Type returns a IPROTO type for the request. +func (req *baseRequest) Type() iproto.Type { + return req.rtype } // Async returns true if the request does not require a response. @@ -689,9 +683,9 @@ func newPapSha256AuthRequest(user, password string) authRequest { } } -// Code returns a IPROTO code for the request. -func (req authRequest) Code() int32 { - return AuthRequestCode +// Type returns a IPROTO type for the request. +func (req authRequest) Type() iproto.Type { + return iproto.IPROTO_AUTH } // Async returns true if the request does not require a response. @@ -705,10 +699,10 @@ func (req authRequest) Ctx() context.Context { } // Body fills an encoder with the auth request body. -func (req authRequest) Body(res SchemaResolver, enc *encoder) error { +func (req authRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error { return enc.Encode(map[uint32]interface{}{ - KeyUserName: req.user, - KeyTuple: []interface{}{req.auth.String(), req.pass}, + uint32(iproto.IPROTO_USER_NAME): req.user, + uint32(iproto.IPROTO_TUPLE): []interface{}{req.auth.String(), req.pass}, }) } @@ -721,12 +715,12 @@ type PingRequest struct { // NewPingRequest returns a new PingRequest. func NewPingRequest() *PingRequest { req := new(PingRequest) - req.requestCode = PingRequestCode + req.rtype = iproto.IPROTO_PING return req } -// Body fills an encoder with the ping request body. -func (req *PingRequest) Body(res SchemaResolver, enc *encoder) error { +// Body fills an msgpack.Encoder with the ping request body. +func (req *PingRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error { return fillPing(enc) } @@ -746,14 +740,15 @@ func (req *PingRequest) Context(ctx context.Context) *PingRequest { type SelectRequest struct { spaceIndexRequest isIteratorSet, fetchPos bool - offset, limit, iterator uint32 + offset, limit uint32 + iterator Iter key, after interface{} } // NewSelectRequest returns a new empty SelectRequest. func NewSelectRequest(space interface{}) *SelectRequest { req := new(SelectRequest) - req.requestCode = SelectRequestCode + req.rtype = iproto.IPROTO_SELECT req.setSpace(space) req.isIteratorSet = false req.fetchPos = false @@ -787,7 +782,7 @@ func (req *SelectRequest) Limit(limit uint32) *SelectRequest { // Iterator set the iterator for the select request. // Note: default value is IterAll if key is not set or IterEq otherwise. -func (req *SelectRequest) Iterator(iterator uint32) *SelectRequest { +func (req *SelectRequest) Iterator(iterator Iter) *SelectRequest { req.iterator = iterator req.isIteratorSet = true return req @@ -828,7 +823,7 @@ func (req *SelectRequest) After(after interface{}) *SelectRequest { } // Body fills an encoder with the select request body. -func (req *SelectRequest) Body(res SchemaResolver, enc *encoder) error { +func (req *SelectRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error { spaceNo, indexNo, err := res.ResolveSpaceIndex(req.space, req.index) if err != nil { return err @@ -859,7 +854,7 @@ type InsertRequest struct { // NewInsertRequest returns a new empty InsertRequest. func NewInsertRequest(space interface{}) *InsertRequest { req := new(InsertRequest) - req.requestCode = InsertRequestCode + req.rtype = iproto.IPROTO_INSERT req.setSpace(space) req.tuple = []interface{}{} return req @@ -872,8 +867,8 @@ func (req *InsertRequest) Tuple(tuple interface{}) *InsertRequest { return req } -// Body fills an encoder with the insert request body. -func (req *InsertRequest) Body(res SchemaResolver, enc *encoder) error { +// Body fills an msgpack.Encoder with the insert request body. +func (req *InsertRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error { spaceNo, _, err := res.ResolveSpaceIndex(req.space, nil) if err != nil { return err @@ -903,7 +898,7 @@ type ReplaceRequest struct { // NewReplaceRequest returns a new empty ReplaceRequest. func NewReplaceRequest(space interface{}) *ReplaceRequest { req := new(ReplaceRequest) - req.requestCode = ReplaceRequestCode + req.rtype = iproto.IPROTO_REPLACE req.setSpace(space) req.tuple = []interface{}{} return req @@ -916,8 +911,8 @@ func (req *ReplaceRequest) Tuple(tuple interface{}) *ReplaceRequest { return req } -// Body fills an encoder with the replace request body. -func (req *ReplaceRequest) Body(res SchemaResolver, enc *encoder) error { +// Body fills an msgpack.Encoder with the replace request body. +func (req *ReplaceRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error { spaceNo, _, err := res.ResolveSpaceIndex(req.space, nil) if err != nil { return err @@ -947,7 +942,7 @@ type DeleteRequest struct { // NewDeleteRequest returns a new empty DeleteRequest. func NewDeleteRequest(space interface{}) *DeleteRequest { req := new(DeleteRequest) - req.requestCode = DeleteRequestCode + req.rtype = iproto.IPROTO_DELETE req.setSpace(space) req.key = []interface{}{} return req @@ -967,8 +962,8 @@ func (req *DeleteRequest) Key(key interface{}) *DeleteRequest { return req } -// Body fills an encoder with the delete request body. -func (req *DeleteRequest) Body(res SchemaResolver, enc *encoder) error { +// Body fills an msgpack.Encoder with the delete request body. +func (req *DeleteRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error { spaceNo, indexNo, err := res.ResolveSpaceIndex(req.space, req.index) if err != nil { return err @@ -999,7 +994,7 @@ type UpdateRequest struct { // NewUpdateRequest returns a new empty UpdateRequest. func NewUpdateRequest(space interface{}) *UpdateRequest { req := new(UpdateRequest) - req.requestCode = UpdateRequestCode + req.rtype = iproto.IPROTO_UPDATE req.setSpace(space) req.key = []interface{}{} req.ops = []interface{}{} @@ -1029,8 +1024,8 @@ func (req *UpdateRequest) Operations(ops *Operations) *UpdateRequest { return req } -// Body fills an encoder with the update request body. -func (req *UpdateRequest) Body(res SchemaResolver, enc *encoder) error { +// Body fills an msgpack.Encoder with the update request body. +func (req *UpdateRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error { spaceNo, indexNo, err := res.ResolveSpaceIndex(req.space, req.index) if err != nil { return err @@ -1061,7 +1056,7 @@ type UpsertRequest struct { // NewUpsertRequest returns a new empty UpsertRequest. func NewUpsertRequest(space interface{}) *UpsertRequest { req := new(UpsertRequest) - req.requestCode = UpsertRequestCode + req.rtype = iproto.IPROTO_UPSERT req.setSpace(space) req.tuple = []interface{}{} req.ops = []interface{}{} @@ -1084,8 +1079,8 @@ func (req *UpsertRequest) Operations(ops *Operations) *UpsertRequest { return req } -// Body fills an encoder with the upsert request body. -func (req *UpsertRequest) Body(res SchemaResolver, enc *encoder) error { +// Body fills an msgpack.Encoder with the upsert request body. +func (req *UpsertRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error { spaceNo, _, err := res.ResolveSpaceIndex(req.space, nil) if err != nil { return err @@ -1113,12 +1108,11 @@ type CallRequest struct { args interface{} } -// NewCallRequest return a new empty CallRequest. It uses request code for -// Tarantool >= 1.7 if go-tarantool was build with go_tarantool_call_17 tag. -// Otherwise, uses request code for Tarantool 1.6. +// NewCallRequest returns a new empty CallRequest. It uses request code for +// Tarantool >= 1.7. func NewCallRequest(function string) *CallRequest { req := new(CallRequest) - req.requestCode = CallRequestCode + req.rtype = iproto.IPROTO_CALL req.function = function return req } @@ -1131,7 +1125,7 @@ func (req *CallRequest) Args(args interface{}) *CallRequest { } // Body fills an encoder with the call request body. -func (req *CallRequest) Body(res SchemaResolver, enc *encoder) error { +func (req *CallRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error { args := req.args if args == nil { args = []interface{}{} @@ -1155,7 +1149,7 @@ func (req *CallRequest) Context(ctx context.Context) *CallRequest { // Deprecated since Tarantool 1.7.2. func NewCall16Request(function string) *CallRequest { req := NewCallRequest(function) - req.requestCode = Call16RequestCode + req.rtype = iproto.IPROTO_CALL_16 return req } @@ -1163,7 +1157,7 @@ func NewCall16Request(function string) *CallRequest { // Tarantool >= 1.7. func NewCall17Request(function string) *CallRequest { req := NewCallRequest(function) - req.requestCode = Call17RequestCode + req.rtype = iproto.IPROTO_CALL return req } @@ -1178,7 +1172,7 @@ type EvalRequest struct { // NewEvalRequest returns a new empty EvalRequest. func NewEvalRequest(expr string) *EvalRequest { req := new(EvalRequest) - req.requestCode = EvalRequestCode + req.rtype = iproto.IPROTO_EVAL req.expr = expr req.args = []interface{}{} return req @@ -1191,8 +1185,8 @@ func (req *EvalRequest) Args(args interface{}) *EvalRequest { return req } -// Body fills an encoder with the eval request body. -func (req *EvalRequest) Body(res SchemaResolver, enc *encoder) error { +// Body fills an msgpack.Encoder with the eval request body. +func (req *EvalRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error { return fillEval(enc, req.expr, req.args) } @@ -1218,7 +1212,7 @@ type ExecuteRequest struct { // NewExecuteRequest returns a new empty ExecuteRequest. func NewExecuteRequest(expr string) *ExecuteRequest { req := new(ExecuteRequest) - req.requestCode = ExecuteRequestCode + req.rtype = iproto.IPROTO_EXECUTE req.expr = expr req.args = []interface{}{} return req @@ -1231,8 +1225,8 @@ func (req *ExecuteRequest) Args(args interface{}) *ExecuteRequest { return req } -// Body fills an encoder with the execute request body. -func (req *ExecuteRequest) Body(res SchemaResolver, enc *encoder) error { +// Body fills an msgpack.Encoder with the execute request body. +func (req *ExecuteRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error { return fillExecute(enc, req.expr, req.args) } diff --git a/request_test.go b/request_test.go index 8429fef98..a7e70ec65 100644 --- a/request_test.go +++ b/request_test.go @@ -8,9 +8,10 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/tarantool/go-iproto" + "github.com/vmihailenco/msgpack/v5" - . "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/test_helpers" + . "github.com/tarantool/go-tarantool/v2" ) const invalidSpaceMsg = "invalid space" @@ -68,7 +69,7 @@ func assertBodyCall(t testing.TB, requests []Request, errorMsg string) { const errBegin = "An unexpected Request.Body() " for _, req := range requests { var reqBuf bytes.Buffer - enc := NewEncoder(&reqBuf) + enc := msgpack.NewEncoder(&reqBuf) err := req.Body(&resolver, enc) if err != nil && errorMsg != "" && err.Error() != errorMsg { @@ -86,11 +87,15 @@ func assertBodyCall(t testing.TB, requests []Request, errorMsg string) { func assertBodyEqual(t testing.TB, reference []byte, req Request) { t.Helper() - reqBody, err := test_helpers.ExtractRequestBody(req, &resolver, NewEncoder) + var reqBuf bytes.Buffer + reqEnc := msgpack.NewEncoder(&reqBuf) + + err := req.Body(&resolver, reqEnc) if err != nil { t.Fatalf("An unexpected Response.Body() error: %q", err.Error()) } + reqBody := reqBuf.Bytes() if !bytes.Equal(reqBody, reference) { t.Errorf("Encoded request %v != reference %v", reqBody, reference) } @@ -165,35 +170,37 @@ func TestRequestsInvalidIndex(t *testing.T) { assertBodyCall(t, requests, invalidIndexMsg) } -func TestRequestsCodes(t *testing.T) { +func TestRequestsTypes(t *testing.T) { tests := []struct { - req Request - code int32 + req Request + rtype iproto.Type }{ - {req: NewSelectRequest(validSpace), code: SelectRequestCode}, - {req: NewUpdateRequest(validSpace), code: UpdateRequestCode}, - {req: NewUpsertRequest(validSpace), code: UpsertRequestCode}, - {req: NewInsertRequest(validSpace), code: InsertRequestCode}, - {req: NewReplaceRequest(validSpace), code: ReplaceRequestCode}, - {req: NewDeleteRequest(validSpace), code: DeleteRequestCode}, - {req: NewCall16Request(validExpr), code: Call16RequestCode}, - {req: NewCall17Request(validExpr), code: Call17RequestCode}, - {req: NewEvalRequest(validExpr), code: EvalRequestCode}, - {req: NewExecuteRequest(validExpr), code: ExecuteRequestCode}, - {req: NewPingRequest(), code: PingRequestCode}, - {req: NewPrepareRequest(validExpr), code: PrepareRequestCode}, - {req: NewUnprepareRequest(validStmt), code: PrepareRequestCode}, - {req: NewExecutePreparedRequest(validStmt), code: ExecuteRequestCode}, - {req: NewBeginRequest(), code: BeginRequestCode}, - {req: NewCommitRequest(), code: CommitRequestCode}, - {req: NewRollbackRequest(), code: RollbackRequestCode}, - {req: NewIdRequest(validProtocolInfo), code: IdRequestCode}, - {req: NewBroadcastRequest(validKey), code: CallRequestCode}, + {req: NewSelectRequest(validSpace), rtype: iproto.IPROTO_SELECT}, + {req: NewUpdateRequest(validSpace), rtype: iproto.IPROTO_UPDATE}, + {req: NewUpsertRequest(validSpace), rtype: iproto.IPROTO_UPSERT}, + {req: NewInsertRequest(validSpace), rtype: iproto.IPROTO_INSERT}, + {req: NewReplaceRequest(validSpace), rtype: iproto.IPROTO_REPLACE}, + {req: NewDeleteRequest(validSpace), rtype: iproto.IPROTO_DELETE}, + {req: NewCallRequest(validExpr), rtype: iproto.IPROTO_CALL}, + {req: NewCall16Request(validExpr), rtype: iproto.IPROTO_CALL_16}, + {req: NewCall17Request(validExpr), rtype: iproto.IPROTO_CALL}, + {req: NewEvalRequest(validExpr), rtype: iproto.IPROTO_EVAL}, + {req: NewExecuteRequest(validExpr), rtype: iproto.IPROTO_EXECUTE}, + {req: NewPingRequest(), rtype: iproto.IPROTO_PING}, + {req: NewPrepareRequest(validExpr), rtype: iproto.IPROTO_PREPARE}, + {req: NewUnprepareRequest(validStmt), rtype: iproto.IPROTO_PREPARE}, + {req: NewExecutePreparedRequest(validStmt), rtype: iproto.IPROTO_EXECUTE}, + {req: NewBeginRequest(), rtype: iproto.IPROTO_BEGIN}, + {req: NewCommitRequest(), rtype: iproto.IPROTO_COMMIT}, + {req: NewRollbackRequest(), rtype: iproto.IPROTO_ROLLBACK}, + {req: NewIdRequest(validProtocolInfo), rtype: iproto.IPROTO_ID}, + {req: NewBroadcastRequest(validKey), rtype: iproto.IPROTO_CALL}, } for _, test := range tests { - if code := test.req.Code(); code != test.code { - t.Errorf("An invalid request code 0x%x, expected 0x%x", code, test.code) + if rtype := test.req.Type(); rtype != test.rtype { + t.Errorf("An invalid request type 0x%x, expected 0x%x", + rtype, test.rtype) } } } @@ -209,6 +216,7 @@ func TestRequestsAsync(t *testing.T) { {req: NewInsertRequest(validSpace), async: false}, {req: NewReplaceRequest(validSpace), async: false}, {req: NewDeleteRequest(validSpace), async: false}, + {req: NewCallRequest(validExpr), async: false}, {req: NewCall16Request(validExpr), async: false}, {req: NewCall17Request(validExpr), async: false}, {req: NewEvalRequest(validExpr), async: false}, @@ -242,6 +250,7 @@ func TestRequestsCtx_default(t *testing.T) { {req: NewInsertRequest(validSpace), expected: nil}, {req: NewReplaceRequest(validSpace), expected: nil}, {req: NewDeleteRequest(validSpace), expected: nil}, + {req: NewCallRequest(validExpr), expected: nil}, {req: NewCall16Request(validExpr), expected: nil}, {req: NewCall17Request(validExpr), expected: nil}, {req: NewEvalRequest(validExpr), expected: nil}, @@ -276,6 +285,7 @@ func TestRequestsCtx_setter(t *testing.T) { {req: NewInsertRequest(validSpace).Context(ctx), expected: ctx}, {req: NewReplaceRequest(validSpace).Context(ctx), expected: ctx}, {req: NewDeleteRequest(validSpace).Context(ctx), expected: ctx}, + {req: NewCallRequest(validExpr).Context(ctx), expected: ctx}, {req: NewCall16Request(validExpr).Context(ctx), expected: ctx}, {req: NewCall17Request(validExpr).Context(ctx), expected: ctx}, {req: NewEvalRequest(validExpr).Context(ctx), expected: ctx}, @@ -301,7 +311,7 @@ func TestRequestsCtx_setter(t *testing.T) { func TestPingRequestDefaultValues(t *testing.T) { var refBuf bytes.Buffer - refEnc := NewEncoder(&refBuf) + refEnc := msgpack.NewEncoder(&refBuf) err := RefImplPingBody(refEnc) if err != nil { t.Errorf("An unexpected RefImplPingBody() error: %q", err.Error()) @@ -315,7 +325,7 @@ func TestPingRequestDefaultValues(t *testing.T) { func TestSelectRequestDefaultValues(t *testing.T) { var refBuf bytes.Buffer - refEnc := NewEncoder(&refBuf) + refEnc := msgpack.NewEncoder(&refBuf) err := RefImplSelectBody(refEnc, validSpace, defaultIndex, 0, 0xFFFFFFFF, IterAll, []interface{}{}, nil, false) if err != nil { @@ -331,7 +341,7 @@ func TestSelectRequestDefaultIteratorEqIfKey(t *testing.T) { var refBuf bytes.Buffer key := []interface{}{uint(18)} - refEnc := NewEncoder(&refBuf) + refEnc := msgpack.NewEncoder(&refBuf) err := RefImplSelectBody(refEnc, validSpace, defaultIndex, 0, 0xFFFFFFFF, IterEq, key, nil, false) if err != nil { @@ -349,7 +359,7 @@ func TestSelectRequestIteratorNotChangedIfKey(t *testing.T) { key := []interface{}{uint(678)} const iter = IterGe - refEnc := NewEncoder(&refBuf) + refEnc := msgpack.NewEncoder(&refBuf) err := RefImplSelectBody(refEnc, validSpace, defaultIndex, 0, 0xFFFFFFFF, iter, key, nil, false) if err != nil { @@ -372,7 +382,7 @@ func TestSelectRequestSetters(t *testing.T) { afterKey := []interface{}{uint(13)} var refBufAfterBytes, refBufAfterKey bytes.Buffer - refEncAfterBytes := NewEncoder(&refBufAfterBytes) + refEncAfterBytes := msgpack.NewEncoder(&refBufAfterBytes) err := RefImplSelectBody(refEncAfterBytes, validSpace, validIndex, offset, limit, iter, key, afterBytes, true) if err != nil { @@ -380,7 +390,7 @@ func TestSelectRequestSetters(t *testing.T) { return } - refEncAfterKey := NewEncoder(&refBufAfterKey) + refEncAfterKey := msgpack.NewEncoder(&refBufAfterKey) err = RefImplSelectBody(refEncAfterKey, validSpace, validIndex, offset, limit, iter, key, afterKey, true) if err != nil { @@ -412,7 +422,7 @@ func TestSelectRequestSetters(t *testing.T) { func TestInsertRequestDefaultValues(t *testing.T) { var refBuf bytes.Buffer - refEnc := NewEncoder(&refBuf) + refEnc := msgpack.NewEncoder(&refBuf) err := RefImplInsertBody(refEnc, validSpace, []interface{}{}) if err != nil { t.Errorf("An unexpected RefImplInsertBody() error: %q", err.Error()) @@ -427,7 +437,7 @@ func TestInsertRequestSetters(t *testing.T) { tuple := []interface{}{uint(24)} var refBuf bytes.Buffer - refEnc := NewEncoder(&refBuf) + refEnc := msgpack.NewEncoder(&refBuf) err := RefImplInsertBody(refEnc, validSpace, tuple) if err != nil { t.Errorf("An unexpected RefImplInsertBody() error: %q", err.Error()) @@ -442,7 +452,7 @@ func TestInsertRequestSetters(t *testing.T) { func TestReplaceRequestDefaultValues(t *testing.T) { var refBuf bytes.Buffer - refEnc := NewEncoder(&refBuf) + refEnc := msgpack.NewEncoder(&refBuf) err := RefImplReplaceBody(refEnc, validSpace, []interface{}{}) if err != nil { t.Errorf("An unexpected RefImplReplaceBody() error: %q", err.Error()) @@ -457,7 +467,7 @@ func TestReplaceRequestSetters(t *testing.T) { tuple := []interface{}{uint(99)} var refBuf bytes.Buffer - refEnc := NewEncoder(&refBuf) + refEnc := msgpack.NewEncoder(&refBuf) err := RefImplReplaceBody(refEnc, validSpace, tuple) if err != nil { t.Errorf("An unexpected RefImplReplaceBody() error: %q", err.Error()) @@ -472,7 +482,7 @@ func TestReplaceRequestSetters(t *testing.T) { func TestDeleteRequestDefaultValues(t *testing.T) { var refBuf bytes.Buffer - refEnc := NewEncoder(&refBuf) + refEnc := msgpack.NewEncoder(&refBuf) err := RefImplDeleteBody(refEnc, validSpace, defaultIndex, []interface{}{}) if err != nil { t.Errorf("An unexpected RefImplDeleteBody() error: %q", err.Error()) @@ -487,7 +497,7 @@ func TestDeleteRequestSetters(t *testing.T) { key := []interface{}{uint(923)} var refBuf bytes.Buffer - refEnc := NewEncoder(&refBuf) + refEnc := msgpack.NewEncoder(&refBuf) err := RefImplDeleteBody(refEnc, validSpace, validIndex, key) if err != nil { t.Errorf("An unexpected RefImplDeleteBody() error: %q", err.Error()) @@ -503,7 +513,7 @@ func TestDeleteRequestSetters(t *testing.T) { func TestUpdateRequestDefaultValues(t *testing.T) { var refBuf bytes.Buffer - refEnc := NewEncoder(&refBuf) + refEnc := msgpack.NewEncoder(&refBuf) err := RefImplUpdateBody(refEnc, validSpace, defaultIndex, []interface{}{}, []Op{}) if err != nil { t.Errorf("An unexpected RefImplUpdateBody() error: %q", err.Error()) @@ -519,7 +529,7 @@ func TestUpdateRequestSetters(t *testing.T) { refOps, reqOps := getTestOps() var refBuf bytes.Buffer - refEnc := NewEncoder(&refBuf) + refEnc := msgpack.NewEncoder(&refBuf) err := RefImplUpdateBody(refEnc, validSpace, validIndex, key, refOps) if err != nil { t.Errorf("An unexpected RefImplUpdateBody() error: %q", err.Error()) @@ -536,7 +546,7 @@ func TestUpdateRequestSetters(t *testing.T) { func TestUpsertRequestDefaultValues(t *testing.T) { var refBuf bytes.Buffer - refEnc := NewEncoder(&refBuf) + refEnc := msgpack.NewEncoder(&refBuf) err := RefImplUpsertBody(refEnc, validSpace, []interface{}{}, []Op{}) if err != nil { t.Errorf("An unexpected RefImplUpsertBody() error: %q", err.Error()) @@ -552,7 +562,7 @@ func TestUpsertRequestSetters(t *testing.T) { refOps, reqOps := getTestOps() var refBuf bytes.Buffer - refEnc := NewEncoder(&refBuf) + refEnc := msgpack.NewEncoder(&refBuf) err := RefImplUpsertBody(refEnc, validSpace, tuple, refOps) if err != nil { t.Errorf("An unexpected RefImplUpsertBody() error: %q", err.Error()) @@ -568,7 +578,7 @@ func TestUpsertRequestSetters(t *testing.T) { func TestCallRequestsDefaultValues(t *testing.T) { var refBuf bytes.Buffer - refEnc := NewEncoder(&refBuf) + refEnc := msgpack.NewEncoder(&refBuf) err := RefImplCallBody(refEnc, validExpr, []interface{}{}) if err != nil { t.Errorf("An unexpected RefImplCallBody() error: %q", err.Error()) @@ -587,14 +597,14 @@ func TestCallRequestsSetters(t *testing.T) { args := []interface{}{uint(34)} var refBuf bytes.Buffer - refEnc := NewEncoder(&refBuf) + refEnc := msgpack.NewEncoder(&refBuf) err := RefImplCallBody(refEnc, validExpr, args) if err != nil { t.Errorf("An unexpected RefImplCallBody() error: %q", err.Error()) return } - req := NewCall16Request(validExpr). + req := NewCallRequest(validExpr). Args(args) req16 := NewCall16Request(validExpr). Args(args) @@ -608,7 +618,7 @@ func TestCallRequestsSetters(t *testing.T) { func TestEvalRequestDefaultValues(t *testing.T) { var refBuf bytes.Buffer - refEnc := NewEncoder(&refBuf) + refEnc := msgpack.NewEncoder(&refBuf) err := RefImplEvalBody(refEnc, validExpr, []interface{}{}) if err != nil { t.Errorf("An unexpected RefImplEvalBody() error: %q", err.Error()) @@ -623,7 +633,7 @@ func TestEvalRequestSetters(t *testing.T) { args := []interface{}{uint(34), int(12)} var refBuf bytes.Buffer - refEnc := NewEncoder(&refBuf) + refEnc := msgpack.NewEncoder(&refBuf) err := RefImplEvalBody(refEnc, validExpr, args) if err != nil { t.Errorf("An unexpected RefImplEvalBody() error: %q", err.Error()) @@ -638,7 +648,7 @@ func TestEvalRequestSetters(t *testing.T) { func TestExecuteRequestDefaultValues(t *testing.T) { var refBuf bytes.Buffer - refEnc := NewEncoder(&refBuf) + refEnc := msgpack.NewEncoder(&refBuf) err := RefImplExecuteBody(refEnc, validExpr, []interface{}{}) if err != nil { t.Errorf("An unexpected RefImplExecuteBody() error: %q", err.Error()) @@ -653,7 +663,7 @@ func TestExecuteRequestSetters(t *testing.T) { args := []interface{}{uint(11)} var refBuf bytes.Buffer - refEnc := NewEncoder(&refBuf) + refEnc := msgpack.NewEncoder(&refBuf) err := RefImplExecuteBody(refEnc, validExpr, args) if err != nil { t.Errorf("An unexpected RefImplExecuteBody() error: %q", err.Error()) @@ -668,7 +678,7 @@ func TestExecuteRequestSetters(t *testing.T) { func TestPrepareRequestDefaultValues(t *testing.T) { var refBuf bytes.Buffer - refEnc := NewEncoder(&refBuf) + refEnc := msgpack.NewEncoder(&refBuf) err := RefImplPrepareBody(refEnc, validExpr) if err != nil { t.Errorf("An unexpected RefImplPrepareBody() error: %q", err.Error()) @@ -682,7 +692,7 @@ func TestPrepareRequestDefaultValues(t *testing.T) { func TestUnprepareRequestDefaultValues(t *testing.T) { var refBuf bytes.Buffer - refEnc := NewEncoder(&refBuf) + refEnc := msgpack.NewEncoder(&refBuf) err := RefImplUnprepareBody(refEnc, *validStmt) if err != nil { t.Errorf("An unexpected RefImplUnprepareBody() error: %q", err.Error()) @@ -698,7 +708,7 @@ func TestExecutePreparedRequestSetters(t *testing.T) { args := []interface{}{uint(11)} var refBuf bytes.Buffer - refEnc := NewEncoder(&refBuf) + refEnc := msgpack.NewEncoder(&refBuf) err := RefImplExecutePreparedBody(refEnc, *validStmt, args) if err != nil { t.Errorf("An unexpected RefImplExecutePreparedBody() error: %q", err.Error()) @@ -714,7 +724,7 @@ func TestExecutePreparedRequestSetters(t *testing.T) { func TestExecutePreparedRequestDefaultValues(t *testing.T) { var refBuf bytes.Buffer - refEnc := NewEncoder(&refBuf) + refEnc := msgpack.NewEncoder(&refBuf) err := RefImplExecutePreparedBody(refEnc, *validStmt, []interface{}{}) if err != nil { t.Errorf("An unexpected RefImplExecutePreparedBody() error: %q", err.Error()) @@ -729,7 +739,7 @@ func TestExecutePreparedRequestDefaultValues(t *testing.T) { func TestBeginRequestDefaultValues(t *testing.T) { var refBuf bytes.Buffer - refEnc := NewEncoder(&refBuf) + refEnc := msgpack.NewEncoder(&refBuf) err := RefImplBeginBody(refEnc, defaultIsolationLevel, defaultTimeout) if err != nil { t.Errorf("An unexpected RefImplBeginBody() error: %q", err.Error()) @@ -743,7 +753,7 @@ func TestBeginRequestDefaultValues(t *testing.T) { func TestBeginRequestSetters(t *testing.T) { var refBuf bytes.Buffer - refEnc := NewEncoder(&refBuf) + refEnc := msgpack.NewEncoder(&refBuf) err := RefImplBeginBody(refEnc, ReadConfirmedLevel, validTimeout) if err != nil { t.Errorf("An unexpected RefImplBeginBody() error: %q", err.Error()) @@ -757,7 +767,7 @@ func TestBeginRequestSetters(t *testing.T) { func TestCommitRequestDefaultValues(t *testing.T) { var refBuf bytes.Buffer - refEnc := NewEncoder(&refBuf) + refEnc := msgpack.NewEncoder(&refBuf) err := RefImplCommitBody(refEnc) if err != nil { t.Errorf("An unexpected RefImplCommitBody() error: %q", err.Error()) @@ -771,7 +781,7 @@ func TestCommitRequestDefaultValues(t *testing.T) { func TestRollbackRequestDefaultValues(t *testing.T) { var refBuf bytes.Buffer - refEnc := NewEncoder(&refBuf) + refEnc := msgpack.NewEncoder(&refBuf) err := RefImplRollbackBody(refEnc) if err != nil { t.Errorf("An unexpected RefImplRollbackBody() error: %q", err.Error()) @@ -785,7 +795,7 @@ func TestRollbackRequestDefaultValues(t *testing.T) { func TestBroadcastRequestDefaultValues(t *testing.T) { var refBuf bytes.Buffer - refEnc := NewEncoder(&refBuf) + refEnc := msgpack.NewEncoder(&refBuf) expectedArgs := []interface{}{validKey} err := RefImplCallBody(refEnc, "box.broadcast", expectedArgs) if err != nil { @@ -801,7 +811,7 @@ func TestBroadcastRequestSetters(t *testing.T) { value := []interface{}{uint(34), int(12)} var refBuf bytes.Buffer - refEnc := NewEncoder(&refBuf) + refEnc := msgpack.NewEncoder(&refBuf) expectedArgs := []interface{}{validKey, value} err := RefImplCallBody(refEnc, "box.broadcast", expectedArgs) if err != nil { diff --git a/response.go b/response.go index e5486b0a4..897b6ce73 100644 --- a/response.go +++ b/response.go @@ -2,6 +2,9 @@ package tarantool import ( "fmt" + + "github.com/tarantool/go-iproto" + "github.com/vmihailenco/msgpack/v5" ) type Response struct { @@ -32,7 +35,7 @@ type SQLInfo struct { InfoAutoincrementIds []uint64 } -func (meta *ColumnMetaData) DecodeMsgpack(d *decoder) error { +func (meta *ColumnMetaData) DecodeMsgpack(d *msgpack.Decoder) error { var err error var l int if l, err = d.DecodeMapLen(); err != nil { @@ -50,18 +53,18 @@ func (meta *ColumnMetaData) DecodeMsgpack(d *decoder) error { if mv, err = d.DecodeInterface(); err != nil { return fmt.Errorf("failed to decode meta data") } - switch mk { - case KeyFieldName: + switch iproto.MetadataKey(mk) { + case iproto.IPROTO_FIELD_NAME: meta.FieldName = mv.(string) - case KeyFieldType: + case iproto.IPROTO_FIELD_TYPE: meta.FieldType = mv.(string) - case KeyFieldColl: + case iproto.IPROTO_FIELD_COLL: meta.FieldCollation = mv.(string) - case KeyFieldIsNullable: + case iproto.IPROTO_FIELD_IS_NULLABLE: meta.FieldIsNullable = mv.(bool) - case KeyIsAutoincrement: + case iproto.IPROTO_FIELD_IS_AUTOINCREMENT: meta.FieldIsAutoincrement = mv.(bool) - case KeyFieldSpan: + case iproto.IPROTO_FIELD_SPAN: meta.FieldSpan = mv.(string) default: return fmt.Errorf("failed to decode meta data") @@ -70,7 +73,7 @@ func (meta *ColumnMetaData) DecodeMsgpack(d *decoder) error { return nil } -func (info *SQLInfo) DecodeMsgpack(d *decoder) error { +func (info *SQLInfo) DecodeMsgpack(d *msgpack.Decoder) error { var err error var l int if l, err = d.DecodeMapLen(); err != nil { @@ -84,12 +87,12 @@ func (info *SQLInfo) DecodeMsgpack(d *decoder) error { if mk, err = d.DecodeUint64(); err != nil { return fmt.Errorf("failed to decode meta data") } - switch mk { - case KeySQLInfoRowCount: + switch iproto.SqlInfoKey(mk) { + case iproto.SQL_INFO_ROW_COUNT: if info.AffectedCount, err = d.DecodeUint64(); err != nil { return fmt.Errorf("failed to decode meta data") } - case KeySQLInfoAutoincrementIds: + case iproto.SQL_INFO_AUTOINCREMENT_IDS: if err = d.Decode(&info.InfoAutoincrementIds); err != nil { return fmt.Errorf("failed to decode meta data") } @@ -100,7 +103,7 @@ func (info *SQLInfo) DecodeMsgpack(d *decoder) error { return nil } -func (resp *Response) smallInt(d *decoder) (i int, err error) { +func (resp *Response) smallInt(d *msgpack.Decoder) (i int, err error) { b, err := resp.buf.ReadByte() if err != nil { return @@ -112,7 +115,7 @@ func (resp *Response) smallInt(d *decoder) (i int, err error) { return d.DecodeInt() } -func (resp *Response) decodeHeader(d *decoder) (err error) { +func (resp *Response) decodeHeader(d *msgpack.Decoder) (err error) { var l int d.Reset(&resp.buf) if l, err = d.DecodeMapLen(); err != nil { @@ -123,14 +126,14 @@ func (resp *Response) decodeHeader(d *decoder) (err error) { if cd, err = resp.smallInt(d); err != nil { return } - switch cd { - case KeySync: + switch iproto.Key(cd) { + case iproto.IPROTO_SYNC: var rid uint64 if rid, err = d.DecodeUint64(); err != nil { return } resp.RequestId = uint32(rid) - case KeyCode: + case iproto.IPROTO_REQUEST_TYPE: var rcode uint64 if rcode, err = d.DecodeUint64(); err != nil { return @@ -156,7 +159,10 @@ func (resp *Response) decodeBody() (err error) { var feature ProtocolFeature var errorExtendedInfo *BoxError = nil - d := newDecoder(&resp.buf) + d := msgpack.NewDecoder(&resp.buf) + d.SetMapDecoder(func(dec *msgpack.Decoder) (interface{}, error) { + return dec.DecodeUntypedMap() + }) if l, err = d.DecodeMapLen(); err != nil { return err @@ -166,8 +172,8 @@ func (resp *Response) decodeBody() (err error) { if cd, err = resp.smallInt(d); err != nil { return err } - switch cd { - case KeyData: + switch iproto.Key(cd) { + case iproto.IPROTO_DATA: var res interface{} var ok bool if res, err = d.DecodeInterface(); err != nil { @@ -176,35 +182,35 @@ func (resp *Response) decodeBody() (err error) { if resp.Data, ok = res.([]interface{}); !ok { return fmt.Errorf("result is not array: %v", res) } - case KeyError: + case iproto.IPROTO_ERROR: if errorExtendedInfo, err = decodeBoxError(d); err != nil { return err } - case KeyError24: + case iproto.IPROTO_ERROR_24: if resp.Error, err = d.DecodeString(); err != nil { return err } - case KeySQLInfo: + case iproto.IPROTO_SQL_INFO: if err = d.Decode(&resp.SQLInfo); err != nil { return err } - case KeyMetaData: + case iproto.IPROTO_METADATA: if err = d.Decode(&resp.MetaData); err != nil { return err } - case KeyStmtID: + case iproto.IPROTO_STMT_ID: if stmtID, err = d.DecodeUint64(); err != nil { return err } - case KeyBindCount: + case iproto.IPROTO_BIND_COUNT: if bindCount, err = d.DecodeUint64(); err != nil { return err } - case KeyVersion: + case iproto.IPROTO_VERSION: if err = d.Decode(&serverProtocolInfo.Version); err != nil { return err } - case KeyFeatures: + case iproto.IPROTO_FEATURES: if larr, err = d.DecodeArrayLen(); err != nil { return err } @@ -216,7 +222,7 @@ func (resp *Response) decodeBody() (err error) { } serverProtocolInfo.Features[i] = feature } - case KeyAuthType: + case iproto.IPROTO_AUTH_TYPE: var auth string if auth, err = d.DecodeString(); err != nil { return err @@ -231,7 +237,7 @@ func (resp *Response) decodeBody() (err error) { if !found { return fmt.Errorf("unknown auth type %s", auth) } - case KeyPos: + case iproto.IPROTO_POSITION: if resp.Pos, err = d.DecodeBytes(); err != nil { return fmt.Errorf("unable to decode a position: %w", err) } @@ -262,8 +268,8 @@ func (resp *Response) decodeBody() (err error) { } if resp.Code != OkCode && resp.Code != PushCode { - resp.Code &^= ErrorCodeBit - err = Error{resp.Code, resp.Error, errorExtendedInfo} + resp.Code &^= uint32(iproto.IPROTO_TYPE_ERROR) + err = Error{iproto.Error(resp.Code), resp.Error, errorExtendedInfo} } } return @@ -277,7 +283,12 @@ func (resp *Response) decodeBodyTyped(res interface{}) (err error) { var errorExtendedInfo *BoxError = nil var l int - d := newDecoder(&resp.buf) + + d := msgpack.NewDecoder(&resp.buf) + d.SetMapDecoder(func(dec *msgpack.Decoder) (interface{}, error) { + return dec.DecodeUntypedMap() + }) + if l, err = d.DecodeMapLen(); err != nil { return err } @@ -286,28 +297,28 @@ func (resp *Response) decodeBodyTyped(res interface{}) (err error) { if cd, err = resp.smallInt(d); err != nil { return err } - switch cd { - case KeyData: + switch iproto.Key(cd) { + case iproto.IPROTO_DATA: if err = d.Decode(res); err != nil { return err } - case KeyError: + case iproto.IPROTO_ERROR: if errorExtendedInfo, err = decodeBoxError(d); err != nil { return err } - case KeyError24: + case iproto.IPROTO_ERROR_24: if resp.Error, err = d.DecodeString(); err != nil { return err } - case KeySQLInfo: + case iproto.IPROTO_SQL_INFO: if err = d.Decode(&resp.SQLInfo); err != nil { return err } - case KeyMetaData: + case iproto.IPROTO_METADATA: if err = d.Decode(&resp.MetaData); err != nil { return err } - case KeyPos: + case iproto.IPROTO_POSITION: if resp.Pos, err = d.DecodeBytes(); err != nil { return fmt.Errorf("unable to decode a position: %w", err) } @@ -318,8 +329,8 @@ func (resp *Response) decodeBodyTyped(res interface{}) (err error) { } } if resp.Code != OkCode && resp.Code != PushCode { - resp.Code &^= ErrorCodeBit - err = Error{resp.Code, resp.Error, errorExtendedInfo} + resp.Code &^= uint32(iproto.IPROTO_TYPE_ERROR) + err = Error{iproto.Error(resp.Code), resp.Error, errorExtendedInfo} } } return diff --git a/schema.go b/schema.go index 87c788fe0..0617924eb 100644 --- a/schema.go +++ b/schema.go @@ -3,6 +3,9 @@ package tarantool import ( "errors" "fmt" + + "github.com/vmihailenco/msgpack/v5" + "github.com/vmihailenco/msgpack/v5/msgpcode" ) // nolint: varcheck,deadcode @@ -16,6 +19,26 @@ const ( vspaceSpFormatFieldNum = 7 ) +func msgpackIsUint(code byte) bool { + return code == msgpcode.Uint8 || code == msgpcode.Uint16 || + code == msgpcode.Uint32 || code == msgpcode.Uint64 || + msgpcode.IsFixedNum(code) +} + +func msgpackIsMap(code byte) bool { + return code == msgpcode.Map16 || code == msgpcode.Map32 || msgpcode.IsFixedMap(code) +} + +func msgpackIsArray(code byte) bool { + return code == msgpcode.Array16 || code == msgpcode.Array32 || + msgpcode.IsFixedArray(code) +} + +func msgpackIsString(code byte) bool { + return msgpcode.IsFixedString(code) || code == msgpcode.Str8 || + code == msgpcode.Str16 || code == msgpcode.Str32 +} + // SchemaResolver is an interface for resolving schema details. type SchemaResolver interface { // ResolveSpaceIndex returns resolved space and index numbers or an @@ -49,7 +72,7 @@ type Space struct { IndexesById map[uint32]*Index } -func (space *Space) DecodeMsgpack(d *decoder) error { +func (space *Space) DecodeMsgpack(d *msgpack.Decoder) error { arrayLen, err := d.DecodeArrayLen() if err != nil { return err @@ -128,13 +151,14 @@ func (space *Space) DecodeMsgpack(d *decoder) error { return nil } +// Field is a schema field. type Field struct { Id uint32 Name string Type string } -func (field *Field) DecodeMsgpack(d *decoder) error { +func (field *Field) DecodeMsgpack(d *msgpack.Decoder) error { l, err := d.DecodeMapLen() if err != nil { return err @@ -172,7 +196,7 @@ type Index struct { Fields []*IndexField } -func (index *Index) DecodeMsgpack(d *decoder) error { +func (index *Index) DecodeMsgpack(d *msgpack.Decoder) error { _, err := d.DecodeArrayLen() if err != nil { return err @@ -243,12 +267,13 @@ func (index *Index) DecodeMsgpack(d *decoder) error { return nil } +// IndexFields is an index field. type IndexField struct { Id uint32 Type string } -func (indexField *IndexField) DecodeMsgpack(d *decoder) error { +func (indexField *IndexField) DecodeMsgpack(d *msgpack.Decoder) error { code, err := d.PeekCode() if err != nil { return err diff --git a/settings/example_test.go b/settings/example_test.go index a2391328f..c9bdc3c49 100644 --- a/settings/example_test.go +++ b/settings/example_test.go @@ -3,9 +3,9 @@ package settings_test import ( "fmt" - "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/settings" - "github.com/tarantool/go-tarantool/test_helpers" + "github.com/tarantool/go-tarantool/v2" + "github.com/tarantool/go-tarantool/v2/settings" + "github.com/tarantool/go-tarantool/v2/test_helpers" ) func example_connect(opts tarantool.Opts) *tarantool.Connection { diff --git a/settings/msgpack.go b/settings/msgpack.go deleted file mode 100644 index 295620aba..000000000 --- a/settings/msgpack.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build !go_tarantool_msgpack_v5 -// +build !go_tarantool_msgpack_v5 - -package settings - -import ( - "gopkg.in/vmihailenco/msgpack.v2" -) - -type encoder = msgpack.Encoder diff --git a/settings/msgpack_helper_test.go b/settings/msgpack_helper_test.go deleted file mode 100644 index 0c002213a..000000000 --- a/settings/msgpack_helper_test.go +++ /dev/null @@ -1,22 +0,0 @@ -//go:build !go_tarantool_msgpack_v5 -// +build !go_tarantool_msgpack_v5 - -package settings_test - -import ( - "io" - - "github.com/tarantool/go-tarantool" - "gopkg.in/vmihailenco/msgpack.v2" -) - -type encoder = msgpack.Encoder - -func NewEncoder(w io.Writer) *encoder { - return msgpack.NewEncoder(w) -} - -func toBoxError(i interface{}) (v tarantool.BoxError, ok bool) { - v, ok = i.(tarantool.BoxError) - return -} diff --git a/settings/msgpack_v5.go b/settings/msgpack_v5.go deleted file mode 100644 index 288418ec6..000000000 --- a/settings/msgpack_v5.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build go_tarantool_msgpack_v5 -// +build go_tarantool_msgpack_v5 - -package settings - -import ( - "github.com/vmihailenco/msgpack/v5" -) - -type encoder = msgpack.Encoder diff --git a/settings/msgpack_v5_helper_test.go b/settings/msgpack_v5_helper_test.go deleted file mode 100644 index 96df6bae1..000000000 --- a/settings/msgpack_v5_helper_test.go +++ /dev/null @@ -1,25 +0,0 @@ -//go:build go_tarantool_msgpack_v5 -// +build go_tarantool_msgpack_v5 - -package settings_test - -import ( - "io" - - "github.com/tarantool/go-tarantool" - "github.com/vmihailenco/msgpack/v5" -) - -type encoder = msgpack.Encoder - -func NewEncoder(w io.Writer) *encoder { - return msgpack.NewEncoder(w) -} - -func toBoxError(i interface{}) (v tarantool.BoxError, ok bool) { - var ptr *tarantool.BoxError - if ptr, ok = i.(*tarantool.BoxError); ok { - v = *ptr - } - return -} diff --git a/settings/request.go b/settings/request.go index 84723bb2d..ae54aebf3 100644 --- a/settings/request.go +++ b/settings/request.go @@ -60,7 +60,10 @@ package settings import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/tarantool/go-iproto" + "github.com/vmihailenco/msgpack/v5" + + "github.com/tarantool/go-tarantool/v2" ) // SetRequest helps to set session settings. @@ -83,13 +86,13 @@ func (req *SetRequest) Context(ctx context.Context) *SetRequest { return req } -// Code returns IPROTO code for set session settings request. -func (req *SetRequest) Code() int32 { - return req.impl.Code() +// Type returns IPROTO type for set session settings request. +func (req *SetRequest) Type() iproto.Type { + return req.impl.Type() } // Body fills an encoder with set session settings request body. -func (req *SetRequest) Body(res tarantool.SchemaResolver, enc *encoder) error { +func (req *SetRequest) Body(res tarantool.SchemaResolver, enc *msgpack.Encoder) error { return req.impl.Body(res, enc) } @@ -123,13 +126,13 @@ func (req *GetRequest) Context(ctx context.Context) *GetRequest { return req } -// Code returns IPROTO code for get session settings request. -func (req *GetRequest) Code() int32 { - return req.impl.Code() +// Type returns IPROTO type for get session settings request. +func (req *GetRequest) Type() iproto.Type { + return req.impl.Type() } // Body fills an encoder with get session settings request body. -func (req *GetRequest) Body(res tarantool.SchemaResolver, enc *encoder) error { +func (req *GetRequest) Body(res tarantool.SchemaResolver, enc *msgpack.Encoder) error { return req.impl.Body(res, enc) } diff --git a/settings/request_test.go b/settings/request_test.go index bc26ff058..477795d2d 100644 --- a/settings/request_test.go +++ b/settings/request_test.go @@ -6,8 +6,11 @@ import ( "testing" "github.com/stretchr/testify/require" - "github.com/tarantool/go-tarantool" - . "github.com/tarantool/go-tarantool/settings" + "github.com/tarantool/go-iproto" + "github.com/vmihailenco/msgpack/v5" + + "github.com/tarantool/go-tarantool/v2" + . "github.com/tarantool/go-tarantool/v2/settings" ) type ValidSchemeResolver struct { @@ -38,37 +41,37 @@ func TestRequestsAPI(t *testing.T) { tests := []struct { req tarantool.Request async bool - code int32 + rtype iproto.Type }{ - {req: NewErrorMarshalingEnabledSetRequest(false), async: false, code: tarantool.UpdateRequestCode}, - {req: NewErrorMarshalingEnabledGetRequest(), async: false, code: tarantool.SelectRequestCode}, - {req: NewSQLDefaultEngineSetRequest("memtx"), async: false, code: tarantool.UpdateRequestCode}, - {req: NewSQLDefaultEngineGetRequest(), async: false, code: tarantool.SelectRequestCode}, - {req: NewSQLDeferForeignKeysSetRequest(false), async: false, code: tarantool.UpdateRequestCode}, - {req: NewSQLDeferForeignKeysGetRequest(), async: false, code: tarantool.SelectRequestCode}, - {req: NewSQLFullColumnNamesSetRequest(false), async: false, code: tarantool.UpdateRequestCode}, - {req: NewSQLFullColumnNamesGetRequest(), async: false, code: tarantool.SelectRequestCode}, - {req: NewSQLFullMetadataSetRequest(false), async: false, code: tarantool.UpdateRequestCode}, - {req: NewSQLFullMetadataGetRequest(), async: false, code: tarantool.SelectRequestCode}, - {req: NewSQLParserDebugSetRequest(false), async: false, code: tarantool.UpdateRequestCode}, - {req: NewSQLParserDebugGetRequest(), async: false, code: tarantool.SelectRequestCode}, - {req: NewSQLRecursiveTriggersSetRequest(false), async: false, code: tarantool.UpdateRequestCode}, - {req: NewSQLRecursiveTriggersGetRequest(), async: false, code: tarantool.SelectRequestCode}, - {req: NewSQLReverseUnorderedSelectsSetRequest(false), async: false, code: tarantool.UpdateRequestCode}, - {req: NewSQLReverseUnorderedSelectsGetRequest(), async: false, code: tarantool.SelectRequestCode}, - {req: NewSQLSelectDebugSetRequest(false), async: false, code: tarantool.UpdateRequestCode}, - {req: NewSQLSelectDebugGetRequest(), async: false, code: tarantool.SelectRequestCode}, - {req: NewSQLVDBEDebugSetRequest(false), async: false, code: tarantool.UpdateRequestCode}, - {req: NewSQLVDBEDebugGetRequest(), async: false, code: tarantool.SelectRequestCode}, - {req: NewSessionSettingsGetRequest(), async: false, code: tarantool.SelectRequestCode}, + {req: NewErrorMarshalingEnabledSetRequest(false), async: false, rtype: iproto.IPROTO_UPDATE}, + {req: NewErrorMarshalingEnabledGetRequest(), async: false, rtype: iproto.IPROTO_SELECT}, + {req: NewSQLDefaultEngineSetRequest("memtx"), async: false, rtype: iproto.IPROTO_UPDATE}, + {req: NewSQLDefaultEngineGetRequest(), async: false, rtype: iproto.IPROTO_SELECT}, + {req: NewSQLDeferForeignKeysSetRequest(false), async: false, rtype: iproto.IPROTO_UPDATE}, + {req: NewSQLDeferForeignKeysGetRequest(), async: false, rtype: iproto.IPROTO_SELECT}, + {req: NewSQLFullColumnNamesSetRequest(false), async: false, rtype: iproto.IPROTO_UPDATE}, + {req: NewSQLFullColumnNamesGetRequest(), async: false, rtype: iproto.IPROTO_SELECT}, + {req: NewSQLFullMetadataSetRequest(false), async: false, rtype: iproto.IPROTO_UPDATE}, + {req: NewSQLFullMetadataGetRequest(), async: false, rtype: iproto.IPROTO_SELECT}, + {req: NewSQLParserDebugSetRequest(false), async: false, rtype: iproto.IPROTO_UPDATE}, + {req: NewSQLParserDebugGetRequest(), async: false, rtype: iproto.IPROTO_SELECT}, + {req: NewSQLRecursiveTriggersSetRequest(false), async: false, rtype: iproto.IPROTO_UPDATE}, + {req: NewSQLRecursiveTriggersGetRequest(), async: false, rtype: iproto.IPROTO_SELECT}, + {req: NewSQLReverseUnorderedSelectsSetRequest(false), async: false, rtype: iproto.IPROTO_UPDATE}, + {req: NewSQLReverseUnorderedSelectsGetRequest(), async: false, rtype: iproto.IPROTO_SELECT}, + {req: NewSQLSelectDebugSetRequest(false), async: false, rtype: iproto.IPROTO_UPDATE}, + {req: NewSQLSelectDebugGetRequest(), async: false, rtype: iproto.IPROTO_SELECT}, + {req: NewSQLVDBEDebugSetRequest(false), async: false, rtype: iproto.IPROTO_UPDATE}, + {req: NewSQLVDBEDebugGetRequest(), async: false, rtype: iproto.IPROTO_SELECT}, + {req: NewSessionSettingsGetRequest(), async: false, rtype: iproto.IPROTO_SELECT}, } for _, test := range tests { require.Equal(t, test.async, test.req.Async()) - require.Equal(t, test.code, test.req.Code()) + require.Equal(t, test.rtype, test.req.Type()) var reqBuf bytes.Buffer - enc := NewEncoder(&reqBuf) + enc := msgpack.NewEncoder(&reqBuf) require.Nilf(t, test.req.Body(&resolver, enc), "No errors on fill") } } diff --git a/settings/tarantool_test.go b/settings/tarantool_test.go index 054d5052a..aeec28cc0 100644 --- a/settings/tarantool_test.go +++ b/settings/tarantool_test.go @@ -7,9 +7,9 @@ import ( "time" "github.com/stretchr/testify/require" - "github.com/tarantool/go-tarantool" - . "github.com/tarantool/go-tarantool/settings" - "github.com/tarantool/go-tarantool/test_helpers" + "github.com/tarantool/go-tarantool/v2" + . "github.com/tarantool/go-tarantool/v2/settings" + "github.com/tarantool/go-tarantool/v2/test_helpers" ) // There is no way to skip tests in testing.M, @@ -89,7 +89,7 @@ func TestErrorMarshalingEnabledSetting(t *testing.T) { resp, err = conn.Eval("return box.error.new(box.error.UNKNOWN)", []interface{}{}) require.Nil(t, err) require.NotNil(t, resp) - _, ok := toBoxError(resp.Data[0]) + _, ok := resp.Data[0].(*tarantool.BoxError) require.True(t, ok) } diff --git a/shutdown_test.go b/shutdown_test.go index 1b06284c0..7a6843811 100644 --- a/shutdown_test.go +++ b/shutdown_test.go @@ -14,8 +14,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - . "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/test_helpers" + . "github.com/tarantool/go-tarantool/v2" + "github.com/tarantool/go-tarantool/v2/test_helpers" ) var shtdnServer = "127.0.0.1:3014" diff --git a/ssl_test.go b/ssl_test.go index 0a62d03c3..58d03fa73 100644 --- a/ssl_test.go +++ b/ssl_test.go @@ -15,8 +15,8 @@ import ( "time" "github.com/tarantool/go-openssl" - . "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/test_helpers" + . "github.com/tarantool/go-tarantool/v2" + "github.com/tarantool/go-tarantool/v2/test_helpers" ) const sslHost = "127.0.0.1" diff --git a/stream.go b/stream.go index 3a03ec68f..939840d19 100644 --- a/stream.go +++ b/stream.go @@ -4,6 +4,9 @@ import ( "context" "fmt" "time" + + "github.com/tarantool/go-iproto" + "github.com/vmihailenco/msgpack/v5" ) type TxnIsolationLevel uint @@ -27,7 +30,7 @@ type Stream struct { Conn *Connection } -func fillBegin(enc *encoder, txnIsolation TxnIsolationLevel, timeout time.Duration) error { +func fillBegin(enc *msgpack.Encoder, txnIsolation TxnIsolationLevel, timeout time.Duration) error { hasTimeout := timeout > 0 hasIsolationLevel := txnIsolation != DefaultIsolationLevel mapLen := 0 @@ -44,7 +47,7 @@ func fillBegin(enc *encoder, txnIsolation TxnIsolationLevel, timeout time.Durati } if hasTimeout { - err = encodeUint(enc, KeyTimeout) + err = enc.EncodeUint(uint64(iproto.IPROTO_TIMEOUT)) if err != nil { return err } @@ -56,12 +59,12 @@ func fillBegin(enc *encoder, txnIsolation TxnIsolationLevel, timeout time.Durati } if hasIsolationLevel { - err = encodeUint(enc, KeyTxnIsolation) + err = enc.EncodeUint(uint64(iproto.IPROTO_TXN_ISOLATION)) if err != nil { return err } - err = encodeUint(enc, uint64(txnIsolation)) + err = enc.EncodeUint(uint64(txnIsolation)) if err != nil { return err } @@ -70,11 +73,11 @@ func fillBegin(enc *encoder, txnIsolation TxnIsolationLevel, timeout time.Durati return err } -func fillCommit(enc *encoder) error { +func fillCommit(enc *msgpack.Encoder) error { return enc.EncodeMapLen(0) } -func fillRollback(enc *encoder) error { +func fillRollback(enc *msgpack.Encoder) error { return enc.EncodeMapLen(0) } @@ -90,7 +93,7 @@ type BeginRequest struct { // NewBeginRequest returns a new BeginRequest. func NewBeginRequest() *BeginRequest { req := new(BeginRequest) - req.requestCode = BeginRequestCode + req.rtype = iproto.IPROTO_BEGIN req.txnIsolation = DefaultIsolationLevel return req } @@ -108,8 +111,8 @@ func (req *BeginRequest) Timeout(timeout time.Duration) *BeginRequest { return req } -// Body fills an encoder with the begin request body. -func (req *BeginRequest) Body(res SchemaResolver, enc *encoder) error { +// Body fills an msgpack.Encoder with the begin request body. +func (req *BeginRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error { return fillBegin(enc, req.txnIsolation, req.timeout) } @@ -134,12 +137,12 @@ type CommitRequest struct { // NewCommitRequest returns a new CommitRequest. func NewCommitRequest() *CommitRequest { req := new(CommitRequest) - req.requestCode = CommitRequestCode + req.rtype = iproto.IPROTO_COMMIT return req } -// Body fills an encoder with the commit request body. -func (req *CommitRequest) Body(res SchemaResolver, enc *encoder) error { +// Body fills an msgpack.Encoder with the commit request body. +func (req *CommitRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error { return fillCommit(enc) } @@ -164,12 +167,12 @@ type RollbackRequest struct { // NewRollbackRequest returns a new RollbackRequest. func NewRollbackRequest() *RollbackRequest { req := new(RollbackRequest) - req.requestCode = RollbackRequestCode + req.rtype = iproto.IPROTO_ROLLBACK return req } -// Body fills an encoder with the rollback request body. -func (req *RollbackRequest) Body(res SchemaResolver, enc *encoder) error { +// Body fills an msgpack.Encoder with the rollback request body. +func (req *RollbackRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error { return fillRollback(enc) } diff --git a/tarantool_test.go b/tarantool_test.go index 39e9c3511..0d56b4ada 100644 --- a/tarantool_test.go +++ b/tarantool_test.go @@ -15,11 +15,13 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/tarantool/go-iproto" + "github.com/vmihailenco/msgpack/v5" - "github.com/stretchr/testify/assert" - . "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/test_helpers" + . "github.com/tarantool/go-tarantool/v2" + "github.com/tarantool/go-tarantool/v2/test_helpers" ) var startOpts test_helpers.StartOpts = test_helpers.StartOpts{ @@ -38,20 +40,20 @@ type Member struct { Val uint } -func (m *Member) EncodeMsgpack(e *encoder) error { +func (m *Member) EncodeMsgpack(e *msgpack.Encoder) error { if err := e.EncodeArrayLen(2); err != nil { return err } if err := e.EncodeString(m.Name); err != nil { return err } - if err := encodeUint(e, uint64(m.Val)); err != nil { + if err := e.EncodeUint(uint64(m.Val)); err != nil { return err } return nil } -func (m *Member) DecodeMsgpack(d *decoder) error { +func (m *Member) DecodeMsgpack(d *msgpack.Decoder) error { var err error var l int if l, err = d.DecodeArrayLen(); err != nil { @@ -909,8 +911,8 @@ func TestClient(t *testing.T) { } //resp, err = conn.Insert(spaceNo, []interface{}{uint(1), "hello", "world"}) resp, err = conn.Insert(spaceNo, &Tuple{Id: 1, Msg: "hello", Name: "world"}) - if tntErr, ok := err.(Error); !ok || tntErr.Code != ErrTupleFound { - t.Errorf("Expected ErrTupleFound but got: %v", err) + if tntErr, ok := err.(Error); !ok || tntErr.Code != iproto.ER_TUPLE_FOUND { + t.Errorf("Expected %s but got: %v", iproto.ER_TUPLE_FOUND, err) } if len(resp.Data) != 0 { t.Errorf("Response Body len != 0") @@ -1684,7 +1686,8 @@ func TestStressSQL(t *testing.T) { if resp == nil { t.Fatal("Response is nil after Execute") } - if resp.Code != ErSpaceExistsCode { + + if iproto.Error(resp.Code) != iproto.ER_SPACE_EXISTS { t.Fatalf("Unexpected response code: %d", resp.Code) } if resp.SQLInfo.AffectedCount != 0 { @@ -2608,6 +2611,39 @@ func TestConnectionDoSelectRequest_pagination_pos(t *testing.T) { testConnectionDoSelectRequestCheck(t, resp, err, true, 2, 1012) } +func TestConnection_Call(t *testing.T) { + var resp *Response + var err error + + conn := test_helpers.ConnectWithValidation(t, server, opts) + defer conn.Close() + + resp, err = conn.Call("simple_concat", []interface{}{"1"}) + if err != nil { + t.Errorf("Failed to use Call") + } + if val, ok := resp.Data[0].(string); !ok || val != "11" { + t.Errorf("result is not {{1}} : %v", resp.Data) + } +} + +func TestCallRequest(t *testing.T) { + var resp *Response + var err error + + conn := test_helpers.ConnectWithValidation(t, server, opts) + defer conn.Close() + + req := NewCallRequest("simple_concat").Args([]interface{}{"1"}) + resp, err = conn.Do(req).Get() + if err != nil { + t.Errorf("Failed to use Call") + } + if val, ok := resp.Data[0].(string); !ok || val != "11" { + t.Errorf("result is not {{1}} : %v", resp.Data) + } +} + func TestClientRequestObjectsWithNilContext(t *testing.T) { conn := test_helpers.ConnectWithValidation(t, server, opts) defer conn.Close() @@ -2648,11 +2684,11 @@ type waitCtxRequest struct { wg sync.WaitGroup } -func (req *waitCtxRequest) Code() int32 { - return NewPingRequest().Code() +func (req *waitCtxRequest) Type() iproto.Type { + return NewPingRequest().Type() } -func (req *waitCtxRequest) Body(res SchemaResolver, enc *encoder) error { +func (req *waitCtxRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error { req.wg.Wait() return NewPingRequest().Body(res, enc) } diff --git a/test_helpers/main.go b/test_helpers/main.go index 4aaa91f50..c234d4c02 100644 --- a/test_helpers/main.go +++ b/test_helpers/main.go @@ -3,7 +3,7 @@ // Package introduces go helpers for starting a tarantool process and // validating Tarantool version. Helpers are based on os/exec calls. // Retries to connect test tarantool instance handled explicitly, -// see tarantool/go-tarantool#136. +// see tarantool/go-tarantool/#136. // // Tarantool's instance Lua scripts use environment variables to configure // box.cfg. Listen port is set in the end of script so it is possible to @@ -23,7 +23,7 @@ import ( "strconv" "time" - "github.com/tarantool/go-tarantool" + "github.com/tarantool/go-tarantool/v2" ) type StartOpts struct { @@ -373,7 +373,7 @@ func copyFile(srcFile, dstFile string) error { return nil } -// msgpack.v2 and msgpack.v5 return different uint types in responses. The +// msgpack.v5 decodes different uint types depending on value. The // function helps to unify a result. func ConvertUint64(v interface{}) (result uint64, err error) { switch v := v.(type) { diff --git a/test_helpers/msgpack.go b/test_helpers/msgpack.go deleted file mode 100644 index 1ea712b38..000000000 --- a/test_helpers/msgpack.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build !go_tarantool_msgpack_v5 -// +build !go_tarantool_msgpack_v5 - -package test_helpers - -import ( - "gopkg.in/vmihailenco/msgpack.v2" -) - -type encoder = msgpack.Encoder diff --git a/test_helpers/msgpack_v5.go b/test_helpers/msgpack_v5.go deleted file mode 100644 index 37f85ef31..000000000 --- a/test_helpers/msgpack_v5.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build go_tarantool_msgpack_v5 -// +build go_tarantool_msgpack_v5 - -package test_helpers - -import ( - "github.com/vmihailenco/msgpack/v5" -) - -type encoder = msgpack.Encoder diff --git a/test_helpers/pool_helper.go b/test_helpers/pool_helper.go index 8c3a7e6ff..a559ef98d 100644 --- a/test_helpers/pool_helper.go +++ b/test_helpers/pool_helper.go @@ -5,21 +5,21 @@ import ( "reflect" "time" - "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/connection_pool" + "github.com/tarantool/go-tarantool/v2" + "github.com/tarantool/go-tarantool/v2/pool" ) type ListenOnInstanceArgs struct { - ConnPool *connection_pool.ConnectionPool - Mode connection_pool.Mode + ConnPool *pool.ConnectionPool + Mode pool.Mode ServersNumber int ExpectedPorts map[string]bool } type CheckStatusesArgs struct { - ConnPool *connection_pool.ConnectionPool + ConnPool *pool.ConnectionPool Servers []string - Mode connection_pool.Mode + Mode pool.Mode ExpectedPoolStatus bool ExpectedStatuses map[string]bool } diff --git a/test_helpers/request_mock.go b/test_helpers/request_mock.go index 19c18545e..80ca1b541 100644 --- a/test_helpers/request_mock.go +++ b/test_helpers/request_mock.go @@ -3,7 +3,10 @@ package test_helpers import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/tarantool/go-iproto" + "github.com/vmihailenco/msgpack/v5" + + "github.com/tarantool/go-tarantool/v2" ) type StrangerRequest struct { @@ -13,15 +16,15 @@ func NewStrangerRequest() *StrangerRequest { return &StrangerRequest{} } -func (sr *StrangerRequest) Code() int32 { - return 0 +func (sr *StrangerRequest) Type() iproto.Type { + return iproto.Type(0) } func (sr *StrangerRequest) Async() bool { return false } -func (sr *StrangerRequest) Body(resolver tarantool.SchemaResolver, enc *encoder) error { +func (sr *StrangerRequest) Body(resolver tarantool.SchemaResolver, enc *msgpack.Encoder) error { return nil } diff --git a/test_helpers/utils.go b/test_helpers/utils.go index 34a2e2980..3771a5f9e 100644 --- a/test_helpers/utils.go +++ b/test_helpers/utils.go @@ -1,14 +1,12 @@ package test_helpers import ( - "bytes" "fmt" - "io" "testing" "time" "github.com/stretchr/testify/require" - "github.com/tarantool/go-tarantool" + "github.com/tarantool/go-tarantool/v2" ) // ConnectWithValidation tries to connect to a Tarantool instance. @@ -230,16 +228,3 @@ func CheckEqualBoxErrors(t *testing.T, expected tarantool.BoxError, actual taran } } } - -func ExtractRequestBody(req tarantool.Request, resolver tarantool.SchemaResolver, - newEncFunc func(w io.Writer) *encoder) ([]byte, error) { - var reqBuf bytes.Buffer - reqEnc := newEncFunc(&reqBuf) - - err := req.Body(resolver, reqEnc) - if err != nil { - return nil, fmt.Errorf("An unexpected Response.Body() error: %q", err.Error()) - } - - return reqBuf.Bytes(), nil -} diff --git a/uuid/example_test.go b/uuid/example_test.go index ef0993e59..6ad8ebad9 100644 --- a/uuid/example_test.go +++ b/uuid/example_test.go @@ -13,8 +13,8 @@ import ( "log" "github.com/google/uuid" - "github.com/tarantool/go-tarantool" - _ "github.com/tarantool/go-tarantool/uuid" + "github.com/tarantool/go-tarantool/v2" + _ "github.com/tarantool/go-tarantool/v2/uuid" ) // Example demonstrates how to use tuples with UUID. To enable UUID support diff --git a/uuid/msgpack.go b/uuid/msgpack.go deleted file mode 100644 index 62504e5f9..000000000 --- a/uuid/msgpack.go +++ /dev/null @@ -1,19 +0,0 @@ -//go:build !go_tarantool_msgpack_v5 -// +build !go_tarantool_msgpack_v5 - -package uuid - -import ( - "reflect" - - "github.com/google/uuid" - "gopkg.in/vmihailenco/msgpack.v2" -) - -type encoder = msgpack.Encoder -type decoder = msgpack.Decoder - -func init() { - msgpack.Register(reflect.TypeOf((*uuid.UUID)(nil)).Elem(), encodeUUID, decodeUUID) - msgpack.RegisterExt(UUID_extId, (*uuid.UUID)(nil)) -} diff --git a/uuid/msgpack_helper_test.go b/uuid/msgpack_helper_test.go deleted file mode 100644 index d5a1cb70e..000000000 --- a/uuid/msgpack_helper_test.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build !go_tarantool_msgpack_v5 -// +build !go_tarantool_msgpack_v5 - -package uuid_test - -import ( - "gopkg.in/vmihailenco/msgpack.v2" -) - -type decoder = msgpack.Decoder diff --git a/uuid/msgpack_v5.go b/uuid/msgpack_v5.go deleted file mode 100644 index 951c437dd..000000000 --- a/uuid/msgpack_v5.go +++ /dev/null @@ -1,27 +0,0 @@ -//go:build go_tarantool_msgpack_v5 -// +build go_tarantool_msgpack_v5 - -package uuid - -import ( - "reflect" - - "github.com/google/uuid" - "github.com/vmihailenco/msgpack/v5" -) - -type encoder = msgpack.Encoder -type decoder = msgpack.Decoder - -func init() { - msgpack.Register(reflect.TypeOf((*uuid.UUID)(nil)).Elem(), encodeUUID, decodeUUID) - msgpack.RegisterExtEncoder(UUID_extId, uuid.UUID{}, - func(e *msgpack.Encoder, v reflect.Value) ([]byte, error) { - uuid := v.Interface().(uuid.UUID) - return uuid.MarshalBinary() - }) - msgpack.RegisterExtDecoder(UUID_extId, uuid.UUID{}, - func(d *msgpack.Decoder, v reflect.Value, extLen int) error { - return decodeUUID(d, v) - }) -} diff --git a/uuid/msgpack_v5_helper_test.go b/uuid/msgpack_v5_helper_test.go deleted file mode 100644 index c2356ef1a..000000000 --- a/uuid/msgpack_v5_helper_test.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build go_tarantool_msgpack_v5 -// +build go_tarantool_msgpack_v5 - -package uuid_test - -import ( - "github.com/vmihailenco/msgpack/v5" -) - -type decoder = msgpack.Decoder diff --git a/uuid/uuid.go b/uuid/uuid.go index a72785c0e..eadd42ae1 100644 --- a/uuid/uuid.go +++ b/uuid/uuid.go @@ -18,12 +18,13 @@ import ( "reflect" "github.com/google/uuid" + "github.com/vmihailenco/msgpack/v5" ) // UUID external type. -const UUID_extId = 2 +const uuid_extID = 2 -func encodeUUID(e *encoder, v reflect.Value) error { +func encodeUUID(e *msgpack.Encoder, v reflect.Value) error { id := v.Interface().(uuid.UUID) bytes, err := id.MarshalBinary() @@ -33,13 +34,13 @@ func encodeUUID(e *encoder, v reflect.Value) error { _, err = e.Writer().Write(bytes) if err != nil { - return fmt.Errorf("msgpack: can't write bytes to encoder writer: %w", err) + return fmt.Errorf("msgpack: can't write bytes to msgpack.Encoder writer: %w", err) } return nil } -func decodeUUID(d *decoder, v reflect.Value) error { +func decodeUUID(d *msgpack.Decoder, v reflect.Value) error { var bytesCount int = 16 bytes := make([]byte, bytesCount) @@ -59,3 +60,16 @@ func decodeUUID(d *decoder, v reflect.Value) error { v.Set(reflect.ValueOf(id)) return nil } + +func init() { + msgpack.Register(reflect.TypeOf((*uuid.UUID)(nil)).Elem(), encodeUUID, decodeUUID) + msgpack.RegisterExtEncoder(uuid_extID, uuid.UUID{}, + func(e *msgpack.Encoder, v reflect.Value) ([]byte, error) { + uuid := v.Interface().(uuid.UUID) + return uuid.MarshalBinary() + }) + msgpack.RegisterExtDecoder(uuid_extID, uuid.UUID{}, + func(d *msgpack.Decoder, v reflect.Value, extLen int) error { + return decodeUUID(d, v) + }) +} diff --git a/uuid/uuid_test.go b/uuid/uuid_test.go index f5a596e76..f09caf03d 100644 --- a/uuid/uuid_test.go +++ b/uuid/uuid_test.go @@ -8,9 +8,11 @@ import ( "time" "github.com/google/uuid" - . "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/test_helpers" - _ "github.com/tarantool/go-tarantool/uuid" + "github.com/vmihailenco/msgpack/v5" + + . "github.com/tarantool/go-tarantool/v2" + "github.com/tarantool/go-tarantool/v2/test_helpers" + _ "github.com/tarantool/go-tarantool/v2/uuid" ) // There is no way to skip tests in testing.M, @@ -32,7 +34,7 @@ type TupleUUID struct { id uuid.UUID } -func (t *TupleUUID) DecodeMsgpack(d *decoder) error { +func (t *TupleUUID) DecodeMsgpack(d *msgpack.Decoder) error { var err error var l int if l, err = d.DecodeArrayLen(); err != nil { diff --git a/watch.go b/watch.go index 61631657c..0508899f0 100644 --- a/watch.go +++ b/watch.go @@ -2,6 +2,9 @@ package tarantool import ( "context" + + "github.com/tarantool/go-iproto" + "github.com/vmihailenco/msgpack/v5" ) // BroadcastRequest helps to send broadcast messages. See: @@ -33,12 +36,12 @@ func (req *BroadcastRequest) Context(ctx context.Context) *BroadcastRequest { } // Code returns IPROTO code for the broadcast request. -func (req *BroadcastRequest) Code() int32 { - return req.call.Code() +func (req *BroadcastRequest) Type() iproto.Type { + return req.call.Type() } -// Body fills an encoder with the broadcast request body. -func (req *BroadcastRequest) Body(res SchemaResolver, enc *encoder) error { +// Body fills an msgpack.Encoder with the broadcast request body. +func (req *BroadcastRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error { return req.call.Body(res, enc) } @@ -64,18 +67,18 @@ type watchRequest struct { // newWatchRequest returns a new watchRequest. func newWatchRequest(key string) *watchRequest { req := new(watchRequest) - req.requestCode = WatchRequestCode + req.rtype = iproto.IPROTO_WATCH req.async = true req.key = key return req } -// Body fills an encoder with the watch request body. -func (req *watchRequest) Body(res SchemaResolver, enc *encoder) error { +// Body fills an msgpack.Encoder with the watch request body. +func (req *watchRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error { if err := enc.EncodeMapLen(1); err != nil { return err } - if err := encodeUint(enc, KeyEvent); err != nil { + if err := enc.EncodeUint(uint64(iproto.IPROTO_EVENT_KEY)); err != nil { return err } return enc.EncodeString(req.key) @@ -98,18 +101,18 @@ type unwatchRequest struct { // newUnwatchRequest returns a new unwatchRequest. func newUnwatchRequest(key string) *unwatchRequest { req := new(unwatchRequest) - req.requestCode = UnwatchRequestCode + req.rtype = iproto.IPROTO_UNWATCH req.async = true req.key = key return req } -// Body fills an encoder with the unwatch request body. -func (req *unwatchRequest) Body(res SchemaResolver, enc *encoder) error { +// Body fills an msgpack.Encoder with the unwatch request body. +func (req *unwatchRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error { if err := enc.EncodeMapLen(1); err != nil { return err } - if err := encodeUint(enc, KeyEvent); err != nil { + if err := enc.EncodeUint(uint64(iproto.IPROTO_EVENT_KEY)); err != nil { return err } return enc.EncodeString(req.key)