From c3ee921d30e4f8be7097d2f7d998e248befbaadf Mon Sep 17 00:00:00 2001 From: Larvan2 <78135608+Larvan2@users.noreply.github.com> Date: Sun, 19 May 2024 15:46:23 +0800 Subject: [PATCH] chore: apply config when geo update --- component/updater/update_geo.go | 23 +++++--------- hub/route/configs.go | 53 ++++++++++++++++++++++----------- main.go | 18 +++++++++-- 3 files changed, 58 insertions(+), 36 deletions(-) diff --git a/component/updater/update_geo.go b/component/updater/update_geo.go index a98d94dc7a..4bb57e0640 100644 --- a/component/updater/update_geo.go +++ b/component/updater/update_geo.go @@ -5,7 +5,6 @@ import ( "fmt" "os" "runtime" - "sync" "time" "github.com/metacubex/mihomo/common/atomic" @@ -19,8 +18,7 @@ import ( ) var ( - updateGeoMux sync.Mutex - UpdatingGeo atomic.Bool + UpdatingGeo atomic.Bool ) func updateGeoDatabases() error { @@ -100,22 +98,15 @@ func updateGeoDatabases() error { return nil } -func UpdateGeoDatabases() error { +func UpdateGeoDatabases(updateNotification chan struct{}) error { log.Infoln("[GEO] Start updating GEO database") - updateGeoMux.Lock() - if UpdatingGeo.Load() { - updateGeoMux.Unlock() return errors.New("GEO database is updating, skip") } UpdatingGeo.Store(true) - updateGeoMux.Unlock() - - defer func() { - UpdatingGeo.Store(false) - }() + defer UpdatingGeo.Store(false) log.Infoln("[GEO] Updating GEO database") @@ -124,6 +115,7 @@ func UpdateGeoDatabases() error { return err } + updateNotification <- struct{}{} return nil } @@ -144,7 +136,7 @@ func getUpdateTime() (err error, time time.Time) { return nil, fileInfo.ModTime() } -func RegisterGeoUpdater() { +func RegisterGeoUpdater(updateNotification chan struct{}) { if C.GeoUpdateInterval <= 0 { log.Errorln("[GEO] Invalid update interval: %d", C.GeoUpdateInterval) return @@ -164,16 +156,15 @@ func RegisterGeoUpdater() { log.Infoln("[GEO] last update time %s", lastUpdate) if lastUpdate.Add(time.Duration(C.GeoUpdateInterval) * time.Hour).Before(time.Now()) { log.Infoln("[GEO] Database has not been updated for %v, update now", time.Duration(C.GeoUpdateInterval)*time.Hour) - if err := UpdateGeoDatabases(); err != nil { + if err := UpdateGeoDatabases(updateNotification); err != nil { log.Errorln("[GEO] Failed to update GEO database: %s", err.Error()) return } } for range ticker.C { - if err := UpdateGeoDatabases(); err != nil { + if err := UpdateGeoDatabases(updateNotification); err != nil { log.Errorln("[GEO] Failed to update GEO database: %s", err.Error()) - return } } }() diff --git a/hub/route/configs.go b/hub/route/configs.go index 47fd26e0a1..35977885fd 100644 --- a/hub/route/configs.go +++ b/hub/route/configs.go @@ -364,30 +364,47 @@ func updateConfigs(w http.ResponseWriter, r *http.Request) { } func updateGeoDatabases(w http.ResponseWriter, r *http.Request) { - if updater.UpdatingGeo.Load() { - render.Status(r, http.StatusBadRequest) - render.JSON(w, r, newError("updating...")) - return - } + updateNotification := make(chan struct{}) + errorChannel := make(chan error, 1) + done := make(chan struct{}) + defer func() { + close(updateNotification) + close(errorChannel) + }() - err := updater.UpdateGeoDatabases() - if err != nil { - render.Status(r, http.StatusBadRequest) - render.JSON(w, r, newError(err.Error())) - return - } + go func() { + defer close(done) + for { + select { + case <-updateNotification: + cfg, err := executor.ParseWithPath(C.Path.Config()) + if err != nil { + log.Errorln("[REST-API] update GEO databases failed: %v", err) + render.Status(r, http.StatusInternalServerError) + render.JSON(w, r, newError("Error parsing configuration")) + return + } + + log.Warnln("[REST-API] update GEO databases success, applying config") + executor.ApplyConfig(cfg, false) + return + case err := <-errorChannel: + log.Errorln("[REST-API] update GEO databases failed: %v", err) + render.Status(r, http.StatusInternalServerError) + render.JSON(w, r, err.Error()) + return + } + } + }() go func() { - cfg, err := executor.ParseWithPath(C.Path.Config()) + err := updater.UpdateGeoDatabases(updateNotification) if err != nil { - log.Errorln("[REST-API] update GEO databases failed: %v", err) - return + errorChannel <- err } - - log.Warnln("[REST-API] update GEO databases successful, apply config...") - - executor.ApplyConfig(cfg, false) }() + <-done + render.NoContent(w, r) } diff --git a/main.go b/main.go index 1d16f8bfc7..081a7eb508 100644 --- a/main.go +++ b/main.go @@ -113,9 +113,23 @@ func main() { } if C.GeoAutoUpdate { - updater.RegisterGeoUpdater() - } + updateNotification := make(chan struct{}) + go updater.RegisterGeoUpdater(updateNotification) + + go func() { + for range updateNotification { + cfg, err := executor.ParseWithPath(C.Path.Config()) + if err != nil { + log.Errorln("[GEO] update GEO databases failed: %v", err) + return + } + + log.Warnln("[GEO] update GEO databases success, applying config") + executor.ApplyConfig(cfg, false) + } + }() + } defer executor.Shutdown() termSign := make(chan os.Signal, 1)