diff --git a/next/assets/assets.go b/next/assets/assets.go index 04e855c..0b5eee2 100644 --- a/next/assets/assets.go +++ b/next/assets/assets.go @@ -2,6 +2,7 @@ package assets import ( "XProxy/next/logger" + "github.com/robfig/cron" urlpkg "net/url" "strings" "sync" @@ -12,63 +13,109 @@ var buildinAssets = map[string]string{ "geosite.dat": "/geosite.dat.xz", } -type UpdateSettings struct { - cron string - mutex sync.Mutex - proxy *urlpkg.URL - assets map[string]string +type updateConfig struct { + spec string + cron *cron.Cron + renew sync.Mutex + running sync.Mutex + proxy *urlpkg.URL + assets map[string]string } -var update UpdateSettings +var update updateConfig -func assetsClone(raw map[string]string) map[string]string { - assets := make(map[string]string, len(raw)) - for file, url := range raw { - assets[file] = strings.Clone(url) - } - return assets -} +//func assetsClone(raw map[string]string) map[string]string { +// assets := make(map[string]string, len(raw)) +// for file, url := range raw { +// assets[file] = strings.Clone(url) +// } +// return assets +//} -func SetCron(cron string) error { - // TODO: setting up crond service - return nil +// GetCron is used to obtain cron service specification. +func GetCron() string { + update.renew.Lock() + spec := strings.Clone(update.spec) + update.renew.Unlock() + return spec } -func GetProxy() string { - update.mutex.Lock() - proxy := update.proxy.String() - update.mutex.Unlock() - return proxy -} +// SetCron is used to update cron service specification. +func SetCron(spec string) error { + if spec == update.spec { + return nil // cron spec without renew + } -func SetProxy(proxy string) error { - var proxyUrl *urlpkg.URL // clear proxy by empty string - if proxy != "" { - url, err := urlpkg.Parse(proxy) + var cs *cron.Cron + if spec != "" { // update cron service + cs = cron.New() + err := cs.AddFunc(spec, func() { + var entry *cron.Entry + if entries := update.cron.Entries(); len(entries) != 0 && entries[0] != nil { + entry = entries[0] + } + logger.Debugf("hello from cron") + if entry != nil { + logger.Debugf("Assets cron service next trigger -> `%s`", entry.Next) + } + }) if err != nil { - logger.Errorf("Invalid proxy url `%s` -> %v", proxy, err) + logger.Errorf("Invalid cron spec `%s` -> %v", spec, err) return err } - proxyUrl = url + cs.Start() } - update.mutex.Lock() - update.proxy = proxyUrl - update.mutex.Unlock() - return nil -} -func SetAssets(assets map[string]string) { - update.mutex.Lock() - update.assets = assetsClone(assets) - update.mutex.Unlock() + update.renew.Lock() + if update.cron != nil { + update.cron.Stop() // stop old cron service + } + update.cron = cs + update.spec = spec + if cs == nil { + logger.Infof("Assets cron service has been terminated") + } else { + logger.Infof("Assets cron service has been updated -> `%s`", spec) + } + update.renew.Unlock() + return nil } -func GetAssets() map[string]string { - update.mutex.Lock() - assets := assetsClone(update.assets) - update.mutex.Unlock() - return assets -} +//func GetProxy() string { +// update.mutex.Lock() +// proxy := update.proxy.String() +// update.mutex.Unlock() +// return proxy +//} +// +//func SetProxy(proxy string) error { +// var proxyUrl *urlpkg.URL // clear proxy by empty string +// if proxy != "" { +// url, err := urlpkg.Parse(proxy) +// if err != nil { +// logger.Errorf("Invalid proxy url `%s` -> %v", proxy, err) +// return err +// } +// proxyUrl = url +// } +// update.mutex.Lock() +// update.proxy = proxyUrl +// update.mutex.Unlock() +// return nil +//} +// +//func SetAssets(assets map[string]string) { +// update.mutex.Lock() +// update.assets = assetsClone(assets) +// update.mutex.Unlock() +//} +// +//func GetAssets() map[string]string { +// update.mutex.Lock() +// assets := assetsClone(update.assets) +// update.mutex.Unlock() +// return assets +//} func LoadBuildin() { updateLocalAssets(buildinAssets, true) diff --git a/next/assets/update.go b/next/assets/update.go index ddec46f..b09aa64 100644 --- a/next/assets/update.go +++ b/next/assets/update.go @@ -4,6 +4,7 @@ import ( "XProxy/next/logger" urlpkg "net/url" "os" + "path" "sync" "time" ) @@ -11,14 +12,18 @@ import ( // saveAsset is used to write to a local file and specify its last modify // time. If the file exists, it will be replaced. func saveAsset(file string, content []byte, date *time.Time) error { - // TODO: create folder if not exist + err := os.MkdirAll(path.Dir(file), 0755) + if err != nil { + logger.Errorf("Failed to create folder -> %v", err) + return err + } + fp, err := os.OpenFile(file, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) if err != nil { - logger.Errorf("Failed to open file `%s` -> %v", file, err) + logger.Errorf("Failed to open file -> %v", err) return err } defer fp.Close() - _, err = fp.Write(content) if err != nil { logger.Errorf("Failed to save file `%s` -> %v", file, err) diff --git a/next/main.go b/next/main.go index b9d01c3..2d53645 100644 --- a/next/main.go +++ b/next/main.go @@ -1,10 +1,27 @@ package main -import "XProxy/next/assets" +import ( + "XProxy/next/assets" + "XProxy/next/logger" + "time" +) func main() { - assets.LoadBuildin() + logger.Warnf("cron -> `%s`", assets.GetCron()) + assets.SetCron("@every 1s") + logger.Warnf("cron -> `%s`", assets.GetCron()) + + time.Sleep(5 * time.Second) + assets.SetCron("@every 2s") + logger.Warnf("cron -> `%s`", assets.GetCron()) + + time.Sleep(8 * time.Second) + assets.SetCron("") + logger.Warnf("cron -> `%s`", assets.GetCron()) + select {} + + //assets.LoadBuildin() //remoteAssets := map[string]string{ // "geoip.dat": "https://cdn.dnomd343.top/v2ray-rules-dat/geoip.dat.xz",