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