1
0
mirror of https://github.com/redis/go-redis.git synced 2025-10-18 22:08:50 +03:00

better conn usable timeout

This commit is contained in:
Nedyalko Dyakov
2025-10-14 23:06:36 +03:00
parent 6c54ab59d9
commit 90bfdb3aa3
3 changed files with 34 additions and 11 deletions

View File

@@ -13,10 +13,18 @@ import (
// - reAuth: a function that takes the new credentials and returns an error if any. // - reAuth: a function that takes the new credentials and returns an error if any.
// - onErr: a function that takes an error and handles it. // - onErr: a function that takes an error and handles it.
// - conn: the connection to re-authenticate. // - conn: the connection to re-authenticate.
// - checkUsableTimeout: the timeout to wait for the connection to be usable - default is 1 second.
type ConnReAuthCredentialsListener struct { type ConnReAuthCredentialsListener struct {
// reAuth is called when the credentials are updated.
reAuth func(conn *pool.Conn, credentials Credentials) error reAuth func(conn *pool.Conn, credentials Credentials) error
// onErr is called when an error occurs.
onErr func(conn *pool.Conn, err error) onErr func(conn *pool.Conn, err error)
// conn is the connection to re-authenticate.
conn *pool.Conn conn *pool.Conn
// checkUsableTimeout is the timeout to wait for the connection to be usable
// when the credentials are updated.
// default is 1 second
checkUsableTimeout time.Duration
} }
// OnNext is called when the credentials are updated. // OnNext is called when the credentials are updated.
@@ -32,7 +40,9 @@ func (c *ConnReAuthCredentialsListener) OnNext(credentials Credentials) {
} }
var err error var err error
timeout := time.After(1 * time.Second)
// this hard-coded timeout is not ideal
timeout := time.After(c.checkUsableTimeout)
// wait for the connection to be usable // wait for the connection to be usable
// this is important because the connection pool may be in the process of reconnecting the connection // this is important because the connection pool may be in the process of reconnecting the connection
// and we don't want to interfere with that process // and we don't want to interfere with that process
@@ -68,6 +78,11 @@ func (c *ConnReAuthCredentialsListener) OnError(err error) {
c.onErr(c.conn, err) c.onErr(c.conn, err)
} }
// SetCheckUsableTimeout sets the timeout for the connection to be usable.
func (c *ConnReAuthCredentialsListener) SetCheckUsableTimeout(timeout time.Duration) {
c.checkUsableTimeout = timeout
}
// NewConnReAuthCredentialsListener creates a new ConnReAuthCredentialsListener. // NewConnReAuthCredentialsListener creates a new ConnReAuthCredentialsListener.
// Implements the auth.CredentialsListener interface. // Implements the auth.CredentialsListener interface.
func NewConnReAuthCredentialsListener(conn *pool.Conn, reAuth func(conn *pool.Conn, credentials Credentials) error, onErr func(conn *pool.Conn, err error)) *ConnReAuthCredentialsListener { func NewConnReAuthCredentialsListener(conn *pool.Conn, reAuth func(conn *pool.Conn, credentials Credentials) error, onErr func(conn *pool.Conn, err error)) *ConnReAuthCredentialsListener {
@@ -75,8 +90,10 @@ func NewConnReAuthCredentialsListener(conn *pool.Conn, reAuth func(conn *pool.Co
conn: conn, conn: conn,
reAuth: reAuth, reAuth: reAuth,
onErr: onErr, onErr: onErr,
checkUsableTimeout: 1 * time.Second,
} }
} }
// Ensure ConnReAuthCredentialsListener implements the CredentialsListener interface. // Ensure ConnReAuthCredentialsListener implements the CredentialsListener interface.
var _ CredentialsListener = (*ConnReAuthCredentialsListener)(nil) var _ CredentialsListener = (*ConnReAuthCredentialsListener)(nil)

View File

@@ -319,6 +319,12 @@ func (c *baseClient) connReAuthCredentialsListener(poolCn *pool.Conn) (auth.Cred
c.reAuthConnection(), c.reAuthConnection(),
c.onAuthenticationErr(), c.onAuthenticationErr(),
) )
// main case where the connection can be stuck in the listener for a long time is when we have a handoff
// so we set the checkUsableTimeout to the handoff timeout if maintnotifications are enabled
// the default timeout if no maintnotifications config is provided is 1 second
if c.opt.MaintNotificationsConfig != nil && c.opt.MaintNotificationsConfig.Mode != maintnotifications.ModeDisabled {
newCredListener.SetCheckUsableTimeout(c.opt.MaintNotificationsConfig.HandoffTimeout)
}
c.credListeners[poolCn] = newCredListener c.credListeners[poolCn] = newCredListener
return newCredListener, func() { return newCredListener, func() {
c.removeCredListener(poolCn) c.removeCredListener(poolCn)