@@ -92,12 +92,24 @@ func (d defaultLogger) Report(event ConnLogKind, conn *Connection, v ...interfac
92
92
case LogReconnectFailed :
93
93
reconnects := v [0 ].(uint )
94
94
err := v [1 ].(error )
95
- log .Printf ("tarantool: reconnect (%d/%d) to %s failed: %s" ,
96
- reconnects , conn .opts .MaxReconnects , conn .Addr (), err )
95
+ addr := conn .Addr ()
96
+ if addr == nil {
97
+ log .Printf ("tarantool: connect (%d/%d) failed: %s" ,
98
+ reconnects , conn .opts .MaxReconnects , err )
99
+ } else {
100
+ log .Printf ("tarantool: reconnect (%d/%d) to %s failed: %s" ,
101
+ reconnects , conn .opts .MaxReconnects , addr , err )
102
+ }
97
103
case LogLastReconnectFailed :
98
104
err := v [0 ].(error )
99
- log .Printf ("tarantool: last reconnect to %s failed: %s, giving it up" ,
100
- conn .Addr (), err )
105
+ addr := conn .Addr ()
106
+ if addr == nil {
107
+ log .Printf ("tarantool: last connect failed: %s, giving it up" ,
108
+ err )
109
+ } else {
110
+ log .Printf ("tarantool: last reconnect to %s failed: %s, giving it up" ,
111
+ addr , err )
112
+ }
101
113
case LogUnexpectedResultId :
102
114
header := v [0 ].(Header )
103
115
log .Printf ("tarantool: connection %s got unexpected request ID (%d) in response " +
@@ -362,8 +374,20 @@ func Connect(ctx context.Context, dialer Dialer, opts Opts) (conn *Connection, e
362
374
363
375
conn .cond = sync .NewCond (& conn .mutex )
364
376
365
- if err = conn .createConnection (ctx ); err != nil {
366
- return nil , err
377
+ if conn .opts .Reconnect > 0 {
378
+ // We don't need these mutex.Lock()/mutex.Unlock() here, but
379
+ // runReconnects() expects mutex.Lock() to be set, so it's
380
+ // easier to add them instead of reworking runReconnects().
381
+ conn .mutex .Lock ()
382
+ err = conn .runReconnects (ctx )
383
+ conn .mutex .Unlock ()
384
+ if err != nil {
385
+ return nil , err
386
+ }
387
+ } else {
388
+ if err = conn .connect (ctx ); err != nil {
389
+ return nil , err
390
+ }
367
391
}
368
392
369
393
go conn .pinger ()
@@ -553,7 +577,7 @@ func pack(h *smallWBuf, enc *msgpack.Encoder, reqid uint32,
553
577
return
554
578
}
555
579
556
- func (conn * Connection ) createConnection (ctx context.Context ) error {
580
+ func (conn * Connection ) connect (ctx context.Context ) error {
557
581
var err error
558
582
if conn .c == nil && conn .state == connDisconnected {
559
583
if err = conn .dial (ctx ); err == nil {
@@ -616,19 +640,30 @@ func (conn *Connection) getDialTimeout() time.Duration {
616
640
return dialTimeout
617
641
}
618
642
619
- func (conn * Connection ) runReconnects () error {
643
+ func (conn * Connection ) runReconnects (ctx context. Context ) error {
620
644
dialTimeout := conn .getDialTimeout ()
621
645
var reconnects uint
622
646
var err error
623
647
648
+ t := time .NewTicker (conn .opts .Reconnect )
649
+ defer t .Stop ()
624
650
for conn .opts .MaxReconnects == 0 || reconnects <= conn .opts .MaxReconnects {
625
- now := time .Now ()
626
-
627
- ctx , cancel := context .WithTimeout (context .Background (), dialTimeout )
628
- err = conn .createConnection (ctx )
651
+ localCtx , cancel := context .WithTimeout (ctx , dialTimeout )
652
+ err = conn .connect (localCtx )
629
653
cancel ()
630
654
631
655
if err != nil {
656
+ // The error will most likely be the one that Dialer
657
+ // returns to us due to the context being cancelled.
658
+ // Although this is not guaranteed. For example,
659
+ // if the dialer may throw another error before checking
660
+ // the context, and the context has already been
661
+ // canceled. Or the context was not canceled after
662
+ // the error was thrown, but before the context was
663
+ // checked here.
664
+ if ctx .Err () != nil {
665
+ return err
666
+ }
632
667
if clientErr , ok := err .(ClientError ); ok &&
633
668
clientErr .Code == ErrConnectionClosed {
634
669
return err
@@ -642,7 +677,12 @@ func (conn *Connection) runReconnects() error {
642
677
reconnects ++
643
678
conn .mutex .Unlock ()
644
679
645
- time .Sleep (time .Until (now .Add (conn .opts .Reconnect )))
680
+ select {
681
+ case <- ctx .Done ():
682
+ // Since the context is cancelled, we don't need to do anything.
683
+ // Conn.connect() will return the correct error.
684
+ case <- t .C :
685
+ }
646
686
647
687
conn .mutex .Lock ()
648
688
}
@@ -656,7 +696,7 @@ func (conn *Connection) reconnectImpl(neterr error, c Conn) {
656
696
if conn .opts .Reconnect > 0 {
657
697
if c == conn .c {
658
698
conn .closeConnection (neterr , false )
659
- if err := conn .runReconnects (); err != nil {
699
+ if err := conn .runReconnects (context . Background () ); err != nil {
660
700
conn .closeConnection (err , true )
661
701
}
662
702
}
0 commit comments