From 46e07f71c4ae62c12e928f8195335bfec5e59dea Mon Sep 17 00:00:00 2001 From: Ben Sarmiento Date: Sat, 17 Feb 2024 06:34:36 +0100 Subject: [PATCH] Fix retries on req body reads --- internal/torrent/fixer.go | 8 ++++---- internal/torrent/repair.go | 13 +++++++++++-- pkg/http/client.go | 8 ++++++++ pkg/realdebrid/api.go | 16 ++++------------ 4 files changed, 27 insertions(+), 18 deletions(-) diff --git a/internal/torrent/fixer.go b/internal/torrent/fixer.go index a540ebf..e44168c 100644 --- a/internal/torrent/fixer.go +++ b/internal/torrent/fixer.go @@ -66,13 +66,13 @@ func (t *TorrentManager) processFixers(instances []realdebrid.Torrent) { } otherId := strings.TrimPrefix(command, "repaired_with:") - for _, instance := range instances { - if instance.ID == otherId { - if instance.Progress != 100 { + for _, instance2 := range instances { + if instance2.ID == otherId { + if instance2.Progress != 100 { t.fixers.Set(id, command) // requeue the fixer break } - torrent := t.getMoreInfo(instance) + torrent := t.getMoreInfo(instance2) t.log.Debugf("Repairing torrent %s again now that fixers ids=%s and %s are done", t.GetKey(torrent), id, otherId) repairMe, _ := allTorrents.Get(t.GetKey(torrent)) toRedownload = append(toRedownload, repairMe) diff --git a/internal/torrent/repair.go b/internal/torrent/repair.go index 1eea89e..11ddd54 100644 --- a/internal/torrent/repair.go +++ b/internal/torrent/repair.go @@ -199,9 +199,16 @@ func (t *TorrentManager) repair(torrent *Torrent) { } // second step: download the broken files - if len(brokenFiles) > 0 { - t.log.Infof("Repairing by downloading only the %d broken out of %d files of torrent %s", len(brokenFiles), torrent.SelectedFiles.Count(), t.GetKey(torrent)) + + if len(brokenFiles) == 1 && allBroken { + // if all files are broken, we can't do anything + t.log.Warnf("Torrent %s has only 1 cached file and it's broken, marking as unfixable", t.GetKey(torrent)) + t.markAsUnfixable(torrent, "the lone cached file is broken") + return + + } else if len(brokenFiles) > 1 { if !allBroken { + t.log.Infof("Repairing by downloading only the %d broken out of %d files of torrent %s", len(brokenFiles), torrent.SelectedFiles.Count(), t.GetKey(torrent)) redownloadedInfo, err := t.redownloadTorrent(torrent, brokenFileIDs) if err != nil { t.log.Warnf("Cannot repair torrent %s by downloading broken files (error=%s) giving up", t.GetKey(torrent), err.Error()) @@ -213,6 +220,8 @@ func (t *TorrentManager) repair(torrent *Torrent) { } } + t.log.Infof("Repairing by downloading 2 batches of the broken %d files of torrent %s", len(brokenFiles), t.GetKey(torrent)) + // divide the broken files into 2 groups group1 := make([]*File, 0) group2 := make([]*File, 0) diff --git a/pkg/http/client.go b/pkg/http/client.go index fc486d8..671df61 100644 --- a/pkg/http/client.go +++ b/pkg/http/client.go @@ -1,6 +1,7 @@ package http import ( + "bytes" "context" "encoding/json" "fmt" @@ -144,8 +145,15 @@ func (r *HTTPClient) Do(req *http.Request) (*http.Response, error) { var resp *http.Response var err error attempt := 0 + var origBody []byte + if req.Method == "POST" { + origBody, _ = io.ReadAll(req.Body) + } for { + if origBody != nil { + req.Body = io.NopCloser(bytes.NewReader(origBody)) + } if resp != nil && resp.Body != nil { resp.Body.Close() } diff --git a/pkg/realdebrid/api.go b/pkg/realdebrid/api.go index b395cf1..a5441d0 100644 --- a/pkg/realdebrid/api.go +++ b/pkg/realdebrid/api.go @@ -29,9 +29,7 @@ func NewRealDebrid(client, unrestrictClient *zurghttp.HTTPClient, log *logutil.L func (rd *RealDebrid) UnrestrictCheck(link string) (*Download, error) { data := url.Values{} data.Set("link", link) - - bodyReader := strings.NewReader(data.Encode()) - requestBody := io.NopCloser(bodyReader) + requestBody := strings.NewReader(data.Encode()) req, err := http.NewRequest("POST", "https://api.real-debrid.com/rest/1.0/unrestrict/check", requestBody) if err != nil { @@ -67,9 +65,7 @@ func (rd *RealDebrid) UnrestrictCheck(link string) (*Download, error) { func (rd *RealDebrid) UnrestrictLink(link string, checkFirstByte bool) (*Download, error) { data := url.Values{} data.Set("link", link) - - bodyReader := strings.NewReader(data.Encode()) - requestBody := io.NopCloser(bodyReader) + requestBody := strings.NewReader(data.Encode()) req, err := http.NewRequest("POST", "https://api.real-debrid.com/rest/1.0/unrestrict/link", requestBody) if err != nil { @@ -218,9 +214,7 @@ func (rd *RealDebrid) GetTorrentInfo(id string) (*TorrentInfo, error) { func (rd *RealDebrid) SelectTorrentFiles(id string, files string) error { data := url.Values{} data.Set("files", files) - - bodyReader := strings.NewReader(data.Encode()) - requestBody := io.NopCloser(bodyReader) + requestBody := strings.NewReader(data.Encode()) reqURL := fmt.Sprintf("https://api.real-debrid.com/rest/1.0/torrents/selectFiles/%s", id) req, err := http.NewRequest("POST", reqURL, requestBody) @@ -269,9 +263,7 @@ func (rd *RealDebrid) AddMagnetHash(magnet string) (*MagnetResponse, error) { // Prepare request data data := url.Values{} data.Set("magnet", fmt.Sprintf("magnet:?xt=urn:btih:%s", magnet)) - - bodyReader := strings.NewReader(data.Encode()) - requestBody := io.NopCloser(bodyReader) + requestBody := strings.NewReader(data.Encode()) // Construct request URL reqURL := "https://api.real-debrid.com/rest/1.0/torrents/addMagnet"