Skip to content

Commit 988edce

Browse files
AnaNekoleg-jukovec
authored andcommitted
code-health: allow to use Call17 as default Call
An incompatible change was introduced in Tarantool 1.7 which was released in 2016. This change is about a new binary protocol command for CALL, which no more restricts a function to returning an array of tuples and allows returning an arbitrary MsgPack/JSON result, including scalars, nil and void (nothing). We should be in-line with tarantool here and provide `Call17` as just `Call`. For backward compatibility in current `go-tarantool` version build tag `go_tarantool_call_17` have been defined. This tag used to change the default `Call` behavior from `Call16` to `Call17`. Closes #125
1 parent 1a1fe7b commit 988edce

28 files changed

+505
-71
lines changed

.github/workflows/testing.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ jobs:
6060
- name: Run tests
6161
run: make test
6262

63+
- name: Run tests with call_17
64+
run: make test TAGS="go_tarantool_call_17"
65+
6366
- name: Run tests, collect code coverage data and send to Coveralls
6467
if: ${{ matrix.coveralls }}
6568
env:
@@ -134,6 +137,13 @@ jobs:
134137
env:
135138
TEST_TNT_SSL: ${{matrix.ssl}}
136139

140+
- name: Run tests with call_17
141+
run: |
142+
source tarantool-enterprise/env.sh
143+
make test TAGS="go_tarantool_call_17"
144+
env:
145+
TEST_TNT_SSL: ${{matrix.ssl}}
146+
137147
- name: Run tests, collect code coverage data and send to Coveralls
138148
if: ${{ matrix.coveralls }}
139149
env:

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release.
1515

1616
### Changed
1717

