@@ -106,17 +106,23 @@ func (u *lastLoginUpdater) updateLastLoginTime(ctx context.Context, dbUser usern
106
106
func (ctx context.Context ) (interface {}, error ) {
107
107
// The leader adds itself to pending users, and processes all
108
108
// pending updates.
109
- u .mu .Lock ()
110
- u .mu .pendingUsers [dbUser ] = struct {}{}
111
- u .mu .Unlock ()
109
+ func () {
110
+ u .mu .Lock ()
111
+ defer u .mu .Unlock ()
112
+ u .mu .pendingUsers [dbUser ] = struct {}{}
113
+ }()
112
114
return nil , u .processPendingUpdates (ctx )
113
115
})
114
116
115
- // Add this user to the pending set if not the leader,
117
+ // Add this user to the pending set if not the leader. This causes the user
118
+ // to be processed the next time a singleflight begins, which means the
119
+ // recorded estimated_last_login_time will be approximate.
116
120
if ! leader {
117
- u .mu .Lock ()
118
- u .mu .pendingUsers [dbUser ] = struct {}{}
119
- u .mu .Unlock ()
121
+ func () {
122
+ u .mu .Lock ()
123
+ defer u .mu .Unlock ()
124
+ u .mu .pendingUsers [dbUser ] = struct {}{}
125
+ }()
120
126
} else {
121
127
// Leader waits for the result in an async task to avoid blocking authentication
122
128
if err := u .execCfg .Stopper .RunAsyncTask (ctx , "wait_last_login_update" , func (ctx context.Context ) {
@@ -132,14 +138,17 @@ func (u *lastLoginUpdater) updateLastLoginTime(ctx context.Context, dbUser usern
132
138
133
139
// processPendingUpdates processes all users in the pending set and clears it.
134
140
func (u * lastLoginUpdater ) processPendingUpdates (ctx context.Context ) error {
135
- u .mu .Lock ()
136
- users := make ([]username.SQLUsername , 0 , len (u .mu .pendingUsers ))
137
- for user := range u .mu .pendingUsers {
138
- users = append (users , user )
139
- }
140
- // Clear the pending users set.
141
- u .mu .pendingUsers = make (map [username.SQLUsername ]struct {})
142
- u .mu .Unlock ()
141
+ var users []username.SQLUsername
142
+ func () {
143
+ u .mu .Lock ()
144
+ defer u .mu .Unlock ()
145
+ users = make ([]username.SQLUsername , 0 , len (u .mu .pendingUsers ))
146
+ for user := range u .mu .pendingUsers {
147
+ users = append (users , user )
148
+ }
149
+ // Clear the pending users set.
150
+ u .mu .pendingUsers = make (map [username.SQLUsername ]struct {})
151
+ }()
143
152
144
153
if len (users ) == 0 {
145
154
return nil
0 commit comments