Skip to content

Commit ab4e64d

Browse files
committed
api: make dialer mandatory
This patch modifies `Connect` api. Now, to connect to the Tarantool, you need to pass an object that satisfies `tarantool.Dialer` interface. You can use one of the existing implementations: `NetDialer` or `OpenSslDialer`. For example: ``` conn, err := tarantool.Connect(context.Background(), tarantool.NetDialer{ Address: "127.0.0.1:3301", User: "user", Password: "secret", }, tarantool.Opts{}) ``` To create a connection pool, you need to pass a `map[string]tarantool.Dialer`, where each dialer is associated with a unique ID (for example, it can be the server address). Dialers will be distinguished from each other using these IDs. For example: ``` connPool, err := pool.Connect(context.Background(), map[string]tarantool.Dialer{ "127.0.0.1": tarantool.NetDialer{ Address: "127.0.0.1", User: "user", Password: "secret", }, }, tarantool.Opts{}) ``` The `conn.RemoteAddr` and `conn.LocalAddr` functions have been removed. To obtain the connection address, you can use `conn.Addr`. Now, `NewWatcher` checks the actual features of the server, rather than relying on the features provided by the user during connection creation. In the case of connection pool, watchers are created for connections that support this feature. `ClientProtocolInfo`, `ServerProtocolInfo` were removed. Now, there is `ProtocolInfo`, which returns the server protocol info. `pool.GetPoolInfo` was renamed to `pool.GetInfo`. Return type changed to `map[string]ConnectionInfo`. Part of #321
1 parent 6225ec4 commit ab4e64d

37 files changed

+1848
-1678
lines changed

