perf: excessive torrent tracker dns resolve (#634)

This commit is contained in:
Levi authored and GitHub committed 2024-08-08 18:55:52 +08:00
1 parent 4d60c47d39
commit 1f791c66e6
7 files changed
+239 -149

No files matched your search

+58 -33
View File
@@ -63,6 +63,7 @@ type Downloader struct {
storage Storage
tasks []*Task
waitTasks []*Task
watchedTasks sync.Map
listener Listener
lock *sync.Mutex
@@ -170,7 +171,7 @@ func (d *Downloader) Setup() error {
go func() {
for _, task := range d.tasks {
if task.Status == base.DownloadStatusDone && task.Uploading {
if err := d.restoreFetcher(task); err != nil {
if err := d.restoreTask(task); err != nil {
d.Logger.Error().Stack().Err(err).Msgf("task upload restore fetcher failed, task id: %s", task.ID)
}
if uploader, ok := task.fetcher.(fetcher.Uploader); ok {
@@ -530,6 +531,17 @@ func (d *Downloader) Stats(id string) (sr any, err error) {
if task == nil {
return sr, ErrTaskNotFound
}
if task.fetcher == nil {
err = func() error {
task.statusLock.Lock()
defer task.statusLock.Unlock()
return d.restoreFetcher(task)
}()
if err != nil {
return
}
}
sr = task.fetcher.Stats()
return
}
@@ -681,6 +693,14 @@ func (d *Downloader) getProtocolConfig(name string, v any) bool {
// wait task done
func (d *Downloader) watch(task *Task) {
if _, loaded := d.watchedTasks.LoadOrStore(task.ID, true); loaded {
return
}
defer func() {
d.watchedTasks.Delete(task.ID)
}()
// wait task upload done
if task.Uploading {
if uploader, ok := task.fetcher.(fetcher.Uploader); ok {
@@ -759,42 +779,47 @@ func (d *Downloader) doOnError(task *Task, err error) {
}
}
func (d *Downloader) restoreFetcher(task *Task) error {
func (d *Downloader) restoreTask(task *Task) error {
if task.fetcher == nil {
fm, err := d.parseFm(task.Meta.Req.URL)
if err := d.restoreFetcher(task); err != nil {
return err
}
}
go d.watch(task)
task.fetcher.Create(task.Meta.Opts)
return nil
}
func (d *Downloader) restoreFetcher(task *Task) error {
var fm fetcher.FetcherManager
for _, f := range d.cfg.FetchManagers {
if f.Name() == task.Protocol {
fm = f
break
}
}
if fm == nil {
return ErrUnSupportedProtocol
}
task.fetcherManager = fm
v, f := fm.Restore()
if v != nil {
err := d.storage.Pop(bucketSave, task.ID, v)
if err != nil {
return err
}
task.fetcherManager = fm
err = func() error {
v, f := fm.Restore()
if v != nil {
err := d.storage.Pop(bucketSave, task.ID, v)
if err != nil {
return err
}
}
task.fetcher = f(task.Meta, v)
return nil
}()
if err != nil {
d.Logger.Error().Stack().Err(err).Msgf("deserialize fetcher failed, task id: %s", task.ID)
}
if task.fetcher == nil {
task.fetcher = fm.Build()
}
d.setupFetcher(fm, task.fetcher)
if task.fetcher.Meta().Req == nil {
task.fetcher.Meta().Req = task.Meta.Req
}
if task.fetcher.Meta().Res == nil {
task.fetcher.Meta().Res = task.Meta.Res
}
go d.watch(task)
} else if task.Status == base.DownloadStatusError {
go d.watch(task)
}
task.fetcher.Create(task.Meta.Opts)
task.fetcher = f(task.Meta, v)
if task.fetcher == nil {
task.fetcher = task.fetcherManager.Build()
}
d.setupFetcher(task.fetcherManager, task.fetcher)
if task.fetcher.Meta().Req == nil {
task.fetcher.Meta().Req = task.Meta.Req
}
if task.fetcher.Meta().Res == nil {
task.fetcher.Meta().Res = task.Meta.Res
}
return nil
}
@@ -872,7 +897,7 @@ func (d *Downloader) doStart(task *Task) (err error) {
return
}
err = d.restoreFetcher(task)
err = d.restoreTask(task)
if err != nil {
d.Logger.Error().Stack().Err(err).Msgf("restore fetcher failed, task id: %s", task.ID)
return
+5 -5
View File
@@ -13,12 +13,12 @@ import (
func Info(w http.ResponseWriter, r *http.Request) {
info := map[string]any{
"version": base.Version,
"runtime": runtime.Version(),
"os": runtime.GOOS,
"arch": runtime.GOARCH,
"version": base.Version,
"runtime": runtime.Version(),
"os": runtime.GOOS,
"arch": runtime.GOARCH,
"inDocker": base.InDocker == "true",
}
info["inDocker"] = base.InDocker == "true"
WriteJson(w, model.NewOkResult(info))
}