mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-29 07:49:14 +01:00
[management] batch disconnect and lock free reconnect (#8373)
This commit is contained in:
@@ -106,7 +106,6 @@ func (s *SqlStore) MarkPeerConnectedIfNewerSession(ctx context.Context, accountI
|
||||
"peer_status_connected": true,
|
||||
"peer_status_last_seen": gorm.Expr("CURRENT_TIMESTAMP"),
|
||||
"peer_status_session_started_at": newSessionStartedAt,
|
||||
"peer_status_login_expired": false,
|
||||
})
|
||||
if result.Error != nil {
|
||||
return false, status.Errorf(status.Internal, "mark peer connected: %v", result.Error)
|
||||
@@ -142,6 +141,51 @@ func (s *SqlStore) MarkPeerDisconnectedIfSameSession(ctx context.Context, accoun
|
||||
return result.RowsAffected > 0, nil
|
||||
}
|
||||
|
||||
// markPeersDisconnectedChunkSize bounds the sessions per statement so the
|
||||
// bound parameter count stays below the database limits.
|
||||
const markPeersDisconnectedChunkSize = 1000
|
||||
|
||||
// MarkPeersDisconnectedIfSameSession is the batched form of
|
||||
// MarkPeerDisconnectedIfSameSession: one UPDATE per chunk of sessions, each
|
||||
// peer guarded by its own (account, peer, session) tuple. A failed chunk does
|
||||
// not stop the others, only a done ctx does; the count then covers the chunks
|
||||
// that succeeded and the error joins the failures.
|
||||
func (s *SqlStore) MarkPeersDisconnectedIfSameSession(ctx context.Context, sessions []types.PeerSession) (int64, error) {
|
||||
var total int64
|
||||
var errs []error
|
||||
for start := 0; start < len(sessions); start += markPeersDisconnectedChunkSize {
|
||||
if err := ctx.Err(); err != nil {
|
||||
errs = append(errs, status.Errorf(status.Internal, "mark peers disconnected: %v", err))
|
||||
break
|
||||
}
|
||||
end := min(start+markPeersDisconnectedChunkSize, len(sessions))
|
||||
tuples := make([][]any, 0, end-start)
|
||||
for _, session := range sessions[start:end] {
|
||||
if session.SessionStartedAt == 0 {
|
||||
continue
|
||||
}
|
||||
tuples = append(tuples, []any{session.AccountID, session.PeerID, session.SessionStartedAt})
|
||||
}
|
||||
if len(tuples) == 0 {
|
||||
continue
|
||||
}
|
||||
result := s.db.WithContext(ctx).
|
||||
Model(&nbpeer.Peer{}).
|
||||
Where("(account_id, id, peer_status_session_started_at) IN ?", tuples).
|
||||
Updates(map[string]any{
|
||||
"peer_status_connected": false,
|
||||
"peer_status_last_seen": gorm.Expr("CURRENT_TIMESTAMP"),
|
||||
"peer_status_session_started_at": int64(0),
|
||||
})
|
||||
if result.Error != nil {
|
||||
errs = append(errs, status.Errorf(status.Internal, "mark peers disconnected: %v", result.Error))
|
||||
continue
|
||||
}
|
||||
total += result.RowsAffected
|
||||
}
|
||||
return total, errors.Join(errs...)
|
||||
}
|
||||
|
||||
// ApproveAccountPeers marks all peers that currently require approval in the given account as approved.
|
||||
func (s *SqlStore) ApproveAccountPeers(ctx context.Context, accountID string) (int, error) {
|
||||
result := s.db.Model(&nbpeer.Peer{}).
|
||||
|
||||
Reference in New Issue
Block a user