box_error_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ func TestErrorTypeMPEncodeDecode(t *testing.T) {
299299
func TestErrorTypeEval(t *testing.T) {
300300
test_helpers.SkipIfErrorMessagePackTypeUnsupported(t)
301301

302-
conn := test_helpers.ConnectWithValidation(t, server, opts)
302+
conn := test_helpers.ConnectWithValidation(t, dialer, opts)
303303
defer conn.Close()
304304

305305
for name, testcase := range tupleCases {
@@ -318,7 +318,7 @@ func TestErrorTypeEval(t *testing.T) {
318318
func TestErrorTypeEvalTyped(t *testing.T) {
319319
test_helpers.SkipIfErrorMessagePackTypeUnsupported(t)
320320

321-
conn := test_helpers.ConnectWithValidation(t, server, opts)
321+
conn := test_helpers.ConnectWithValidation(t, dialer, opts)
322322
defer conn.Close()
323323

324324
for name, testcase := range tupleCases {
@@ -336,7 +336,7 @@ func TestErrorTypeEvalTyped(t *testing.T) {
336336
func TestErrorTypeInsert(t *testing.T) {
337337
test_helpers.SkipIfErrorMessagePackTypeUnsupported(t)
338338

339-
conn := test_helpers.ConnectWithValidation(t, server, opts)
339+
conn := test_helpers.ConnectWithValidation(t, dialer, opts)
340340
defer conn.Close()
341341

342342
truncateEval := fmt.Sprintf("box.space[%q]:truncate()", space)
@@ -374,7 +374,7 @@ func TestErrorTypeInsert(t *testing.T) {
374374
func TestErrorTypeInsertTyped(t *testing.T) {
375375
test_helpers.SkipIfErrorMessagePackTypeUnsupported(t)
376376

377-
conn := test_helpers.ConnectWithValidation(t, server, opts)
377+
conn := test_helpers.ConnectWithValidation(t, dialer, opts)
378378
defer conn.Close()
379379

380380
truncateEval := fmt.Sprintf("box.space[%q]:truncate()", space)
@@ -416,7 +416,7 @@ func TestErrorTypeInsertTyped(t *testing.T) {
416416
func TestErrorTypeSelect(t *testing.T) {
417417
test_helpers.SkipIfErrorMessagePackTypeUnsupported(t)
418418

419-
conn := test_helpers.ConnectWithValidation(t, server, opts)
419+
conn := test_helpers.ConnectWithValidation(t, dialer, opts)
420420
defer conn.Close()
421421

422422
truncateEval := fmt.Sprintf("box.space[%q]:truncate()", space)
@@ -461,7 +461,7 @@ func TestErrorTypeSelect(t *testing.T) {
461461
func TestErrorTypeSelectTyped(t *testing.T) {
462462
test_helpers.SkipIfErrorMessagePackTypeUnsupported(t)
463463

464-
conn := test_helpers.ConnectWithValidation(t, server, opts)
464+
conn := test_helpers.ConnectWithValidation(t, dialer, opts)
465465
defer conn.Close()
466466

467467
truncateEval := fmt.Sprintf("box.space[%q]:truncate()", space)

connection.go

Lines changed: 23 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"io"
1111
"log"
1212
"math"
13+
"net"
1314
"runtime"
1415
"sync"
1516
"sync/atomic"
@@ -90,15 +91,15 @@ func (d defaultLogger) Report(event ConnLogKind, conn *Connection, v ...interfac
9091
reconnects := v[0].(uint)
9192
err := v[1].(error)
9293
log.Printf("tarantool: reconnect (%d/%d) to %s failed: %s",
93-
reconnects, conn.opts.MaxReconnects, conn.addr, err)
94+
reconnects, conn.opts.MaxReconnects, conn.Addr(), err)
9495
case LogLastReconnectFailed:
9596
err := v[0].(error)
9697
log.Printf("tarantool: last reconnect to %s failed: %s, giving it up",
97-
conn.addr, err)
98+
conn.Addr(), err)
9899
case LogUnexpectedResultId:
99100
resp := v[0].(*Response)
100101
log.Printf("tarantool: connection %s got unexpected resultId (%d) in response",
101-
conn.addr, resp.RequestId)
102+
conn.Addr(), resp.RequestId)
102103
case LogWatchEventReadFailed:
103104
err := v[0].(error)
104105
log.Printf("tarantool: unable to parse watch event: %s", err)
@@ -156,10 +157,11 @@ func (d defaultLogger) Report(event ConnLogKind, conn *Connection, v ...interfac
156157
// More on graceful shutdown:
157158
// https://www.tarantool.io/en/doc/latest/dev_guide/internals/iproto/graceful_shutdown/
158159
type Connection struct {
159-
addr string
160-
c Conn
161-
mutex sync.Mutex
162-
cond *sync.Cond
160+
addr net.Addr
161+
dialer Dialer
162+
c Conn
163+
mutex sync.Mutex
164+
cond *sync.Cond
163165
// Schema contains schema loaded on connection.
164166
Schema *Schema
165167
// schemaResolver contains a SchemaResolver implementation.
@@ -262,11 +264,6 @@ const (
262264

263265
// Opts is a way to configure Connection
264266
type Opts struct {
265-
// Auth is an authentication method.
266-
Auth Auth
267-
// Dialer is a Dialer object used to create a new connection to a
268-
// Tarantool instance. TtDialer is a default one.
269-
Dialer Dialer
270267
// Timeout for response to a particular request. The timeout is reset when
271268
// push messages are received. If Timeout is zero, any request can be
272269
// blocked infinitely.
@@ -289,10 +286,6 @@ type Opts struct {
289286
// endlessly.
290287
// After MaxReconnects attempts Connection becomes closed.
291288
MaxReconnects uint
292-
// Username for logging in to Tarantool.
293-
User string
294-
// User password for logging in to Tarantool.
295-
Pass string
296289
// RateLimit limits number of 'in-fly' request, i.e. already put into
297290
// requests queue, but not yet answered by server or timeouted.
298291
// It is disabled by default.
@@ -317,83 +310,23 @@ type Opts struct {
317310
Handle interface{}
318311
// Logger is user specified logger used for error messages.
319312
Logger Logger
320-
// Transport is the connection type, by default the connection is unencrypted.
321-
Transport string
322-
// SslOpts is used only if the Transport == 'ssl' is set.
323-
Ssl SslOpts
324-
// RequiredProtocolInfo contains minimal protocol version and
325-
// list of protocol features that should be supported by
326-
// Tarantool server. By default there are no restrictions.
327-
RequiredProtocolInfo ProtocolInfo
328-
}
329-
330-
// SslOpts is a way to configure ssl transport.
331-
type SslOpts struct {
332-
// KeyFile is a path to a private SSL key file.
333-
KeyFile string
334-
// CertFile is a path to an SSL certificate file.
335-
CertFile string
336-
// CaFile is a path to a trusted certificate authorities (CA) file.
337-
CaFile string
338-
// Ciphers is a colon-separated (:) list of SSL cipher suites the connection
339-
// can use.
340-
//
341-
// We don't provide a list of supported ciphers. This is what OpenSSL
342-
// does. The only limitation is usage of TLSv1.2 (because other protocol
343-
// versions don't seem to support the GOST cipher). To add additional
344-
// ciphers (GOST cipher), you must configure OpenSSL.
345-
//
346-
// See also
347-
//
348-
// * https://www.openssl.org/docs/man1.1.1/man1/ciphers.html
349-
Ciphers string
350-
// Password is a password for decrypting the private SSL key file.
351-
// The priority is as follows: try to decrypt with Password, then
352-
// try PasswordFile.
353-
Password string
354-
// PasswordFile is a path to the list of passwords for decrypting
355-
// the private SSL key file. The connection tries every line from the
356-
// file as a password.
357-
PasswordFile string
358-
}
359-
360-
// Clone returns a copy of the Opts object.
361-
// Any changes in copy RequiredProtocolInfo will not affect the original
362-
// RequiredProtocolInfo value.
363-
func (opts Opts) Clone() Opts {
364-
optsCopy := opts
365-
optsCopy.RequiredProtocolInfo = opts.RequiredProtocolInfo.Clone()
366-
367-
return optsCopy
368313
}
369314

370315
// Connect creates and configures a new Connection.
371-
//
372-
// Address could be specified in following ways:
373-
//
374-
// - TCP connections (tcp://192.168.1.1:3013, tcp://my.host:3013,
375-
// tcp:192.168.1.1:3013, tcp:my.host:3013, 192.168.1.1:3013, my.host:3013)
376-
//
377-
// - Unix socket, first '/' or '.' indicates Unix socket
378-
// (unix:///abs/path/tnt.sock, unix:path/tnt.sock, /abs/path/tnt.sock,
379-
// ./rel/path/tnt.sock, unix/:path/tnt.sock)
380-
func Connect(ctx context.Context, addr string, opts Opts) (conn *Connection, err error) {
316+
func Connect(ctx context.Context, dialer Dialer, opts Opts) (conn *Connection, err error) {
381317
conn = &Connection{
382-
addr: addr,
318+
dialer: dialer,
383319
requestId: 0,
384320
contextRequestId: 1,
385321
Greeting: &Greeting{},
386322
control: make(chan struct{}),
387-
opts: opts.Clone(),
323+
opts: opts,
388324
dec: msgpack.NewDecoder(&smallBuf{}),
389325
}
390326
maxprocs := uint32(runtime.GOMAXPROCS(-1))
391327
if conn.opts.Concurrency == 0 || conn.opts.Concurrency > maxprocs*128 {
392328
conn.opts.Concurrency = maxprocs * 4
393329
}
394-
if conn.opts.Dialer == nil {
395-
conn.opts.Dialer = TtDialer{}
396-
}
397330
if c := conn.opts.Concurrency; c&(c-1) != 0 {
398331
for i := uint(1); i < 32; i *= 2 {
399332
c |= c >> i
@@ -474,30 +407,10 @@ func (conn *Connection) CloseGraceful() error {
474407
}
475408

476409
// Addr returns a configured address of Tarantool socket.
477-
func (conn *Connection) Addr() string {
410+
func (conn *Connection) Addr() net.Addr {
478411
return conn.addr
479412
}
480413

481-
// RemoteAddr returns an address of Tarantool socket.
482-
func (conn *Connection) RemoteAddr() string {
483-
conn.mutex.Lock()
484-
defer conn.mutex.Unlock()
485-
if conn.c == nil {
486-
return ""
487-
}
488-
return conn.c.RemoteAddr().String()
489-
}
490-
491-
// LocalAddr returns an address of outgoing socket.
492-
func (conn *Connection) LocalAddr() string {
493-
conn.mutex.Lock()
494-
defer conn.mutex.Unlock()
495-
if conn.c == nil {
496-
return ""
497-
}
498-
return conn.c.LocalAddr().String()
499-
}
500-
501414
// Handle returns a user-specified handle from Opts.
502415
func (conn *Connection) Handle() interface{} {
503416
return conn.opts.Handle
@@ -514,19 +427,14 @@ func (conn *Connection) dial(ctx context.Context) error {
514427
opts := conn.opts
515428

516429
var c Conn
517-
c, err := conn.opts.Dialer.Dial(ctx, conn.addr, DialOpts{
518-
IoTimeout: opts.Timeout,
519-
Transport: opts.Transport,
520-
Ssl: opts.Ssl,
521-
RequiredProtocol: opts.RequiredProtocolInfo,
522-
Auth: opts.Auth,
523-
User: opts.User,
524-
Password: opts.Pass,
430+
c, err := conn.dialer.Dial(ctx, DialOpts{
431+
IoTimeout: opts.Timeout,
525432
})
526433
if err != nil {
527434
return err
528435
}
529436

437+
conn.addr = c.Addr()
530438
conn.Greeting.Version = c.Greeting().Version
531439
conn.serverProtocolInfo = c.ProtocolInfo()
532440

@@ -1447,8 +1355,7 @@ func isFeatureInSlice(expected iproto.Feature, actualSlice []iproto.Feature) boo
14471355

14481356
// NewWatcher creates a new Watcher object for the connection.
14491357
//
1450-
// You need to require IPROTO_FEATURE_WATCHERS to use watchers, see examples
1451-
// for the function.
1358+
// Server must support IPROTO_FEATURE_WATCHERS to use watchers.
14521359
//
14531360
// After watcher creation, the watcher callback is invoked for the first time.
14541361
// In this case, the callback is triggered whether or not the key has already
@@ -1484,9 +1391,9 @@ func (conn *Connection) NewWatcher(key string, callback WatchCallback) (Watcher,
14841391
// That's why we can't just check the Tarantool response for an unsupported
14851392
// request error.
14861393
if !isFeatureInSlice(iproto.IPROTO_FEATURE_WATCHERS,
1487-
conn.opts.RequiredProtocolInfo.Features) {
1488-
err := fmt.Errorf("the feature %s must be required by connection "+
1489-
"options to create a watcher", iproto.IPROTO_FEATURE_WATCHERS)
1394+
conn.c.ProtocolInfo().Features) {
1395+
err := fmt.Errorf("the feature %s must be supported by connection "+
1396+
"to create a watcher", iproto.IPROTO_FEATURE_WATCHERS)
14901397
return nil, err
14911398
}
14921399

@@ -1577,23 +1484,14 @@ func (conn *Connection) newWatcherImpl(key string, callback WatchCallback) (Watc
15771484
}, nil
15781485
}
15791486

1580-
// ServerProtocolVersion returns protocol version and protocol features
1487+
// ProtocolInfo returns protocol version and protocol features
15811488
// supported by connected Tarantool server. Beware that values might be
15821489
// outdated if connection is in a disconnected state.
1583-
// Since 1.10.0
1584-
func (conn *Connection) ServerProtocolInfo() ProtocolInfo {
1490+
// Since 2.0.0
1491+
func (conn *Connection) ProtocolInfo() ProtocolInfo {
15851492
return conn.serverProtocolInfo.Clone()
15861493
}
15871494

1588-
// ClientProtocolVersion returns protocol version and protocol features
1589-
// supported by Go connection client.
1590-
// Since 1.10.0
1591-
func (conn *Connection) ClientProtocolInfo() ProtocolInfo {
1592-
info := clientProtocolInfo.Clone()
1593-
info.Auth = conn.opts.Auth
1594-
return info
1595-
}
1596-
15971495
func shutdownEventCallback(event WatchEvent) {
15981496
// Receives "true" on server shutdown.
15991497
// See https://www.tarantool.io/en/doc/latest/dev_guide/internals/iproto/graceful_shutdown/

connection_test.go

Lines changed: 0 additions & 32 deletions
This file was deleted.

crud/example_test.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,18 @@ const (
1717

1818
var exampleOpts = tarantool.Opts{
1919
Timeout: 5 * time.Second,
20-
User: "test",
21-
Pass: "test",
20+
}
21+
22+
var exampleDialer = tarantool.NetDialer{
23+
Address: exampleServer,
24+
User: "test",
25+
Password: "test",
2226
}
2327

2428
func exampleConnect() *tarantool.Connection {
2529
ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
2630
defer cancel()
27-
conn, err := tarantool.Connect(ctx, exampleServer, exampleOpts)
31+
conn, err := tarantool.Connect(ctx, exampleDialer, exampleOpts)
2832
if err != nil {
2933
panic("Connection is not established: " + err.Error())
3034
}

0 commit comments

Comments
 (0)