chore: apply config when geo update

This commit is contained in:
Larvan2 2024-05-19 15:46:23 +08:00
parent df69a31e62
commit c3ee921d30
3 changed files with 60 additions and 38 deletions

View File

@ -5,7 +5,6 @@ import (
"fmt" "fmt"
"os" "os"
"runtime" "runtime"
"sync"
"time" "time"
"github.com/metacubex/mihomo/common/atomic" "github.com/metacubex/mihomo/common/atomic"
@ -19,8 +18,7 @@ import (
) )
var ( var (
updateGeoMux sync.Mutex UpdatingGeo atomic.Bool
UpdatingGeo atomic.Bool
) )
func updateGeoDatabases() error { func updateGeoDatabases() error {
@ -100,22 +98,15 @@ func updateGeoDatabases() error {
return nil return nil
} }
func UpdateGeoDatabases() error { func UpdateGeoDatabases(updateNotification chan struct{}) error {
log.Infoln("[GEO] Start updating GEO database") log.Infoln("[GEO] Start updating GEO database")
updateGeoMux.Lock()
if UpdatingGeo.Load() { if UpdatingGeo.Load() {
updateGeoMux.Unlock()
return errors.New("GEO database is updating, skip") return errors.New("GEO database is updating, skip")
} }
UpdatingGeo.Store(true) UpdatingGeo.Store(true)
updateGeoMux.Unlock() defer UpdatingGeo.Store(false)
defer func() {
UpdatingGeo.Store(false)
}()
log.Infoln("[GEO] Updating GEO database") log.Infoln("[GEO] Updating GEO database")
@ -124,6 +115,7 @@ func UpdateGeoDatabases() error {
return err return err
} }
updateNotification <- struct{}{}
return nil return nil
} }
@ -144,7 +136,7 @@ func getUpdateTime() (err error, time time.Time) {
return nil, fileInfo.ModTime() return nil, fileInfo.ModTime()
} }
func RegisterGeoUpdater() { func RegisterGeoUpdater(updateNotification chan struct{}) {
if C.GeoUpdateInterval <= 0 { if C.GeoUpdateInterval <= 0 {
log.Errorln("[GEO] Invalid update interval: %d", C.GeoUpdateInterval) log.Errorln("[GEO] Invalid update interval: %d", C.GeoUpdateInterval)
return return
@ -164,16 +156,15 @@ func RegisterGeoUpdater() {
log.Infoln("[GEO] last update time %s", lastUpdate) log.Infoln("[GEO] last update time %s", lastUpdate)
if lastUpdate.Add(time.Duration(C.GeoUpdateInterval) * time.Hour).Before(time.Now()) { 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) 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()) log.Errorln("[GEO] Failed to update GEO database: %s", err.Error())
return return
} }
} }
for range ticker.C { 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()) log.Errorln("[GEO] Failed to update GEO database: %s", err.Error())
return
} }
} }
}() }()

View File

@ -364,30 +364,47 @@ func updateConfigs(w http.ResponseWriter, r *http.Request) {
} }
func updateGeoDatabases(w http.ResponseWriter, r *http.Request) { func updateGeoDatabases(w http.ResponseWriter, r *http.Request) {
if updater.UpdatingGeo.Load() { updateNotification := make(chan struct{})
render.Status(r, http.StatusBadRequest) errorChannel := make(chan error, 1)
render.JSON(w, r, newError("updating...")) done := make(chan struct{})
return 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() { go func() {
cfg, err := executor.ParseWithPath(C.Path.Config()) defer close(done)
if err != nil { for {
log.Errorln("[REST-API] update GEO databases failed: %v", err) select {
return 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
}
} }
log.Warnln("[REST-API] update GEO databases successful, apply config...")
executor.ApplyConfig(cfg, false)
}() }()
go func() {
err := updater.UpdateGeoDatabases(updateNotification)
if err != nil {
errorChannel <- err
}
}()
<-done
render.NoContent(w, r) render.NoContent(w, r)
} }

18
main.go
View File

@ -113,9 +113,23 @@ func main() {
} }
if C.GeoAutoUpdate { 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() defer executor.Shutdown()
termSign := make(chan os.Signal, 1) termSign := make(chan os.Signal, 1)