- Imporve memeoery footprint
- Add batch processing for arr repairs
This commit is contained in:
@@ -234,6 +234,35 @@ func (a *Arr) searchRadarr(files []ContentFile) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *Arr) SearchMissing(files []ContentFile) error {
|
func (a *Arr) SearchMissing(files []ContentFile) error {
|
||||||
|
if len(files) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return a.batchSearchMissing(files)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Arr) batchSearchMissing(files []ContentFile) error {
|
||||||
|
if len(files) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
BatchSize := 50
|
||||||
|
// Batch search for missing files
|
||||||
|
if len(files) > BatchSize {
|
||||||
|
for i := 0; i < len(files); i += BatchSize {
|
||||||
|
end := i + BatchSize
|
||||||
|
if end > len(files) {
|
||||||
|
end = len(files)
|
||||||
|
}
|
||||||
|
if err := a.searchMissing(files[i:end]); err != nil {
|
||||||
|
// continue searching the rest of the files
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return a.searchMissing(files)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Arr) searchMissing(files []ContentFile) error {
|
||||||
switch a.Type {
|
switch a.Type {
|
||||||
case Sonarr:
|
case Sonarr:
|
||||||
return a.searchSonarr(files)
|
return a.searchSonarr(files)
|
||||||
@@ -245,6 +274,28 @@ func (a *Arr) SearchMissing(files []ContentFile) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *Arr) DeleteFiles(files []ContentFile) error {
|
func (a *Arr) DeleteFiles(files []ContentFile) error {
|
||||||
|
if len(files) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
BatchSize := 50
|
||||||
|
// Batch delete files
|
||||||
|
if len(files) > BatchSize {
|
||||||
|
for i := 0; i < len(files); i += BatchSize {
|
||||||
|
end := i + BatchSize
|
||||||
|
if end > len(files) {
|
||||||
|
end = len(files)
|
||||||
|
}
|
||||||
|
if err := a.batchDeleteFiles(files[i:end]); err != nil {
|
||||||
|
// continue deleting the rest of the files
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return a.batchDeleteFiles(files)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Arr) batchDeleteFiles(files []ContentFile) error {
|
||||||
ids := make([]int, 0)
|
ids := make([]int, 0)
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
ids = append(ids, f.FileId)
|
ids = append(ids, f.FileId)
|
||||||
|
|||||||
@@ -534,7 +534,7 @@ func (c *Cache) setTorrent(t CachedTorrent, callback func(torrent CachedTorrent)
|
|||||||
mergedFiles := mergeFiles(o, updatedTorrent) // Useful for merging files across multiple torrents, while keeping the most recent
|
mergedFiles := mergeFiles(o, updatedTorrent) // Useful for merging files across multiple torrents, while keeping the most recent
|
||||||
updatedTorrent.Files = mergedFiles
|
updatedTorrent.Files = mergedFiles
|
||||||
}
|
}
|
||||||
c.torrents.set(torrentName, t, updatedTorrent)
|
c.torrents.set(torrentName, t)
|
||||||
go c.SaveTorrent(t)
|
go c.SaveTorrent(t)
|
||||||
if callback != nil {
|
if callback != nil {
|
||||||
go callback(updatedTorrent)
|
go callback(updatedTorrent)
|
||||||
@@ -550,7 +550,7 @@ func (c *Cache) setTorrents(torrents map[string]CachedTorrent, callback func())
|
|||||||
mergedFiles := mergeFiles(o, updatedTorrent)
|
mergedFiles := mergeFiles(o, updatedTorrent)
|
||||||
updatedTorrent.Files = mergedFiles
|
updatedTorrent.Files = mergedFiles
|
||||||
}
|
}
|
||||||
c.torrents.set(torrentName, t, updatedTorrent)
|
c.torrents.set(torrentName, t)
|
||||||
}
|
}
|
||||||
c.SaveTorrents()
|
c.SaveTorrents()
|
||||||
if callback != nil {
|
if callback != nil {
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ type directoryFilter struct {
|
|||||||
|
|
||||||
type torrents struct {
|
type torrents struct {
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
byID map[string]CachedTorrent
|
storage map[string]CachedTorrent // id to CachedTorrent
|
||||||
byName map[string]CachedTorrent
|
byName map[string]string // name to id
|
||||||
}
|
}
|
||||||
|
|
||||||
type folders struct {
|
type folders struct {
|
||||||
@@ -72,8 +72,8 @@ func newTorrentCache(dirFilters map[string][]directoryFilter) *torrentCache {
|
|||||||
|
|
||||||
tc := &torrentCache{
|
tc := &torrentCache{
|
||||||
torrents: torrents{
|
torrents: torrents{
|
||||||
byID: make(map[string]CachedTorrent),
|
storage: make(map[string]CachedTorrent), // id to CachedTorrent
|
||||||
byName: make(map[string]CachedTorrent),
|
byName: make(map[string]string),
|
||||||
},
|
},
|
||||||
folders: folders{
|
folders: folders{
|
||||||
listing: make(map[string][]os.FileInfo),
|
listing: make(map[string][]os.FileInfo),
|
||||||
@@ -88,8 +88,8 @@ func newTorrentCache(dirFilters map[string][]directoryFilter) *torrentCache {
|
|||||||
|
|
||||||
func (tc *torrentCache) reset() {
|
func (tc *torrentCache) reset() {
|
||||||
tc.torrents.Lock()
|
tc.torrents.Lock()
|
||||||
tc.torrents.byID = make(map[string]CachedTorrent)
|
tc.torrents.byName = make(map[string]string)
|
||||||
tc.torrents.byName = make(map[string]CachedTorrent)
|
tc.torrents.storage = make(map[string]CachedTorrent) // Reset the storage map
|
||||||
tc.torrents.Unlock()
|
tc.torrents.Unlock()
|
||||||
|
|
||||||
// reset the sorted listing
|
// reset the sorted listing
|
||||||
@@ -105,23 +105,27 @@ func (tc *torrentCache) reset() {
|
|||||||
func (tc *torrentCache) getByID(id string) (CachedTorrent, bool) {
|
func (tc *torrentCache) getByID(id string) (CachedTorrent, bool) {
|
||||||
tc.torrents.RLock()
|
tc.torrents.RLock()
|
||||||
defer tc.torrents.RUnlock()
|
defer tc.torrents.RUnlock()
|
||||||
torrent, exists := tc.torrents.byID[id]
|
torrent, exists := tc.torrents.storage[id]
|
||||||
return torrent, exists
|
return torrent, exists
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tc *torrentCache) getByName(name string) (CachedTorrent, bool) {
|
func (tc *torrentCache) getByName(name string) (CachedTorrent, bool) {
|
||||||
tc.torrents.RLock()
|
tc.torrents.RLock()
|
||||||
defer tc.torrents.RUnlock()
|
defer tc.torrents.RUnlock()
|
||||||
torrent, exists := tc.torrents.byName[name]
|
torrentID, exists := tc.torrents.byName[name]
|
||||||
|
if !exists {
|
||||||
|
return CachedTorrent{}, false
|
||||||
|
}
|
||||||
|
torrent, exists := tc.torrents.storage[torrentID]
|
||||||
return torrent, exists
|
return torrent, exists
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tc *torrentCache) set(name string, torrent, newTorrent CachedTorrent) {
|
func (tc *torrentCache) set(name string, torrent CachedTorrent) {
|
||||||
tc.torrents.Lock()
|
tc.torrents.Lock()
|
||||||
// Set the id first
|
// Set the id first
|
||||||
|
|
||||||
tc.torrents.byName[name] = torrent
|
tc.torrents.byName[name] = torrent.Id
|
||||||
tc.torrents.byID[torrent.Id] = torrent // This is the unadulterated torrent
|
tc.torrents.storage[torrent.Id] = torrent
|
||||||
tc.torrents.Unlock()
|
tc.torrents.Unlock()
|
||||||
tc.sortNeeded.Store(true)
|
tc.sortNeeded.Store(true)
|
||||||
}
|
}
|
||||||
@@ -154,7 +158,11 @@ func (tc *torrentCache) refreshListing() {
|
|||||||
|
|
||||||
tc.torrents.RLock()
|
tc.torrents.RLock()
|
||||||
all := make([]sortableFile, 0, len(tc.torrents.byName))
|
all := make([]sortableFile, 0, len(tc.torrents.byName))
|
||||||
for name, t := range tc.torrents.byName {
|
for name, torrentID := range tc.torrents.byName {
|
||||||
|
t, exists := tc.torrents.storage[torrentID]
|
||||||
|
if !exists {
|
||||||
|
continue // Skip if torrent not found
|
||||||
|
}
|
||||||
all = append(all, sortableFile{t.Id, name, t.AddedOn, t.Bytes, t.Bad})
|
all = append(all, sortableFile{t.Id, name, t.AddedOn, t.Bytes, t.Bad})
|
||||||
}
|
}
|
||||||
tc.sortNeeded.Store(false)
|
tc.sortNeeded.Store(false)
|
||||||
@@ -280,9 +288,9 @@ func (tc *torrentCache) torrentMatchDirectory(filters []directoryFilter, file so
|
|||||||
func (tc *torrentCache) getAll() map[string]CachedTorrent {
|
func (tc *torrentCache) getAll() map[string]CachedTorrent {
|
||||||
tc.torrents.RLock()
|
tc.torrents.RLock()
|
||||||
defer tc.torrents.RUnlock()
|
defer tc.torrents.RUnlock()
|
||||||
result := make(map[string]CachedTorrent, len(tc.torrents.byID))
|
result := make(map[string]CachedTorrent, len(tc.torrents.storage))
|
||||||
for name, torrent := range tc.torrents.byID {
|
for torrentID, torrent := range tc.torrents.storage {
|
||||||
result[name] = torrent
|
result[torrentID] = torrent
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@@ -290,14 +298,18 @@ func (tc *torrentCache) getAll() map[string]CachedTorrent {
|
|||||||
func (tc *torrentCache) getAllCount() int {
|
func (tc *torrentCache) getAllCount() int {
|
||||||
tc.torrents.RLock()
|
tc.torrents.RLock()
|
||||||
defer tc.torrents.RUnlock()
|
defer tc.torrents.RUnlock()
|
||||||
return len(tc.torrents.byID)
|
return len(tc.torrents.storage)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tc *torrentCache) getAllByName() map[string]CachedTorrent {
|
func (tc *torrentCache) getAllByName() map[string]CachedTorrent {
|
||||||
tc.torrents.RLock()
|
tc.torrents.RLock()
|
||||||
defer tc.torrents.RUnlock()
|
defer tc.torrents.RUnlock()
|
||||||
results := make(map[string]CachedTorrent, len(tc.torrents.byName))
|
results := make(map[string]CachedTorrent, len(tc.torrents.byName))
|
||||||
for name, torrent := range tc.torrents.byName {
|
for name, torrentID := range tc.torrents.byName {
|
||||||
|
torrent, exists := tc.torrents.storage[torrentID]
|
||||||
|
if !exists {
|
||||||
|
continue // Skip if torrent not found
|
||||||
|
}
|
||||||
results[name] = torrent
|
results[name] = torrent
|
||||||
}
|
}
|
||||||
return results
|
return results
|
||||||
@@ -306,8 +318,8 @@ func (tc *torrentCache) getAllByName() map[string]CachedTorrent {
|
|||||||
func (tc *torrentCache) getIdMaps() map[string]struct{} {
|
func (tc *torrentCache) getIdMaps() map[string]struct{} {
|
||||||
tc.torrents.RLock()
|
tc.torrents.RLock()
|
||||||
defer tc.torrents.RUnlock()
|
defer tc.torrents.RUnlock()
|
||||||
res := make(map[string]struct{}, len(tc.torrents.byID))
|
res := make(map[string]struct{}, len(tc.torrents.storage))
|
||||||
for id := range tc.torrents.byID {
|
for id := range tc.torrents.storage {
|
||||||
res[id] = struct{}{}
|
res[id] = struct{}{}
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
@@ -316,7 +328,7 @@ func (tc *torrentCache) getIdMaps() map[string]struct{} {
|
|||||||
func (tc *torrentCache) removeId(id string) {
|
func (tc *torrentCache) removeId(id string) {
|
||||||
tc.torrents.Lock()
|
tc.torrents.Lock()
|
||||||
defer tc.torrents.Unlock()
|
defer tc.torrents.Unlock()
|
||||||
delete(tc.torrents.byID, id)
|
delete(tc.torrents.storage, id)
|
||||||
tc.sortNeeded.Store(true)
|
tc.sortNeeded.Store(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user