Skip to content

Commit 568bdaf

Browse files
laoshanxiclaude
andcommitted
fix(server): resolve refresh connector data outside the rotation transaction
Rotate invokes the freshIdentity callback from inside UpdateRefreshToken's transaction, and the SQLite storage pools a single connection (SetMaxOpenConns(1)), so the GetOfflineSessions read issued by refreshConnectorData from that callback waits forever for the connection the transaction already holds. Every later token request then queues behind the exhausted pool: a single refresh grant wedges /token permanently while /healthz keeps passing. Restore the pre-refactor behavior of resolving the connector data before rotation starts, gated on the same userIdent condition the callback used. Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: laoshanxi <178029200@qq.com>
1 parent ab64ed7 commit 568bdaf

1 file changed

Lines changed: 13 additions & 3 deletions

File tree

server/grants/refresh.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,13 +108,23 @@ func (g *refresh) Authorize(ctx context.Context, req *Request, client storage.Cl
108108
// upstream provider: use the claims cached in UserIdentity at the last login
109109
// instead of contacting the connector (which may fail if the upstream token
110110
// has expired). Otherwise re-read the identity from the connector.
111+
//
112+
// The connector data is resolved before Rotate starts: Rotate invokes
113+
// freshIdentity from inside the UpdateRefreshToken transaction, and the
114+
// SQLite storage pools a single connection (SetMaxOpenConns(1)), so a
115+
// storage read issued from that callback waits forever for the connection
116+
// the transaction already holds.
117+
var connectorData []byte
118+
var connectorDataErr error
119+
if userIdent == nil {
120+
connectorData, connectorDataErr = g.refreshConnectorData(ctx, refreshToken)
121+
}
111122
freshIdentity := func(ctx context.Context) (connector.Identity, error) {
112123
if userIdent != nil {
113124
return tokens.IdentityFromClaims(userIdent.Claims), nil
114125
}
115-
connectorData, err := g.refreshConnectorData(ctx, refreshToken)
116-
if err != nil {
117-
return connector.Identity{}, err
126+
if connectorDataErr != nil {
127+
return connector.Identity{}, connectorDataErr
118128
}
119129
return g.refreshWithConnector(ctx, conn, connectorData, scopes, tokens.IdentityFromClaims(refreshToken.Claims))
120130
}

0 commit comments

Comments
 (0)