You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Lidarr/src/NzbDrone.Core/Download/TrackedDownloads/DownloadMonitoringService.cs

193 lines
7.5 KiB

using System;
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.TPL;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.MediaFiles.Events;
using NzbDrone.Core.Messaging.Commands;
using NzbDrone.Core.Messaging.Events;
namespace NzbDrone.Core.Download.TrackedDownloads
{
public class DownloadMonitoringService : IExecute<CheckForFinishedDownloadCommand>,
IHandle<AlbumGrabbedEvent>,
IHandle<TrackImportedEvent>,
IHandle<TrackedDownloadsRemovedEvent>
{
private readonly IDownloadClientStatusService _downloadClientStatusService;
private readonly IDownloadClientFactory _downloadClientFactory;
private readonly IEventAggregator _eventAggregator;
private readonly IManageCommandQueue _manageCommandQueue;
private readonly IConfigService _configService;
private readonly IFailedDownloadService _failedDownloadService;
private readonly ICompletedDownloadService _completedDownloadService;
private readonly ITrackedDownloadService _trackedDownloadService;
private readonly Logger _logger;
private readonly Debouncer _refreshDebounce;
public DownloadMonitoringService(IDownloadClientStatusService downloadClientStatusService,
IDownloadClientFactory downloadClientFactory,
IEventAggregator eventAggregator,
IManageCommandQueue manageCommandQueue,
IConfigService configService,
IFailedDownloadService failedDownloadService,
ICompletedDownloadService completedDownloadService,
ITrackedDownloadService trackedDownloadService,
Logger logger)
{
_downloadClientStatusService = downloadClientStatusService;
_downloadClientFactory = downloadClientFactory;
_eventAggregator = eventAggregator;
_manageCommandQueue = manageCommandQueue;
_configService = configService;
_failedDownloadService = failedDownloadService;
_completedDownloadService = completedDownloadService;
_trackedDownloadService = trackedDownloadService;
_logger = logger;
_refreshDebounce = new Debouncer(QueueRefresh, TimeSpan.FromSeconds(5));
}
private void QueueRefresh()
{
_manageCommandQueue.Push(new CheckForFinishedDownloadCommand());
}
private void Refresh()
{
_refreshDebounce.Pause();
try
{
var downloadClients = _downloadClientFactory.DownloadHandlingEnabled();
var trackedDownloads = new List<TrackedDownload>();
foreach (var downloadClient in downloadClients)
{
var clientTrackedDownloads = ProcessClientDownloads(downloadClient);
trackedDownloads.AddRange(clientTrackedDownloads.Where(DownloadIsTrackable));
}
_trackedDownloadService.UpdateTrackable(trackedDownloads);
_eventAggregator.PublishEvent(new TrackedDownloadRefreshedEvent(trackedDownloads));
}
finally
{
_refreshDebounce.Resume();
}
}
private List<TrackedDownload> ProcessClientDownloads(IDownloadClient downloadClient)
{
List<DownloadClientItem> downloadClientHistory = new List<DownloadClientItem>();
var trackedDownloads = new List<TrackedDownload>();
try
{
downloadClientHistory = downloadClient.GetItems().ToList();
_downloadClientStatusService.RecordSuccess(downloadClient.Definition.Id);
}
catch (Exception ex)
{
_downloadClientStatusService.RecordFailure(downloadClient.Definition.Id);
_logger.Warn(ex, "Unable to retrieve queue and history items from " + downloadClient.Definition.Name);
}
foreach (var downloadItem in downloadClientHistory)
{
var newItems = ProcessClientItems(downloadClient, downloadItem);
trackedDownloads.AddRange(newItems);
}
if (_configService.EnableCompletedDownloadHandling && _configService.RemoveCompletedDownloads)
{
RemoveCompletedDownloads(trackedDownloads);
}
return trackedDownloads;
}
private void RemoveCompletedDownloads(List<TrackedDownload> trackedDownloads)
{
foreach (var trackedDownload in trackedDownloads.Where(c => c.DownloadItem.CanBeRemoved && c.State == TrackedDownloadStage.Imported))
{
_eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload));
}
}
private List<TrackedDownload> ProcessClientItems(IDownloadClient downloadClient, DownloadClientItem downloadItem)
{
var trackedDownloads = new List<TrackedDownload>();
try
{
var trackedDownload = _trackedDownloadService.TrackDownload((DownloadClientDefinition)downloadClient.Definition, downloadItem);
if (trackedDownload != null && trackedDownload.State == TrackedDownloadStage.Downloading)
{
_failedDownloadService.Process(trackedDownload);
if (_configService.EnableCompletedDownloadHandling)
{
_completedDownloadService.Process(trackedDownload);
}
}
trackedDownloads.AddIfNotNull(trackedDownload);
}
catch (Exception e)
{
_logger.Error(e, "Couldn't process tracked download {0}", downloadItem.Title);
}
return trackedDownloads;
}
private bool DownloadIsTrackable(TrackedDownload trackedDownload)
{
// If the download has already been imported or failed don't track it
Whole album matching and fingerprinting (#592) * Cache result of GetAllArtists * Fixed: Manual import not respecting album import notifications * Fixed: partial album imports stay in queue, prompting manual import * Fixed: Allow release if tracks are missing * Fixed: Be tolerant of missing/extra "The" at start of artist name * Improve manual import UI * Omit video tracks from DB entirely * Revert "faster test packaging in build.sh" This reverts commit 2723e2a7b86bcbff9051fd2aced07dd807b4bcb7. -u and -T are not supported on macOS * Fix tests on linux and macOS * Actually lint on linux On linux yarn runs scripts with sh not bash so ** doesn't recursively glob * Match whole albums * Option to disable fingerprinting * Rip out MediaInfo * Don't split up things that have the same album selected in manual import * Try to speed up IndentificationService * More speedups * Some fixes and increase power of recording id * Fix NRE when no tags * Fix NRE when some (but not all) files in a directory have missing tags * Bump taglib, tidy up tag parsing * Add a health check * Remove media info setting * Tags -> audioTags * Add some tests where tags are null * Rename history events * Add missing method to interface * Reinstate MediaInfo tags and update info with artist scan Also adds migration to remove old format media info * This file no longer exists * Don't penalise year if missing from tags * Formatting improvements * Use correct system newline * Switch to the netstandard2.0 library to support net 461 * TagLib.File is IDisposable so should be in a using * Improve filename matching and add tests * Neater logging of parsed tags * Fix disk scan tests for new media info update * Fix quality detection source * Fix Inexact Artist/Album match * Add button to clear track mapping * Fix warning * Pacify eslint * Use \ not / * Fix UI updates * Fix media covers Prevent localizing URL propaging back to the metadata object * Reduce database overhead broadcasting UI updates * Relax timings a bit to make test pass * Remove irrelevant tests * Test framework for identification service * Fix PreferMissingToBadMatch test case * Make fingerprinting more robust * More logging * Penalize unknown media format and country * Prefer USA to UK * Allow Data CD * Fix exception if fingerprinting fails for all files * Fix tests * Fix NRE * Allow apostrophes and remove accents in filename aggregation * Address codacy issues * Cope with old versions of fpcalc and suggest upgrade * fpcalc health check passes if fingerprinting disabled * Get the Artist meta with the artist * Fix the mapper so that lazy loaded lists will be populated on Join And therefore we can join TrackFiles on Tracks by default and avoid an extra query * Rename subtitle -> lyric * Tidy up MediaInfoFormatter
5 years ago
if (trackedDownload.State == TrackedDownloadStage.DownloadFailed
|| trackedDownload.State == TrackedDownloadStage.Imported)
{
return false;
}
// If CDH is disabled and the download status is complete don't track it
if (!_configService.EnableCompletedDownloadHandling && trackedDownload.DownloadItem.Status == DownloadItemStatus.Completed)
{
return false;
}
return true;
}
public void Execute(CheckForFinishedDownloadCommand message)
{
Refresh();
}
public void Handle(AlbumGrabbedEvent message)
{
_refreshDebounce.Execute();
}
public void Handle(TrackImportedEvent message)
{
_refreshDebounce.Execute();
}
public void Handle(TrackedDownloadsRemovedEvent message)
{
var trackedDownloads = _trackedDownloadService.GetTrackedDownloads().Where(t => t.IsTrackable && DownloadIsTrackable(t)).ToList();
_eventAggregator.PublishEvent(new TrackedDownloadRefreshedEvent(trackedDownloads));
}
}
}