diff --git a/component/resource/fetcher.go b/component/resource/fetcher.go index 39beee856..ffbef0d54 100644 --- a/component/resource/fetcher.go +++ b/component/resource/fetcher.go @@ -3,6 +3,7 @@ package resource import ( "context" "os" + "sync" "time" "github.com/metacubex/mihomo/common/utils" @@ -27,6 +28,7 @@ type Fetcher[V any] struct { interval time.Duration onUpdate func(V) watcher *fswatch.Watcher + loadBufMutex sync.Mutex } func (f *Fetcher[V]) Name() string { @@ -46,17 +48,11 @@ func (f *Fetcher[V]) UpdatedAt() time.Time { } func (f *Fetcher[V]) Initial() (V, error) { - var ( - buf []byte - contents V - err error - ) - if stat, fErr := os.Stat(f.vehicle.Path()); fErr == nil { // local file exists, use it first - buf, err = os.ReadFile(f.vehicle.Path()) + buf, err := os.ReadFile(f.vehicle.Path()) modTime := stat.ModTime() - contents, _, err = f.loadBuf(buf, utils.MakeHash(buf), false) + contents, _, err := f.loadBuf(buf, utils.MakeHash(buf), false) f.updatedAt = modTime // reset updatedAt to file's modTime if err == nil { @@ -69,15 +65,18 @@ func (f *Fetcher[V]) Initial() (V, error) { } // parse local file error, fallback to remote - contents, _, err = f.Update() + contents, _, updateErr := f.Update() + // start the pull loop even if f.Update() failed + err := f.startPullLoop(false) if err != nil { return lo.Empty[V](), err } - err = f.startPullLoop(false) - if err != nil { - return lo.Empty[V](), err + + if updateErr != nil { + return lo.Empty[V](), updateErr } + return contents, nil } @@ -94,6 +93,9 @@ func (f *Fetcher[V]) SideUpdate(buf []byte) (V, bool, error) { } func (f *Fetcher[V]) loadBuf(buf []byte, hash utils.HashType, updateFile bool) (V, bool, error) { + f.loadBufMutex.Lock() + defer f.loadBufMutex.Unlock() + now := time.Now() if f.hash.Equal(hash) { if updateFile {