From f458ea1496e25fedba5fb8c08a517c2c493f2ee3 Mon Sep 17 00:00:00 2001 From: Daichi Tomaru Date: Mon, 26 Dec 2022 10:38:47 +0900 Subject: [PATCH] Add MaxConnectRetryInterval client option for reconnect exponential backoff related to #589 Signed-off-by: Daichi Tomaru --- client.go | 13 +++++++++++-- options.go | 10 ++++++++++ options_reader.go | 5 +++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/client.go b/client.go index 200daa8..f0dfd7f 100644 --- a/client.go +++ b/client.go @@ -255,6 +255,7 @@ func (c *client) Connect() Token { return } + connectRetryInterval := c.options.ConnectRetryInterval RETRYCONN: var conn net.Conn var rc byte @@ -262,10 +263,18 @@ func (c *client) Connect() Token { conn, rc, t.sessionPresent, err = c.attemptConnection() if err != nil { if c.options.ConnectRetry { - DEBUG.Println(CLI, "Connect failed, sleeping for", int(c.options.ConnectRetryInterval.Seconds()), "seconds and will then retry, error:", err.Error()) - time.Sleep(c.options.ConnectRetryInterval) + DEBUG.Println(CLI, "Connect failed, sleeping for", int(connectRetryInterval.Seconds()), "seconds and will then retry, error:", err.Error()) + time.Sleep(connectRetryInterval) if c.status.ConnectionStatus() == connecting { // Possible connection aborted elsewhere + if c.options.ConnectRetryInterval >= c.options.MaxConnectRetryInterval { + goto RETRYCONN + } + if cri := connectRetryInterval * 2; cri <= c.options.MaxConnectRetryInterval { + connectRetryInterval = cri + } else { + connectRetryInterval = c.options.MaxConnectRetryInterval + } goto RETRYCONN } } diff --git a/options.go b/options.go index 5aaa7d9..d53fef4 100644 --- a/options.go +++ b/options.go @@ -88,6 +88,7 @@ type ClientOptions struct { ConnectTimeout time.Duration MaxReconnectInterval time.Duration AutoReconnect bool + MaxConnectRetryInterval time.Duration ConnectRetryInterval time.Duration ConnectRetry bool Store Store @@ -136,6 +137,7 @@ func NewClientOptions() *ClientOptions { ConnectTimeout: 30 * time.Second, MaxReconnectInterval: 10 * time.Minute, AutoReconnect: true, + MaxConnectRetryInterval: 30 * time.Second, ConnectRetryInterval: 30 * time.Second, ConnectRetry: false, Store: nil, @@ -386,6 +388,14 @@ func (o *ClientOptions) SetAutoReconnect(a bool) *ClientOptions { return o } +// SetMaxConnectRetryInterval sets the maximum time that will be waited between connection attempts +// when initially connecting if ConnectRetry is TRUE +// If ConnectRetryInterval >= MaxConnectRetryInterval, ConnectRetryInterval is kept between the attempts +func (o *ClientOptions) SetMaxConnectRetryInterval(t time.Duration) *ClientOptions { + o.MaxConnectRetryInterval = t + return o +} + // SetConnectRetryInterval sets the time that will be waited between connection attempts // when initially connecting if ConnectRetry is TRUE func (o *ClientOptions) SetConnectRetryInterval(t time.Duration) *ClientOptions { diff --git a/options_reader.go b/options_reader.go index 10a9e49..e1f1698 100644 --- a/options_reader.go +++ b/options_reader.go @@ -137,6 +137,11 @@ func (r *ClientOptionsReader) AutoReconnect() bool { return s } +func (r *ClientOptionsReader) MaxConnectRetryInterval() time.Duration { + s := r.options.MaxConnectRetryInterval + return s +} + // ConnectRetryInterval returns the delay between retries on the initial connection (if ConnectRetry true) func (r *ClientOptionsReader) ConnectRetryInterval() time.Duration { s := r.options.ConnectRetryInterval