Repair logic
This commit is contained in:
@@ -28,6 +28,7 @@ type TorrentManager struct {
|
||||
DownloadCache cmap.ConcurrentMap[string, *realdebrid.Download]
|
||||
DownloadMap cmap.ConcurrentMap[string, *realdebrid.Download]
|
||||
allAccessKeys mapset.Set[string]
|
||||
forRepairs mapset.Set[string]
|
||||
latestState *LibraryState
|
||||
requiredVersion string
|
||||
workerPool *ants.Pool
|
||||
@@ -42,6 +43,7 @@ func NewTorrentManager(cfg config.ConfigInterface, api *realdebrid.RealDebrid, p
|
||||
Config: cfg,
|
||||
Api: api,
|
||||
allAccessKeys: mapset.NewSet[string](),
|
||||
forRepairs: mapset.NewSet[string](),
|
||||
latestState: &LibraryState{},
|
||||
requiredVersion: "11.01.2024",
|
||||
workerPool: p,
|
||||
|
||||
@@ -37,12 +37,22 @@ func (t *TorrentManager) RefreshTorrents() []string {
|
||||
|
||||
freshKeys := mapset.NewSet[string]()
|
||||
allTorrents, _ := t.DirectoryMap.Get(INT_ALL)
|
||||
toReinsert := mapset.NewSet[string]()
|
||||
noInfoCount := 0
|
||||
for info := range infoChan {
|
||||
if info == nil {
|
||||
noInfoCount++
|
||||
continue
|
||||
}
|
||||
torrentID := info.DownloadedIDs.ToSlice()[0]
|
||||
if !info.AnyInProgress() && t.forRepairs.Contains(torrentID) {
|
||||
// if it's 100% and it's a temp repair, remove it
|
||||
t.Api.DeleteTorrent(torrentID)
|
||||
toReinsert.Add(t.GetKey(info))
|
||||
infoChan <- nil
|
||||
t.forRepairs.Remove(torrentID)
|
||||
continue
|
||||
}
|
||||
if !info.AnyInProgress() {
|
||||
freshKeys.Add(t.GetKey(info))
|
||||
}
|
||||
@@ -54,6 +64,7 @@ func (t *TorrentManager) RefreshTorrents() []string {
|
||||
}
|
||||
}
|
||||
t.log.Infof("Compiled into %d torrents, %d were missing info", allTorrents.Count(), noInfoCount)
|
||||
|
||||
var updatedPaths []string
|
||||
// torrents yet to be assigned in a directory
|
||||
freshKeys.Difference(t.allAccessKeys).Each(func(accessKey string) bool {
|
||||
@@ -82,6 +93,12 @@ func (t *TorrentManager) RefreshTorrents() []string {
|
||||
return false
|
||||
})
|
||||
|
||||
toReinsert.Each(func(accessKey string) bool {
|
||||
torrent, _ := allTorrents.Get(accessKey)
|
||||
t.reinsertTorrent(torrent, "")
|
||||
return false
|
||||
})
|
||||
|
||||
return updatedPaths
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
|
||||
const (
|
||||
EXPIRED_LINK_TOLERANCE_HOURS = 24
|
||||
REPAIR_SEMAPHORE = "semaphore"
|
||||
)
|
||||
|
||||
func (t *TorrentManager) RepairAll() {
|
||||
@@ -119,7 +118,6 @@ func (t *TorrentManager) Repair(torrent *Torrent) {
|
||||
_ = t.workerPool.Submit(func() {
|
||||
t.log.Infof("Repairing torrent %s", t.GetKey(torrent))
|
||||
t.repair(torrent)
|
||||
torrent.InProgressIDs.Remove(REPAIR_SEMAPHORE)
|
||||
t.log.Infof("Finished repairing torrent %s", t.GetKey(torrent))
|
||||
})
|
||||
}
|
||||
@@ -129,7 +127,6 @@ func (t *TorrentManager) repair(torrent *Torrent) {
|
||||
t.log.Infof("Torrent %s is in progress, skipping repair until download is done", t.GetKey(torrent))
|
||||
return
|
||||
}
|
||||
torrent.InProgressIDs.Add(REPAIR_SEMAPHORE)
|
||||
|
||||
proceed := t.canCapacityHandle() // blocks for approx 45 minutes if active torrents are full
|
||||
if !proceed {
|
||||
@@ -249,8 +246,10 @@ func (t *TorrentManager) repair(torrent *Torrent) {
|
||||
}
|
||||
|
||||
func (t *TorrentManager) reinsertTorrent(torrent *Torrent, brokenFiles string) bool {
|
||||
oldTorrentIDs := make([]string, 0)
|
||||
// broken files means broken links
|
||||
|
||||
oldTorrentIDs := make([]string, 0)
|
||||
|
||||
// if brokenFiles is not provided
|
||||
if brokenFiles == "" {
|
||||
// only replace the torrent if we are reinserting all files
|
||||
@@ -294,7 +293,17 @@ func (t *TorrentManager) reinsertTorrent(torrent *Torrent, brokenFiles string) b
|
||||
return false
|
||||
}
|
||||
|
||||
if info.Status == "magnet_error" || info.Status == "error" || info.Status == "virus" || info.Status == "dead" {
|
||||
// documented status: magnet_error, magnet_conversion, waiting_files_selection, queued, downloading, downloaded, error, virus, compressing, uploading, dead
|
||||
okStatuses := []string{"magnet_conversion", "waiting_files_selection", "queued", "downloading", "downloaded", "uploading"}
|
||||
// not compressing because we need playable files
|
||||
isOkStatus := false
|
||||
for _, status := range okStatuses {
|
||||
if info.Status == status {
|
||||
isOkStatus = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !isOkStatus {
|
||||
t.log.Warnf("The redownloaded torrent id=%s is in error state: %s", newTorrentID, info.Status)
|
||||
t.Api.DeleteTorrent(newTorrentID)
|
||||
return false
|
||||
@@ -302,8 +311,13 @@ func (t *TorrentManager) reinsertTorrent(torrent *Torrent, brokenFiles string) b
|
||||
|
||||
if info.Progress != 100 {
|
||||
t.log.Infof("Torrent id=%s is not cached anymore so we have to wait until completion (this should fix the issue already)", info.ID)
|
||||
for _, id := range oldTorrentIDs {
|
||||
t.Api.DeleteTorrent(id)
|
||||
t.forRepairs.Add(newTorrentID)
|
||||
if len(oldTorrentIDs) > 0 {
|
||||
for _, id := range oldTorrentIDs {
|
||||
t.Api.DeleteTorrent(id)
|
||||
}
|
||||
} else {
|
||||
t.forRepairs.Add(newTorrentID)
|
||||
}
|
||||
return true
|
||||
}
|
||||
@@ -316,8 +330,13 @@ func (t *TorrentManager) reinsertTorrent(torrent *Torrent, brokenFiles string) b
|
||||
}
|
||||
|
||||
t.log.Infof("Repair successful id=%s", newTorrentID)
|
||||
for _, id := range oldTorrentIDs {
|
||||
t.Api.DeleteTorrent(id)
|
||||
t.forRepairs.Add(newTorrentID)
|
||||
if len(oldTorrentIDs) > 0 {
|
||||
for _, id := range oldTorrentIDs {
|
||||
t.Api.DeleteTorrent(id)
|
||||
}
|
||||
} else {
|
||||
t.forRepairs.Add(newTorrentID)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ func (d *Download) UnmarshalJSON(data []byte) error {
|
||||
type Torrent struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"filename"`
|
||||
Hash string `json:"hash"`
|
||||
Progress int `json:"-"`
|
||||
Status string `json:"status"`
|
||||
Links []string `json:"links"`
|
||||
|
||||
Reference in New Issue
Block a user