diff --git a/component/resource/fetcher.go b/component/resource/fetcher.go index e6291293..c82a54a3 100644 --- a/component/resource/fetcher.go +++ b/component/resource/fetcher.go @@ -10,6 +10,7 @@ import ( types "github.com/metacubex/mihomo/constant/provider" "github.com/metacubex/mihomo/log" + "github.com/sagernet/fswatch" "github.com/samber/lo" ) @@ -30,6 +31,7 @@ type Fetcher[V any] struct { parser Parser[V] interval time.Duration OnUpdate func(V) + watcher *fswatch.Watcher } func (f *Fetcher[V]) Name() string { @@ -113,7 +115,20 @@ func (f *Fetcher[V]) Initial() (V, error) { f.hash = md5.Sum(buf) // pull contents automatically - if f.interval > 0 { + if f.vehicle.Type() == types.File { + f.watcher, err = fswatch.NewWatcher(fswatch.Options{ + Path: []string{f.vehicle.Path()}, + Direct: true, + Callback: f.update, + }) + if err != nil { + return lo.Empty[V](), err + } + err = f.watcher.Start() + if err != nil { + return lo.Empty[V](), err + } + } else if f.interval > 0 { go f.pullLoop() } @@ -155,6 +170,9 @@ func (f *Fetcher[V]) Destroy() error { if f.interval > 0 { f.done <- struct{}{} } + if f.watcher != nil { + _ = f.watcher.Close() + } return nil } @@ -170,27 +188,31 @@ func (f *Fetcher[V]) pullLoop() { select { case <-timer.C: timer.Reset(f.interval) - elm, same, err := f.Update() - if err != nil { - log.Errorln("[Provider] %s pull error: %s", f.Name(), err.Error()) - continue - } - - if same { - log.Debugln("[Provider] %s's content doesn't change", f.Name()) - continue - } - - log.Infoln("[Provider] %s's content update", f.Name()) - if f.OnUpdate != nil { - f.OnUpdate(elm) - } + f.update(f.vehicle.Path()) case <-f.done: return } } } +func (f *Fetcher[V]) update(path string) { + elm, same, err := f.Update() + if err != nil { + log.Errorln("[Provider] %s pull error: %s", f.Name(), err.Error()) + return + } + + if same { + log.Debugln("[Provider] %s's content doesn't change", f.Name()) + return + } + + log.Infoln("[Provider] %s's content update", f.Name()) + if f.OnUpdate != nil { + f.OnUpdate(elm) + } +} + func safeWrite(path string, buf []byte) error { dir := filepath.Dir(path) diff --git a/go.mod b/go.mod index 7085d8b1..9c3a2180 100644 --- a/go.mod +++ b/go.mod @@ -35,6 +35,7 @@ require ( github.com/oschwald/maxminddb-golang v1.12.0 github.com/puzpuzpuz/xsync/v3 v3.2.0 github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a + github.com/sagernet/fswatch v0.1.1 github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a github.com/sagernet/sing v0.5.0-alpha.13 github.com/sagernet/sing-mux v0.2.1-0.20240124034317-9bfb33698bb6 @@ -93,7 +94,6 @@ require ( github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/quic-go/qpack v0.4.0 // indirect github.com/quic-go/qtls-go1-20 v0.4.1 // indirect - github.com/sagernet/fswatch v0.1.1 // indirect github.com/sagernet/nftables v0.3.0-beta.4 // indirect github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect