diff --git a/internal/handlers/home.go b/internal/handlers/home.go
index 121c766..f3efbe6 100644
--- a/internal/handlers/home.go
+++ b/internal/handlers/home.go
@@ -206,21 +206,13 @@ func (zr *Handlers) handleHome(resp http.ResponseWriter, req *http.Request) {
Can Repair |
%t |
-
- | Repair Every... |
- %d mins |
-
| Action to take on RAR'ed torrents |
%s |
- | API Timeout |
- %d secs |
-
-
- | Download Timeout |
- %d secs |
+ Repair Every... |
+ %d mins |
| Refresh Download Mount Every... |
@@ -230,6 +222,14 @@ func (zr *Handlers) handleHome(resp http.ResponseWriter, req *http.Request) {
Dump Torrents Every... |
%d mins |
+
+ | API Timeout |
+ %d secs |
+
+
+ | Download Timeout |
+ %d secs |
+
| Rate Limit Sleep for... |
%d secs |
@@ -286,6 +286,9 @@ func (zr *Handlers) handleHome(resp http.ResponseWriter, req *http.Request) {
+
@@ -331,12 +334,12 @@ func (zr *Handlers) handleHome(resp http.ResponseWriter, req *http.Request) {
response.Config.EnableRetainRDTorrentName(),
response.Config.EnableRetainFolderNameExtension(),
response.Config.EnableRepair(),
- response.Config.GetRepairEveryMins(),
response.Config.GetRarAction(),
- response.Config.GetApiTimeoutSecs(),
- response.Config.GetDownloadTimeoutSecs(),
+ response.Config.GetRepairEveryMins(),
response.Config.GetDownloadsEveryMins(),
response.Config.GetDumpTorrentsEveryMins(),
+ response.Config.GetApiTimeoutSecs(),
+ response.Config.GetDownloadTimeoutSecs(),
response.Config.GetRateLimitSleepSecs(),
response.Config.GetRetriesUntilFailed(),
response.Config.GetNetworkBufferSize(),
@@ -360,7 +363,7 @@ func (zr *Handlers) handleRebootWorkerPool(resp http.ResponseWriter, req *http.R
func (zr *Handlers) handleRebootRefreshWorker(resp http.ResponseWriter, req *http.Request) {
resp.Header().Set("Refresh", "2; url=/")
- zr.torMgr.RefreshKillSwitch <- struct{}{}
+ zr.torMgr.RefreshWorkerKillSwitch <- struct{}{}
zr.torMgr.StartRefreshJob()
zr.log.Infof("Rebooted refresh worker")
fmt.Fprint(resp, "Rebooting refresh worker...")
@@ -368,7 +371,7 @@ func (zr *Handlers) handleRebootRefreshWorker(resp http.ResponseWriter, req *htt
func (zr *Handlers) handleRebootRepairWorker(resp http.ResponseWriter, req *http.Request) {
resp.Header().Set("Refresh", "2; url=/")
- zr.torMgr.RepairKillSwitch <- struct{}{}
+ zr.torMgr.RepairWorkerKillSwitch <- struct{}{}
zr.torMgr.StartRepairJob()
zr.log.Infof("Rebooted repair worker")
fmt.Fprint(resp, "Rebooting repair worker...")
@@ -395,6 +398,13 @@ func (zr *Handlers) handleAnalyzeTorrents(resp http.ResponseWriter, req *http.Re
fmt.Fprint(resp, "Analyzing all torrents...")
}
+func (zr *Handlers) handleTriggerRepairAll(resp http.ResponseWriter, req *http.Request) {
+ resp.Header().Set("Refresh", "2; url=/")
+ zr.torMgr.RepairAllTrigger <- struct{}{}
+ zr.log.Infof("Triggered repair of all torrents")
+ fmt.Fprint(resp, "Repairing all torrents...")
+}
+
func bToMb(b uint64) uint64 {
return b / 1024 / 1024
}
diff --git a/internal/handlers/router.go b/internal/handlers/router.go
index 35de821..0cc70be 100644
--- a/internal/handlers/router.go
+++ b/internal/handlers/router.go
@@ -56,6 +56,7 @@ func AttachHandlers(router *chi.Mux, downloader *universal.Downloader, torMgr *t
router.Post("/downloads/remount", hs.handleRemountDownloads)
router.Post("/torrents/dump", hs.handleDumpTorrents)
router.Post("/torrents/analyze", hs.handleAnalyzeTorrents)
+ router.Post("/torrents/repair", hs.handleTriggerRepairAll)
// version
router.Get(fmt.Sprintf("/{mountType}/%s", version.FILE), hs.handleVersionFile)
router.Head(fmt.Sprintf("/{mountType}/%s", version.FILE), hs.handleCheckVersionFile)
diff --git a/internal/torrent/bins.go b/internal/torrent/bins.go
index bcf6381..da5774f 100644
--- a/internal/torrent/bins.go
+++ b/internal/torrent/bins.go
@@ -134,7 +134,7 @@ func (t *TorrentManager) binOnceDoneErrorCheck(torrentId, status string) bool {
if status == "downloading" || status == "downloaded" || status == "uploading" || status == "queued" || status == "compressing" || status == "waiting_files_selection" {
return false
}
- t.repairLog.Errorf("Bin: error status=%s, checking if %s should be deleted", status, torrentId)
+ t.repairLog.Infof("Bin: error status=%s, checking if %s should be deleted", status, torrentId)
return t.binOnceDone(torrentId, true)
}
diff --git a/internal/torrent/manager.go b/internal/torrent/manager.go
index 50d7876..1b3dcf5 100644
--- a/internal/torrent/manager.go
+++ b/internal/torrent/manager.go
@@ -39,11 +39,12 @@ type TorrentManager struct {
RootNode *fs.FileNode
- RefreshKillSwitch chan struct{}
- RepairKillSwitch chan struct{}
- RemountTrigger chan struct{}
- DumpTrigger chan struct{}
- AnalyzeTrigger chan struct{}
+ RefreshWorkerKillSwitch chan struct{}
+ RepairWorkerKillSwitch chan struct{}
+ RemountTrigger chan struct{}
+ RepairAllTrigger chan struct{}
+ DumpTrigger chan struct{}
+ AnalyzeTrigger chan struct{}
latestState *LibraryState
inProgressHashes mapset.Set[string]
@@ -76,11 +77,12 @@ func NewTorrentManager(cfg config.ConfigInterface, api *realdebrid.RealDebrid, w
RootNode: fs.NewFileNode("root", true),
- RefreshKillSwitch: make(chan struct{}, 1),
- RepairKillSwitch: make(chan struct{}, 1),
- RemountTrigger: make(chan struct{}, 1),
- DumpTrigger: make(chan struct{}, 1),
- AnalyzeTrigger: make(chan struct{}, 1),
+ RefreshWorkerKillSwitch: make(chan struct{}, 1),
+ RepairWorkerKillSwitch: make(chan struct{}, 1),
+ RemountTrigger: make(chan struct{}, 1),
+ // RepairAllTrigger: make(chan struct{}, 1), // initialized in repair.go
+ DumpTrigger: make(chan struct{}, 1),
+ AnalyzeTrigger: make(chan struct{}, 1),
latestState: &LibraryState{log: log},
}
diff --git a/internal/torrent/refresh.go b/internal/torrent/refresh.go
index bb73169..ba15973 100644
--- a/internal/torrent/refresh.go
+++ b/internal/torrent/refresh.go
@@ -152,7 +152,7 @@ func (t *TorrentManager) StartRefreshJob() {
t.refreshTorrents(false)
t.log.Info("Finished refreshing torrents")
- case <-t.RefreshKillSwitch:
+ case <-t.RefreshWorkerKillSwitch:
t.log.Info("Stopping periodic refresh job")
return
}
diff --git a/internal/torrent/repair.go b/internal/torrent/repair.go
index 46491b9..393cbd8 100644
--- a/internal/torrent/repair.go
+++ b/internal/torrent/repair.go
@@ -26,6 +26,7 @@ func (t *TorrentManager) StartRepairJob() {
}
t.repairTrigger = make(chan *Torrent)
t.repairQueue = mapset.NewSet[*Torrent]()
+ t.RepairAllTrigger = make(chan struct{})
// there is 1 repair worker, with max 1 blocking task
t.workerPool.Submit(func() {
t.repairLog.Debug("Starting periodic repair job")
@@ -36,10 +37,12 @@ func (t *TorrentManager) StartRepairJob() {
select {
case <-repairTicker.C:
t.invokeRepair(nil)
+ case <-t.RepairAllTrigger:
+ t.invokeRepair(nil)
case torrent := <-t.repairTrigger:
// On-demand trigger with a specific torrent
t.invokeRepair(torrent)
- case <-t.RepairKillSwitch:
+ case <-t.RepairWorkerKillSwitch:
t.repairLog.Info("Stopping periodic repair job")
return
}
@@ -76,15 +79,19 @@ func (t *TorrentManager) invokeRepair(torrent *Torrent) {
// TriggerRepair allows an on-demand repair to be initiated.
func (t *TorrentManager) TriggerRepair(torrent *Torrent) {
+ if !t.Config.EnableRepair() {
+ if torrent != nil {
+ t.repairLog.Warnf("Repair is disabled, skipping repair for torrent %s", t.GetKey(torrent))
+ } else {
+ t.repairLog.Warn("Repair is disabled, skipping repair")
+ }
+ return
+ }
if torrent != nil {
if err := torrent.State.Event(context.Background(), "break_torrent"); err != nil {
// t.repairLog.Errorf("Failed to mark torrent %s as broken: %v", t.GetKey(torrent), err)
return
}
- if !t.Config.EnableRepair() {
- t.repairLog.Warnf("Repair is disabled, skipping repair for torrent %s", t.GetKey(torrent))
- return
- }
}
t.repairTrigger <- torrent
}