periodic repair

This commit is contained in:
Ben Sarmiento
2024-01-27 14:14:11 +01:00
parent 05d2544fe8
commit a851282b2a
7 changed files with 97 additions and 19 deletions

View File

@@ -4,6 +4,7 @@ import (
"io"
"os"
"strings"
"sync"
"github.com/debridmediamanager/zurg/internal/config"
"github.com/debridmediamanager/zurg/pkg/logutil"
@@ -32,6 +33,9 @@ type TorrentManager struct {
requiredVersion string
workerPool *ants.Pool
repairPool *ants.Pool
repairTrigger chan *Torrent
repairRunning bool
repairRunningMu sync.Mutex
log *logutil.Logger
}

View File

@@ -46,7 +46,7 @@ func (t *TorrentManager) refreshTorrents() []string {
wg.Wait()
close(infoChan)
t.log.Debugf("Fetched info for %d torrents", len(instances))
t.log.Infof("Fetched info for %d torrents", len(instances))
// delete expired fixers
doesNotExist.Each(func(fixerID string) bool {
@@ -122,7 +122,7 @@ func (t *TorrentManager) refreshTorrents() []string {
// startRefreshJob periodically refreshes the torrents
func (t *TorrentManager) startRefreshJob() {
_ = t.workerPool.Submit(func() {
t.log.Info("Starting periodic refresh")
t.log.Info("Starting periodic refresh job")
for {
<-time.After(time.Duration(t.Config.GetRefreshEverySeconds()) * time.Second)

View File

@@ -18,17 +18,68 @@ const (
func (t *TorrentManager) startRepairJob() {
if !t.Config.EnableRepair() {
t.log.Info("Repair is disabled, skipping repair job")
t.log.Debug("Repair is disabled, skipping repair job")
return
}
t.repairTrigger = make(chan *Torrent)
// there is 1 repair worker, with max 1 blocking task
_ = t.repairPool.Submit(func() {
t.repairAll()
t.log.Info("Starting periodic repair job")
repairTicker := time.NewTicker(time.Duration(t.Config.GetRepairEveryMinutes()) * time.Minute)
defer repairTicker.Stop()
for {
select {
case <-repairTicker.C:
t.invokeRepair(nil)
case torrent := <-t.repairTrigger:
// On-demand trigger with a specific torrent
t.invokeRepair(torrent)
}
}
})
}
func (t *TorrentManager) repairAll() {
func (t *TorrentManager) invokeRepair(torrent *Torrent) {
t.repairRunningMu.Lock()
if t.repairRunning {
t.repairRunningMu.Unlock()
// don't do anything if repair is already running
return
}
t.repairRunning = true
t.repairRunningMu.Unlock()
// Execute the repair job
t.repairAll(torrent)
// After repair is done
t.repairRunningMu.Lock()
t.repairRunning = false
t.repairRunningMu.Unlock()
}
// TriggerRepair allows an on-demand repair to be initiated.
func (t *TorrentManager) TriggerRepair(torrent *Torrent) {
select {
case t.repairTrigger <- torrent:
// Repair triggered
default:
// Already a repair request pending, so do nothing
}
}
func (t *TorrentManager) repairAll(torrent *Torrent) {
t.log.Info("Periodic repair invoked; searching for broken torrents")
allTorrents, _ := t.DirectoryMap.Get(INT_ALL)
// todo: a more elegant way to do this
var allTorrents cmap.ConcurrentMap[string, *Torrent]
if torrent == nil {
allTorrents, _ = t.DirectoryMap.Get(INT_ALL)
} else {
allTorrents = cmap.New[*Torrent]()
allTorrents.Set(t.GetKey(torrent), torrent)
}
// collect all torrents that need to be repaired
toRepair := mapset.NewSet[*Torrent]()