Skip to content

Commit

Permalink
Merge pull request #363 from nats-io/retry_close_option
Browse files Browse the repository at this point in the history
[ADDED] AllowCloseRetry option
  • Loading branch information
kozlovic authored Nov 17, 2021
2 parents 9937a12 + f27faca commit f14408e
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 2 deletions.
32 changes: 31 additions & 1 deletion stan.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,21 @@ type Options struct {
// ConnectionLostCB specifies the handler to be invoked when the connection
// is permanently lost.
ConnectionLostCB ConnectionLostHandler

// AllowCloseRetry specifies that a failed connection Close() can be retried.
//
// By default, after the first call to Close(), the underlying NATS connection
// is closed (when owned by the library), regardless if the library gets a
// response from the server or not, and calling Close() again is a no-op.
// With AllowCloseRetry set to true, if the library fails to get a response
// from the close protocol, calling Close() again is possible and the library
// will try to resend the protocol. It means that the underlying NATS connection
// won't be closed until the library successfully gets a response from the server.
// This behavior can have side effects in that the underlying NATS connection
// may stay open (or reconnect) when otherwise it would have been closed after
// calling Close(). So AllowCloseRetry is disabled by default to maintain
// expected default behavior in regard with the underlying NATS connection state.
AllowCloseRetry bool
}

// GetDefaultOptions returns default configuration options for the client.
Expand Down Expand Up @@ -308,6 +323,15 @@ func SetConnectionLostHandler(handler ConnectionLostHandler) Option {
}
}

// AllowCloseRetry is an Option that allows a failed connection close to be retried.
// See option AllowCloseRetry for more information.
func AllowCloseRetry(allow bool) Option {
return func(o *Options) error {
o.AllowCloseRetry = allow
return nil
}
}

// A conn represents a bare connection to a stan cluster.
type conn struct {
sync.RWMutex
Expand Down Expand Up @@ -682,6 +706,12 @@ func (sc *conn) Close() error {
if !sc.closed {
sc.closed = true
sc.cleanupOnClose(ErrConnectionClosed)
if !sc.opts.AllowCloseRetry {
sc.fullyClosed = true
if sc.ncOwned {
defer sc.nc.Close()
}
}
}

req := &pb.CloseRequest{ClientID: sc.clientID}
Expand All @@ -700,7 +730,7 @@ func (sc *conn) Close() error {
}
// As long as we got a valid response, we consider the connection fully closed.
sc.fullyClosed = true
if sc.ncOwned {
if sc.ncOwned && sc.opts.AllowCloseRetry {
sc.nc.Close()
}
if cr.Error != "" {
Expand Down
5 changes: 4 additions & 1 deletion stan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1012,7 +1012,10 @@ func TestConnCloseError(t *testing.T) {
s := RunServer(clusterName)
defer s.Shutdown()

sc := NewDefaultConnection(t)
sc, err := Connect(clusterName, clientName, AllowCloseRetry(true))
if err != nil {
t.Fatalf("Error on connect: %v", err)
}
defer sc.Close()

nc, err := nats.Connect(nats.DefaultURL)
Expand Down

0 comments on commit f14408e

Please sign in to comment.