From b5a923fd177730ce46e993c4f13e3d6408583dfd Mon Sep 17 00:00:00 2001 From: Ben Sarmiento Date: Sat, 2 Dec 2023 02:05:35 +0100 Subject: [PATCH] Fix repairs --- internal/torrent/manager.go | 55 +++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/internal/torrent/manager.go b/internal/torrent/manager.go index 4cabe16..a34e2b7 100644 --- a/internal/torrent/manager.go +++ b/internal/torrent/manager.go @@ -238,21 +238,13 @@ func (t *TorrentManager) startRefreshJob() { } func (t *TorrentManager) RefreshTorrents() { + // get all torrent info instances, _, err := t.Api.GetTorrents(0) if err != nil { t.log.Warnf("Cannot get torrents: %v\n", err) return } instanceCount := len(instances) - - // todo: inefficient - // handle deleted torrents in info cache - // but only do it if there is an info cache filled - infoCache, _ := t.DirectoryMap.Get(INT_INFO_CACHE) - if infoCache.Count() > 0 { - t.cleanInfoCache(instances) - } - infoChan := make(chan *Torrent, instanceCount) var wg sync.WaitGroup for i := range instances { @@ -267,6 +259,14 @@ func (t *TorrentManager) RefreshTorrents() { close(infoChan) t.log.Infof("Fetched info for %d torrents", instanceCount) + // todo: inefficient + // handle deleted torrents in info cache + // but only do it if there is an info cache filled + infoCache, _ := t.DirectoryMap.Get(INT_INFO_CACHE) + if infoCache.Count() > 0 { + t.cleanInfoCache(instances) + } + freshKeys := set.NewStringSet() oldTorrents, _ := t.DirectoryMap.Get(INT_ALL) noInfoCount := 0 @@ -298,8 +298,8 @@ func (t *TorrentManager) RefreshTorrents() { t.accessKeySet.Add(accessKey) return true }) - // now we can build the directory responses t.checkForOtherDeletedTorrents() + // now we can build the directory responses t.UpdateDirectoryResponsesCache() t.log.Infof("Compiled into %d torrents, %d were missing info", oldTorrents.Count(), noInfoCount) @@ -340,15 +340,15 @@ func (t *TorrentManager) cleanInfoCache(torrents []realdebrid.Torrent) { // getMoreInfo gets original name, size and files for a torrent func (t *TorrentManager) getMoreInfo(rdTorrent realdebrid.Torrent) *Torrent { infoCache, _ := t.DirectoryMap.Get(INT_INFO_CACHE) - if infoCache.Has(rdTorrent.ID) { - tor, _ := infoCache.Get(rdTorrent.ID) + if tor, exists := infoCache.Get(rdTorrent.ID); exists { + // in memory cache is always fresh return tor } var info *realdebrid.TorrentInfo var err error - // file cache torrentFromFile := t.readTorrentFromFile(rdTorrent.ID) + // check staleness of file cache if torrentFromFile != nil && len(torrentFromFile.ID) > 0 && len(torrentFromFile.Links) > 0 && len(torrentFromFile.Links) == len(rdTorrent.Links) && torrentFromFile.Links[0] == rdTorrent.Links[0] { info = torrentFromFile info.Progress = rdTorrent.Progress @@ -381,6 +381,10 @@ func (t *TorrentManager) getMoreInfo(rdTorrent realdebrid.Torrent) *Torrent { } if len(selectedFiles) > len(info.Links) && info.Progress == 100 { t.log.Warnf("Torrent id=%s is partly expired, it has %d selected files but only %d links", info.ID, len(selectedFiles), len(info.Links)) + for i, file := range selectedFiles { + file.Link = "repair" + i++ + } } else if len(selectedFiles) == len(info.Links) { // all links are still intact! good! for i, file := range selectedFiles { @@ -447,8 +451,10 @@ func (t *TorrentManager) readTorrentFromFile(torrentID string) *realdebrid.Torre file, err := os.Open(filePath) if err != nil { if os.IsNotExist(err) { + t.log.Debug("[file] file does not exist") return nil } + t.log.Debugf("[file] error opening file: %v", err) return nil } defer file.Close() @@ -457,9 +463,11 @@ func (t *TorrentManager) readTorrentFromFile(torrentID string) *realdebrid.Torre var torrent realdebrid.TorrentInfo dataDecoder := gob.NewDecoder(r) if err := dataDecoder.Decode(&torrent); err != nil { + t.log.Debugf("[file] error decoding torrent: %v", err) return nil } if torrent.Version != t.requiredVersion { + t.log.Debugf("[file] not the right version: %s", torrent.Version) return nil } return &torrent @@ -492,7 +500,7 @@ func (t *TorrentManager) organizeChaos(links []string, selectedFiles []*File) ([ resultsChan <- Result{Response: download} return } - resp := t.Api.UnrestrictUntilOk(link, t.Config.ShouldServeFromRclone()) + resp := t.UnrestrictUntilOk(link) resultsChan <- Result{Response: resp} }) } @@ -544,6 +552,7 @@ func (t *TorrentManager) repairAll() { } allTorrents, _ := t.DirectoryMap.Get(INT_ALL) + var toRepair []string allTorrents.IterCb(func(_ string, torrent *Torrent) { if torrent.AnyInProgress() { t.log.Debugf("Skipping %s for repairs because it is in progress", torrent.AccessKey) @@ -553,15 +562,18 @@ func (t *TorrentManager) repairAll() { torrent.SelectedFiles.IterCb(func(_ string, file *File) { if file.Link == "repair" && !forRepair { file.Link = "repairing" - t.log.Debugf("Found a file to repair for torrent %s", torrent.AccessKey) forRepair = true } }) if forRepair { - t.log.Infof("Repairing %s", torrent.AccessKey) - t.Repair(torrent.AccessKey) + toRepair = append(toRepair, torrent.AccessKey) } }) + t.log.Debugf("Found %d torrents to repair", len(toRepair)) + for _, accessKey := range toRepair { + t.log.Infof("Repairing %s", accessKey) + t.Repair(accessKey) + } } func (t *TorrentManager) checkForOtherDeletedTorrents() { @@ -577,7 +589,7 @@ func (t *TorrentManager) checkForOtherDeletedTorrents() { if unselected == torrent.SelectedFiles.Count() && unselected > 0 { t.log.Infof("Deleting %s", torrent.AccessKey) toDelete = append(toDelete, torrent.AccessKey) - } else { + } else if unselected > 0 { // save to file for i := range torrent.Instances { t.writeTorrentToFile(&torrent.Instances[i]) @@ -590,8 +602,8 @@ func (t *TorrentManager) checkForOtherDeletedTorrents() { } func (t *TorrentManager) Delete(accessKey string, deleteInRD bool, updateDirectoryResponses bool) { - t.log.Infof("Deleting torrent %s", accessKey) if deleteInRD { + t.log.Infof("Deleting torrent %s in RD", accessKey) allTorrents, _ := t.DirectoryMap.Get(INT_ALL) if torrent, ok := allTorrents.Get(accessKey); ok { for _, instance := range torrent.Instances { @@ -612,11 +624,6 @@ func (t *TorrentManager) Delete(accessKey string, deleteInRD bool, updateDirecto } func (t *TorrentManager) Repair(accessKey string) { - if !t.Config.EnableRepair() { - t.log.Warn("Repair is disabled; if you do not have other zurg instances running, you should enable repair") - return - } - allTorrents, _ := t.DirectoryMap.Get(INT_ALL) torrent, _ := allTorrents.Get(accessKey) if torrent == nil {