From 2cb29284f653d90faee366e80e5cbd3d4ac6d19f Mon Sep 17 00:00:00 2001 From: Ben Sarmiento Date: Tue, 16 Jan 2024 02:05:41 +0100 Subject: [PATCH] Add lock for repairs --- internal/torrent/refresh.go | 2 ++ internal/torrent/repair.go | 14 +++++++++++++- internal/torrent/types.go | 5 ++++- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/internal/torrent/refresh.go b/internal/torrent/refresh.go index 867c873..bffedc9 100644 --- a/internal/torrent/refresh.go +++ b/internal/torrent/refresh.go @@ -168,6 +168,7 @@ func (t *TorrentManager) getMoreInfo(rdTorrent realdebrid.Torrent) *Torrent { OriginalName: info.OriginalName, Added: info.Added, Hash: info.Hash, + Lock: &sync.Mutex{}, } // SelectedFiles is a subset of Files with only the selected ones // it also has a Link field, which can be empty @@ -233,6 +234,7 @@ func (t *TorrentManager) mergeToMain(existing, toMerge *Torrent) Torrent { Unfixable: existing.Unfixable || toMerge.Unfixable, UnassignedLinks: existing.UnassignedLinks.Union(toMerge.UnassignedLinks), BrokenLinks: existing.BrokenLinks.Union(toMerge.BrokenLinks), + Lock: &sync.Mutex{}, } // this function triggers only when we have a new DownloadedID diff --git a/internal/torrent/repair.go b/internal/torrent/repair.go index cc0ea19..d0128f0 100644 --- a/internal/torrent/repair.go +++ b/internal/torrent/repair.go @@ -100,6 +100,10 @@ func (t *TorrentManager) repairAll() { } func (t *TorrentManager) Repair(torrent *Torrent) { + if torrent.Unfixable { + t.log.Warnf("Torrent %s is unfixable, skipping repair", t.GetKey(torrent)) + return + } // save the broken files to the file cache infoCache, _ := t.DirectoryMap.Get(INT_INFO_CACHE) torrent.DownloadedIDs.Each(func(id string) bool { @@ -117,13 +121,17 @@ func (t *TorrentManager) Repair(torrent *Torrent) { }) _ = t.workerPool.Submit(func() { t.log.Infof("Repairing torrent %s", t.GetKey(torrent)) + torrent.Lock.Lock() + defer torrent.Lock.Unlock() + torrent.Repairing = true t.repair(torrent) + torrent.Repairing = false t.log.Infof("Finished repairing torrent %s", t.GetKey(torrent)) }) } func (t *TorrentManager) repair(torrent *Torrent) { - if torrent.AnyInProgress() { + if torrent.AnyInProgress() || torrent.Repairing { t.log.Infof("Torrent %s is in progress, skipping repair until download is done", t.GetKey(torrent)) return } @@ -379,10 +387,14 @@ func (t *TorrentManager) markAsUnplayable(torrent *Torrent) { func (t *TorrentManager) markAsUnfixable(torrent *Torrent) { t.log.Warnf("Marking torrent %s as unfixable", t.GetKey(torrent)) + torrent.Lock.Lock() + defer torrent.Lock.Unlock() torrent.Unfixable = true infoCache, _ := t.DirectoryMap.Get(INT_INFO_CACHE) torrent.DownloadedIDs.Each(func(id string) bool { info, _ := infoCache.Get(id) + info.Lock.Lock() + defer info.Lock.Unlock() info.Unfixable = true t.writeTorrentToFile(id, info) return false diff --git a/internal/torrent/types.go b/internal/torrent/types.go index 27d3f37..3259797 100644 --- a/internal/torrent/types.go +++ b/internal/torrent/types.go @@ -3,6 +3,7 @@ package torrent import ( stdjson "encoding/json" "strings" + "sync" "time" "github.com/debridmediamanager/zurg/pkg/realdebrid" @@ -26,7 +27,9 @@ type Torrent struct { Unfixable bool `json:"Unfixable"` // modified over time BrokenLinks mapset.Set[string] `json:"BrokenLinks"` // only relevant on repair - Version string `json:"Version"` // only used for files + Version string `json:"Version"` // only used for files + Repairing bool `json:"-"` + Lock *sync.Mutex `json:"-"` } func (t *Torrent) MarshalJSON() ([]byte, error) {