change: smarter change notifications

This commit replaces the ChangeSet with a simpler bool based
change model that can be directly used in the map builder to
build the appropriate map response based on the change that
has occured. Previously, we fell back to sending full maps
for a lot of changes as that was consider "the safe" thing to
do to ensure no updates were missed.

This was slightly problematic as a node that already has a list
of peers will only do full replacement of the peers if the list
is non-empty, meaning that it was not possible to remove all
nodes (if for example policy changed).

Now we will keep track of last seen nodes, so we can send remove
ids, but also we are much smarter on how we send smaller, partial
maps when needed.

Fixes #2389

Signed-off-by: Kristoffer Dalby <kristoffer@dalby.cc>
This commit is contained in:
Kristoffer Dalby
2025-12-15 14:36:21 +00:00
parent f67ed36fe2
commit 5767ca5085
12 changed files with 1280 additions and 616 deletions

View File

@@ -473,14 +473,16 @@ func (a *AuthProviderOIDC) getRegistrationIDFromState(state string) *types.Regis
func (a *AuthProviderOIDC) createOrUpdateUserFromClaim(
claims *types.OIDCClaims,
) (*types.User, change.ChangeSet, error) {
var user *types.User
var err error
var newUser bool
var c change.ChangeSet
) (*types.User, change.Change, error) {
var (
user *types.User
err error
newUser bool
c change.Change
)
user, err = a.h.state.GetUserByOIDCIdentifier(claims.Identifier())
if err != nil && !errors.Is(err, db.ErrUserNotFound) {
return nil, change.EmptySet, fmt.Errorf("creating or updating user: %w", err)
return nil, change.Change{}, fmt.Errorf("creating or updating user: %w", err)
}
// if the user is still not found, create a new empty user.
@@ -496,7 +498,7 @@ func (a *AuthProviderOIDC) createOrUpdateUserFromClaim(
if newUser {
user, c, err = a.h.state.CreateUser(*user)
if err != nil {
return nil, change.EmptySet, fmt.Errorf("creating user: %w", err)
return nil, change.Change{}, fmt.Errorf("creating user: %w", err)
}
} else {
_, c, err = a.h.state.UpdateUser(types.UserID(user.ID), func(u *types.User) error {
@@ -504,7 +506,7 @@ func (a *AuthProviderOIDC) createOrUpdateUserFromClaim(
return nil
})
if err != nil {
return nil, change.EmptySet, fmt.Errorf("updating user: %w", err)
return nil, change.Change{}, fmt.Errorf("updating user: %w", err)
}
}
@@ -545,7 +547,7 @@ func (a *AuthProviderOIDC) handleRegistration(
// Send both changes. Empty changes are ignored by Change().
a.h.Change(nodeChange, routesChange)
return !nodeChange.Empty(), nil
return !nodeChange.IsEmpty(), nil
}
func renderOIDCCallbackTemplate(