Skip to content

Commit 09015cd

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 a0ce232 commit 09015cd

37 files changed

+1861
-1691
lines changed

box_error_test.go

+6-6
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

+23-125
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
// schemaResolver contains a SchemaResolver implementation.
164166
schemaResolver SchemaResolver
165167
// requestId contains the last request ID for requests with nil context.
@@ -260,11 +262,6 @@ const (
260262

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

368313
// Connect creates and configures a new Connection.
369-
//
370-
// Address could be specified in following ways:
371-
//
372-
// - TCP connections (tcp://192.168.1.1:3013, tcp://my.host:3013,
373-
// tcp:192.168.1.1:3013, tcp:my.host:3013, 192.168.1.1:3013, my.host:3013)
374-
//
375-
// - Unix socket, first '/' or '.' indicates Unix socket
376-
// (unix:///abs/path/tnt.sock, unix:path/tnt.sock, /abs/path/tnt.sock,
377-
// ./rel/path/tnt.sock, unix/:path/tnt.sock)
378-
func Connect(ctx context.Context, addr string, opts Opts) (conn *Connection, err error) {
314+
func Connect(ctx context.Context, dialer Dialer, opts Opts) (conn *Connection, err error) {
379315
conn = &Connection{
380-
addr: addr,
316+
dialer: dialer,
381317
requestId: 0,
382318
contextRequestId: 1,
383319
Greeting: &Greeting{},
384320
control: make(chan struct{}),
385-
opts: opts.Clone(),
321+
opts: opts,
386322
dec: msgpack.NewDecoder(&smallBuf{}),
387323
}
388324
maxprocs := uint32(runtime.GOMAXPROCS(-1))
389325
if conn.opts.Concurrency == 0 || conn.opts.Concurrency > maxprocs*128 {
390326
conn.opts.Concurrency = maxprocs * 4
391327
}
392-
if conn.opts.Dialer == nil {
393-
conn.opts.Dialer = TtDialer{}
394-
}
395328
if c := conn.opts.Concurrency; c&(c-1) != 0 {
396329
for i := uint(1); i < 32; i *= 2 {
397330
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

@@ -1453,8 +1361,7 @@ func isFeatureInSlice(expected iproto.Feature, actualSlice []iproto.Feature) boo
14531361

14541362
// NewWatcher creates a new Watcher object for the connection.
14551363
//
1456-
// You need to require IPROTO_FEATURE_WATCHERS to use watchers, see examples
1457-
// for the function.
1364+
// Server must support IPROTO_FEATURE_WATCHERS to use watchers.
14581365
//
14591366
// After watcher creation, the watcher callback is invoked for the first time.
14601367
// In this case, the callback is triggered whether or not the key has already
@@ -1490,9 +1397,9 @@ func (conn *Connection) NewWatcher(key string, callback WatchCallback) (Watcher,
14901397
// That's why we can't just check the Tarantool response for an unsupported
14911398
// request error.
14921399
if !isFeatureInSlice(iproto.IPROTO_FEATURE_WATCHERS,
1493-
conn.opts.RequiredProtocolInfo.Features) {
1494-
err := fmt.Errorf("the feature %s must be required by connection "+
1495-
"options to create a watcher", iproto.IPROTO_FEATURE_WATCHERS)
1400+
conn.c.ProtocolInfo().Features) {
1401+
err := fmt.Errorf("the feature %s must be supported by connection "+
1402+
"to create a watcher", iproto.IPROTO_FEATURE_WATCHERS)
14961403
return nil, err
14971404
}
14981405

@@ -1583,23 +1490,14 @@ func (conn *Connection) newWatcherImpl(key string, callback WatchCallback) (Watc
15831490
}, nil
15841491
}
15851492

1586-
// ServerProtocolVersion returns protocol version and protocol features
1493+
// ProtocolInfo returns protocol version and protocol features
15871494
// supported by connected Tarantool server. Beware that values might be
15881495
// outdated if connection is in a disconnected state.
1589-
// Since 1.10.0
1590-
func (conn *Connection) ServerProtocolInfo() ProtocolInfo {
1496+
// Since 2.0.0
1497+
func (conn *Connection) ProtocolInfo() ProtocolInfo {
15911498
return conn.serverProtocolInfo.Clone()
15921499
}
15931500

1594-
// ClientProtocolVersion returns protocol version and protocol features
1595-
// supported by Go connection client.
1596-
// Since 1.10.0
1597-
func (conn *Connection) ClientProtocolInfo() ProtocolInfo {
1598-
info := clientProtocolInfo.Clone()
1599-
info.Auth = conn.opts.Auth
1600-
return info
1601-
}
1602-
16031501
func shutdownEventCallback(event WatchEvent) {
16041502
// Receives "true" on server shutdown.
16051503
// See https://www.tarantool.io/en/doc/latest/dev_guide/internals/iproto/graceful_shutdown/

connection_test.go

-32
This file was deleted.

crud/example_test.go

+7-3
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)