18+
- Add `Call16` method, support build tag `go_tarantool_call_17`
19+
to choose behavior for `Call` method (#125)
20+
1821
### Fixed
1922

2023
## [1.6.0] - 2022-06-01

Makefile

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ BENCH_REFERENCE_REPO := ${BENCH_PATH}/go-tarantool
1313
BENCH_OPTIONS := -bench=. -run=^Benchmark -benchmem -benchtime=${DURATION} -count=${COUNT}
1414
GO_TARANTOOL_URL := https://github.com/tarantool/go-tarantool
1515
GO_TARANTOOL_DIR := ${PROJECT_DIR}/${BENCH_PATH}/go-tarantool
16+
TAGS :=
1617

1718
.PHONY: clean
1819
clean:
@@ -33,7 +34,7 @@ golangci-lint:
3334

3435
.PHONY: test
3536
test:
36-
go test ./... -v -p 1
37+
go test -tags "$(TAGS)" ./... -v -p 1
3738

3839
.PHONY: testdata
3940
testdata:
@@ -43,38 +44,38 @@ testdata:
4344
test-connection-pool:
4445
@echo "Running tests in connection_pool package"
4546
go clean -testcache
46-
go test ./connection_pool/ -v -p 1
47+
go test -tags "$(TAGS)" ./connection_pool/ -v -p 1
4748

4849
.PHONY: test-multi
4950
test-multi:
5051
@echo "Running tests in multiconnection package"
5152
go clean -testcache
52-
go test ./multi/ -v -p 1
53+
go test -tags "$(TAGS)" ./multi/ -v -p 1
5354

5455
.PHONY: test-queue
5556
test-queue:
5657
@echo "Running tests in queue package"
5758
cd ./queue/ && tarantool -e "require('queue')"
5859
go clean -testcache
59-
go test ./queue/ -v -p 1
60+
go test -tags "$(TAGS)" ./queue/ -v -p 1
6061

6162
.PHONY: test-uuid
6263
test-uuid:
6364
@echo "Running tests in UUID package"
6465
go clean -testcache
65-
go test ./uuid/ -v -p 1
66+
go test -tags "$(TAGS)" ./uuid/ -v -p 1
6667

6768
.PHONY: test-main
6869
test-main:
6970
@echo "Running tests in main package"
7071
go clean -testcache
71-
go test . -v -p 1
72+
go test -tags "$(TAGS)" . -v -p 1
7273

7374
.PHONY: coverage
7475
coverage:
7576
go clean -testcache
7677
go get golang.org/x/tools/cmd/cover
77-
go test ./... -v -p 1 -covermode=atomic -coverprofile=$(COVERAGE_FILE) -coverpkg=./...
78+
go test -tags "$(TAGS)" ./... -v -p 1 -covermode=atomic -coverprofile=$(COVERAGE_FILE) -coverpkg=./...
7879
go tool cover -func=$(COVERAGE_FILE)
7980

8081
.PHONY: coveralls
@@ -94,7 +95,7 @@ ${BENCH_PATH} bench-deps:
9495
.PHONY: bench
9596
${BENCH_FILE} bench: ${BENCH_PATH}
9697
@echo "Running benchmark tests from the current branch"
97-
go test ${TEST_PATH} ${BENCH_OPTIONS} 2>&1 \
98+
go test -tags "$(TAGS)" ${TEST_PATH} ${BENCH_OPTIONS} 2>&1 \
9899
| tee ${BENCH_FILE}
99100
benchstat ${BENCH_FILE}
100101

@@ -104,7 +105,7 @@ ${GO_TARANTOOL_DIR}:
104105

105106
${REFERENCE_FILE}: ${GO_TARANTOOL_DIR}
106107
@echo "Running benchmark tests from master for using results in bench-diff target"
107-
cd ${GO_TARANTOOL_DIR} && git pull && go test ./... ${BENCH_OPTIONS} 2>&1 \
108+
cd ${GO_TARANTOOL_DIR} && git pull && go test ./... -tags "$(TAGS)" ${BENCH_OPTIONS} 2>&1 \
108109
| tee ${REFERENCE_FILE}
109110

110111
bench-diff: ${BENCH_FILES}

README.md

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,20 @@ of any Go program.
5454

5555
### Build tags
5656

57-
To disable SSL support and linking with OpenSSL, you can use the tag:
58-
```
59-
go_tarantool_ssl_disable
60-
```
57+
We define multiple [build tags](https://pkg.go.dev/go/build#hdr-Build_Constraints).
58+
59+
This allows us to introduce new features without losing backward compatibility.
60+
61+
1. To disable SSL support and linking with OpenSSL, you can use the tag:
62+
```
63+
go_tarantool_ssl_disable
64+
```
65+
2. to change the default `Call` behavior from `Call16` to `Call17`, you can use the build
66+
tag:
67+
```
68+
go_tarantool_call_17
69+
```
70+
**Note:** In future releases, `Call17` may be used as default `Call` behavior.
6171

6272
## Documentation
6373

call_16_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//go:build !go_tarantool_call_17
2+
// +build !go_tarantool_call_17
3+
4+
package tarantool_test
5+
6+
import (
7+
"testing"
8+
9+
. "github.com/tarantool/go-tarantool"
10+
)
11+
12+
func TestConnection_Call(t *testing.T) {
13+
var resp *Response
14+
var err error
15+
16+
conn := connect(t, server, opts)
17+
defer conn.Close()
18+
19+
// Call16
20+
resp, err = conn.Call("simple_incr", []interface{}{1})
21+
if err != nil {
22+
t.Errorf("Failed to use Call")
23+
}
24+
if resp.Data[0].([]interface{})[0].(uint64) != 2 {
25+
t.Errorf("result is not {{1}} : %v", resp.Data)
26+
}
27+
}

call_17_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//go:build go_tarantool_call_17
2+
// +build go_tarantool_call_17
3+
4+
package tarantool_test
5+
6+
import (
7+
"testing"
8+
9+
. "github.com/tarantool/go-tarantool"
10+
)
11+
12+
func TestConnection_Call(t *testing.T) {
13+
var resp *Response
14+
var err error
15+
16+
conn := connect(t, server, opts)
17+
defer conn.Close()
18+
19+
// Call17
20+
resp, err = conn.Call17("simple_incr", []interface{}{1})
21+
if err != nil {
22+
t.Errorf("Failed to use Call")
23+
}
24+
if resp.Data[0].(uint64) != 2 {
25+
t.Errorf("result is not {{1}} : %v", resp.Data)
26+
}
27+
}

connection.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,9 @@ func (d defaultLogger) Report(event ConnLogKind, conn *Connection, v ...interfac
116116
//
117117
// ATTENTION: result argument for *Typed methods should deserialize from
118118
// msgpack array, cause Tarantool always returns result as an array.
119-
// For all space related methods and Call* (but not Call17*) methods Tarantool
119+
// For all space related methods and Call16* (but not Call17*) methods Tarantool
120120
// always returns array of array (array of tuples for space related methods).
121-
// For Eval* and Call17* Tarantool always returns array, but does not forces
121+
// For Eval* and Call* Tarantool always returns array, but does not forces
122122
// array of arrays.
123123
type Connection struct {
124124
addr string

connection_pool/call_16_test.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
//go:build !go_tarantool_call_17
2+
// +build !go_tarantool_call_17
3+
4+
package connection_pool_test
5+
6+
import (
7+
"testing"
8+
9+
"github.com/stretchr/testify/require"
10+
"github.com/tarantool/go-tarantool/connection_pool"
11+
"github.com/tarantool/go-tarantool/test_helpers"
12+
)
13+
14+
func TestCall(t *testing.T) {
15+
roles := []bool{false, true, false, false, true}
16+
17+
err := test_helpers.SetClusterRO(servers, connOpts, roles)
18+
require.Nilf(t, err, "fail to set roles for cluster")
19+
20+
connPool, err := connection_pool.Connect(servers, connOpts)
21+
require.Nilf(t, err, "failed to connect")
22+
require.NotNilf(t, connPool, "conn is nil after Connect")
23+
24+
defer connPool.Close()
25+
26+
// PreferRO
27+
resp, err := connPool.Call("box.info", []interface{}{}, connection_pool.PreferRO)
28+
require.Nilf(t, err, "failed to Call")
29+
require.NotNilf(t, resp, "response is nil after Call")
30+
require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Call")
31+
32+
val := resp.Data[0].([]interface{})[0].(map[interface{}]interface{})["ro"]
33+
ro, ok := val.(bool)
34+
require.Truef(t, ok, "expected `true` with mode `PreferRO`")
35+
require.Truef(t, ro, "expected `true` with mode `PreferRO`")
36+
37+
// PreferRW
38+
resp, err = connPool.Call("box.info", []interface{}{}, connection_pool.PreferRW)
39+
require.Nilf(t, err, "failed to Call")
40+
require.NotNilf(t, resp, "response is nil after Call")
41+
require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Call")
42+
43+
val = resp.Data[0].([]interface{})[0].(map[interface{}]interface{})["ro"]
44+
ro, ok = val.(bool)
45+
require.Truef(t, ok, "expected `false` with mode `PreferRW`")
46+
require.Falsef(t, ro, "expected `false` with mode `PreferRW`")
47+
48+
// RO
49+
resp, err = connPool.Call("box.info", []interface{}{}, connection_pool.RO)
50+
require.Nilf(t, err, "failed to Call")
51+
require.NotNilf(t, resp, "response is nil after Call")
52+
require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Call")
53+
54+
val = resp.Data[0].([]interface{})[0].(map[interface{}]interface{})["ro"]
55+
ro, ok = val.(bool)
56+
require.Truef(t, ok, "expected `true` with mode `RO`")
57+
require.Truef(t, ro, "expected `true` with mode `RO`")
58+
59+
// RW
60+
resp, err = connPool.Call("box.info", []interface{}{}, connection_pool.RW)
61+
require.Nilf(t, err, "failed to Call")
62+
require.NotNilf(t, resp, "response is nil after Call")
63+
require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Call")
64+
65+
val = resp.Data[0].([]interface{})[0].(map[interface{}]interface{})["ro"]
66+
ro, ok = val.(bool)
67+
require.Truef(t, ok, "expected `false` with mode `RW`")
68+
require.Falsef(t, ro, "expected `false` with mode `RW`")
69+
}

connection_pool/call_17_test.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
//go:build go_tarantool_call_17
2+
// +build go_tarantool_call_17
3+
4+
package connection_pool_test
5+
6+
import (
7+
"testing"
8+
9+
"github.com/stretchr/testify/require"
10+
"github.com/tarantool/go-tarantool/connection_pool"
11+
"github.com/tarantool/go-tarantool/test_helpers"
12+
)
13+
14+
func TestCall(t *testing.T) {
15+
roles := []bool{false, true, false, false, true}
16+
17+
err := test_helpers.SetClusterRO(servers, connOpts, roles)
18+
require.Nilf(t, err, "fail to set roles for cluster")
19+
20+
connPool, err := connection_pool.Connect(servers, connOpts)
21+
require.Nilf(t, err, "failed to connect")
22+
require.NotNilf(t, connPool, "conn is nil after Connect")
23+
24+
defer connPool.Close()
25+
26+
// PreferRO
27+
resp, err := connPool.Call("box.info", []interface{}{}, connection_pool.PreferRO)
28+
require.Nilf(t, err, "failed to Call")
29+
require.NotNilf(t, resp, "response is nil after Call")
30+
require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Call")
31+
32+
val := resp.Data[0].(map[interface{}]interface{})["ro"]
33+
ro, ok := val.(bool)
34+
require.Truef(t, ok, "expected `true` with mode `PreferRO`")
35+
require.Truef(t, ro, "expected `true` with mode `PreferRO`")
36+
37+
// PreferRW
38+
resp, err = connPool.Call("box.info", []interface{}{}, connection_pool.PreferRW)
39+
require.Nilf(t, err, "failed to Call")
40+
require.NotNilf(t, resp, "response is nil after Call")
41+
require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Call")
42+
43+
val = resp.Data[0].(map[interface{}]interface{})["ro"]
44+
ro, ok = val.(bool)
45+
require.Truef(t, ok, "expected `false` with mode `PreferRW`")
46+
require.Falsef(t, ro, "expected `false` with mode `PreferRW`")
47+
48+
// RO
49+
resp, err = connPool.Call("box.info", []interface{}{}, connection_pool.RO)
50+
require.Nilf(t, err, "failed to Call")
51+
require.NotNilf(t, resp, "response is nil after Call")
52+
require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Call")
53+
54+
val = resp.Data[0].(map[interface{}]interface{})["ro"]
55+
ro, ok = val.(bool)
56+
require.Truef(t, ok, "expected `true` with mode `RO`")
57+
require.Truef(t, ro, "expected `true` with mode `RO`")
58+
59+
// RW
60+
resp, err = connPool.Call("box.info", []interface{}{}, connection_pool.RW)
61+
require.Nilf(t, err, "failed to Call")
62+
require.NotNilf(t, resp, "response is nil after Call")
63+
require.GreaterOrEqualf(t, len(resp.Data), 1, "response.Data is empty after Call")
64+
65+
val = resp.Data[0].(map[interface{}]interface{})["ro"]
66+
ro, ok = val.(bool)
67+
require.Truef(t, ok, "expected `false` with mode `RW`")
68+
require.Falsef(t, ro, "expected `false` with mode `RW`")
69+
}

0 commit comments

Comments
 (0)