mirror of
https://github.com/Radarr/Radarr.git
synced 2024-09-11 03:52:33 +02:00
moved cleanup of deleted files to their own service.
detaching of episodes when files are deleted is done through events now.
This commit is contained in:
parent
40a959a309
commit
9a8414edde
@ -13,7 +13,7 @@
|
||||
namespace NzbDrone.Core.Test.IndexerSearchTests
|
||||
{
|
||||
public abstract class IndexerSearchTestBase<TSearch> : CoreTest<TSearch>
|
||||
where TSearch : SearchBase
|
||||
where TSearch : IndexerSearchBase
|
||||
{
|
||||
protected Series _series;
|
||||
protected Episode _episode;
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
namespace NzbDrone.Core.Test.IndexerSearchTests
|
||||
{
|
||||
public class TestSearch : SearchBase
|
||||
public class TestSearch : IndexerSearchBase
|
||||
{
|
||||
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
|
64
NzbDrone.Core.Test/MediaFileTests/GhostFileCleanupFixture.cs
Normal file
64
NzbDrone.Core.Test/MediaFileTests/GhostFileCleanupFixture.cs
Normal file
@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FizzWare.NBuilder;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv;
|
||||
using System.Linq;
|
||||
|
||||
namespace NzbDrone.Core.Test.MediaFileTests
|
||||
{
|
||||
public class GhostFileCleanupFixture : CoreTest<GhostFileCleanupService>
|
||||
{
|
||||
|
||||
private void GiveEpisodeFiles(IEnumerable<EpisodeFile> episodeFiles)
|
||||
{
|
||||
Mocker.GetMock<IMediaFileService>()
|
||||
.Setup(c => c.GetFilesBySeries(It.IsAny<int>()))
|
||||
.Returns(episodeFiles.ToList());
|
||||
}
|
||||
|
||||
|
||||
private const string DeletedPath = "ANY FILE WITH THIS PATH IS CONSIDERED DELETED!";
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
Mocker.GetMock<DiskProvider>()
|
||||
.Setup(e => e.FileExists(It.Is<String>(c => c != DeletedPath)))
|
||||
.Returns(true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_skip_files_that_exist_in_disk()
|
||||
{
|
||||
var episodeFiles = Builder<EpisodeFile>.CreateListOfSize(10)
|
||||
.Build();
|
||||
|
||||
GiveEpisodeFiles(episodeFiles);
|
||||
|
||||
Subject.RemoveNonExistingFiles(0);
|
||||
|
||||
Mocker.GetMock<IEpisodeService>().Verify(c => c.UpdateEpisode(It.IsAny<Episode>()), Times.Never());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_delete_none_existing_files()
|
||||
{
|
||||
var episodeFiles = Builder<EpisodeFile>.CreateListOfSize(10)
|
||||
.Random(2)
|
||||
.With(c => c.Path = DeletedPath)
|
||||
.Build();
|
||||
|
||||
GiveEpisodeFiles(episodeFiles);
|
||||
|
||||
Subject.RemoveNonExistingFiles(0);
|
||||
|
||||
Mocker.GetMock<IMediaFileService>().Verify(c => c.Delete(It.Is<EpisodeFile>(e => e.Path == DeletedPath)), Times.Exactly(2));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -151,6 +151,7 @@
|
||||
<Compile Include="JobTests\RenameSeasonJobFixture.cs" />
|
||||
<Compile Include="DecisionEngineTests\LanguageSpecificationFixture.cs" />
|
||||
<Compile Include="MediaCoverTests\MediaCoverServiceFixture.cs" />
|
||||
<Compile Include="MediaFileTests\GhostFileCleanupFixture.cs" />
|
||||
<Compile Include="MediaFileTests\MediaFileRepositoryFixture.cs" />
|
||||
<Compile Include="ProviderTests\DownloadClientTests\NzbgetProviderTests\DownloadNzbFixture.cs" />
|
||||
<Compile Include="ProviderTests\DownloadClientTests\NzbgetProviderTests\QueueFixture.cs" />
|
||||
@ -172,7 +173,6 @@
|
||||
<Compile Include="Configuration\ConfigCachingFixture.cs" />
|
||||
<Compile Include="DecisionEngineTests\AllowedReleaseGroupSpecificationFixture.cs" />
|
||||
<Compile Include="DecisionEngineTests\CustomStartDateSpecificationFixture.cs" />
|
||||
<Compile Include="ProviderTests\DiskScanProviderTests\CleanUpFixture.cs" />
|
||||
<Compile Include="ProviderTests\DiskScanProviderTests\CleanUpDropFolderFixture.cs" />
|
||||
<Compile Include="ProviderTests\DiskScanProviderTests\GetVideoFilesFixture.cs" />
|
||||
<Compile Include="ProviderTests\DiskScanProviderTests\ScanFixture.cs" />
|
||||
|
@ -1,117 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Model;
|
||||
using NzbDrone.Core.Providers;
|
||||
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Test.Common;
|
||||
using NzbDrone.Test.Common.AutoMoq;
|
||||
|
||||
namespace NzbDrone.Core.Test.ProviderTests.DiskScanProviderTests
|
||||
{
|
||||
// ReSharper disable InconsistentNaming
|
||||
public class CleanUpFixture : CoreTest
|
||||
{
|
||||
[Test]
|
||||
public void should_skip_existing_files()
|
||||
{
|
||||
var episodes = Builder<EpisodeFile>.CreateListOfSize(10).Build();
|
||||
|
||||
Mocker.GetMock<DiskProvider>()
|
||||
.Setup(e => e.FileExists(It.IsAny<String>()))
|
||||
.Returns(true);
|
||||
|
||||
|
||||
//Act
|
||||
Mocker.Resolve<DiskScanProvider>().CleanUp(episodes);
|
||||
|
||||
//Assert
|
||||
Mocker.VerifyAllMocks();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_delete_none_existing_files()
|
||||
{
|
||||
var episodes = Builder<EpisodeFile>.CreateListOfSize(10).Build();
|
||||
|
||||
Mocker.GetMock<DiskProvider>()
|
||||
.Setup(e => e.FileExists(It.IsAny<String>()))
|
||||
.Returns(false);
|
||||
|
||||
Mocker.GetMock<IEpisodeService>()
|
||||
.Setup(e => e.GetEpisodesByFileId(It.IsAny<int>()))
|
||||
.Returns(new List<Episode>());
|
||||
|
||||
Mocker.GetMock<IMediaFileService>()
|
||||
.Setup(e => e.Delete(It.IsAny<int>()));
|
||||
|
||||
|
||||
//Act
|
||||
Mocker.Resolve<DiskScanProvider>().CleanUp(episodes);
|
||||
|
||||
//Assert
|
||||
Mocker.VerifyAllMocks();
|
||||
|
||||
Mocker.GetMock<IEpisodeService>()
|
||||
.Verify(e => e.GetEpisodesByFileId(It.IsAny<int>()), Times.Exactly(10));
|
||||
|
||||
Mocker.GetMock<IMediaFileService>()
|
||||
.Verify(e => e.Delete(It.IsAny<int>()), Times.Exactly(10));
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_delete_none_existing_files_remove_links_to_episodes()
|
||||
{
|
||||
var episodes = Builder<EpisodeFile>.CreateListOfSize(10).Build();
|
||||
|
||||
Mocker.GetMock<DiskProvider>()
|
||||
.Setup(e => e.FileExists(It.IsAny<String>()))
|
||||
.Returns(false);
|
||||
|
||||
Mocker.GetMock<IEpisodeService>()
|
||||
.Setup(e => e.GetEpisodesByFileId(It.IsAny<int>()))
|
||||
.Returns(new List<Episode> { new Episode { EpisodeFile = new EpisodeFile { Id = 10 } }, new Episode { EpisodeFile = new EpisodeFile { Id = 10 } } });
|
||||
|
||||
Mocker.GetMock<IEpisodeService>()
|
||||
.Setup(e => e.UpdateEpisode(It.IsAny<Episode>()));
|
||||
|
||||
Mocker.GetMock<IMediaFileService>()
|
||||
.Setup(e => e.Delete(It.IsAny<int>()));
|
||||
|
||||
Mocker.GetMock<IConfigService>()
|
||||
.SetupGet(s => s.AutoIgnorePreviouslyDownloadedEpisodes)
|
||||
.Returns(true);
|
||||
|
||||
//Act
|
||||
Mocker.Resolve<DiskScanProvider>().CleanUp(episodes);
|
||||
|
||||
//Assert
|
||||
Mocker.VerifyAllMocks();
|
||||
|
||||
Mocker.GetMock<IEpisodeService>()
|
||||
.Verify(e => e.GetEpisodesByFileId(It.IsAny<int>()), Times.Exactly(10));
|
||||
|
||||
Mocker.GetMock<IEpisodeService>()
|
||||
.Verify(e => e.UpdateEpisode(It.Is<Episode>(g => g.EpisodeFileId == 0)), Times.Exactly(20));
|
||||
|
||||
Mocker.GetMock<IMediaFileService>()
|
||||
.Verify(e => e.Delete(It.IsAny<int>()), Times.Exactly(10));
|
||||
|
||||
Mocker.GetMock<IMediaFileService>()
|
||||
.Verify(e => e.Delete(It.IsAny<int>()), Times.Exactly(10));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -42,8 +42,8 @@ private static void RegisterAssembly(this ContainerBuilder container, string ass
|
||||
.As<IndexerBase>().SingleInstance();
|
||||
|
||||
container.RegisterAssemblyTypes(assembly)
|
||||
.Where(t => t.IsSubclassOf(typeof(SearchBase)))
|
||||
.As<SearchBase>().SingleInstance();
|
||||
.Where(t => t.IsSubclassOf(typeof(IndexerSearchBase)))
|
||||
.As<IndexerSearchBase>().SingleInstance();
|
||||
|
||||
container.RegisterAssemblyTypes(assembly)
|
||||
.Where(t => t.IsSubclassOf(typeof(ExternalNotificationBase)))
|
||||
|
@ -14,6 +14,7 @@ namespace NzbDrone.Core.Datastore
|
||||
TModel Update(TModel model);
|
||||
TModel UpSert(TModel model);
|
||||
void Delete(int id);
|
||||
void Delete(TModel model);
|
||||
IList<TModel> InsertMany(IList<TModel> model);
|
||||
IList<TModel> UpdateMany(IList<TModel> model);
|
||||
void DeleteMany(List<TModel> model);
|
||||
@ -67,6 +68,11 @@ public TModel Update(TModel model)
|
||||
return ObjectDatabase.Update(model);
|
||||
}
|
||||
|
||||
public void Delete(TModel model)
|
||||
{
|
||||
ObjectDatabase.Delete(model);
|
||||
}
|
||||
|
||||
public IList<TModel> InsertMany(IList<TModel> model)
|
||||
{
|
||||
return ObjectDatabase.InsertMany(model);
|
||||
|
@ -7,11 +7,10 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Model;
|
||||
using NzbDrone.Core.Download.Clients.Sabnzbd;
|
||||
|
||||
namespace NzbDrone.Core.Providers
|
||||
namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
||||
{
|
||||
public class AutoConfigureProvider
|
||||
public class SabAutoConfigureService
|
||||
{
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
namespace NzbDrone.Core.IndexerSearch
|
||||
{
|
||||
public class DailyEpisodeSearch : SearchBase
|
||||
public class DailyEpisodeSearch : IndexerSearchBase
|
||||
{
|
||||
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
namespace NzbDrone.Core.IndexerSearch
|
||||
{
|
||||
public class EpisodeSearch : SearchBase
|
||||
public class EpisodeSearch : IndexerSearchBase
|
||||
{
|
||||
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
|
@ -13,18 +13,19 @@
|
||||
|
||||
namespace NzbDrone.Core.IndexerSearch
|
||||
{
|
||||
public abstract class SearchBase
|
||||
public abstract class IndexerSearchBase
|
||||
{
|
||||
private readonly ISeriesRepository _seriesRepository;
|
||||
protected readonly IEpisodeService _episodeService;
|
||||
protected readonly DownloadProvider _downloadProvider;
|
||||
private readonly IEpisodeService _episodeService;
|
||||
private readonly DownloadProvider _downloadProvider;
|
||||
private readonly ISceneMappingService _sceneMappingService;
|
||||
private readonly IDownloadDirector DownloadDirector;
|
||||
|
||||
protected readonly IIndexerService _indexerService;
|
||||
protected readonly ISceneMappingService _sceneMappingService;
|
||||
protected readonly IDownloadDirector DownloadDirector;
|
||||
|
||||
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
protected SearchBase(ISeriesRepository seriesRepository, IEpisodeService episodeService, DownloadProvider downloadProvider,
|
||||
protected IndexerSearchBase(ISeriesRepository seriesRepository, IEpisodeService episodeService, DownloadProvider downloadProvider,
|
||||
IIndexerService indexerService, ISceneMappingService sceneMappingService,
|
||||
IDownloadDirector downloadDirector)
|
||||
{
|
||||
@ -36,7 +37,7 @@ protected SearchBase(ISeriesRepository seriesRepository, IEpisodeService episode
|
||||
DownloadDirector = downloadDirector;
|
||||
}
|
||||
|
||||
protected SearchBase()
|
||||
protected IndexerSearchBase()
|
||||
{
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
namespace NzbDrone.Core.IndexerSearch
|
||||
{
|
||||
public class PartialSeasonSearch : SearchBase
|
||||
public class PartialSeasonSearch : IndexerSearchBase
|
||||
{
|
||||
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
|
14
NzbDrone.Core/MediaFiles/Events/EpisodeFileDeletedEvent.cs
Normal file
14
NzbDrone.Core/MediaFiles/Events/EpisodeFileDeletedEvent.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using NzbDrone.Common.Eventing;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles.Events
|
||||
{
|
||||
public class EpisodeFileDeletedEvent : IEvent
|
||||
{
|
||||
public EpisodeFile EpisodeFile { get; private set; }
|
||||
|
||||
public EpisodeFileDeletedEvent(EpisodeFile episodeFile)
|
||||
{
|
||||
EpisodeFile = episodeFile;
|
||||
}
|
||||
}
|
||||
}
|
48
NzbDrone.Core/MediaFiles/GhostFileCleanupService.cs
Normal file
48
NzbDrone.Core/MediaFiles/GhostFileCleanupService.cs
Normal file
@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using NLog;
|
||||
using NzbDrone.Common;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles
|
||||
{
|
||||
public interface ICleanGhostFiles
|
||||
{
|
||||
void RemoveNonExistingFiles(int seriesId);
|
||||
}
|
||||
|
||||
|
||||
public class GhostFileCleanupService : ICleanGhostFiles
|
||||
{
|
||||
private readonly IMediaFileService _mediaFileService;
|
||||
private readonly DiskProvider _diskProvider;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public GhostFileCleanupService(IMediaFileService mediaFileService, DiskProvider diskProvider, Logger logger)
|
||||
{
|
||||
_mediaFileService = mediaFileService;
|
||||
_diskProvider = diskProvider;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void RemoveNonExistingFiles(int seriesId)
|
||||
{
|
||||
var seriesFile = _mediaFileService.GetFilesBySeries(seriesId);
|
||||
|
||||
foreach (var episodeFile in seriesFile)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_diskProvider.FileExists(episodeFile.Path))
|
||||
{
|
||||
_logger.Trace("File [{0}] no longer exists on disk. removing from db", episodeFile.Path);
|
||||
_mediaFileService.Delete(episodeFile);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var message = String.Format("Unable to cleanup EpisodeFile in DB: {0}", episodeFile.Id);
|
||||
_logger.ErrorException(message, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
using NLog;
|
||||
using NzbDrone.Common.Eventing;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Tv.Events;
|
||||
|
||||
@ -12,7 +13,7 @@ public interface IMediaFileService
|
||||
{
|
||||
EpisodeFile Add(EpisodeFile episodeFile);
|
||||
void Update(EpisodeFile episodeFile);
|
||||
void Delete(int episodeFileId);
|
||||
void Delete(EpisodeFile episodeFile);
|
||||
bool Exists(string path);
|
||||
EpisodeFile GetFileByPath(string path);
|
||||
List<EpisodeFile> GetFilesBySeries(int seriesId);
|
||||
@ -23,15 +24,17 @@ public class MediaFileService : IMediaFileService, IHandleAsync<SeriesDeletedEve
|
||||
{
|
||||
private readonly IConfigService _configService;
|
||||
private readonly IEpisodeService _episodeService;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private readonly Logger _logger;
|
||||
private readonly IMediaFileRepository _mediaFileRepository;
|
||||
|
||||
|
||||
public MediaFileService(IMediaFileRepository mediaFileRepository, IConfigService configService, IEpisodeService episodeService, Logger logger)
|
||||
public MediaFileService(IMediaFileRepository mediaFileRepository, IConfigService configService, IEpisodeService episodeService, IEventAggregator eventAggregator, Logger logger)
|
||||
{
|
||||
_mediaFileRepository = mediaFileRepository;
|
||||
_configService = configService;
|
||||
_episodeService = episodeService;
|
||||
_eventAggregator = eventAggregator;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
@ -45,16 +48,10 @@ public void Update(EpisodeFile episodeFile)
|
||||
_mediaFileRepository.Update(episodeFile);
|
||||
}
|
||||
|
||||
public void Delete(int episodeFileId)
|
||||
public void Delete(EpisodeFile episodeFile)
|
||||
{
|
||||
_mediaFileRepository.Delete(episodeFileId);
|
||||
|
||||
var ep = _episodeService.GetEpisodesByFileId(episodeFileId);
|
||||
|
||||
foreach (var episode in ep)
|
||||
{
|
||||
_episodeService.SetEpisodeIgnore(episode.Id, true);
|
||||
}
|
||||
_mediaFileRepository.Delete(episodeFile);
|
||||
_eventAggregator.Publish(new EpisodeFileDeletedEvent(episodeFile));
|
||||
}
|
||||
|
||||
public bool Exists(string path)
|
||||
|
@ -201,6 +201,7 @@
|
||||
<Compile Include="DecisionEngine\QualityUpgradableSpecification.cs" />
|
||||
<Compile Include="DecisionEngine\Specifications\UpgradeDiskSpecification.cs" />
|
||||
<Compile Include="DecisionEngine\Specifications\UpgradeHistorySpecification.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\SabAutoConfigureService.cs" />
|
||||
<Compile Include="Download\EpisodeDownloadedEvent.cs" />
|
||||
<Compile Include="Download\EpisodeGrabbedEvent.cs" />
|
||||
<Compile Include="Download\SeriesRenamedEvent.cs" />
|
||||
@ -215,7 +216,7 @@
|
||||
<Compile Include="IndexerSearch\DailyEpisodeSearch.cs" />
|
||||
<Compile Include="IndexerSearch\EpisodeSearch.cs" />
|
||||
<Compile Include="IndexerSearch\PartialSeasonSearch.cs" />
|
||||
<Compile Include="IndexerSearch\SearchBase.cs" />
|
||||
<Compile Include="IndexerSearch\IndexerSearchBase.cs" />
|
||||
<Compile Include="Indexers\IndexerRepository.cs" />
|
||||
<Compile Include="Indexers\NewznabRepository.cs" />
|
||||
<Compile Include="Instrumentation\LogInjectionModule.cs" />
|
||||
@ -249,6 +250,8 @@
|
||||
<Compile Include="Lifecycle\AppRestartJob.cs" />
|
||||
<Compile Include="Lifecycle\IInitializable.cs" />
|
||||
<Compile Include="MediaCover\MediaCover.cs" />
|
||||
<Compile Include="MediaFiles\Events\EpisodeFileDeletedEvent.cs" />
|
||||
<Compile Include="MediaFiles\GhostFileCleanupService.cs" />
|
||||
<Compile Include="MediaFiles\MediaFileRepository.cs" />
|
||||
<Compile Include="Organizer\EpisodeSortingType.cs" />
|
||||
<Compile Include="Organizer\FileNameBuilder.cs" />
|
||||
@ -338,9 +341,6 @@
|
||||
<Compile Include="Providers\XemProvider.cs" />
|
||||
<Compile Include="Qualities\Quality.cs" />
|
||||
<Compile Include="Tv\Season.cs" />
|
||||
<Compile Include="Providers\AutoConfigureProvider.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Providers\BackupProvider.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
|
@ -20,21 +20,21 @@ public class DiskScanProvider
|
||||
private static readonly string[] MediaExtensions = new[] { ".mkv", ".avi", ".wmv", ".mp4", ".mpg", ".mpeg", ".xvid", ".flv", ".mov", ".rm", ".rmvb", ".divx", ".dvr-ms", ".ts", ".ogm", ".m4v", ".strm" };
|
||||
private readonly DiskProvider _diskProvider;
|
||||
private readonly IEpisodeService _episodeService;
|
||||
private readonly ICleanGhostFiles _ghostFileCleaner;
|
||||
private readonly IMediaFileService _mediaFileService;
|
||||
private readonly IConfigService _configService;
|
||||
private readonly IBuildFileNames _buildFileNames;
|
||||
private readonly RecycleBinProvider _recycleBinProvider;
|
||||
private readonly MediaInfoProvider _mediaInfoProvider;
|
||||
private readonly ISeriesRepository _seriesRepository;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
|
||||
public DiskScanProvider(DiskProvider diskProvider, IEpisodeService episodeService, IMediaFileService mediaFileService, IConfigService configService, IBuildFileNames buildFileNames,
|
||||
public DiskScanProvider(DiskProvider diskProvider, IEpisodeService episodeService, ICleanGhostFiles ghostFileCleaner, IMediaFileService mediaFileService, IConfigService configService, IBuildFileNames buildFileNames,
|
||||
RecycleBinProvider recycleBinProvider, MediaInfoProvider mediaInfoProvider, ISeriesRepository seriesRepository, IEventAggregator eventAggregator)
|
||||
{
|
||||
_diskProvider = diskProvider;
|
||||
_episodeService = episodeService;
|
||||
_ghostFileCleaner = ghostFileCleaner;
|
||||
_mediaFileService = mediaFileService;
|
||||
_configService = configService;
|
||||
_buildFileNames = buildFileNames;
|
||||
_recycleBinProvider = recycleBinProvider;
|
||||
_mediaInfoProvider = mediaInfoProvider;
|
||||
@ -74,8 +74,7 @@ public virtual List<EpisodeFile> Scan(Series series, string path)
|
||||
return new List<EpisodeFile>();
|
||||
}
|
||||
|
||||
var seriesFile = _mediaFileService.GetFilesBySeries(series.Id);
|
||||
CleanUp(seriesFile);
|
||||
_ghostFileCleaner.RemoveNonExistingFiles(series.Id);
|
||||
|
||||
var mediaFileList = GetVideoFiles(path);
|
||||
var importedFiles = new List<EpisodeFile>();
|
||||
@ -237,43 +236,7 @@ public virtual EpisodeFile MoveEpisodeFile(EpisodeFile episodeFile, bool newDown
|
||||
return episodeFile;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes files that no longer exist on disk from the database
|
||||
/// </summary>
|
||||
/// <param name = "files">list of files to verify</param>
|
||||
public virtual void CleanUp(IList<EpisodeFile> files)
|
||||
{
|
||||
foreach (var episodeFile in files)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_diskProvider.FileExists(episodeFile.Path))
|
||||
{
|
||||
Logger.Trace("File [{0}] no longer exists on disk. removing from db", episodeFile.Path);
|
||||
|
||||
//Set the EpisodeFileId for each episode attached to this file to 0
|
||||
foreach (var episode in _episodeService.GetEpisodesByFileId(episodeFile.Id))
|
||||
{
|
||||
Logger.Trace("Detaching episode {0} from file.", episode.Id);
|
||||
episode.EpisodeFile = null;
|
||||
episode.Ignored = _configService.AutoIgnorePreviouslyDownloadedEpisodes;
|
||||
episode.GrabDate = null;
|
||||
episode.PostDownloadStatus = PostDownloadStatusType.Unknown;
|
||||
_episodeService.UpdateEpisode(episode);
|
||||
}
|
||||
|
||||
//Delete it from the DB
|
||||
Logger.Trace("Removing EpisodeFile from DB.");
|
||||
_mediaFileService.Delete(episodeFile.Id);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var message = String.Format("Unable to cleanup EpisodeFile in DB: {0}", episodeFile.Id);
|
||||
Logger.ErrorException(message, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void CleanUpDropFolder(string path)
|
||||
{
|
||||
|
@ -3,8 +3,10 @@
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Eventing;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
using NzbDrone.Core.MetadataSource;
|
||||
using NzbDrone.Core.Model;
|
||||
using NzbDrone.Core.Providers;
|
||||
@ -37,6 +39,7 @@ public interface IEpisodeService
|
||||
|
||||
public class EpisodeService : IEpisodeService,
|
||||
IHandle<EpisodeGrabbedEvent>,
|
||||
IHandle<EpisodeFileDeletedEvent>,
|
||||
IHandleAsync<SeriesDeletedEvent>
|
||||
{
|
||||
|
||||
@ -46,13 +49,17 @@ public class EpisodeService : IEpisodeService,
|
||||
private readonly ISeasonRepository _seasonRepository;
|
||||
private readonly IEpisodeRepository _episodeRepository;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private readonly IConfigService _configService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public EpisodeService(TvDbProxy tvDbProxyProxy, ISeasonRepository seasonRepository, IEpisodeRepository episodeRepository, IEventAggregator eventAggregator)
|
||||
public EpisodeService(TvDbProxy tvDbProxyProxy, ISeasonRepository seasonRepository, IEpisodeRepository episodeRepository, IEventAggregator eventAggregator, IConfigService configService, Logger logger)
|
||||
{
|
||||
_tvDbProxy = tvDbProxyProxy;
|
||||
_seasonRepository = seasonRepository;
|
||||
_episodeRepository = episodeRepository;
|
||||
_eventAggregator = eventAggregator;
|
||||
_configService = configService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void AddEpisode(Episode episode)
|
||||
@ -379,5 +386,18 @@ public void HandleAsync(SeriesDeletedEvent message)
|
||||
var episodes = GetEpisodeBySeries(message.Series.Id);
|
||||
_episodeRepository.DeleteMany(episodes);
|
||||
}
|
||||
|
||||
public void Handle(EpisodeFileDeletedEvent message)
|
||||
{
|
||||
foreach (var episode in GetEpisodesByFileId(message.EpisodeFile.Id))
|
||||
{
|
||||
_logger.Trace("Detaching episode {0} from file.", episode.Id);
|
||||
episode.EpisodeFile = null;
|
||||
episode.Ignored = _configService.AutoIgnorePreviouslyDownloadedEpisodes;
|
||||
episode.GrabDate = null;
|
||||
episode.PostDownloadStatus = PostDownloadStatusType.Unknown;
|
||||
UpdateEpisode(episode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -102,9 +102,16 @@ protected string GetTestFilePath(string fileName)
|
||||
return Path.Combine(Directory.GetCurrentDirectory(), "Files", fileName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected void VerifyEventPublished<TEvent>() where TEvent : IEvent
|
||||
{
|
||||
Mocker.GetMock<IEventAggregator>().Verify(c => c.Publish(It.IsAny<TEvent>()), Times.Once());
|
||||
VerifyEventPublished<TEvent>(Times.Once());
|
||||
}
|
||||
|
||||
protected void VerifyEventPublished<TEvent>(Times times) where TEvent : IEvent
|
||||
{
|
||||
Mocker.GetMock<IEventAggregator>().Verify(c => c.Publish(It.IsAny<TEvent>()), times);
|
||||
}
|
||||
|
||||
protected void VerifyEventNotPublished<TEvent>() where TEvent : IEvent
|
||||
|
Loading…
Reference in New Issue
Block a user