-
Notifications
You must be signed in to change notification settings - Fork 2.5k
fix(pool): Pool ReAuth should not interfere with handoff #3547
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 11 commits
Commits
Show all changes
39 commits
Select commit
Hold shift + click to select a range
5fe0bfa
fix(pool): wip, pool reauth should not interfere with handoff
ndyakov d39da69
fix credListeners map
ndyakov 8a629fb
fix race in tests
ndyakov 6c54ab5
Merge branch 'master' into ndyakov/pool-reauth
ndyakov 90bfdb3
better conn usable timeout
ndyakov 07283ec
add design decision comment
ndyakov 1bbf2e6
few small improvements
ndyakov 1428068
update marked as queued
ndyakov e7dc339
add Used to clarify the state of the conn
ndyakov 77c0c73
rename test
ndyakov 011ef96
fix(test): fix flaky test
ndyakov e03396e
lock inside the listeners collection
ndyakov 391b6c5
address pr comments
ndyakov 6ad9a67
Update internal/auth/cred_listeners.go
ndyakov 0c4f8fb
Update internal/pool/buffer_size_test.go
ndyakov acb55d8
wip refactor entraid
ndyakov d74671b
fix maintnotif pool hook
ndyakov 0e10cd7
fix mocks
ndyakov afba8c2
fix nil listener
ndyakov 4bc6d33
sync and async reauth based on conn lifecycle
ndyakov 3020e3a
be able to reject connection OnGet
ndyakov f886775
pass hooks so the tests can observe reauth
ndyakov 72cf74a
give some time for the background to execute commands
ndyakov c715185
fix tests
ndyakov f14095b
only async reauth
ndyakov e94cc9f
Merge branch 'master' into ndyakov/pool-reauth
ndyakov 19f4080
Update internal/pool/pool.go
ndyakov 4049d5e
Update internal/auth/streaming/pool_hook.go
ndyakov 494a89b
Merge branch 'master' into ndyakov/pool-reauth
ndyakov 3211b13
Update internal/pool/conn.go
ndyakov b11f928
chore(redisotel): use metric.WithAttributeSet to avoid copy (#3552)
boekkooi-impossiblecloud 8ca7979
chore(docs): explain why MaxRetries is disabled for ClusterClient (#3…
Pika-Gopher ce49979
exponential backoff
ndyakov 67daad7
address pr comments
ndyakov 528f2e9
Merge remote-tracking branch 'origin/master' into ndyakov/pool-reauth
ndyakov 1ee5293
address pr comments
ndyakov 44917ef
remove rlock
ndyakov f0fbea6
add some comments
ndyakov e469358
add comments
ndyakov File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
package auth | ||
|
||
import ( | ||
"runtime" | ||
"time" | ||
|
||
"github.com/redis/go-redis/v9/internal/pool" | ||
) | ||
|
||
// ConnReAuthCredentialsListener is a struct that implements the CredentialsListener interface. | ||
// It is used to re-authenticate the credentials when they are updated. | ||
// It holds reference to the connection to re-authenticate and will pass it to the reAuth and onErr callbacks. | ||
// It contains: | ||
// - reAuth: a function that takes the new credentials and returns an error if any. | ||
// - onErr: a function that takes an error and handles it. | ||
// - conn: the connection to re-authenticate. | ||
// - checkUsableTimeout: the timeout to wait for the connection to be usable - default is 1 second. | ||
type ConnReAuthCredentialsListener struct { | ||
// reAuth is called when the credentials are updated. | ||
reAuth func(conn *pool.Conn, credentials Credentials) error | ||
// onErr is called when an error occurs. | ||
onErr func(conn *pool.Conn, err error) | ||
// conn is the connection to re-authenticate. | ||
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. | ||
// It calls the reAuth function with the new credentials. | ||
// If the reAuth function returns an error, it calls the onErr function with the error. | ||
func (c *ConnReAuthCredentialsListener) OnNext(credentials Credentials) { | ||
if c.conn.IsClosed() { | ||
return | ||
} | ||
|
||
if c.reAuth == nil { | ||
return | ||
} | ||
|
||
var err error | ||
|
||
// this hard-coded timeout is not ideal | ||
timeout := time.After(c.checkUsableTimeout) | ||
// wait for the connection to be usable | ||
// 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 | ||
// but we also don't want to block for too long, so incorporate a timeout | ||
for err == nil && !c.conn.Usable.CompareAndSwap(true, false) { | ||
select { | ||
case <-timeout: | ||
err = pool.ErrConnUnusableTimeout | ||
default: | ||
runtime.Gosched() | ||
} | ||
} | ||
if err == nil { | ||
defer c.conn.SetUsable(true) | ||
} | ||
|
||
for err == nil && !c.conn.Used.CompareAndSwap(false, true) { | ||
select { | ||
case <-timeout: | ||
err = pool.ErrConnUnusableTimeout | ||
default: | ||
runtime.Gosched() | ||
} | ||
} | ||
|
||
// we timed out waiting for the connection to be usable | ||
// do not try to re-authenticate, instead call the onErr function | ||
// which will handle the error and close the connection if needed | ||
if err != nil { | ||
c.OnError(err) | ||
return | ||
} | ||
|
||
defer c.conn.Used.Store(false) | ||
// we set the usable flag, so restore it back to usable after we're done | ||
if err = c.reAuth(c.conn, credentials); err != nil { | ||
c.OnError(err) | ||
} | ||
} | ||
|
||
// OnError is called when an error occurs. | ||
// It can be called from both the credentials provider and the reAuth function. | ||
func (c *ConnReAuthCredentialsListener) OnError(err error) { | ||
if c.onErr == nil { | ||
return | ||
} | ||
|
||
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. | ||
// 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 { | ||
return &ConnReAuthCredentialsListener{ | ||
conn: conn, | ||
reAuth: reAuth, | ||
onErr: onErr, | ||
checkUsableTimeout: 1 * time.Second, | ||
} | ||
} | ||
|
||
// Ensure ConnReAuthCredentialsListener implements the CredentialsListener interface. | ||
var _ CredentialsListener = (*ConnReAuthCredentialsListener)(nil) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.