Updste repair

This commit is contained in:
Mukhtar Akere
2025-06-18 12:44:05 +01:00
parent b2e99585f7
commit c15e9d8f70
5 changed files with 64 additions and 27 deletions

View File

@@ -919,6 +919,7 @@ func (r *RealDebrid) GetProfile() (*types.Profile, error) {
Expiration: data.Expiration,
Type: data.Type,
}
r.Profile = profile
return profile, nil
}

View File

@@ -570,6 +570,10 @@ func (c *Cache) GetTorrentByName(name string) *CachedTorrent {
return nil
}
func (c *Cache) GetTorrentsName() map[string]CachedTorrent {
return c.torrents.getAllByName()
}
func (c *Cache) GetTorrent(torrentId string) *CachedTorrent {
if torrent, ok := c.torrents.getByID(torrentId); ok {
return &torrent

View File

@@ -293,6 +293,16 @@ func (tc *torrentCache) getAllCount() int {
return len(tc.torrents.byID)
}
func (tc *torrentCache) getAllByName() map[string]CachedTorrent {
tc.torrents.RLock()
defer tc.torrents.RUnlock()
results := make(map[string]CachedTorrent, len(tc.torrents.byName))
for name, torrent := range tc.torrents.byName {
results[name] = torrent
}
return results
}
func (tc *torrentCache) getIdMaps() map[string]struct{} {
tc.torrents.RLock()
defer tc.torrents.RUnlock()

View File

@@ -103,11 +103,17 @@ func (r *Repair) checkTorrentFiles(torrentPath string, files []arr.ContentFile,
r.logger.Debug().Msgf("No cache found for %s. Skipping", debridName)
return files // Return all files as broken if no cache found
}
tor, ok := r.torrentsMap.Load(debridName)
if !ok {
r.logger.Debug().Msgf("Could not find torrents for %s. Skipping", debridName)
}
torrentsMap := tor.(map[string]store.CachedTorrent)
// Check if torrent exists
torrentName := filepath.Clean(filepath.Base(torrentPath))
torrent := cache.GetTorrentByName(torrentName)
if torrent == nil {
torrent, ok := torrentsMap[torrentName]
if !ok {
r.logger.Debug().Msgf("No torrent found for %s. Skipping", torrentName)
return files // Return all files as broken if torrent not found
}
@@ -118,7 +124,7 @@ func (r *Repair) checkTorrentFiles(torrentPath string, files []arr.ContentFile,
filePaths[i] = file.TargetPath
}
brokenFilePaths := cache.GetBrokenFiles(torrent, filePaths)
brokenFilePaths := cache.GetBrokenFiles(&torrent, filePaths)
if len(brokenFilePaths) > 0 {
r.logger.Debug().Msgf("%d broken files found in %s", len(brokenFilePaths), torrentName)
@@ -141,15 +147,9 @@ func (r *Repair) checkTorrentFiles(torrentPath string, files []arr.ContentFile,
func (r *Repair) findDebridForPath(dir string, clients map[string]types.Client) string {
// Check cache first
r.cacheMutex.RLock()
if r.debridPathCache == nil {
r.debridPathCache = make(map[string]string)
if debridName, exists := r.debridPathCache.Load(dir); exists {
return debridName.(string)
}
if debridName, exists := r.debridPathCache[dir]; exists {
r.cacheMutex.RUnlock()
return debridName
}
r.cacheMutex.RUnlock()
// Find debrid client
for _, client := range clients {
@@ -162,18 +162,14 @@ func (r *Repair) findDebridForPath(dir string, clients map[string]types.Client)
debridName := client.Name()
// Cache the result
r.cacheMutex.Lock()
r.debridPathCache[dir] = debridName
r.cacheMutex.Unlock()
r.debridPathCache.Store(dir, debridName)
return debridName
}
}
// Cache empty result to avoid repeated lookups
r.cacheMutex.Lock()
r.debridPathCache[dir] = ""
r.cacheMutex.Unlock()
r.debridPathCache.Store(dir, "")
return ""
}

View File

@@ -41,8 +41,8 @@ type Repair struct {
workers int
scheduler gocron.Scheduler
debridPathCache map[string]string // Cache for path -> debrid name mapping
cacheMutex sync.RWMutex
debridPathCache sync.Map // debridPath:debridName cache.Emptied after each run
torrentsMap sync.Map //debridName: map[string]*store.CacheTorrent. Emptied after each run
ctx context.Context
}
@@ -214,6 +214,27 @@ func (r *Repair) newJob(arrsNames []string, mediaIDs []string) *Job {
}
}
// initRun initializes the repair run, setting up necessary configurations, checks and caches
func (r *Repair) initRun(ctx context.Context) {
if r.useWebdav {
// Webdav use is enabled, initialize debrid torrent caches
caches := r.deb.Caches()
if len(caches) == 0 {
return
}
for name, cache := range caches {
r.torrentsMap.Store(name, cache.GetTorrentsName())
}
}
}
// // onComplete is called when the repair job is completed
func (r *Repair) onComplete() {
// Set the cache maps to nil
r.torrentsMap = sync.Map{} // Clear the torrent map
r.debridPathCache = sync.Map{}
}
func (r *Repair) preRunChecks() error {
if r.useWebdav {
@@ -271,6 +292,7 @@ func (r *Repair) AddJob(arrsNames []string, mediaIDs []string, autoProcess, recu
job.CompletedAt = time.Now()
}
}
r.onComplete() // Clear caches and maps after job completion
}()
return nil
}
@@ -313,6 +335,9 @@ func (r *Repair) repair(job *Job) error {
return err
}
// Initialize the run
r.initRun(job.ctx)
// Use a mutex to protect concurrent access to brokenItems
var mu sync.Mutex
brokenItems := map[string][]arr.ContentFile{}
@@ -475,16 +500,17 @@ func (r *Repair) repairArr(job *Job, _arr string, tmdbId string) ([]arr.ContentF
}()
}
for _, m := range media {
select {
case <-job.ctx.Done():
break
default:
workerChan <- m
go func() {
defer close(workerChan)
for _, m := range media {
select {
case <-job.ctx.Done():
return
case workerChan <- m:
}
}
}
}()
close(workerChan)
wg.Wait()
if len(brokenItems) == 0 {
r.logger.Info().Msgf("No broken items found for %s", a.Name)