From 6a430d1d7c9eb31a2c82c26a721f82f071bb23b4 Mon Sep 17 00:00:00 2001 From: Daniel Date: Thu, 16 Dec 2021 12:25:05 +0100 Subject: [PATCH 1/2] Fix active profile invalidation and revision counting --- profile/database.go | 44 ++++++++++++++++++++++++++++++++------ profile/profile-layered.go | 23 +++++++++++++++++--- 2 files changed, 57 insertions(+), 10 deletions(-) diff --git a/profile/database.go b/profile/database.go index 484f5cf3..efae476e 100644 --- a/profile/database.go +++ b/profile/database.go @@ -54,6 +54,7 @@ func startProfileUpdateChecker() error { } }() + profileFeed: for { select { case r := <-profilesSub.Feed: @@ -62,15 +63,44 @@ func startProfileUpdateChecker() error { return errors.New("subscription canceled") } - // Don't mark profiles as outdated that are saved internally, as - // profiles only exist once in memory. - p, ok := r.(*Profile) - if ok && p.savedInternally { - return + // Get active profile. + activeProfile := getActiveProfile(strings.TrimPrefix(r.Key(), profilesDBPath)) + if activeProfile == nil { + continue profileFeed } - // Mark profile as outdated. - markActiveProfileAsOutdated(strings.TrimPrefix(r.Key(), profilesDBPath)) + // If the record is being deleted, but there is an active profile, + // create an empty profile instead. + if r.Meta().IsDeleted() { + newProfile := New( + activeProfile.Source, + activeProfile.ID, + activeProfile.LinkedPath, + nil, + ) + // Copy some metadata from the old profile. + newProfile.Name = activeProfile.Name + // Save the new profile. + err := newProfile.Save() + if err != nil { + log.Errorf("profile: failed to save new profile for profile reset: %s", err) + } + // Set to outdated, so it is loaded in the layered profiles. + activeProfile.outdated.Set() + } + + // Always increase the revision counter of the layer profile. + // This marks previous connections in the UI as decided with outdated settings. + if activeProfile.layeredProfile != nil { + activeProfile.layeredProfile.IncreaseRevisionCounter(true) + } + + // If the profile is saved externally (eg. via the API), have the + // next one to use it reload the profile from the database. + receivedProfile, err := EnsureProfile(r) + if err != nil || !receivedProfile.savedInternally { + activeProfile.outdated.Set() + } case <-ctx.Done(): return nil } diff --git a/profile/profile-layered.go b/profile/profile-layered.go index 60948b28..943ee67f 100644 --- a/profile/profile-layered.go +++ b/profile/profile-layered.go @@ -165,6 +165,25 @@ func (lp *LayeredProfile) LocalProfile() *Profile { return lp.localProfile } +// RevisionCnt returns the current profile revision counter. +func (lp *LayeredProfile) IncreaseRevisionCounter(lock bool) (revisionCounter uint64) { + if lp == nil { + return 0 + } + + if lock { + lp.Lock() + defer lp.Unlock() + } + + // Increase the revision counter. + lp.RevisionCounter++ + // Push the increased counter to the UI. + pushLayeredProfile(lp) + + return lp.RevisionCounter +} + // RevisionCnt returns the current profile revision counter. func (lp *LayeredProfile) RevisionCnt() (revisionCounter uint64) { if lp == nil { @@ -241,9 +260,7 @@ func (lp *LayeredProfile) Update() (revisionCounter uint64) { lp.updateCaches() // bump revision counter - lp.RevisionCounter++ - - pushLayeredProfile(lp) + lp.IncreaseRevisionCounter(false) } return lp.RevisionCounter From 3e17bc8ec24e5c8b7839968cace11e9632b6e36e Mon Sep 17 00:00:00 2001 From: Daniel Date: Thu, 16 Dec 2021 13:42:17 +0100 Subject: [PATCH 2/2] Make function to increase profile revision counter internal --- profile/database.go | 2 +- profile/profile-layered.go | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/profile/database.go b/profile/database.go index efae476e..1ce873d3 100644 --- a/profile/database.go +++ b/profile/database.go @@ -92,7 +92,7 @@ func startProfileUpdateChecker() error { // Always increase the revision counter of the layer profile. // This marks previous connections in the UI as decided with outdated settings. if activeProfile.layeredProfile != nil { - activeProfile.layeredProfile.IncreaseRevisionCounter(true) + activeProfile.layeredProfile.increaseRevisionCounter(true) } // If the profile is saved externally (eg. via the API), have the diff --git a/profile/profile-layered.go b/profile/profile-layered.go index 943ee67f..ef40c7fc 100644 --- a/profile/profile-layered.go +++ b/profile/profile-layered.go @@ -165,8 +165,9 @@ func (lp *LayeredProfile) LocalProfile() *Profile { return lp.localProfile } -// RevisionCnt returns the current profile revision counter. -func (lp *LayeredProfile) IncreaseRevisionCounter(lock bool) (revisionCounter uint64) { +// increaseRevisionCounter increases the revision counter and pushes the +// layered profile to listeners. +func (lp *LayeredProfile) increaseRevisionCounter(lock bool) (revisionCounter uint64) { if lp == nil { return 0 } @@ -260,7 +261,7 @@ func (lp *LayeredProfile) Update() (revisionCounter uint64) { lp.updateCaches() // bump revision counter - lp.IncreaseRevisionCounter(false) + lp.increaseRevisionCounter(false) } return lp.RevisionCounter