From aa0842eb1fbb0de91544c521a3cff9b104e328a6 Mon Sep 17 00:00:00 2001 From: ice-cronus <105345303+ice-cronus@users.noreply.github.com> Date: Thu, 23 Mar 2023 13:00:59 +0300 Subject: [PATCH 1/2] PrepareExecute && PrepareExecuteTyped && UpsertTyped implementation and tests --- .testdata/tarantool_bootstrap_3301.lua | 57 ++++++ .testdata/tarantool_bootstrap_3302.lua | 56 ++++++ .testdata/tarantool_bootstrap_3303.lua | 56 ++++++ Makefile | 2 +- auth_test.go | 3 +- box_error_test.go | 5 +- call_16_test.go | 4 +- call_17_test.go | 4 +- connection.go | 54 ++++++ connection_pool/call_16_test.go | 5 +- connection_pool/call_17_test.go | 5 +- connection_pool/connection_pool.go | 51 ++++- connection_pool/connection_pool_test.go | 7 +- connection_pool/connector.go | 13 +- connection_pool/connector_test.go | 5 +- connection_pool/example_test.go | 6 +- connection_pool/pooler.go | 6 +- connection_pool/round_robin.go | 2 +- connection_pool/round_robin_test.go | 4 +- connection_pool/watcher.go | 2 +- connection_test.go | 141 +++++++++++++- connector.go | 3 + crud/common.go | 2 +- crud/count.go | 2 +- crud/delete.go | 2 +- crud/error_test.go | 2 +- crud/example_test.go | 4 +- crud/get.go | 2 +- crud/insert.go | 2 +- crud/insert_many.go | 2 +- crud/len.go | 2 +- crud/max.go | 2 +- crud/min.go | 2 +- crud/replace.go | 2 +- crud/replace_many.go | 2 +- crud/request_test.go | 6 +- crud/select.go | 2 +- crud/stats.go | 2 +- crud/storage_info.go | 2 +- crud/tarantool_test.go | 6 +- crud/truncate.go | 2 +- crud/update.go | 2 +- crud/upsert.go | 2 +- crud/upsert_many.go | 2 +- datetime/datetime_test.go | 6 +- datetime/example_test.go | 4 +- datetime/interval_test.go | 4 +- datetime/msgpack_helper_test.go | 2 +- datetime/msgpack_v5_helper_test.go | 3 +- decimal/decimal_test.go | 7 +- decimal/example_test.go | 4 +- decimal/fuzzing_test.go | 3 +- decimal/msgpack_helper_test.go | 2 +- decimal/msgpack_v5_helper_test.go | 3 +- dial_test.go | 2 +- errors.go | 235 ++++++++++++++++++++++++ example_custom_unpacking_test.go | 2 +- example_test.go | 4 +- future_test.go | 2 +- go.mod | 8 +- go.sum | 20 ++ msgpack_helper_test.go | 3 +- msgpack_v5.go | 1 + msgpack_v5_helper_test.go | 3 +- multi/call_16_test.go | 2 +- multi/call_17_test.go | 2 +- multi/example_test.go | 2 +- multi/multi.go | 12 +- multi/multi_test.go | 4 +- protocol_test.go | 2 +- queue/example_connection_pool_test.go | 9 +- queue/example_msgpack_test.go | 4 +- queue/example_test.go | 4 +- queue/queue.go | 3 +- queue/queue_test.go | 6 +- request.go | 3 + request_test.go | 4 +- settings/example_test.go | 6 +- settings/msgpack_helper_test.go | 3 +- settings/msgpack_v5_helper_test.go | 3 +- settings/request.go | 2 +- settings/request_test.go | 5 +- settings/tarantool_test.go | 7 +- shutdown_test.go | 5 +- ssl_test.go | 5 +- tarantool_test.go | 5 +- test_helpers/main.go | 2 +- test_helpers/pool_helper.go | 4 +- test_helpers/request_mock.go | 2 +- test_helpers/utils.go | 3 +- uuid/example_test.go | 5 +- uuid/uuid_test.go | 7 +- 92 files changed, 851 insertions(+), 133 deletions(-) create mode 100644 .testdata/tarantool_bootstrap_3301.lua create mode 100644 .testdata/tarantool_bootstrap_3302.lua create mode 100644 .testdata/tarantool_bootstrap_3303.lua diff --git a/.testdata/tarantool_bootstrap_3301.lua b/.testdata/tarantool_bootstrap_3301.lua new file mode 100644 index 000000000..a828721c5 --- /dev/null +++ b/.testdata/tarantool_bootstrap_3301.lua @@ -0,0 +1,57 @@ +#!/usr/bin/env tarantool +-- Details: https:www.tarantool.io/en/doc/latest/reference/configuration/ +box.cfg{ + work_dir = '/tmp/tarantool_data/3301', + memtx_dir = '/tmp/tarantool_data/3301/memtx', + wal_dir = '/tmp/tarantool_data/3301/wal', + memtx_memory = 1048576000, -- 100Mb + sql_cache_size = 104857600, -- 100Mb + memtx_use_mvcc_engine = true, + pid_file = "tarantool3301.pid", + worker_pool_threads = 16, + iproto_threads = 8, + listen = 3301, + checkpoint_interval = 0, + replication_synchro_quorum = 3, + replication_synchro_timeout = 10, + election_mode = 'candidate', + replication = { + 'replicator:password@localhost:3301', + 'replicator:password@localhost:3302', + 'replicator:password@localhost:3303' + }, + read_only = false, +} + +box.once("schema", function() + box.schema.user.create('replicator', {password = 'password'}) + box.schema.user.grant('replicator', 'replication') + + box.schema.user.passwd('pass') + + box.execute([[CREATE TABLE IF NOT EXISTS test_table ( + id VARCHAR(40) primary key , + name VARCHAR(100) NOT NULL, + type int NOT NULL + );]]) + + box.execute([[CREATE UNIQUE INDEX IF NOT EXISTS t_idx_1 ON test_table (name, type);]]) + + box.space.TEST_TABLE:alter({is_sync = true}) + + print('box.once executed') +end) + +function get_cluster_members() + a = {} + a["uri"] = 'localhost:3301' + a["type"] = 'writable' + b = {} + b["uri"] = 'localhost:3302' + b["type"] = 'non-writable' + c = {} + c["uri"] = 'localhost:3303' + c["type"] = 'non-writable' + + return { a, b, c } +end diff --git a/.testdata/tarantool_bootstrap_3302.lua b/.testdata/tarantool_bootstrap_3302.lua new file mode 100644 index 000000000..8c74f781e --- /dev/null +++ b/.testdata/tarantool_bootstrap_3302.lua @@ -0,0 +1,56 @@ +#!/usr/bin/env tarantool +-- Details: https:www.tarantool.io/en/doc/latest/reference/configuration/ +box.cfg{ + work_dir = '/tmp/tarantool_data/3302', + memtx_dir = '/tmp/tarantool_data/3302/memtx', + wal_dir = '/tmp/tarantool_data/3302/wal', + memtx_memory = 1048576000, -- 100Mb + sql_cache_size = 104857600, -- 100Mb + memtx_use_mvcc_engine = true, + pid_file = "tarantool3302.pid", + worker_pool_threads = 16, + iproto_threads = 8, + listen = 3302, + checkpoint_interval = 0, + replication_synchro_quorum = 3, + replication_synchro_timeout = 10, + election_mode = 'voter', + replication = { + 'replicator:password@localhost:3301', + 'replicator:password@localhost:3302', + 'replicator:password@localhost:3303' + }, + read_only = false, +} + +box.once("schema", function() + box.schema.user.create('replicator', {password = 'password'}) + box.schema.user.grant('replicator', 'replication') + + box.schema.user.passwd('pass') + + box.execute([[CREATE TABLE IF NOT EXISTS test_table ( + id VARCHAR(40) primary key , + name VARCHAR(100) NOT NULL, + type int NOT NULL + );]]) + + box.execute([[CREATE UNIQUE INDEX IF NOT EXISTS t_idx_1 ON test_table (name, type);]]) + box.space.TEST_TABLE:alter({is_sync = true}) + + print('box.once executed') +end) + +function get_cluster_members() + a = {} + a["uri"] = 'localhost:3301' + a["type"] = 'writable' + b = {} + b["uri"] = 'localhost:3302' + b["type"] = 'non-writable' + c = {} + c["uri"] = 'localhost:3303' + c["type"] = 'non-writable' + + return { a, b, c } +end diff --git a/.testdata/tarantool_bootstrap_3303.lua b/.testdata/tarantool_bootstrap_3303.lua new file mode 100644 index 000000000..c4ac6173c --- /dev/null +++ b/.testdata/tarantool_bootstrap_3303.lua @@ -0,0 +1,56 @@ +#!/usr/bin/env tarantool +-- Details: https:www.tarantool.io/en/doc/latest/reference/configuration/ +box.cfg{ + work_dir = '/tmp/tarantool_data/3303', + memtx_dir = '/tmp/tarantool_data/3303/memtx', + wal_dir = '/tmp/tarantool_data/3303/wal', + memtx_memory = 1048576000, -- 100Mb + sql_cache_size = 104857600, -- 100Mb + memtx_use_mvcc_engine = true, + pid_file = "tarantool3303.pid", + worker_pool_threads = 16, + iproto_threads = 8, + listen = 3303, + checkpoint_interval = 0, + replication_synchro_quorum = 3, + replication_synchro_timeout = 10, + election_mode = 'voter', + replication = { + 'replicator:password@localhost:3301', + 'replicator:password@localhost:3302', + 'replicator:password@localhost:3303' + }, + read_only = false, +} + +box.once("schema", function() + box.schema.user.create('replicator', {password = 'password'}) + box.schema.user.grant('replicator', 'replication') + + box.schema.user.passwd('pass') + + box.execute([[CREATE TABLE IF NOT EXISTS test_table ( + id VARCHAR(40) primary key , + name VARCHAR(100) NOT NULL, + type int NOT NULL + );]]) + + box.execute([[CREATE UNIQUE INDEX IF NOT EXISTS t_idx_1 ON test_table (name, type);]]) + box.space.TEST_TABLE:alter({is_sync = true}) + + print('box.once executed') +end) + +function get_cluster_members() + a = {} + a["uri"] = 'localhost:3301' + a["type"] = 'writable' + b = {} + b["uri"] = 'localhost:3302' + b["type"] = 'non-writable' + c = {} + c["uri"] = 'localhost:3303' + c["type"] = 'non-writable' + + return { a, b, c } +end diff --git a/Makefile b/Makefile index 2f4dd8d93..fef26fa31 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ BENCH_REFERENCE_REPO := ${BENCH_PATH}/go-tarantool BENCH_OPTIONS := -bench=. -run=^Benchmark -benchmem -benchtime=${DURATION} -count=${COUNT} GO_TARANTOOL_URL := https://github.com/tarantool/go-tarantool GO_TARANTOOL_DIR := ${PROJECT_DIR}/${BENCH_PATH}/go-tarantool -TAGS := +TAGS := go_tarantool_msgpack_v5,go_tarantool_ssl_disable TTCTL := tt ifeq (,$(shell which tt 2>/dev/null)) TTCTL := tarantoolctl diff --git a/auth_test.go b/auth_test.go index 6964f2552..f3866299c 100644 --- a/auth_test.go +++ b/auth_test.go @@ -5,7 +5,8 @@ import ( "testing" "github.com/stretchr/testify/assert" - . "github.com/tarantool/go-tarantool" + + . "github.com/ice-blockchain/go-tarantool" ) func TestAuth_String(t *testing.T) { diff --git a/box_error_test.go b/box_error_test.go index 276ca2cf8..9e71c78f6 100644 --- a/box_error_test.go +++ b/box_error_test.go @@ -6,8 +6,9 @@ import ( "testing" "github.com/stretchr/testify/require" - . "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/test_helpers" + + . "github.com/ice-blockchain/go-tarantool" + "github.com/ice-blockchain/go-tarantool/test_helpers" ) var samples = map[string]BoxError{ diff --git a/call_16_test.go b/call_16_test.go index f23f0f783..1f4725f37 100644 --- a/call_16_test.go +++ b/call_16_test.go @@ -6,8 +6,8 @@ package tarantool_test import ( "testing" - . "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/test_helpers" + . "github.com/ice-blockchain/go-tarantool" + "github.com/ice-blockchain/go-tarantool/test_helpers" ) func TestConnection_Call(t *testing.T) { diff --git a/call_17_test.go b/call_17_test.go index 824ed850b..567d68814 100644 --- a/call_17_test.go +++ b/call_17_test.go @@ -6,8 +6,8 @@ package tarantool_test import ( "testing" - . "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/test_helpers" + . "github.com/ice-blockchain/go-tarantool" + "github.com/ice-blockchain/go-tarantool/test_helpers" ) func TestConnection_Call(t *testing.T) { diff --git a/connection.go b/connection.go index 7da3f26d0..cc909f74c 100644 --- a/connection.go +++ b/connection.go @@ -11,6 +11,7 @@ import ( "log" "math" "runtime" + "strings" "sync" "sync/atomic" "time" @@ -172,6 +173,9 @@ type Connection struct { shutdownWatcher Watcher // requestCnt is a counter of active requests. requestCnt int64 + + sqlPreparedStatementCache sync.Map //map[string]*Prepared + cacheMx sync.Mutex } var _ = Connector(&Connection{}) // Check compatibility with connector interface. @@ -1252,6 +1256,56 @@ func (conn *Connection) NewPrepared(expr string) (*Prepared, error) { return NewPreparedFromResponse(conn, resp) } +func (conn *Connection) prepareExecute(f func(future *Future) (*Response, error), expr string, args map[string]interface{}) (*Response, error) { + if preparedStatement, prepareErr := conn.sqlPreparedStatement(expr); prepareErr != nil { + return nil, prepareErr + } else { + executeReq := NewExecutePreparedRequest(preparedStatement).Args(args) + fut := conn.Do(executeReq) + r, err := f(fut) + if err != nil { + if ter, ok := err.(Error); ok && + (ter.Code == ER_WRONG_QUERY_ID || (ter.Code == ER_SQL_EXECUTE && strings.Contains(ter.Msg, "statement has expired"))) { + conn.cacheMx.Lock() + conn.sqlPreparedStatementCache.Delete(expr) + conn.cacheMx.Unlock() + return conn.prepareExecute(f, expr, args) + } + } + return r, err + } +} + +func (conn *Connection) PrepareExecute(sql string, args map[string]interface{}) (resp *Response, err error) { + return conn.prepareExecute(func(fut *Future) (*Response, error) { return fut.Get() }, sql, args) +} + +func (conn *Connection) PrepareExecuteTyped(sql string, args map[string]interface{}, result interface{}) (err error) { + _, err = conn.prepareExecute(func(fut *Future) (*Response, error) { return nil, fut.GetTyped(result) }, sql, args) + return +} + +func (conn *Connection) PrepareExecuteAsync(sql string, args map[string]interface{}) (resp *Future) { + _, _ = conn.prepareExecute(func(fut *Future) (*Response, error) { resp = fut; return nil, nil }, sql, args) + return +} +func (conn *Connection) sqlPreparedStatement(sql string) (prepared *Prepared, err error) { + if preparedIf, ok := conn.sqlPreparedStatementCache.Load(sql); ok { + prepared = preparedIf.(*Prepared) + } else { + conn.cacheMx.Lock() + defer conn.cacheMx.Unlock() + if preparedIf, ok = conn.sqlPreparedStatementCache.Load(sql); ok { + prepared = preparedIf.(*Prepared) + } else { + if prepared, err = conn.NewPrepared(sql); err == nil { + conn.sqlPreparedStatementCache.Store(sql, prepared) + } + } + } + return +} + // NewStream creates new Stream object for connection. // // Since v. 2.10.0, Tarantool supports streams and interactive transactions over them. diff --git a/connection_pool/call_16_test.go b/connection_pool/call_16_test.go index bf2ab2eb7..56d3ed7f5 100644 --- a/connection_pool/call_16_test.go +++ b/connection_pool/call_16_test.go @@ -7,8 +7,9 @@ import ( "testing" "github.com/stretchr/testify/require" - "github.com/tarantool/go-tarantool/connection_pool" - "github.com/tarantool/go-tarantool/test_helpers" + + "github.com/ice-blockchain/go-tarantool/connection_pool" + "github.com/ice-blockchain/go-tarantool/test_helpers" ) func TestCall(t *testing.T) { diff --git a/connection_pool/call_17_test.go b/connection_pool/call_17_test.go index 94e5bb888..1978ec8e8 100644 --- a/connection_pool/call_17_test.go +++ b/connection_pool/call_17_test.go @@ -7,8 +7,9 @@ import ( "testing" "github.com/stretchr/testify/require" - "github.com/tarantool/go-tarantool/connection_pool" - "github.com/tarantool/go-tarantool/test_helpers" + + "github.com/ice-blockchain/go-tarantool/connection_pool" + "github.com/ice-blockchain/go-tarantool/test_helpers" ) func TestCall(t *testing.T) { diff --git a/connection_pool/connection_pool.go b/connection_pool/connection_pool.go index 569669be4..3d1ec0cdc 100644 --- a/connection_pool/connection_pool.go +++ b/connection_pool/connection_pool.go @@ -11,13 +11,15 @@ package connection_pool import ( + "context" "errors" "fmt" "log" + "runtime" "sync" "time" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) var ( @@ -108,6 +110,31 @@ type connState struct { conn *tarantool.Connection role Role } +type BasicAuth struct { + User, Pass string +} + +func ConnectWithWritableAwareDefaults(ctx context.Context, cancel context.CancelFunc, requiresWrite bool, auth BasicAuth, addresses ...string) (tarantool.Connector, error) { + conOpts := tarantool.Opts{ + Timeout: 10 * time.Second, + MaxReconnects: 10, + User: auth.User, + Pass: auth.Pass, + Concurrency: 128 * uint32(runtime.GOMAXPROCS(-1)), + } + poolOpts := OptsPool{ + CheckTimeout: 2 * time.Second, + } + pool, err := ConnectWithOpts(addresses, conOpts, poolOpts) + if err != nil { + return nil, err + } + mode := RO + if requiresWrite { + mode = RW + } + return NewConnectorAdapter(pool, mode), nil +} // ConnectWithOpts creates pool for instances with addresses addrs // with options opts. @@ -341,6 +368,14 @@ func (connPool *ConnectionPool) Upsert(space interface{}, tuple, ops interface{} return conn.Upsert(space, tuple, ops) } +func (connPool *ConnectionPool) UpsertTyped(space, tuple, ops, result interface{}, mode ...Mode) (err error) { + conn, err := connPool.getConnByMode(RW, mode) + if err != nil { + return err + } + return conn.UpsertTyped(space, tuple, ops, result) +} + // Call16 calls registered Tarantool function. // It uses request code for Tarantool >= 1.7 if go-tarantool // was build with go_tarantool_call_17 tag. @@ -517,6 +552,20 @@ func (connPool *ConnectionPool) ExecuteTyped(expr string, args interface{}, resu return conn.ExecuteTyped(expr, args, result) } +func (connPool *ConnectionPool) PrepareExecuteTyped(sql string, args map[string]interface{}, result interface{}, userMode Mode) (err error) { + conn, err := connPool.getNextConnection(userMode) + if err != nil { + return err + } + return conn.PrepareExecuteTyped(sql, args, result) +} +func (connPool *ConnectionPool) PrepareExecute(sql string, args map[string]interface{}, userMode Mode) (r *tarantool.Response, err error) { + conn, err := connPool.getNextConnection(userMode) + if err != nil { + return nil, err + } + return conn.PrepareExecute(sql, args) +} // 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 { diff --git a/connection_pool/connection_pool_test.go b/connection_pool/connection_pool_test.go index 860786fbe..c0ac6cd2f 100644 --- a/connection_pool/connection_pool_test.go +++ b/connection_pool/connection_pool_test.go @@ -12,9 +12,10 @@ import ( "time" "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/ice-blockchain/go-tarantool" + "github.com/ice-blockchain/go-tarantool/connection_pool" + "github.com/ice-blockchain/go-tarantool/test_helpers" ) var spaceNo = uint32(520) diff --git a/connection_pool/connector.go b/connection_pool/connector.go index c108aba0b..2488adfeb 100644 --- a/connection_pool/connector.go +++ b/connection_pool/connector.go @@ -5,7 +5,7 @@ import ( "fmt" "time" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) // ConnectorAdapter allows to use Pooler as Connector. @@ -97,6 +97,10 @@ func (c *ConnectorAdapter) Upsert(space interface{}, tuple, ops interface{}) (*tarantool.Response, error) { return c.pool.Upsert(space, tuple, ops, c.mode) } +func (c *ConnectorAdapter) UpsertTyped(space interface{}, + tuple, ops, result interface{}) error { + return c.pool.UpsertTyped(space, tuple, ops, result, c.mode) +} // Call calls registered Tarantool function. // It uses request code for Tarantool >= 1.7 if go-tarantool @@ -135,6 +139,10 @@ func (c *ConnectorAdapter) Execute(expr string, return c.pool.Execute(expr, args, c.mode) } +func (c *ConnectorAdapter) PrepareExecute(sql string, args map[string]interface{}) (resp *tarantool.Response, err error) { + return c.pool.PrepareExecute(sql, args, c.mode) +} + // GetTyped performs select (with limit = 1 and offset = 0) // to box space and fills typed result. func (c *ConnectorAdapter) GetTyped(space, index interface{}, @@ -288,6 +296,9 @@ func (c *ConnectorAdapter) ExecuteAsync(expr string, func (c *ConnectorAdapter) NewPrepared(expr string) (*tarantool.Prepared, error) { return c.pool.NewPrepared(expr, c.mode) } +func (c *ConnectorAdapter) PrepareExecuteTyped(sql string, args map[string]interface{}, result interface{}) (err error) { + return c.pool.PrepareExecuteTyped(sql, args, result, c.mode) +} // NewStream creates new Stream object for connection. // diff --git a/connection_pool/connector_test.go b/connection_pool/connector_test.go index f53a05b22..3e9a4108d 100644 --- a/connection_pool/connector_test.go +++ b/connection_pool/connector_test.go @@ -7,8 +7,9 @@ import ( "time" "github.com/stretchr/testify/require" - "github.com/tarantool/go-tarantool" - . "github.com/tarantool/go-tarantool/connection_pool" + + "github.com/ice-blockchain/go-tarantool" + . "github.com/ice-blockchain/go-tarantool/connection_pool" ) var testMode Mode = RW diff --git a/connection_pool/example_test.go b/connection_pool/example_test.go index cf59455ca..773a0c8eb 100644 --- a/connection_pool/example_test.go +++ b/connection_pool/example_test.go @@ -4,9 +4,9 @@ import ( "fmt" "time" - "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/connection_pool" - "github.com/tarantool/go-tarantool/test_helpers" + "github.com/ice-blockchain/go-tarantool" + "github.com/ice-blockchain/go-tarantool/connection_pool" + "github.com/ice-blockchain/go-tarantool/test_helpers" ) type Tuple struct { diff --git a/connection_pool/pooler.go b/connection_pool/pooler.go index 856f5d5be..71b1f32b6 100644 --- a/connection_pool/pooler.go +++ b/connection_pool/pooler.go @@ -3,7 +3,7 @@ package connection_pool import ( "time" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) // Pooler is the interface that must be implemented by a connection pool. @@ -35,6 +35,7 @@ type Pooler interface { mode Mode) (*tarantool.Response, error) Execute(expr string, args interface{}, mode Mode) (*tarantool.Response, error) + PrepareExecute(sql string, args map[string]interface{}, mode Mode) (resp *tarantool.Response, err error) GetTyped(space, index interface{}, key interface{}, result interface{}, mode ...Mode) error @@ -48,6 +49,7 @@ type Pooler interface { mode ...Mode) error UpdateTyped(space, index interface{}, key, ops interface{}, result interface{}, mode ...Mode) error + UpsertTyped(space, tuple, ops, result interface{}, mode ...Mode) (err error) CallTyped(functionName string, args interface{}, result interface{}, mode Mode) error Call16Typed(functionName string, args interface{}, result interface{}, @@ -58,6 +60,8 @@ type Pooler interface { mode Mode) error ExecuteTyped(expr string, args interface{}, result interface{}, mode Mode) (tarantool.SQLInfo, []tarantool.ColumnMetaData, error) + PrepareExecuteTyped(sql string, args map[string]interface{}, result interface{}, + mode Mode) (err error) SelectAsync(space, index interface{}, offset, limit, iterator uint32, key interface{}, mode ...Mode) *tarantool.Future diff --git a/connection_pool/round_robin.go b/connection_pool/round_robin.go index a7fb73e18..8b7b8713d 100644 --- a/connection_pool/round_robin.go +++ b/connection_pool/round_robin.go @@ -3,7 +3,7 @@ package connection_pool import ( "sync" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) type RoundRobinStrategy struct { diff --git a/connection_pool/round_robin_test.go b/connection_pool/round_robin_test.go index 03038eada..cb62aa29f 100644 --- a/connection_pool/round_robin_test.go +++ b/connection_pool/round_robin_test.go @@ -3,8 +3,8 @@ package connection_pool_test import ( "testing" - "github.com/tarantool/go-tarantool" - . "github.com/tarantool/go-tarantool/connection_pool" + "github.com/ice-blockchain/go-tarantool" + . "github.com/ice-blockchain/go-tarantool/connection_pool" ) const ( diff --git a/connection_pool/watcher.go b/connection_pool/watcher.go index d60cfa171..f83aa9857 100644 --- a/connection_pool/watcher.go +++ b/connection_pool/watcher.go @@ -3,7 +3,7 @@ package connection_pool import ( "sync" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) // watcherContainer is a very simple implementation of a thread-safe container diff --git a/connection_test.go b/connection_test.go index 05f29b093..b9800683d 100644 --- a/connection_test.go +++ b/connection_test.go @@ -1,11 +1,19 @@ package tarantool_test import ( + "context" + "errors" + "fmt" + "sync" "testing" + "time" + "github.com/google/uuid" "github.com/stretchr/testify/require" - . "github.com/tarantool/go-tarantool" + . "github.com/ice-blockchain/go-tarantool" + "github.com/ice-blockchain/go-tarantool/connection_pool" + "github.com/ice-blockchain/go-tarantool/test_helpers" ) func TestOptsClonePreservesRequiredProtocolFeatures(t *testing.T) { @@ -29,3 +37,134 @@ func TestOptsClonePreservesRequiredProtocolFeatures(t *testing.T) { }, }) } + +func TestPrepareExecuteBlackbox(t *testing.T) { + ttShutdown, _, err := setTarantoolCluster("3301", "3302", "3303") + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + db, err := connection_pool.ConnectWithWritableAwareDefaults(ctx, cancel, true, connection_pool.BasicAuth{"admin", "pass"}, + "localhost:3301", + "localhost:3302", + "localhost:3303", + "bogus:2322", + ) + defer func(db Connector) { + if db != nil { + if cErr := db.Close(); cErr != nil { + panic(cErr) + } + if db.ConnectedNow() { + panic("still connected") + } + } + ttShutdown() + }(db) + if err != nil { + panic(fmt.Sprintf("Could not connect to cluster %v", err)) + } + var wg sync.WaitGroup + for i := 0; i < 100; i++ { + wg.Add(1) + go func() { + defer wg.Done() + execPrepareExecute(ctx, db) + }() + } + wg.Wait() +} + +func execPrepareExecute(ctx context.Context, db Connector) { + for ctx != nil && ctx.Err() == nil { + id := uuid.New().String() + id2 := uuid.New().String() + if db == nil || ctx == nil { + return + } + if r, rErr := db.PrepareExecute("INSERT into test_table(id, name, type) values (:id,:name,:type)", map[string]interface{}{"name": id2, "type": 3, "id": id}); (rErr != nil && !errors.Is(rErr, ctx.Err())) || r.Code != OkCode { + if r == nil || r.Code != ER_TUPLE_FOUND { + panic(errors.New(fmt.Sprintf("Insert failed because: %v --- %v\n", rErr, r))) + } + } + if db == nil || ctx == nil { + return + } + if r, rErr := db.PrepareExecute("SELECT * from test_table where name=:name and type=:type", map[string]interface{}{"name": id2, "type": 3}); (rErr != nil && !errors.Is(rErr, ctx.Err())) || r.Code != OkCode { + //if r, rErr := db.Select("TEST_TABLE", "T_IDX_1", 0, 1, tarantool.IterEq, []interface{}{id2, 3}); (rErr != nil && !errors.Is(rErr, ctx.Err())) || r.Code != tarantool.OkCode { + panic(errors.New(fmt.Sprintf("Query failed because: %v------%v\n", rErr, r))) + } else { + if rErr != nil && !errors.Is(rErr, ctx.Err()) { + panic(rErr) + } + if len(r.Tuples()) != 0 { + single := r.Tuples()[0] + if single[0].(string) != id { + panic(errors.New(fmt.Sprintf("expected:%v actual:%v", id, single[0].(string)))) + } + } else { + fmt.Sprintln("Query returned nothing") + } + } + if db == nil || ctx == nil { + return + } + if r, rErr := db.PrepareExecute("DELETE from test_table where name=:name and type=:type", map[string]interface{}{"name": id2, "type": 3}); (rErr != nil && !errors.Is(rErr, ctx.Err())) || r.Code != OkCode { + //if r, rErr := db.Delete("TEST_TABLE", "T_IDX_1", []interface{}{id2, 3}); (rErr != nil && !errors.Is(rErr, ctx.Err())) || r.Code != tarantool.OkCode { + if r == nil || r.Code != ER_TUPLE_NOT_FOUND { + panic(errors.New(fmt.Sprintf("Delete failed because: %v --- %v\n", rErr, r))) + } + } + } + +} + +func TestPrepareExecuteConnectionReestablished(t *testing.T) { + ttShutdown, _, err := setTarantoolCluster("3301", "3302", "3303") + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + db, err := connection_pool.ConnectWithWritableAwareDefaults(ctx, cancel, true, connection_pool.BasicAuth{"admin", "pass"}, + "localhost:3301", + "localhost:3302", + "localhost:3303", + "bogus:2322", + ) + defer func(db Connector) { + if db != nil { + if cErr := db.Close(); cErr != nil { + panic(cErr) + } + if db.ConnectedNow() { + panic("still connected") + } + } + ttShutdown() + }(db) + if err != nil { + panic(fmt.Sprintf("Could not connect to cluster %v", err)) + } + execPrepareExecute(ctx, db) + ttShutdown() + ttShutdown, _, err = setTarantoolCluster("3301", "3302", "3303") + execPrepareExecute(ctx, db) +} + +func setTarantoolCluster(ports ...string) (func(), []test_helpers.TarantoolInstance, error) { + tts := make([]test_helpers.TarantoolInstance, len(ports)) + for i, p := range ports { + var err error + tts[i], err = test_helpers.StartTarantool(test_helpers.StartOpts{ + InitScript: fmt.Sprintf("./.testdata/tarantool_bootstrap_%v.lua", p), + Listen: fmt.Sprintf("127.0.0.1:%v", p), + User: "admin", + Pass: "pass", + ConnectRetry: 5, + RetryTimeout: 1 * time.Second, + WaitStart: time.Duration(i * int(5*time.Second)), + }) + if err != nil { + panic(err) + } + } + return func() { + for _, tt := range tts { + test_helpers.StopTarantoolWithCleanup(tt) + } + }, tts, nil +} diff --git a/connector.go b/connector.go index d93c69ec8..50ba6ee07 100644 --- a/connector.go +++ b/connector.go @@ -19,6 +19,7 @@ type Connector interface { Call17(functionName string, args interface{}) (resp *Response, err error) Eval(expr string, args interface{}) (resp *Response, err error) Execute(expr string, args interface{}) (resp *Response, err error) + PrepareExecute(sql string, args map[string]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) @@ -26,11 +27,13 @@ type Connector interface { ReplaceTyped(space interface{}, tuple interface{}, result interface{}) (err error) DeleteTyped(space, index interface{}, key interface{}, result interface{}) (err error) UpdateTyped(space, index interface{}, key, ops interface{}, result interface{}) (err error) + UpsertTyped(space, tuple, ops, result interface{}) (err error) CallTyped(functionName string, args interface{}, result interface{}) (err error) Call16Typed(functionName string, args interface{}, result interface{}) (err error) Call17Typed(functionName string, args interface{}, result interface{}) (err error) EvalTyped(expr string, args interface{}, result interface{}) (err error) ExecuteTyped(expr string, args interface{}, result interface{}) (SQLInfo, []ColumnMetaData, error) + PrepareExecuteTyped(sql string, args map[string]interface{}, result interface{}) (err error) SelectAsync(space, index interface{}, offset, limit, iterator uint32, key interface{}) *Future InsertAsync(space interface{}, tuple interface{}) *Future diff --git a/crud/common.go b/crud/common.go index 2c4a3030c..a64426634 100644 --- a/crud/common.go +++ b/crud/common.go @@ -56,7 +56,7 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) type baseRequest struct { diff --git a/crud/count.go b/crud/count.go index 68e29f9fb..2ffc1f0bc 100644 --- a/crud/count.go +++ b/crud/count.go @@ -3,7 +3,7 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) // CountResult describes result for `crud.count` method. diff --git a/crud/delete.go b/crud/delete.go index 5859d3d6b..2689c8873 100644 --- a/crud/delete.go +++ b/crud/delete.go @@ -3,7 +3,7 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) // DeleteOpts describes options for `crud.delete` method. diff --git a/crud/error_test.go b/crud/error_test.go index 8bd973399..de784f205 100644 --- a/crud/error_test.go +++ b/crud/error_test.go @@ -3,8 +3,8 @@ package crud_test import ( "testing" + "github.com/ice-blockchain/go-tarantool/crud" "github.com/stretchr/testify/require" - "github.com/tarantool/go-tarantool/crud" ) func TestErrorMany(t *testing.T) { diff --git a/crud/example_test.go b/crud/example_test.go index 3f2ebbf88..b3f16c548 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/ice-blockchain/go-tarantool" + "github.com/ice-blockchain/go-tarantool/crud" ) const ( diff --git a/crud/get.go b/crud/get.go index 9f65a34fd..9973548dc 100644 --- a/crud/get.go +++ b/crud/get.go @@ -3,7 +3,7 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) // GetOpts describes options for `crud.get` method. diff --git a/crud/insert.go b/crud/insert.go index b8c34c9bd..11773c964 100644 --- a/crud/insert.go +++ b/crud/insert.go @@ -3,7 +3,7 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) // InsertOpts describes options for `crud.insert` method. diff --git a/crud/insert_many.go b/crud/insert_many.go index 9d2194642..403ed10e0 100644 --- a/crud/insert_many.go +++ b/crud/insert_many.go @@ -3,7 +3,7 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) // InsertManyOpts describes options for `crud.insert_many` method. diff --git a/crud/len.go b/crud/len.go index 8ebea253c..bed8a5d34 100644 --- a/crud/len.go +++ b/crud/len.go @@ -3,7 +3,7 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) // LenResult describes result for `crud.len` method. diff --git a/crud/max.go b/crud/max.go index fda960040..173ec0861 100644 --- a/crud/max.go +++ b/crud/max.go @@ -3,7 +3,7 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) // MaxOpts describes options for `crud.max` method. diff --git a/crud/min.go b/crud/min.go index 53794b21e..e77888d77 100644 --- a/crud/min.go +++ b/crud/min.go @@ -3,7 +3,7 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) // MinOpts describes options for `crud.min` method. diff --git a/crud/replace.go b/crud/replace.go index 378a1ae22..9fd07499a 100644 --- a/crud/replace.go +++ b/crud/replace.go @@ -3,7 +3,7 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) // ReplaceOpts describes options for `crud.replace` method. diff --git a/crud/replace_many.go b/crud/replace_many.go index 511d60575..a6b89383e 100644 --- a/crud/replace_many.go +++ b/crud/replace_many.go @@ -3,7 +3,7 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) // ReplaceManyOpts describes options for `crud.replace_many` method. diff --git a/crud/request_test.go b/crud/request_test.go index 3198a39c0..1ed2329f1 100644 --- a/crud/request_test.go +++ b/crud/request_test.go @@ -6,9 +6,9 @@ import ( "errors" "testing" - "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/crud" - "github.com/tarantool/go-tarantool/test_helpers" + "github.com/ice-blockchain/go-tarantool" + "github.com/ice-blockchain/go-tarantool/crud" + "github.com/ice-blockchain/go-tarantool/test_helpers" ) const invalidSpaceMsg = "invalid space" diff --git a/crud/select.go b/crud/select.go index 97048a365..519f4050c 100644 --- a/crud/select.go +++ b/crud/select.go @@ -3,7 +3,7 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) // SelectOpts describes options for `crud.select` method. diff --git a/crud/stats.go b/crud/stats.go index aa4184746..0a95ff640 100644 --- a/crud/stats.go +++ b/crud/stats.go @@ -3,7 +3,7 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) // StatsRequest helps you to create request object to call `crud.stats` diff --git a/crud/storage_info.go b/crud/storage_info.go index 625029b51..951426aff 100644 --- a/crud/storage_info.go +++ b/crud/storage_info.go @@ -3,7 +3,7 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) // StatusTable describes information for instance. diff --git a/crud/tarantool_test.go b/crud/tarantool_test.go index 71f7d62b1..d2cbe279f 100644 --- a/crud/tarantool_test.go +++ b/crud/tarantool_test.go @@ -7,10 +7,10 @@ import ( "testing" "time" + "github.com/ice-blockchain/go-tarantool" + "github.com/ice-blockchain/go-tarantool/crud" + "github.com/ice-blockchain/go-tarantool/test_helpers" "github.com/stretchr/testify/require" - "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/crud" - "github.com/tarantool/go-tarantool/test_helpers" ) var server = "127.0.0.1:3013" diff --git a/crud/truncate.go b/crud/truncate.go index 1cd343a4d..c9276ae18 100644 --- a/crud/truncate.go +++ b/crud/truncate.go @@ -3,7 +3,7 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) // TruncateResult describes result for `crud.truncate` method. diff --git a/crud/update.go b/crud/update.go index 40951c95a..28fdbdb20 100644 --- a/crud/update.go +++ b/crud/update.go @@ -3,7 +3,7 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) // UpdateOpts describes options for `crud.update` method. diff --git a/crud/upsert.go b/crud/upsert.go index c116bbca5..36fb5ad8f 100644 --- a/crud/upsert.go +++ b/crud/upsert.go @@ -3,7 +3,7 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) // UpsertOpts describes options for `crud.upsert` method. diff --git a/crud/upsert_many.go b/crud/upsert_many.go index a195f5efa..f688855ca 100644 --- a/crud/upsert_many.go +++ b/crud/upsert_many.go @@ -3,7 +3,7 @@ package crud import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) // UpsertManyOpts describes options for `crud.upsert_many` method. diff --git a/datetime/datetime_test.go b/datetime/datetime_test.go index f4cc8b2a1..b64267872 100644 --- a/datetime/datetime_test.go +++ b/datetime/datetime_test.go @@ -9,9 +9,9 @@ import ( "testing" "time" - . "github.com/tarantool/go-tarantool" - . "github.com/tarantool/go-tarantool/datetime" - "github.com/tarantool/go-tarantool/test_helpers" + . "github.com/ice-blockchain/go-tarantool" + . "github.com/ice-blockchain/go-tarantool/datetime" + "github.com/ice-blockchain/go-tarantool/test_helpers" ) var noTimezoneLoc = time.FixedZone(NoTimezone, 0) diff --git a/datetime/example_test.go b/datetime/example_test.go index 50725e6a3..893712e58 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/ice-blockchain/go-tarantool" + . "github.com/ice-blockchain/go-tarantool/datetime" ) // Example demonstrates how to use tuples with datetime. To enable support of diff --git a/datetime/interval_test.go b/datetime/interval_test.go index 2d1ad41f9..634d06f35 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/ice-blockchain/go-tarantool/datetime" + "github.com/ice-blockchain/go-tarantool/test_helpers" ) func TestIntervalAdd(t *testing.T) { diff --git a/datetime/msgpack_helper_test.go b/datetime/msgpack_helper_test.go index 7af2ee6ad..657634c2e 100644 --- a/datetime/msgpack_helper_test.go +++ b/datetime/msgpack_helper_test.go @@ -4,7 +4,7 @@ package datetime_test import ( - . "github.com/tarantool/go-tarantool/datetime" + . "github.com/ice-blockchain/go-tarantool/datetime" "gopkg.in/vmihailenco/msgpack.v2" ) diff --git a/datetime/msgpack_v5_helper_test.go b/datetime/msgpack_v5_helper_test.go index d750ef006..0cdf6222a 100644 --- a/datetime/msgpack_v5_helper_test.go +++ b/datetime/msgpack_v5_helper_test.go @@ -4,8 +4,9 @@ package datetime_test import ( - . "github.com/tarantool/go-tarantool/datetime" "github.com/vmihailenco/msgpack/v5" + + . "github.com/ice-blockchain/go-tarantool/datetime" ) type encoder = msgpack.Encoder diff --git a/decimal/decimal_test.go b/decimal/decimal_test.go index d81e6c488..3326beeee 100644 --- a/decimal/decimal_test.go +++ b/decimal/decimal_test.go @@ -10,9 +10,10 @@ 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/ice-blockchain/go-tarantool" + . "github.com/ice-blockchain/go-tarantool/decimal" + "github.com/ice-blockchain/go-tarantool/test_helpers" ) var isDecimalSupported = false diff --git a/decimal/example_test.go b/decimal/example_test.go index 1d335a4c3..5993e9d0e 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/ice-blockchain/go-tarantool" + . "github.com/ice-blockchain/go-tarantool/decimal" ) // To enable support of decimal in msgpack with diff --git a/decimal/fuzzing_test.go b/decimal/fuzzing_test.go index c69a68719..749d9b1d1 100644 --- a/decimal/fuzzing_test.go +++ b/decimal/fuzzing_test.go @@ -7,7 +7,8 @@ import ( "testing" "github.com/shopspring/decimal" - . "github.com/tarantool/go-tarantool/decimal" + + . "github.com/ice-blockchain/go-tarantool/decimal" ) func strToDecimal(t *testing.T, buf string) decimal.Decimal { diff --git a/decimal/msgpack_helper_test.go b/decimal/msgpack_helper_test.go index 3824f70b8..5d849aa43 100644 --- a/decimal/msgpack_helper_test.go +++ b/decimal/msgpack_helper_test.go @@ -4,7 +4,7 @@ package decimal_test import ( - . "github.com/tarantool/go-tarantool/decimal" + . "github.com/ice-blockchain/go-tarantool/decimal" "gopkg.in/vmihailenco/msgpack.v2" ) diff --git a/decimal/msgpack_v5_helper_test.go b/decimal/msgpack_v5_helper_test.go index 6bb78168a..72b6754ef 100644 --- a/decimal/msgpack_v5_helper_test.go +++ b/decimal/msgpack_v5_helper_test.go @@ -4,8 +4,9 @@ package decimal_test import ( - . "github.com/tarantool/go-tarantool/decimal" "github.com/vmihailenco/msgpack/v5" + + . "github.com/ice-blockchain/go-tarantool/decimal" ) type encoder = msgpack.Encoder diff --git a/dial_test.go b/dial_test.go index 182e9c866..f5e42281e 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/ice-blockchain/go-tarantool" ) type mockErrorDialer struct { diff --git a/errors.go b/errors.go index 906184c24..2cf1fb037 100644 --- a/errors.go +++ b/errors.go @@ -172,3 +172,238 @@ const ( 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. ) +const ( + ER_UNKNOWN uint32 = iota + ER_ILLEGAL_PARAMS + ER_MEMORY_ISSUE + ER_TUPLE_FOUND + ER_TUPLE_NOT_FOUND + ER_UNSUPPORTED + ER_NONMASTER + ER_READONLY + ER_INJECTION + ER_CREATE_SPACE + ER_SPACE_EXISTS + ER_DROP_SPACE + ER_ALTER_SPACE + ER_INDEX_TYPE + ER_MODIFY_INDEX + ER_LAST_DROP + ER_TUPLE_FORMAT_LIMIT + ER_DROP_PRIMARY_KEY + ER_KEY_PART_TYPE + ER_EXACT_MATCH + ER_INVALID_MSGPACK + ER_PROC_RET + ER_TUPLE_NOT_ARRAY + ER_FIELD_TYPE + ER_INDEX_PART_TYPE_MISMATCH + ER_UPDATE_SPLICE + ER_UPDATE_ARG_TYPE + ER_FORMAT_MISMATCH_INDEX_PART + ER_UNKNOWN_UPDATE_OP + ER_UPDATE_FIELD + ER_FUNCTION_TX_ACTIVE + ER_KEY_PART_COUNT + ER_PROC_LUA + ER_NO_SUCH_PROC + ER_NO_SUCH_TRIGGER + ER_NO_SUCH_INDEX_ID + ER_NO_SUCH_SPACE + ER_NO_SUCH_FIELD_NO + ER_EXACT_FIELD_COUNT + ER_FIELD_MISSING + ER_WAL_IO + ER_MORE_THAN_ONE_TUPLE + ER_ACCESS_DENIED + ER_CREATE_USER + ER_DROP_USER + ER_NO_SUCH_USER + ER_USER_EXISTS + ER_PASSWORD_MISMATCH + ER_UNKNOWN_REQUEST_TYPE + ER_UNKNOWN_SCHEMA_OBJECT + ER_CREATE_FUNCTION + ER_NO_SUCH_FUNCTION + ER_FUNCTION_EXISTS + ER_BEFORE_REPLACE_RET + ER_MULTISTATEMENT_TRANSACTION + ER_TRIGGER_EXISTS + ER_USER_MAX + ER_NO_SUCH_ENGINE + ER_RELOAD_CFG + ER_CFG + ER_SAVEPOINT_EMPTY_TX + ER_NO_SUCH_SAVEPOINT + ER_UNKNOWN_REPLICA + ER_REPLICASET_UUID_MISMATCH + ER_INVALID_UUID + ER_REPLICASET_UUID_IS_RO + ER_INSTANCE_UUID_MISMATCH + ER_REPLICA_ID_IS_RESERVED + ER_INVALID_ORDER + ER_MISSING_REQUEST_FIELD + ER_IDENTIFIER + ER_DROP_FUNCTION + ER_ITERATOR_TYPE + ER_REPLICA_MAX + ER_INVALID_XLOG + ER_INVALID_XLOG_NAME + ER_INVALID_XLOG_ORDER + ER_NO_CONNECTION + ER_TIMEOUT + ER_ACTIVE_TRANSACTION + ER_CURSOR_NO_TRANSACTION + ER_CROSS_ENGINE_TRANSACTION + ER_NO_SUCH_ROLE + ER_ROLE_EXISTS + ER_CREATE_ROLE + ER_INDEX_EXISTS + ER_SESSION_CLOSED + ER_ROLE_LOOP + ER_GRANT + ER_PRIV_GRANTED + ER_ROLE_GRANTED + ER_PRIV_NOT_GRANTED + ER_ROLE_NOT_GRANTED + ER_MISSING_SNAPSHOT + ER_CANT_UPDATE_PRIMARY_KEY + ER_UPDATE_INTEGER_OVERFLOW + ER_GUEST_USER_PASSWORD + ER_TRANSACTION_CONFLICT + ER_UNSUPPORTED_PRIV + ER_LOAD_FUNCTION + ER_FUNCTION_LANGUAGE + ER_RTREE_RECT + ER_PROC_C + ER_UNKNOWN_RTREE_INDEX_DISTANCE_TYPE + ER_PROTOCOL + ER_UPSERT_UNIQUE_SECONDARY_KEY + ER_WRONG_INDEX_RECORD + ER_WRONG_INDEX_PARTS + ER_WRONG_INDEX_OPTIONS + ER_WRONG_SCHEMA_VERSION + ER_MEMTX_MAX_TUPLE_SIZE + ER_WRONG_SPACE_OPTIONS + ER_UNSUPPORTED_INDEX_FEATURE + ER_VIEW_IS_RO + ER_NO_TRANSACTION + ER_SYSTEM + ER_LOADING + ER_CONNECTION_TO_SELF + ER_KEY_PART_IS_TOO_LONG + ER_COMPRESSION + ER_CHECKPOINT_IN_PROGRESS + ER_SUB_STMT_MAX + ER_COMMIT_IN_SUB_STMT + ER_ROLLBACK_IN_SUB_STMT + ER_DECOMPRESSION + ER_INVALID_XLOG_TYPE + ER_ALREADY_RUNNING + ER_INDEX_FIELD_COUNT_LIMIT + ER_LOCAL_INSTANCE_ID_IS_READ_ONLY + ER_BACKUP_IN_PROGRESS + ER_READ_VIEW_ABORTED + ER_INVALID_INDEX_FILE + ER_INVALID_RUN_FILE + ER_INVALID_VYLOG_FILE + ER_CASCADE_ROLLBACK + ER_VY_QUOTA_TIMEOUT + ER_PARTIAL_KEY + ER_TRUNCATE_SYSTEM_SPACE + ER_LOAD_MODULE + ER_VINYL_MAX_TUPLE_SIZE + ER_WRONG_DD_VERSION + ER_WRONG_SPACE_FORMAT + ER_CREATE_SEQUENCE + ER_ALTER_SEQUENCE + ER_DROP_SEQUENCE + ER_NO_SUCH_SEQUENCE + ER_SEQUENCE_EXISTS + ER_SEQUENCE_OVERFLOW + ER_NO_SUCH_INDEX_NAME + ER_SPACE_FIELD_IS_DUPLICATE + ER_CANT_CREATE_COLLATION + ER_WRONG_COLLATION_OPTIONS + ER_NULLABLE_PRIMARY + ER_NO_SUCH_FIELD_NAME_IN_SPACE + ER_TRANSACTION_YIELD + ER_NO_SUCH_GROUP + ER_SQL_BIND_VALUE + ER_SQL_BIND_TYPE + ER_SQL_BIND_PARAMETER_MAX + ER_SQL_EXECUTE + ER_UPDATE_DECIMAL_OVERFLOW + ER_SQL_BIND_NOT_FOUND + ER_ACTION_MISMATCH + ER_VIEW_MISSING_SQL + ER_FOREIGN_KEY_CONSTRAINT + ER_NO_SUCH_MODULE + ER_NO_SUCH_COLLATION + ER_CREATE_FK_CONSTRAINT + ER_DROP_FK_CONSTRAINT + ER_NO_SUCH_CONSTRAINT + ER_CONSTRAINT_EXISTS + ER_SQL_TYPE_MISMATCH + ER_ROWID_OVERFLOW + ER_DROP_COLLATION + ER_ILLEGAL_COLLATION_MIX + ER_SQL_NO_SUCH_PRAGMA + ER_SQL_CANT_RESOLVE_FIELD + ER_INDEX_EXISTS_IN_SPACE + ER_INCONSISTENT_TYPES + ER_SQL_SYNTAX_WITH_POS + ER_SQL_STACK_OVERFLOW + ER_SQL_SELECT_WILDCARD + ER_SQL_STATEMENT_EMPTY + ER_SQL_KEYWORD_IS_RESERVED + ER_SQL_SYNTAX_NEAR_TOKEN + ER_SQL_UNKNOWN_TOKEN + ER_SQL_PARSER_GENERIC + ER_SQL_ANALYZE_ARGUMENT + ER_SQL_COLUMN_COUNT_MAX + ER_HEX_LITERAL_MAX + ER_INT_LITERAL_MAX + ER_SQL_PARSER_LIMIT + ER_INDEX_DEF_UNSUPPORTED + ER_CK_DEF_UNSUPPORTED + ER_MULTIKEY_INDEX_MISMATCH + ER_CREATE_CK_CONSTRAINT + ER_CK_CONSTRAINT_FAILED + ER_SQL_COLUMN_COUNT + ER_FUNC_INDEX_FUNC + ER_FUNC_INDEX_FORMAT + ER_FUNC_INDEX_PARTS + ER_NO_SUCH_FIELD_NAME + ER_FUNC_WRONG_ARG_COUNT + ER_BOOTSTRAP_READONLY + ER_SQL_FUNC_WRONG_RET_COUNT + ER_FUNC_INVALID_RETURN_TYPE + ER_SQL_PARSER_GENERIC_WITH_POS + ER_REPLICA_NOT_ANON + ER_CANNOT_REGISTER + ER_SESSION_SETTING_INVALID_VALUE + ER_SQL_PREPARE + ER_WRONG_QUERY_ID + ER_SEQUENCE_NOT_STARTED + ER_NO_SUCH_SESSION_SETTING + ER_UNCOMMITTED_FOREIGN_SYNC_TXNS + ER_SYNC_MASTER_MISMATCH + ER_SYNC_QUORUM_TIMEOUT + ER_SYNC_ROLLBACK + ER_TUPLE_METADATA_IS_TOO_BIG + ER_XLOG_GAP + ER_TOO_EARLY_SUBSCRIBE + ER_SQL_CANT_ADD_AUTOINC + ER_QUORUM_WAIT + ER_INTERFERING_PROMOTE + ER_ELECTION_DISABLED + ER_TXN_ROLLBACK + ER_NOT_LEADER + ER_SYNC_QUEUE_UNCLAIMED + ER_SYNC_QUEUE_FOREIGN + ER_UNABLE_TO_PROCESS_IN_STREAM + ER_UNABLE_TO_PROCESS_OUT_OF_STREAM + ER_TRANSACTION_TIMEOUT + ER_ACTIVE_TIMER +) diff --git a/example_custom_unpacking_test.go b/example_custom_unpacking_test.go index 26d19f3af..81124c511 100644 --- a/example_custom_unpacking_test.go +++ b/example_custom_unpacking_test.go @@ -5,7 +5,7 @@ import ( "log" "time" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) type Tuple2 struct { diff --git a/example_test.go b/example_test.go index 7b0ee9a6a..6d930407d 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/ice-blockchain/go-tarantool" + "github.com/ice-blockchain/go-tarantool/test_helpers" ) type Tuple struct { diff --git a/future_test.go b/future_test.go index e7e9ab507..2c4d7fe8e 100644 --- a/future_test.go +++ b/future_test.go @@ -6,7 +6,7 @@ import ( "testing" "time" - . "github.com/tarantool/go-tarantool" + . "github.com/ice-blockchain/go-tarantool" ) func assertResponseIteratorValue(t testing.TB, it ResponseIterator, diff --git a/go.mod b/go.mod index ee97cb2a1..a447cfb57 100644 --- a/go.mod +++ b/go.mod @@ -1,17 +1,13 @@ -module github.com/tarantool/go-tarantool +module github.com/ice-blockchain/go-tarantool go 1.11 require ( github.com/google/uuid v1.3.0 - 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-openssl v0.0.8-0.20230307065445-720eeb389195 + github.com/tarantool/go-tarantool v1.10.0 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..dc784ccf1 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,8 @@ 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/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= 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= @@ -11,28 +13,39 @@ github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 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-openssl v0.0.8-0.20220711094538-d93c1eff4f49/go.mod h1:M7H4xYSbzqpW/ZRBMyH0eyqQBsnhAMfsYk5mv0yid7A= 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/tarantool/go-tarantool v1.10.0 h1:4sLGAFliIbCNuo3vnWXe5UcfnLChyfw8+IDDIk57YvU= +github.com/tarantool/go-tarantool v1.10.0/go.mod h1:oPjvZNKaN4iKbf8YPo3pGpxzk6cRZF1neAxgq8WcBh8= 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= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 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/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 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= @@ -43,6 +56,12 @@ 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= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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= @@ -52,3 +71,4 @@ gopkg.in/vmihailenco/msgpack.v2 v2.9.2 h1:gjPqo9orRVlSAH/065qw3MsFCDpH7fa1KpiizX 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= +gotest.tools/v3 v3.2.0/go.mod h1:Mcr9QNxkg0uMvy/YElmo4SpXgJKWgQvYrT7Kw5RzJ1A= diff --git a/msgpack_helper_test.go b/msgpack_helper_test.go index 896c105d3..37ad4df9d 100644 --- a/msgpack_helper_test.go +++ b/msgpack_helper_test.go @@ -4,8 +4,9 @@ package tarantool_test import ( - "github.com/tarantool/go-tarantool" "gopkg.in/vmihailenco/msgpack.v2" + + "github.com/ice-blockchain/go-tarantool" ) type encoder = msgpack.Encoder diff --git a/msgpack_v5.go b/msgpack_v5.go index e8cd9aa29..f1583fdf9 100644 --- a/msgpack_v5.go +++ b/msgpack_v5.go @@ -22,6 +22,7 @@ func newDecoder(r io.Reader) *decoder { dec.SetMapDecoder(func(dec *msgpack.Decoder) (interface{}, error) { return dec.DecodeUntypedMap() }) + dec.UseLooseInterfaceDecoding(true) return dec } diff --git a/msgpack_v5_helper_test.go b/msgpack_v5_helper_test.go index 88154c26f..4346a18ac 100644 --- a/msgpack_v5_helper_test.go +++ b/msgpack_v5_helper_test.go @@ -4,8 +4,9 @@ package tarantool_test import ( - "github.com/tarantool/go-tarantool" "github.com/vmihailenco/msgpack/v5" + + "github.com/ice-blockchain/go-tarantool" ) type encoder = msgpack.Encoder diff --git a/multi/call_16_test.go b/multi/call_16_test.go index 35bcd20fb..6b478f54a 100644 --- a/multi/call_16_test.go +++ b/multi/call_16_test.go @@ -6,7 +6,7 @@ package multi import ( "testing" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) func TestCall(t *testing.T) { diff --git a/multi/call_17_test.go b/multi/call_17_test.go index 378961fda..cb67c56e8 100644 --- a/multi/call_17_test.go +++ b/multi/call_17_test.go @@ -6,7 +6,7 @@ package multi import ( "testing" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) func TestCall(t *testing.T) { diff --git a/multi/example_test.go b/multi/example_test.go index e43461141..1bf28f9c0 100644 --- a/multi/example_test.go +++ b/multi/example_test.go @@ -4,7 +4,7 @@ import ( "fmt" "time" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) func ExampleConnect() { diff --git a/multi/multi.go b/multi/multi.go index 6aba2a426..d30f54431 100644 --- a/multi/multi.go +++ b/multi/multi.go @@ -18,7 +18,7 @@ import ( "sync/atomic" "time" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) const ( @@ -532,3 +532,13 @@ func (connMulti *ConnectionMulti) Do(req tarantool.Request) *tarantool.Future { } return connMulti.getCurrentConnection().Do(req) } + +func (connMulti *ConnectionMulti) PrepareExecute(sql string, args map[string]interface{}) (resp *tarantool.Response, err error) { + return connMulti.getCurrentConnection().PrepareExecute(sql, args) +} +func (connMulti *ConnectionMulti) PrepareExecuteTyped(sql string, args map[string]interface{}, result interface{}) (err error) { + return connMulti.getCurrentConnection().PrepareExecuteTyped(sql, args, result) +} +func (connMulti *ConnectionMulti) UpsertTyped(space, tuple, ops, result interface{}) (err error) { + return connMulti.getCurrentConnection().UpsertTyped(space, tuple, ops, result) +} diff --git a/multi/multi_test.go b/multi/multi_test.go index ad98912c2..a9e073ca6 100644 --- a/multi/multi_test.go +++ b/multi/multi_test.go @@ -10,8 +10,8 @@ import ( "github.com/stretchr/testify/require" - "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/test_helpers" + "github.com/ice-blockchain/go-tarantool" + "github.com/ice-blockchain/go-tarantool/test_helpers" ) var server1 = "127.0.0.1:3013" diff --git a/protocol_test.go b/protocol_test.go index c747d9bff..77ef1b406 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/ice-blockchain/go-tarantool" ) func TestProtocolInfoClonePreservesFeatures(t *testing.T) { diff --git a/queue/example_connection_pool_test.go b/queue/example_connection_pool_test.go index e41cdc639..96cab2051 100644 --- a/queue/example_connection_pool_test.go +++ b/queue/example_connection_pool_test.go @@ -7,10 +7,11 @@ 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/ice-blockchain/go-tarantool" + "github.com/ice-blockchain/go-tarantool/connection_pool" + "github.com/ice-blockchain/go-tarantool/queue" + "github.com/ice-blockchain/go-tarantool/test_helpers" ) // QueueConnectionHandler handles new connections in a ConnectionPool. diff --git a/queue/example_msgpack_test.go b/queue/example_msgpack_test.go index 2ed7f5542..af41a1283 100644 --- a/queue/example_msgpack_test.go +++ b/queue/example_msgpack_test.go @@ -13,8 +13,8 @@ import ( "log" "time" - "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/queue" + "github.com/ice-blockchain/go-tarantool" + "github.com/ice-blockchain/go-tarantool/queue" ) type dummyData struct { diff --git a/queue/example_test.go b/queue/example_test.go index d546b43d7..95b63bd37 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/ice-blockchain/go-tarantool" + "github.com/ice-blockchain/go-tarantool/queue" ) // Example demonstrates an operations like Put and Take with queue. diff --git a/queue/queue.go b/queue/queue.go index df13f09bb..99a4685bc 100644 --- a/queue/queue.go +++ b/queue/queue.go @@ -13,7 +13,8 @@ import ( "time" "github.com/google/uuid" - "github.com/tarantool/go-tarantool" + + "github.com/ice-blockchain/go-tarantool" ) // Queue is a handle to Tarantool queue's tube. diff --git a/queue/queue_test.go b/queue/queue_test.go index 905fefc32..db42c12b4 100644 --- a/queue/queue_test.go +++ b/queue/queue_test.go @@ -8,9 +8,9 @@ import ( "testing" "time" - . "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/queue" - "github.com/tarantool/go-tarantool/test_helpers" + . "github.com/ice-blockchain/go-tarantool" + "github.com/ice-blockchain/go-tarantool/queue" + "github.com/ice-blockchain/go-tarantool/test_helpers" ) var server = "127.0.0.1:3013" diff --git a/request.go b/request.go index 7c79c5863..ad40a1fbf 100644 --- a/request.go +++ b/request.go @@ -214,6 +214,9 @@ func (conn *Connection) Update(space, index interface{}, key, ops interface{}) ( func (conn *Connection) Upsert(space interface{}, tuple, ops interface{}) (resp *Response, err error) { return conn.UpsertAsync(space, tuple, ops).Get() } +func (conn *Connection) UpsertTyped(space interface{}, tuple, ops, result interface{}) (err error) { + return conn.UpsertAsync(space, tuple, ops).GetTyped(result) +} // Call calls registered Tarantool function. // It uses request code for Tarantool >= 1.7 if go-tarantool diff --git a/request_test.go b/request_test.go index 8429fef98..5cb5cf806 100644 --- a/request_test.go +++ b/request_test.go @@ -9,8 +9,8 @@ import ( "github.com/stretchr/testify/assert" - . "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/test_helpers" + . "github.com/ice-blockchain/go-tarantool" + "github.com/ice-blockchain/go-tarantool/test_helpers" ) const invalidSpaceMsg = "invalid space" diff --git a/settings/example_test.go b/settings/example_test.go index a2391328f..030211837 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/ice-blockchain/go-tarantool" + "github.com/ice-blockchain/go-tarantool/settings" + "github.com/ice-blockchain/go-tarantool/test_helpers" ) func example_connect(opts tarantool.Opts) *tarantool.Connection { diff --git a/settings/msgpack_helper_test.go b/settings/msgpack_helper_test.go index 0c002213a..3ae598fc1 100644 --- a/settings/msgpack_helper_test.go +++ b/settings/msgpack_helper_test.go @@ -6,8 +6,9 @@ package settings_test import ( "io" - "github.com/tarantool/go-tarantool" "gopkg.in/vmihailenco/msgpack.v2" + + "github.com/ice-blockchain/go-tarantool" ) type encoder = msgpack.Encoder diff --git a/settings/msgpack_v5_helper_test.go b/settings/msgpack_v5_helper_test.go index 96df6bae1..c51eacb93 100644 --- a/settings/msgpack_v5_helper_test.go +++ b/settings/msgpack_v5_helper_test.go @@ -6,8 +6,9 @@ package settings_test import ( "io" - "github.com/tarantool/go-tarantool" "github.com/vmihailenco/msgpack/v5" + + "github.com/ice-blockchain/go-tarantool" ) type encoder = msgpack.Encoder diff --git a/settings/request.go b/settings/request.go index 84723bb2d..0615c30a4 100644 --- a/settings/request.go +++ b/settings/request.go @@ -60,7 +60,7 @@ package settings import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) // SetRequest helps to set session settings. diff --git a/settings/request_test.go b/settings/request_test.go index bc26ff058..d884d4c60 100644 --- a/settings/request_test.go +++ b/settings/request_test.go @@ -6,8 +6,9 @@ import ( "testing" "github.com/stretchr/testify/require" - "github.com/tarantool/go-tarantool" - . "github.com/tarantool/go-tarantool/settings" + + "github.com/ice-blockchain/go-tarantool" + . "github.com/ice-blockchain/go-tarantool/settings" ) type ValidSchemeResolver struct { diff --git a/settings/tarantool_test.go b/settings/tarantool_test.go index d32767116..25d4df241 100644 --- a/settings/tarantool_test.go +++ b/settings/tarantool_test.go @@ -7,9 +7,10 @@ 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/ice-blockchain/go-tarantool" + . "github.com/ice-blockchain/go-tarantool/settings" + "github.com/ice-blockchain/go-tarantool/test_helpers" ) // There is no way to skip tests in testing.M, diff --git a/shutdown_test.go b/shutdown_test.go index d9b1db111..759e0216f 100644 --- a/shutdown_test.go +++ b/shutdown_test.go @@ -13,8 +13,9 @@ import ( "time" "github.com/stretchr/testify/require" - . "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/test_helpers" + + . "github.com/ice-blockchain/go-tarantool" + "github.com/ice-blockchain/go-tarantool/test_helpers" ) var shtdnServer = "127.0.0.1:3014" diff --git a/ssl_test.go b/ssl_test.go index ca0773b58..64527331a 100644 --- a/ssl_test.go +++ b/ssl_test.go @@ -15,8 +15,9 @@ import ( "time" "github.com/tarantool/go-openssl" - . "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/test_helpers" + + . "github.com/ice-blockchain/go-tarantool" + "github.com/ice-blockchain/go-tarantool/test_helpers" ) const sslHost = "127.0.0.1" diff --git a/tarantool_test.go b/tarantool_test.go index 125642dcf..a730e784c 100644 --- a/tarantool_test.go +++ b/tarantool_test.go @@ -18,8 +18,9 @@ import ( "github.com/stretchr/testify/require" "github.com/stretchr/testify/assert" - . "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/test_helpers" + + . "github.com/ice-blockchain/go-tarantool" + "github.com/ice-blockchain/go-tarantool/test_helpers" ) var startOpts test_helpers.StartOpts = test_helpers.StartOpts{ diff --git a/test_helpers/main.go b/test_helpers/main.go index 4aaa91f50..f6fa44be9 100644 --- a/test_helpers/main.go +++ b/test_helpers/main.go @@ -23,7 +23,7 @@ import ( "strconv" "time" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) type StartOpts struct { diff --git a/test_helpers/pool_helper.go b/test_helpers/pool_helper.go index 8c3a7e6ff..9e3e1c288 100644 --- a/test_helpers/pool_helper.go +++ b/test_helpers/pool_helper.go @@ -5,8 +5,8 @@ import ( "reflect" "time" - "github.com/tarantool/go-tarantool" - "github.com/tarantool/go-tarantool/connection_pool" + "github.com/ice-blockchain/go-tarantool" + "github.com/ice-blockchain/go-tarantool/connection_pool" ) type ListenOnInstanceArgs struct { diff --git a/test_helpers/request_mock.go b/test_helpers/request_mock.go index 19c18545e..ee3508b58 100644 --- a/test_helpers/request_mock.go +++ b/test_helpers/request_mock.go @@ -3,7 +3,7 @@ package test_helpers import ( "context" - "github.com/tarantool/go-tarantool" + "github.com/ice-blockchain/go-tarantool" ) type StrangerRequest struct { diff --git a/test_helpers/utils.go b/test_helpers/utils.go index 34a2e2980..50169f764 100644 --- a/test_helpers/utils.go +++ b/test_helpers/utils.go @@ -8,7 +8,8 @@ import ( "time" "github.com/stretchr/testify/require" - "github.com/tarantool/go-tarantool" + + "github.com/ice-blockchain/go-tarantool" ) // ConnectWithValidation tries to connect to a Tarantool instance. diff --git a/uuid/example_test.go b/uuid/example_test.go index ef0993e59..fcfa972f6 100644 --- a/uuid/example_test.go +++ b/uuid/example_test.go @@ -13,8 +13,9 @@ import ( "log" "github.com/google/uuid" - "github.com/tarantool/go-tarantool" - _ "github.com/tarantool/go-tarantool/uuid" + + "github.com/ice-blockchain/go-tarantool" + _ "github.com/ice-blockchain/go-tarantool/uuid" ) // Example demonstrates how to use tuples with UUID. To enable UUID support diff --git a/uuid/uuid_test.go b/uuid/uuid_test.go index e04ab5ab9..5e1dd57e4 100644 --- a/uuid/uuid_test.go +++ b/uuid/uuid_test.go @@ -8,9 +8,10 @@ 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/ice-blockchain/go-tarantool" + "github.com/ice-blockchain/go-tarantool/test_helpers" + _ "github.com/ice-blockchain/go-tarantool/uuid" ) // There is no way to skip tests in testing.M, From 6a4816fbdb2db489921ad5ef59e0208533c959c2 Mon Sep 17 00:00:00 2001 From: ice-cronus <105345303+ice-cronus@users.noreply.github.com> Date: Thu, 23 Mar 2023 13:06:21 +0300 Subject: [PATCH 2/2] read/write balancer for the pool package with new connections at runtime detection --- balancer/balancer.go | 98 +++ connection_pool/connection_pool.go | 113 ++- .../connection_pool_new_conn_test.go | 344 ++++++++ connection_pool/connector_rw_balanced.go | 251 ++++++ connection_pool/connector_rw_balanced_test.go | 746 ++++++++++++++++++ connection_test.go | 8 +- go.mod | 7 +- go.sum | 24 +- 8 files changed, 1534 insertions(+), 57 deletions(-) create mode 100644 balancer/balancer.go create mode 100644 connection_pool/connection_pool_new_conn_test.go create mode 100644 connection_pool/connector_rw_balanced.go create mode 100644 connection_pool/connector_rw_balanced_test.go diff --git a/balancer/balancer.go b/balancer/balancer.go new file mode 100644 index 000000000..c369ecdbd --- /dev/null +++ b/balancer/balancer.go @@ -0,0 +1,98 @@ +package balancer + +import ( + "fmt" + "strings" + "unicode" + + "github.com/ice-blockchain/go-tarantool" +) + +type clusterMemberType string + +const ( + Writable = clusterMemberType("writable") + NonWritable = clusterMemberType("non-writable") +) + +func CheckIfRequiresWriteForRequest(req tarantool.Request, _default bool) bool { + switch req.(type) { + case *tarantool.PrepareRequest: + case *tarantool.UnprepareRequest: + case *tarantool.ExecutePreparedRequest: + return _default // How can we get access to privateField to verify with CheckIfRequiresWrite? + case *tarantool.IdRequest: + return _default + case *tarantool.PingRequest: + return _default + case *tarantool.SelectRequest: + return false + case *tarantool.InsertRequest: + return true + case *tarantool.ReplaceRequest: + return true + case *tarantool.DeleteRequest: + return true + case *tarantool.UpdateRequest: + return true + case *tarantool.UpsertRequest: + return true + case *tarantool.CallRequest: + case *tarantool.EvalRequest: + case *tarantool.ExecuteRequest: + case *tarantool.BeginRequest: + return true + case *tarantool.CommitRequest: + return true + case *tarantool.RollbackRequest: + return true + default: + return _default + } + return _default +} + +func CheckIfRequiresWrite(expr string, _default bool) (string, bool) { + trimmedS := strings.ToLower(strings.TrimLeftFunc(expr, func(r rune) bool { + return unicode.IsSpace(r) || unicode.IsControl(r) + })) + nonWritableTemplate := fmt.Sprintf("{{%s}}", NonWritable) + if isNonWritable := strings.HasPrefix(trimmedS, nonWritableTemplate); isNonWritable { + return strings.Replace(expr, nonWritableTemplate, "", 1), false + } + + writableTemplate := fmt.Sprintf("{{%s}}", Writable) + if isWritable := strings.HasPrefix(trimmedS, writableTemplate); isWritable { + return strings.Replace(expr, writableTemplate, "", 1), true + } + + if isWritable := strings.HasPrefix(trimmedS, "insert"); isWritable { + return expr, true + } + + if isWritable := strings.HasPrefix(trimmedS, "delete"); isWritable { + return expr, true + } + + if isWritable := strings.HasPrefix(trimmedS, "update"); isWritable { + return expr, true + } + + if isWritable := strings.HasPrefix(trimmedS, "replace"); isWritable { + return expr, true + } + + if isNonWritable := strings.HasPrefix(trimmedS, "values"); isNonWritable { + return expr, false + } + + if isNonWritable := strings.HasPrefix(trimmedS, "with"); isNonWritable { + return expr, false + } + + if isNonWritable := strings.HasPrefix(trimmedS, "select"); isNonWritable { + return expr, false + } + + return expr, _default +} diff --git a/connection_pool/connection_pool.go b/connection_pool/connection_pool.go index 3d1ec0cdc..9d5c28b12 100644 --- a/connection_pool/connection_pool.go +++ b/connection_pool/connection_pool.go @@ -66,7 +66,8 @@ type OptsPool struct { // been updated. CheckTimeout time.Duration // ConnectionHandler provides an ability to handle connection updates. - ConnectionHandler ConnectionHandler + ConnectionHandler ConnectionHandler + NodesGetFunctionName string } /* @@ -145,7 +146,9 @@ func ConnectWithOpts(addrs []string, connOpts tarantool.Opts, opts OptsPool) (co if opts.CheckTimeout <= 0 { return nil, ErrWrongCheckTimeout } - + if opts.NodesGetFunctionName == "" { + opts.NodesGetFunctionName = "get_cluster_members" + } size := len(addrs) rwPool := NewEmptyRoundRobin(size) roPool := NewEmptyRoundRobin(size) @@ -185,7 +188,7 @@ func ConnectWithOpts(addrs []string, connOpts tarantool.Opts, opts OptsPool) (co for _, s := range states { go connPool.checker(s) } - + go connPool.checkNewClusterMembers() return connPool, nil } @@ -938,48 +941,57 @@ func (connPool *ConnectionPool) fillPools() ([]connState, bool) { // It is called before checker() goroutines and before closeImpl() may be // called so we don't expect concurrency issues here. for i, addr := range connPool.addrs { - states[i] = connState{ - addr: addr, - notify: make(chan tarantool.ConnEvent, 10), - conn: nil, - role: UnknownRole, + states[i], somebodyAlive = connPool.handleNewConnection(addr, somebodyAlive) + if states[i].role == UnknownRole { + continue } - connOpts := connPool.connOpts - connOpts.Notify = states[i].notify + } + + return states, somebodyAlive +} - conn, err := tarantool.Connect(addr, connOpts) +func (connPool *ConnectionPool) handleNewConnection(addr string, somebodyAlive bool) (state connState, alive bool) { + state = connState{ + addr: addr, + notify: make(chan tarantool.ConnEvent, 10), + conn: nil, + role: UnknownRole, + } + alive = somebodyAlive + connOpts := connPool.connOpts + connOpts.Notify = state.notify + + conn, err := tarantool.Connect(addr, connOpts) + if err != nil { + log.Printf("tarantool: connect to %s failed: %s\n", addr, err.Error()) + } else if conn != nil { + role, err := connPool.getConnectionRole(conn) if err != nil { - log.Printf("tarantool: connect to %s failed: %s\n", addr, err.Error()) - } else if conn != nil { - role, err := connPool.getConnectionRole(conn) - if err != nil { + conn.Close() + log.Printf("tarantool: storing connection to %s failed: %s\n", addr, err) + return state, alive + } + + if connPool.handlerDiscovered(conn, role) { + if connPool.addConnection(addr, conn, role) != nil { conn.Close() - log.Printf("tarantool: storing connection to %s failed: %s\n", addr, err) - continue + connPool.handlerDeactivated(conn, role) } - if connPool.handlerDiscovered(conn, role) { - if connPool.addConnection(addr, conn, role) != nil { - conn.Close() - connPool.handlerDeactivated(conn, role) - } - - if conn.ConnectedNow() { - states[i].conn = conn - states[i].role = role - somebodyAlive = true - } else { - connPool.deleteConnection(addr) - conn.Close() - connPool.handlerDeactivated(conn, role) - } + if conn.ConnectedNow() { + state.conn = conn + state.role = role + alive = true } else { + connPool.deleteConnection(addr) conn.Close() + connPool.handlerDeactivated(conn, role) } + } else { + conn.Close() } } - - return states, somebodyAlive + return state, alive } func (pool *ConnectionPool) updateConnection(s connState) connState { @@ -1139,6 +1151,39 @@ func (pool *ConnectionPool) checker(s connState) { } } +func (pool *ConnectionPool) checkNewClusterMembers() { + timer := time.NewTicker(pool.opts.CheckTimeout) + defer timer.Stop() + for { + select { + case <-pool.done: + return + case <-timer.C: + var resp [][]map[string]interface{} + if err := pool.Call17Typed(pool.opts.NodesGetFunctionName, []interface{}{}, &resp, PreferRO); err == nil && len(resp) > 0 && len(resp[0]) > 0 { + addrs := resp[0] + for _, addr := range addrs { + addrUri := addr["uri"].(string) + if !pool.containsAddr(addrUri) { + pool.addrs = append(pool.addrs, addrUri) + s, _ := pool.handleNewConnection(addrUri, true) // We 100% have active connection cuz we got it before. + go pool.checker(s) + } + } + } else { + log.Printf("Failed to fetch new cluster configuration %v\n", err) + } + } + } +} +func (pool *ConnectionPool) containsAddr(addr string) bool { + for _, poolAddr := range pool.addrs { + if poolAddr == addr { + return true + } + } + return false +} func (connPool *ConnectionPool) getNextConnection(mode Mode) (*tarantool.Connection, error) { switch mode { diff --git a/connection_pool/connection_pool_new_conn_test.go b/connection_pool/connection_pool_new_conn_test.go new file mode 100644 index 000000000..bdf03394a --- /dev/null +++ b/connection_pool/connection_pool_new_conn_test.go @@ -0,0 +1,344 @@ +package connection_pool_test + +import ( + "bytes" + "github.com/ice-blockchain/go-tarantool/connection_pool" + "github.com/ice-blockchain/go-tarantool/test_helpers" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "testing" + "text/template" + "time" +) + +func TestUpdateRWInstances(t *testing.T) { + roles := []bool{false, true, false, false, true} + + allPorts := map[string]bool{ + servers[0]: true, + servers[1]: true, + servers[2]: true, + servers[3]: true, + servers[4]: true, + } + + masterPorts := map[string]bool{ + servers[0]: true, + servers[2]: true, + servers[3]: true, + } + + replicaPorts := map[string]bool{ + servers[1]: true, + servers[4]: true, + } + + serversNumber := len(servers) + + 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() + + // ANY + args := test_helpers.ListenOnInstanceArgs{ + ServersNumber: serversNumber, + ExpectedPorts: allPorts, + ConnPool: connPool, + Mode: connection_pool.ANY, + } + + err = test_helpers.ProcessListenOnInstance(args) + require.Nil(t, err) + + // RW + args = test_helpers.ListenOnInstanceArgs{ + ServersNumber: serversNumber, + ExpectedPorts: masterPorts, + ConnPool: connPool, + Mode: connection_pool.RW, + } + + err = test_helpers.ProcessListenOnInstance(args) + require.Nil(t, err) + + // RO + args = test_helpers.ListenOnInstanceArgs{ + ServersNumber: serversNumber, + ExpectedPorts: replicaPorts, + ConnPool: connPool, + Mode: connection_pool.RO, + } + + err = test_helpers.ProcessListenOnInstance(args) + require.Nil(t, err) + + // PreferRW + args = test_helpers.ListenOnInstanceArgs{ + ServersNumber: serversNumber, + ExpectedPorts: masterPorts, + ConnPool: connPool, + Mode: connection_pool.PreferRW, + } + + err = test_helpers.ProcessListenOnInstance(args) + require.Nil(t, err) + + // PreferRO + args = test_helpers.ListenOnInstanceArgs{ + ServersNumber: serversNumber, + ExpectedPorts: replicaPorts, + ConnPool: connPool, + Mode: connection_pool.PreferRO, + } + + err = test_helpers.ProcessListenOnInstance(args) + require.Nil(t, err) + + roles = []bool{true, false, true, true, false} + + masterPorts = map[string]bool{ + servers[1]: true, + servers[4]: true, + } + + replicaPorts = map[string]bool{ + servers[0]: true, + servers[2]: true, + servers[3]: true, + } + + err = test_helpers.SetClusterRO(servers, connOpts, roles) + require.Nilf(t, err, "fail to set roles for cluster") + + // ANY + args = test_helpers.ListenOnInstanceArgs{ + ServersNumber: serversNumber, + ExpectedPorts: allPorts, + ConnPool: connPool, + Mode: connection_pool.ANY, + } + + err = test_helpers.Retry(test_helpers.ProcessListenOnInstance, args, defaultCountRetry, defaultTimeoutRetry) + require.Nil(t, err) + + // RW + args = test_helpers.ListenOnInstanceArgs{ + ServersNumber: serversNumber, + ExpectedPorts: masterPorts, + ConnPool: connPool, + Mode: connection_pool.RW, + } + + err = test_helpers.Retry(test_helpers.ProcessListenOnInstance, args, defaultCountRetry, defaultTimeoutRetry) + require.Nil(t, err) + + // RO + args = test_helpers.ListenOnInstanceArgs{ + ServersNumber: serversNumber, + ExpectedPorts: replicaPorts, + ConnPool: connPool, + Mode: connection_pool.RO, + } + + err = test_helpers.Retry(test_helpers.ProcessListenOnInstance, args, defaultCountRetry, defaultTimeoutRetry) + require.Nil(t, err) + + // PreferRW + args = test_helpers.ListenOnInstanceArgs{ + ServersNumber: serversNumber, + ExpectedPorts: masterPorts, + ConnPool: connPool, + Mode: connection_pool.PreferRW, + } + + err = test_helpers.Retry(test_helpers.ProcessListenOnInstance, args, defaultCountRetry, defaultTimeoutRetry) + require.Nil(t, err) + + // PreferRO + args = test_helpers.ListenOnInstanceArgs{ + ServersNumber: serversNumber, + ExpectedPorts: replicaPorts, + ConnPool: connPool, + Mode: connection_pool.PreferRO, + } + + err = test_helpers.Retry(test_helpers.ProcessListenOnInstance, args, defaultCountRetry, defaultTimeoutRetry) + require.Nil(t, err) +} + +const getClusterMembersTemplate = ` +function get_cluster_members() + ret = {} +{{range $key, $value := .}} + s = {} + s["uri"] = "{{$key}}" + {{if $value}} + s["type"] = "writeable" + {{else}} + s["type"] = 'non-writable' + {{end}} + ret[#ret+1]=s +{{end}} + return ret +end +` + +func TestNewConnectionAddedToCluster(t *testing.T) { + roles := []bool{false, true, false} + initiallySetupServers := servers[:3] + allPorts := map[string]bool{ + servers[0]: true, + servers[1]: true, + servers[2]: true, + // Addition of [3], [4] postponed (at runtime) + } + + masterPorts := map[string]bool{ + servers[0]: true, + servers[2]: true, + } + + replicaPorts := map[string]bool{ + servers[1]: true, + } + + serversNumber := len(initiallySetupServers) + + err := test_helpers.SetClusterRO(initiallySetupServers, connOpts, roles) + require.Nilf(t, err, "fail to set roles for cluster") + + connPool, err := connection_pool.Connect(initiallySetupServers, connOpts) + require.Nilf(t, err, "failed to connect") + require.NotNilf(t, connPool, "conn is nil after Connect") + + defer connPool.Close() + + // ANY + args := test_helpers.ListenOnInstanceArgs{ + ServersNumber: serversNumber, + ExpectedPorts: allPorts, + ConnPool: connPool, + Mode: connection_pool.ANY, + } + + err = test_helpers.ProcessListenOnInstance(args) + require.Nil(t, err) + + // RW + args = test_helpers.ListenOnInstanceArgs{ + ServersNumber: serversNumber, + ExpectedPorts: masterPorts, + ConnPool: connPool, + Mode: connection_pool.RW, + } + + err = test_helpers.ProcessListenOnInstance(args) + require.Nil(t, err) + + // RO + args = test_helpers.ListenOnInstanceArgs{ + ServersNumber: serversNumber, + ExpectedPorts: replicaPorts, + ConnPool: connPool, + Mode: connection_pool.RO, + } + + err = test_helpers.ProcessListenOnInstance(args) + require.Nil(t, err) + + // PreferRW + args = test_helpers.ListenOnInstanceArgs{ + ServersNumber: serversNumber, + ExpectedPorts: masterPorts, + ConnPool: connPool, + Mode: connection_pool.PreferRW, + } + + err = test_helpers.ProcessListenOnInstance(args) + require.Nil(t, err) + + // PreferRO + args = test_helpers.ListenOnInstanceArgs{ + ServersNumber: serversNumber, + ExpectedPorts: replicaPorts, + ConnPool: connPool, + Mode: connection_pool.PreferRO, + } + + err = test_helpers.ProcessListenOnInstance(args) + require.Nil(t, err) + + roles = []bool{true, false, true, true, false} + + masterPorts = map[string]bool{ + servers[1]: true, + servers[4]: true, + } + + replicaPorts = map[string]bool{ + servers[0]: true, + servers[2]: true, + servers[3]: true, + } + + err = test_helpers.SetClusterRO(servers, connOpts, roles) + require.Nilf(t, err, "fail to set roles for cluster") + + getClusterMembers, err := template.New("get_cluster_members").Parse(getClusterMembersTemplate) + require.NoError(t, err) + serversMap := make(map[string]bool) + for _, server := range servers { + _, isWriteable := masterPorts[server] + serversMap[server] = isWriteable + } + buf := bytes.NewBuffer([]byte{}) + require.NoError(t, getClusterMembers.Execute(buf, serversMap)) + _, err = connPool.Eval(buf.String(), []interface{}{}, connection_pool.RW) + require.NoError(t, err) + time.Sleep(time.Second) + checkConnectedArgs := test_helpers.CheckStatusesArgs{ + ConnPool: connPool, + Mode: connection_pool.ANY, + Servers: servers, + ExpectedPoolStatus: true, + ExpectedStatuses: map[string]bool{ + servers[0]: true, + servers[1]: true, + servers[2]: true, + servers[3]: true, + servers[4]: true, + }, + } + + err = test_helpers.Retry(test_helpers.CheckPoolStatuses, checkConnectedArgs, defaultCountRetry, defaultTimeoutRetry) + require.Nil(t, err) + assert.Equal(t, servers, connPool.GetAddrs()) + + checkConnectedArgs = test_helpers.CheckStatusesArgs{ + ConnPool: connPool, + Mode: connection_pool.RW, + Servers: []string{servers[1], servers[4]}, + ExpectedPoolStatus: true, + ExpectedStatuses: masterPorts, + } + + err = test_helpers.Retry(test_helpers.CheckPoolStatuses, checkConnectedArgs, defaultCountRetry, defaultTimeoutRetry) + require.Nil(t, err) + + checkConnectedArgs = test_helpers.CheckStatusesArgs{ + ConnPool: connPool, + Mode: connection_pool.RO, + Servers: []string{servers[0], servers[2], servers[3]}, + ExpectedPoolStatus: true, + ExpectedStatuses: replicaPorts, + } + + err = test_helpers.Retry(test_helpers.CheckPoolStatuses, checkConnectedArgs, defaultCountRetry, defaultTimeoutRetry) + require.Nil(t, err) + +} diff --git a/connection_pool/connector_rw_balanced.go b/connection_pool/connector_rw_balanced.go new file mode 100644 index 000000000..b8946c228 --- /dev/null +++ b/connection_pool/connector_rw_balanced.go @@ -0,0 +1,251 @@ +package connection_pool + +import ( + "time" + + "github.com/hashicorp/go-multierror" + + "github.com/ice-blockchain/go-tarantool" + "github.com/ice-blockchain/go-tarantool/balancer" +) + +type RWBalancedConnectorAdapter struct { + pool Pooler + defaultMode Mode +} + +func NewRWBalancedConnector(pool Pooler, defaultMode Mode) tarantool.Connector { + return &RWBalancedConnectorAdapter{ + pool: pool, + defaultMode: defaultMode, + } +} + +func (b *RWBalancedConnectorAdapter) mode(writeable bool) Mode { + if writeable { + return RW + } else { + return PreferRO + } +} +func (b *RWBalancedConnectorAdapter) ConnectedNow() bool { + ret, err := b.pool.ConnectedNow(b.defaultMode) + if err != nil { + return false + } + return ret +} + +func (b *RWBalancedConnectorAdapter) Close() error { + return multierror.Append(nil, b.pool.Close()...).ErrorOrNil() +} + +func (b *RWBalancedConnectorAdapter) Ping() (besp *tarantool.Response, err error) { + return b.pool.Ping(b.defaultMode) +} + +func (b *RWBalancedConnectorAdapter) ConfiguredTimeout() time.Duration { + timeout, err := b.pool.ConfiguredTimeout(b.mode(false)) + if err != nil { + return 0 * time.Second + } + return timeout +} + +func (b *RWBalancedConnectorAdapter) Select(space, index interface{}, offset, limit, iterator uint32, key interface{}) (besp *tarantool.Response, err error) { + return b.pool.Select(space, index, offset, limit, iterator, key, b.mode(false)) +} + +func (b *RWBalancedConnectorAdapter) Insert(space interface{}, tuple interface{}) (besp *tarantool.Response, err error) { + return b.pool.Insert(space, tuple, b.mode(true)) +} + +func (b *RWBalancedConnectorAdapter) Replace(space interface{}, tuple interface{}) (besp *tarantool.Response, err error) { + return b.pool.Replace(space, tuple, b.mode(true)) +} + +func (b *RWBalancedConnectorAdapter) Delete(space, index interface{}, key interface{}) (besp *tarantool.Response, err error) { + return b.pool.Delete(space, index, key, b.mode(true)) +} + +func (b *RWBalancedConnectorAdapter) Update(space, index interface{}, key, ops interface{}) (besp *tarantool.Response, err error) { + return b.pool.Update(space, index, key, ops, b.mode(true)) +} + +func (b *RWBalancedConnectorAdapter) Upsert(space interface{}, tuple, ops interface{}) (besp *tarantool.Response, err error) { + return b.pool.Upsert(space, tuple, ops, b.mode(true)) +} + +func (b *RWBalancedConnectorAdapter) Call(functionName string, args interface{}) (besp *tarantool.Response, err error) { + script, requiresWrite := balancer.CheckIfRequiresWrite(functionName, true) + return b.pool.Call(script, args, b.mode(requiresWrite)) +} + +func (b *RWBalancedConnectorAdapter) Call16(functionName string, args interface{}) (besp *tarantool.Response, err error) { + script, requiresWrite := balancer.CheckIfRequiresWrite(functionName, true) + return b.pool.Call16(script, args, b.mode(requiresWrite)) +} + +func (b *RWBalancedConnectorAdapter) Call17(functionName string, args interface{}) (besp *tarantool.Response, err error) { + script, requiresWrite := balancer.CheckIfRequiresWrite(functionName, true) + return b.pool.Call17(script, args, b.mode(requiresWrite)) +} + +func (b *RWBalancedConnectorAdapter) Eval(expr string, args interface{}) (besp *tarantool.Response, err error) { + script, requiresWrite := balancer.CheckIfRequiresWrite(expr, true) + return b.pool.Eval(script, args, b.mode(requiresWrite)) +} + +func (b *RWBalancedConnectorAdapter) Execute(expr string, args interface{}) (besp *tarantool.Response, err error) { + script, requiresWrite := balancer.CheckIfRequiresWrite(expr, true) + return b.pool.Execute(script, args, b.mode(requiresWrite)) +} + +func (b *RWBalancedConnectorAdapter) PrepareExecute(sql string, args map[string]interface{}) (besp *tarantool.Response, err error) { + script, requiresWrite := balancer.CheckIfRequiresWrite(sql, true) + return b.pool.PrepareExecute(script, args, b.mode(requiresWrite)) +} + +func (b *RWBalancedConnectorAdapter) GetTyped(space, index interface{}, key interface{}, result interface{}) (err error) { + return b.pool.GetTyped(space, index, key, result, b.mode(false)) + +} + +func (b *RWBalancedConnectorAdapter) SelectTyped(space, index interface{}, offset, limit, iterator uint32, key interface{}, result interface{}) (err error) { + return b.pool.SelectTyped(space, index, offset, limit, iterator, key, result, b.mode(false)) + +} + +func (b *RWBalancedConnectorAdapter) InsertTyped(space interface{}, tuple interface{}, result interface{}) (err error) { + return b.pool.InsertTyped(space, tuple, result, b.mode(true)) + +} + +func (b *RWBalancedConnectorAdapter) ReplaceTyped(space interface{}, tuple interface{}, result interface{}) (err error) { + return b.pool.ReplaceTyped(space, tuple, result, b.mode(true)) + +} + +func (b *RWBalancedConnectorAdapter) DeleteTyped(space, index interface{}, key interface{}, result interface{}) (err error) { + return b.pool.DeleteTyped(space, index, key, result, b.mode(true)) + +} + +func (b *RWBalancedConnectorAdapter) UpdateTyped(space, index interface{}, key, ops interface{}, result interface{}) (err error) { + return b.pool.UpdateTyped(space, index, key, ops, result, b.mode(true)) + +} + +func (b *RWBalancedConnectorAdapter) UpsertTyped(space, tuple, ops, result interface{}) (err error) { + return b.pool.UpsertTyped(space, tuple, ops, result, b.mode(true)) + +} + +func (b *RWBalancedConnectorAdapter) CallTyped(functionName string, args interface{}, result interface{}) (err error) { + script, requiresWrite := balancer.CheckIfRequiresWrite(functionName, true) + return b.pool.CallTyped(script, args, result, b.mode(requiresWrite)) + +} + +func (b *RWBalancedConnectorAdapter) Call16Typed(functionName string, args interface{}, result interface{}) (err error) { + script, requiresWrite := balancer.CheckIfRequiresWrite(functionName, true) + return b.pool.Call16Typed(script, args, result, b.mode(requiresWrite)) +} + +func (b *RWBalancedConnectorAdapter) Call17Typed(functionName string, args interface{}, result interface{}) (err error) { + script, requiresWrite := balancer.CheckIfRequiresWrite(functionName, true) + return b.pool.Call17Typed(script, args, result, b.mode(requiresWrite)) +} + +func (b *RWBalancedConnectorAdapter) EvalTyped(expr string, args interface{}, result interface{}) (err error) { + script, requiresWrite := balancer.CheckIfRequiresWrite(expr, true) + return b.pool.EvalTyped(script, args, result, b.mode(requiresWrite)) + +} + +func (b *RWBalancedConnectorAdapter) ExecuteTyped(expr string, args interface{}, result interface{}) (tarantool.SQLInfo, []tarantool.ColumnMetaData, error) { + script, requiresWrite := balancer.CheckIfRequiresWrite(expr, true) + return b.pool.ExecuteTyped(script, args, result, b.mode(requiresWrite)) + +} + +func (b *RWBalancedConnectorAdapter) PrepareExecuteTyped(sql string, args map[string]interface{}, result interface{}) (err error) { + script, requiresWrite := balancer.CheckIfRequiresWrite(sql, true) + return b.pool.PrepareExecuteTyped(script, args, result, b.mode(requiresWrite)) + +} + +func (b *RWBalancedConnectorAdapter) SelectAsync(space, index interface{}, offset, limit, iterator uint32, key interface{}) *tarantool.Future { + return b.pool.SelectAsync(space, index, offset, limit, iterator, key, b.mode(false)) +} + +func (b *RWBalancedConnectorAdapter) InsertAsync(space interface{}, tuple interface{}) *tarantool.Future { + return b.pool.InsertAsync(space, tuple, b.mode(true)) +} + +func (b *RWBalancedConnectorAdapter) ReplaceAsync(space interface{}, tuple interface{}) *tarantool.Future { + return b.pool.ReplaceAsync(space, tuple, b.mode(true)) +} + +func (b *RWBalancedConnectorAdapter) DeleteAsync(space, index interface{}, key interface{}) *tarantool.Future { + return b.pool.DeleteAsync(space, index, key, b.mode(true)) + +} + +func (b *RWBalancedConnectorAdapter) UpdateAsync(space, index interface{}, key, ops interface{}) *tarantool.Future { + return b.pool.UpdateAsync(space, index, key, ops, b.mode(true)) +} + +func (b *RWBalancedConnectorAdapter) UpsertAsync(space interface{}, tuple interface{}, ops interface{}) *tarantool.Future { + return b.pool.UpsertAsync(space, tuple, ops, b.mode(true)) + +} + +func (b *RWBalancedConnectorAdapter) CallAsync(functionName string, args interface{}) *tarantool.Future { + script, requiresWrite := balancer.CheckIfRequiresWrite(functionName, true) + return b.pool.CallAsync(script, args, b.mode(requiresWrite)) +} + +func (b *RWBalancedConnectorAdapter) Call16Async(functionName string, args interface{}) *tarantool.Future { + script, requiresWrite := balancer.CheckIfRequiresWrite(functionName, true) + return b.pool.Call16Async(script, args, b.mode(requiresWrite)) +} + +func (b *RWBalancedConnectorAdapter) Call17Async(functionName string, args interface{}) *tarantool.Future { + script, requiresWrite := balancer.CheckIfRequiresWrite(functionName, true) + return b.pool.Call17Async(script, args, b.mode(requiresWrite)) +} + +func (b *RWBalancedConnectorAdapter) EvalAsync(expr string, args interface{}) *tarantool.Future { + script, requiresWrite := balancer.CheckIfRequiresWrite(expr, true) + return b.pool.EvalAsync(script, args, b.mode(requiresWrite)) + +} + +func (b *RWBalancedConnectorAdapter) ExecuteAsync(expr string, args interface{}) *tarantool.Future { + script, requiresWrite := balancer.CheckIfRequiresWrite(expr, true) + return b.pool.ExecuteAsync(script, args, b.mode(requiresWrite)) + +} + +func (b *RWBalancedConnectorAdapter) NewPrepared(expr string) (*tarantool.Prepared, error) { + script, requiresWrite := balancer.CheckIfRequiresWrite(expr, true) + return b.pool.NewPrepared(script, b.mode(requiresWrite)) + +} + +func (b *RWBalancedConnectorAdapter) NewStream() (*tarantool.Stream, error) { + return b.pool.NewStream(b.defaultMode) + +} + +func (b *RWBalancedConnectorAdapter) NewWatcher(key string, callback tarantool.WatchCallback) (tarantool.Watcher, error) { + return b.pool.NewWatcher(key, callback, b.mode(true)) + +} + +func (b *RWBalancedConnectorAdapter) Do(req tarantool.Request) *tarantool.Future { + requiresWrite := balancer.CheckIfRequiresWriteForRequest(req, b.defaultMode == RW || b.defaultMode == PreferRW) + return b.pool.Do(req, b.mode(requiresWrite)) + +} diff --git a/connection_pool/connector_rw_balanced_test.go b/connection_pool/connector_rw_balanced_test.go new file mode 100644 index 000000000..08d287963 --- /dev/null +++ b/connection_pool/connector_rw_balanced_test.go @@ -0,0 +1,746 @@ +package connection_pool_test + +import ( + "errors" + "github.com/ice-blockchain/go-tarantool" + "github.com/ice-blockchain/go-tarantool/balancer" + "github.com/ice-blockchain/go-tarantool/connection_pool" + "github.com/stretchr/testify/require" + "sync/atomic" + "testing" + "time" +) + +type requiresWriteMockPool struct { + requiresWrite bool + called uint64 +} + +func (r *requiresWriteMockPool) validateMode(mode connection_pool.Mode) error { + atomic.AddUint64(&r.called, 1) + if mode == connection_pool.ANY { + return errors.New("Any connection is not applicable for RW balanced pool, it shold be RO or RW") + } + if r.requiresWrite && (mode == connection_pool.RO || mode == connection_pool.PreferRO) { + return errors.New("read only connection requested for writeable case") + } + if !r.requiresWrite && (mode == connection_pool.RW || mode == connection_pool.PreferRW) { + return errors.New("writable connection requested for read only case") + } + return nil +} +func (r *requiresWriteMockPool) ConnectedNow(mode connection_pool.Mode) (bool, error) { + return true, r.validateMode(mode) +} + +func (r *requiresWriteMockPool) Close() []error { + return []error{} +} + +func (r *requiresWriteMockPool) Ping(mode connection_pool.Mode) (*tarantool.Response, error) { + return nil, r.validateMode(mode) +} + +func (r *requiresWriteMockPool) ConfiguredTimeout(mode connection_pool.Mode) (time.Duration, error) { + return time.Millisecond, r.validateMode(mode) +} + +func (r *requiresWriteMockPool) Select(space, index interface{}, offset, limit, iterator uint32, key interface{}, mode ...connection_pool.Mode) (*tarantool.Response, error) { + return nil, r.validateMode(mode[0]) +} + +func (r *requiresWriteMockPool) Insert(space interface{}, tuple interface{}, mode ...connection_pool.Mode) (*tarantool.Response, error) { + return nil, r.validateMode(mode[0]) +} + +func (r *requiresWriteMockPool) Replace(space interface{}, tuple interface{}, mode ...connection_pool.Mode) (*tarantool.Response, error) { + return nil, r.validateMode(mode[0]) +} + +func (r *requiresWriteMockPool) Delete(space, index interface{}, key interface{}, mode ...connection_pool.Mode) (*tarantool.Response, error) { + return nil, r.validateMode(mode[0]) +} + +func (r *requiresWriteMockPool) Update(space, index interface{}, key, ops interface{}, mode ...connection_pool.Mode) (*tarantool.Response, error) { + return nil, r.validateMode(mode[0]) +} + +func (r *requiresWriteMockPool) Upsert(space interface{}, tuple, ops interface{}, mode ...connection_pool.Mode) (*tarantool.Response, error) { + return nil, r.validateMode(mode[0]) +} + +func (r *requiresWriteMockPool) Call(functionName string, args interface{}, mode connection_pool.Mode) (*tarantool.Response, error) { + return nil, r.validateMode(mode) +} + +func (r *requiresWriteMockPool) Call16(functionName string, args interface{}, mode connection_pool.Mode) (*tarantool.Response, error) { + return nil, r.validateMode(mode) +} + +func (r *requiresWriteMockPool) Call17(functionName string, args interface{}, mode connection_pool.Mode) (*tarantool.Response, error) { + return nil, r.validateMode(mode) +} + +func (r *requiresWriteMockPool) Eval(expr string, args interface{}, mode connection_pool.Mode) (*tarantool.Response, error) { + return nil, r.validateMode(mode) +} + +func (r *requiresWriteMockPool) Execute(expr string, args interface{}, mode connection_pool.Mode) (*tarantool.Response, error) { + return nil, r.validateMode(mode) +} + +func (r *requiresWriteMockPool) PrepareExecute(sql string, args map[string]interface{}, mode connection_pool.Mode) (resp *tarantool.Response, err error) { + return nil, r.validateMode(mode) +} + +func (r *requiresWriteMockPool) GetTyped(space, index interface{}, key interface{}, result interface{}, mode ...connection_pool.Mode) error { + return r.validateMode(mode[0]) +} + +func (r *requiresWriteMockPool) SelectTyped(space, index interface{}, offset, limit, iterator uint32, key interface{}, result interface{}, mode ...connection_pool.Mode) error { + return r.validateMode(mode[0]) +} + +func (r *requiresWriteMockPool) InsertTyped(space interface{}, tuple interface{}, result interface{}, mode ...connection_pool.Mode) error { + return r.validateMode(mode[0]) +} + +func (r *requiresWriteMockPool) ReplaceTyped(space interface{}, tuple interface{}, result interface{}, mode ...connection_pool.Mode) error { + return r.validateMode(mode[0]) +} + +func (r *requiresWriteMockPool) DeleteTyped(space, index interface{}, key interface{}, result interface{}, mode ...connection_pool.Mode) error { + return r.validateMode(mode[0]) +} + +func (r *requiresWriteMockPool) UpdateTyped(space, index interface{}, key, ops interface{}, result interface{}, mode ...connection_pool.Mode) error { + return r.validateMode(mode[0]) +} + +func (r *requiresWriteMockPool) UpsertTyped(space, tuple, ops, result interface{}, mode ...connection_pool.Mode) (err error) { + return r.validateMode(mode[0]) +} + +func (r *requiresWriteMockPool) CallTyped(functionName string, args interface{}, result interface{}, mode connection_pool.Mode) error { + return r.validateMode(mode) +} + +func (r *requiresWriteMockPool) Call16Typed(functionName string, args interface{}, result interface{}, mode connection_pool.Mode) error { + return r.validateMode(mode) +} + +func (r *requiresWriteMockPool) Call17Typed(functionName string, args interface{}, result interface{}, mode connection_pool.Mode) error { + return r.validateMode(mode) +} + +func (r *requiresWriteMockPool) EvalTyped(expr string, args interface{}, result interface{}, mode connection_pool.Mode) error { + return r.validateMode(mode) +} + +func (r *requiresWriteMockPool) ExecuteTyped(expr string, args interface{}, result interface{}, mode connection_pool.Mode) (tarantool.SQLInfo, []tarantool.ColumnMetaData, error) { + return tarantool.SQLInfo{}, nil, r.validateMode(mode) +} + +func (r *requiresWriteMockPool) PrepareExecuteTyped(sql string, args map[string]interface{}, result interface{}, mode connection_pool.Mode) (err error) { + return r.validateMode(mode) +} + +func (r *requiresWriteMockPool) SelectAsync(space, index interface{}, offset, limit, iterator uint32, key interface{}, mode ...connection_pool.Mode) *tarantool.Future { + f := tarantool.NewFuture() + f.SetError(r.validateMode(mode[0])) + f.AppendPush(nil) + return f +} + +func (r *requiresWriteMockPool) InsertAsync(space interface{}, tuple interface{}, mode ...connection_pool.Mode) *tarantool.Future { + f := tarantool.NewFuture() + f.SetError(r.validateMode(mode[0])) + f.AppendPush(nil) + return f +} + +func (r *requiresWriteMockPool) ReplaceAsync(space interface{}, tuple interface{}, mode ...connection_pool.Mode) *tarantool.Future { + f := tarantool.NewFuture() + f.SetError(r.validateMode(mode[0])) + f.AppendPush(nil) + return f +} + +func (r *requiresWriteMockPool) DeleteAsync(space, index interface{}, key interface{}, mode ...connection_pool.Mode) *tarantool.Future { + f := tarantool.NewFuture() + f.SetError(r.validateMode(mode[0])) + f.AppendPush(nil) + return f +} + +func (r *requiresWriteMockPool) UpdateAsync(space, index interface{}, key, ops interface{}, mode ...connection_pool.Mode) *tarantool.Future { + f := tarantool.NewFuture() + f.SetError(r.validateMode(mode[0])) + f.AppendPush(nil) + return f +} + +func (r *requiresWriteMockPool) UpsertAsync(space interface{}, tuple interface{}, ops interface{}, mode ...connection_pool.Mode) *tarantool.Future { + f := tarantool.NewFuture() + f.SetError(r.validateMode(mode[0])) + f.AppendPush(nil) + return f +} + +func (r *requiresWriteMockPool) CallAsync(functionName string, args interface{}, mode connection_pool.Mode) *tarantool.Future { + f := tarantool.NewFuture() + f.SetError(r.validateMode(mode)) + f.AppendPush(nil) + return f +} + +func (r *requiresWriteMockPool) Call16Async(functionName string, args interface{}, mode connection_pool.Mode) *tarantool.Future { + f := tarantool.NewFuture() + f.SetError(r.validateMode(mode)) + f.AppendPush(nil) + return f +} + +func (r *requiresWriteMockPool) Call17Async(functionName string, args interface{}, mode connection_pool.Mode) *tarantool.Future { + f := tarantool.NewFuture() + f.SetError(r.validateMode(mode)) + f.AppendPush(nil) + return f +} + +func (r *requiresWriteMockPool) EvalAsync(expr string, args interface{}, mode connection_pool.Mode) *tarantool.Future { + f := tarantool.NewFuture() + f.SetError(r.validateMode(mode)) + f.AppendPush(nil) + return f +} + +func (r *requiresWriteMockPool) ExecuteAsync(expr string, args interface{}, mode connection_pool.Mode) *tarantool.Future { + f := tarantool.NewFuture() + f.SetError(r.validateMode(mode)) + f.AppendPush(nil) + return f +} + +func (r *requiresWriteMockPool) NewPrepared(expr string, mode connection_pool.Mode) (*tarantool.Prepared, error) { + return nil, r.validateMode(mode) +} + +func (r *requiresWriteMockPool) NewStream(mode connection_pool.Mode) (*tarantool.Stream, error) { + return nil, r.validateMode(mode) +} + +func (r *requiresWriteMockPool) NewWatcher(key string, callback tarantool.WatchCallback, mode connection_pool.Mode) (tarantool.Watcher, error) { + return nil, r.validateMode(mode) +} + +func (r *requiresWriteMockPool) Do(req tarantool.Request, mode connection_pool.Mode) (fut *tarantool.Future) { + f := tarantool.NewFuture() + f.SetError(r.validateMode(mode)) + f.AppendPush(nil) + return f +} + +func NewRWConnectorAdapter(pool connection_pool.Pooler, mode connection_pool.Mode) *connection_pool.RWBalancedConnectorAdapter { + return connection_pool.NewRWBalancedConnector(pool, mode).(*connection_pool.RWBalancedConnectorAdapter) +} + +func TestRWConnectorConnectedNow(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: false} + c := NewRWConnectorAdapter(m, connection_pool.RW) + + require.Falsef(t, c.ConnectedNow(), "unexpected result") + require.Equalf(t, uint64(1), m.called, "should be called only once") + +} + +func TestRWConnectorGetTyped(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: false} + c := NewRWConnectorAdapter(m, testMode) + + err := c.GetTyped(reqSpace, reqIndex, reqKey, reqResult) + + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorSelect(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: false} + c := NewRWConnectorAdapter(m, testMode) + + _, err := c.Select(reqSpace, reqIndex, reqOffset, reqLimit, reqIterator, reqKey) + + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorSelectTyped(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: false} + c := NewRWConnectorAdapter(m, testMode) + + err := c.SelectTyped(reqSpace, reqIndex, reqOffset, reqLimit, + reqIterator, reqKey, reqResult) + + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorSelectAsync(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: false} + c := NewRWConnectorAdapter(m, testMode) + + fut := c.SelectAsync(reqSpace, reqIndex, reqOffset, reqLimit, + reqIterator, reqKey) + + require.NoError(t, fut.Err()) + require.Equalf(t, uint64(1), m.called, "should be called only once") + +} + +func TestRWConnectorInsert(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + _, err := c.Insert(reqSpace, reqTuple) + + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorInsertTyped(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + err := c.InsertTyped(reqSpace, reqTuple, reqResult) + + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorInsertAsync(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + fut := c.InsertAsync(reqSpace, reqTuple) + + require.NoError(t, fut.Err()) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorReplace(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + _, err := c.Replace(reqSpace, reqTuple) + + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorReplaceTyped(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + err := c.ReplaceTyped(reqSpace, reqTuple, reqResult) + + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorReplaceAsync(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + fut := c.ReplaceAsync(reqSpace, reqTuple) + + require.NoError(t, fut.Err()) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorDelete(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + _, err := c.Delete(reqSpace, reqIndex, reqKey) + + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorDeleteTyped(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + err := c.DeleteTyped(reqSpace, reqIndex, reqKey, reqResult) + + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorDeleteAsync(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + fut := c.DeleteAsync(reqSpace, reqIndex, reqKey) + + require.NoError(t, fut.Err()) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorUpdate(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + _, err := c.Update(reqSpace, reqIndex, reqKey, reqOps) + + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") + +} + +func TestRWConnectorUpdateTyped(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + err := c.UpdateTyped(reqSpace, reqIndex, reqKey, reqOps, reqResult) + + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorUpdateAsync(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + fut := c.UpdateAsync(reqSpace, reqIndex, reqKey, reqOps) + + require.NoError(t, fut.Err()) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorUpsert(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + _, err := c.Upsert(reqSpace, reqTuple, reqOps) + + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") + +} + +func TestRWConnectorUpsertAsync(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + fut := c.UpsertAsync(reqSpace, reqTuple, reqOps) + + require.NoError(t, fut.Err()) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorCall(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + _, err := c.Call(reqFunctionName, reqArgs) + + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorCallTyped(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + err := c.CallTyped(reqFunctionName, reqArgs, reqResult) + + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") + +} + +func TestRWConnectorCallAsync(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + fut := c.CallAsync(reqFunctionName, reqArgs) + + require.NoError(t, fut.Err()) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorCallNonWriteable(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: false} + c := NewRWConnectorAdapter(m, testMode) + + _, err := c.Call("{{"+string(balancer.NonWritable)+"}}"+reqFunctionName, reqArgs) + + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorCallTypedNonWriteable(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: false} + c := NewRWConnectorAdapter(m, testMode) + + err := c.CallTyped("{{"+string(balancer.NonWritable)+"}}"+reqFunctionName, reqArgs, reqResult) + + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") + +} + +func TestRWConnectorCallAsyncNonWriteable(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: false} + c := NewRWConnectorAdapter(m, testMode) + + fut := c.CallAsync("{{"+string(balancer.NonWritable)+"}}"+reqFunctionName, reqArgs) + + require.NoError(t, fut.Err()) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorCall16(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + _, err := c.Call16(reqFunctionName, reqArgs) + + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorCall16Typed(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + err := c.Call16Typed(reqFunctionName, reqArgs, reqResult) + + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") + +} +func TestRWConnectorCall16Async(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + fut := c.Call16Async(reqFunctionName, reqArgs) + + require.NoError(t, fut.Err()) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorCall16NonWritable(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: false} + c := NewRWConnectorAdapter(m, testMode) + + _, err := c.Call16("{{"+string(balancer.NonWritable)+"}}"+reqFunctionName, reqArgs) + + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorCall16TypedNonWriteable(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: false} + c := NewRWConnectorAdapter(m, testMode) + + err := c.Call16Typed("{{"+string(balancer.NonWritable)+"}}"+reqFunctionName, reqArgs, reqResult) + + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") + +} +func TestRWConnectorCall16AsyncNonWriteable(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: false} + c := NewRWConnectorAdapter(m, testMode) + + fut := c.Call16Async("{{"+string(balancer.NonWritable)+"}}"+reqFunctionName, reqArgs) + + require.NoError(t, fut.Err()) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorCall17(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + _, err := c.Call17(reqFunctionName, reqArgs) + + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") + +} + +func TestRWConnectorCall17Typed(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + _, err := c.Call17(reqFunctionName, reqArgs) + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorCall17Async(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + fut := c.Call17Async(reqFunctionName, reqArgs) + + require.NoError(t, fut.Err()) + require.Equalf(t, uint64(1), m.called, "should be called only once") + +} +func TestRWConnectorCall17NonWriteable(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: false} + c := NewRWConnectorAdapter(m, testMode) + + _, err := c.Call17("{{"+string(balancer.NonWritable)+"}}"+reqFunctionName, reqArgs) + + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") + +} + +func TestRWConnectorCall17TypedNonWriteable(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: false} + c := NewRWConnectorAdapter(m, testMode) + + err := c.Call17Typed("{{"+string(balancer.NonWritable)+"}}"+reqFunctionName, reqArgs, reqResult) + + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorCall17AsyncNonWriteable(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: false} + c := NewRWConnectorAdapter(m, testMode) + + fut := c.Call17Async("{{"+string(balancer.NonWritable)+"}}"+reqFunctionName, reqArgs) + + require.NoError(t, fut.Err()) + require.Equalf(t, uint64(1), m.called, "should be called only once") + +} + +func TestRWConnectorEval(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + _, err := c.Eval(reqFunctionName, reqArgs) + + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorEvalTyped(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + err := c.EvalTyped(reqFunctionName, reqArgs, reqResult) + + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") + +} + +func TestRWConnectorEvalAsync(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + fut := c.EvalAsync(reqFunctionName, reqArgs) + + require.NoError(t, fut.Err()) + require.Equalf(t, uint64(1), m.called, "should be called only once") + +} + +func TestRWConnectorEvalNonWriteable(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: false} + c := NewRWConnectorAdapter(m, testMode) + + _, err := c.Eval("{{"+string(balancer.NonWritable)+"}}"+reqFunctionName, reqArgs) + + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorEvalTypedNonWriteable(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: false} + c := NewRWConnectorAdapter(m, testMode) + + err := c.EvalTyped("{{"+string(balancer.NonWritable)+"}}"+reqFunctionName, reqArgs, reqResult) + + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") + +} + +func TestRWConnectorEvalAsyncNonWriteable(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: false} + c := NewRWConnectorAdapter(m, testMode) + + fut := c.EvalAsync("{{"+string(balancer.NonWritable)+"}}"+reqFunctionName, reqArgs) + + require.NoError(t, fut.Err()) + require.Equalf(t, uint64(1), m.called, "should be called only once") + +} + +func TestRWConnectorExecute(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + _, err := c.Execute(reqFunctionName, reqArgs) + + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorExecuteTyped(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + _, _, err := c.ExecuteTyped(reqFunctionName, reqArgs, reqResult) + + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorExecuteAsync(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + fut := c.ExecuteAsync(reqFunctionName, reqArgs) + + require.NoError(t, fut.Err()) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorNewPrepared(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + _, err := c.NewPrepared(reqFunctionName) + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorNewStream(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + _, err := c.NewStream() + + require.NoError(t, err) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} + +func TestRWConnectorDo(t *testing.T) { + m := &requiresWriteMockPool{requiresWrite: true} + c := NewRWConnectorAdapter(m, testMode) + + fut := c.Do(reqRequest) + + require.NoError(t, fut.Err()) + require.Equalf(t, uint64(1), m.called, "should be called only once") +} diff --git a/connection_test.go b/connection_test.go index b9800683d..3ac01f31f 100644 --- a/connection_test.go +++ b/connection_test.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "os" "sync" "testing" "time" @@ -39,7 +40,7 @@ func TestOptsClonePreservesRequiredProtocolFeatures(t *testing.T) { } func TestPrepareExecuteBlackbox(t *testing.T) { - ttShutdown, _, err := setTarantoolCluster("3301", "3302", "3303") + //ttShutdown, _, err := setTarantoolCluster("3301", "3302", "3303") ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) db, err := connection_pool.ConnectWithWritableAwareDefaults(ctx, cancel, true, connection_pool.BasicAuth{"admin", "pass"}, "localhost:3301", @@ -56,7 +57,7 @@ func TestPrepareExecuteBlackbox(t *testing.T) { panic("still connected") } } - ttShutdown() + //ttShutdown() }(db) if err != nil { panic(fmt.Sprintf("Could not connect to cluster %v", err)) @@ -70,6 +71,7 @@ func TestPrepareExecuteBlackbox(t *testing.T) { }() } wg.Wait() + time.Sleep(180 * time.Second) } func execPrepareExecute(ctx context.Context, db Connector) { @@ -149,6 +151,8 @@ func setTarantoolCluster(ports ...string) (func(), []test_helpers.TarantoolInsta tts := make([]test_helpers.TarantoolInstance, len(ports)) for i, p := range ports { var err error + _ = os.MkdirAll(fmt.Sprintf("/tmp/tarantool_data/%v/memtx", p), 0777) + _ = os.MkdirAll(fmt.Sprintf("/tmp/tarantool_data/%v/wal", p), 0777) tts[i], err = test_helpers.StartTarantool(test_helpers.StartOpts{ InitScript: fmt.Sprintf("./.testdata/tarantool_bootstrap_%v.lua", p), Listen: fmt.Sprintf("127.0.0.1:%v", p), diff --git a/go.mod b/go.mod index a447cfb57..c26307844 100644 --- a/go.mod +++ b/go.mod @@ -4,10 +4,15 @@ go 1.11 require ( github.com/google/uuid v1.3.0 + github.com/hashicorp/go-multierror v1.1.1 + 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-openssl v0.0.8-0.20230307065445-720eeb389195 - github.com/tarantool/go-tarantool v1.10.0 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 dc784ccf1..710cff5c3 100644 --- a/go.sum +++ b/go.sum @@ -2,10 +2,12 @@ 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/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= 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/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= @@ -13,39 +15,28 @@ github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 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-openssl v0.0.8-0.20220711094538-d93c1eff4f49/go.mod h1:M7H4xYSbzqpW/ZRBMyH0eyqQBsnhAMfsYk5mv0yid7A= 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/tarantool/go-tarantool v1.10.0 h1:4sLGAFliIbCNuo3vnWXe5UcfnLChyfw8+IDDIk57YvU= -github.com/tarantool/go-tarantool v1.10.0/go.mod h1:oPjvZNKaN4iKbf8YPo3pGpxzk6cRZF1neAxgq8WcBh8= 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= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 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/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 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= @@ -56,12 +47,6 @@ 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= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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= @@ -71,4 +56,3 @@ gopkg.in/vmihailenco/msgpack.v2 v2.9.2 h1:gjPqo9orRVlSAH/065qw3MsFCDpH7fa1KpiizX 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= -gotest.tools/v3 v3.2.0/go.mod h1:Mcr9QNxkg0uMvy/YElmo4SpXgJKWgQvYrT7Kw5RzJ1A=