removed all the jobs.

pull/3113/head
Keivan Beigi 11 years ago
parent 40f384968a
commit ec58b8b595

@ -9,20 +9,24 @@ namespace NzbDrone.Common.Messaging
public class MessageAggregator : IMessageAggregator
{
private readonly Logger _logger;
private readonly Func<IEnumerable<IProcessMessage>> _handlers;
private readonly Func<IEnumerable<IProcessMessage>> _handlerFactory;
public MessageAggregator(Logger logger, Func<IEnumerable<IProcessMessage>> handlers)
{
_logger = logger;
_handlers = handlers;
_handlerFactory = handlers;
}
public void PublishEvent<TEvent>(TEvent @event) where TEvent : IEvent
{
_logger.Trace("Publishing {0}", @event.GetType().Name);
var handlers = _handlerFactory().ToList();
//call synchronous handlers first.
foreach (var handler in _handlers().OfType<IHandle<TEvent>>())
foreach (var handler in handlers.OfType<IHandle<TEvent>>())
{
try
{
@ -36,7 +40,7 @@ namespace NzbDrone.Common.Messaging
}
}
foreach (var handler in _handlers().OfType<IHandleAsync<TEvent>>())
foreach (var handler in handlers.OfType<IHandleAsync<TEvent>>())
{
var handlerLocal = handler;
Task.Factory.StartNew(() =>
@ -52,7 +56,7 @@ namespace NzbDrone.Common.Messaging
public void PublishCommand<TCommand>(TCommand command) where TCommand : ICommand
{
_logger.Trace("Publishing {0}", command.GetType().Name);
var handler = _handlers().OfType<IExecute<TCommand>>().Single();
var handler = _handlerFactory().OfType<IExecute<TCommand>>().Single();
_logger.Debug("{0} -> {1}", command.GetType().Name, handler.GetType().Name);
handler.Execute(command);
_logger.Debug("{0} <- {1}", command.GetType().Name, handler.GetType().Name);

@ -106,21 +106,19 @@ namespace NzbDrone.Core.Test.Datastore
{
var childModel = new JobDefinition
{
Type = "Address",
Name = "Name",
Name = "Address",
Interval = 12
};
Subject.Insert(childModel);
childModel.Type = "A";
childModel.Name = "B";
childModel.Name = "A";
childModel.Interval = 0;
Subject.SetFields(childModel, t => t.Name);
Db.All<JobDefinition>().Single().Type.Should().Be("Address");
Db.All<JobDefinition>().Single().Name.Should().Be("Address");
Db.All<JobDefinition>().Single().Name.Should().Be("B");
Db.All<JobDefinition>().Single().Interval.Should().Be(12);
}

@ -1,111 +0,0 @@

using System;
using System.Collections.Generic;
using FizzWare.NBuilder;
using Moq;
using NUnit.Framework;
using NzbDrone.Core.Jobs.Implementations;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Jobs;
using NzbDrone.Core.Model.Notification;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common;
using NzbDrone.Test.Common.AutoMoq;
using System.Linq;
namespace NzbDrone.Core.Test.JobTests
{
[TestFixture]
public class DiskScanJobTest : CoreTest
{
[Test]
public void series_specific_scan_should_scan_series()
{
var series = Builder<Series>.CreateNew()
.With(s => s.Id = 12)
.Build();
Mocker.GetMock<ISeriesRepository>()
.Setup(p => p.Get(series.Id))
.Returns(series);
Mocker.Resolve<DiskScanJob>().Start(new ProgressNotification("Test"), new { SeriesId = series.Id });
Mocker.VerifyAllMocks();
}
[Test]
public void job_with_no_target_should_scan_all_series()
{
var series = Builder<Series>.CreateListOfSize(2)
.TheFirst(1).With(s => s.Id = 12)
.TheNext(1).With(s => s.Id = 15)
.Build().ToList();
Mocker.GetMock<ISeriesRepository>()
.Setup(p => p.All())
.Returns(series);
Mocker.Resolve<DiskScanJob>().Start(new ProgressNotification("Test"), null);
Mocker.VerifyAllMocks();
}
[Test]
public void failed_scan_should_not_terminated_job()
{
var series = Builder<Series>.CreateListOfSize(2)
.TheFirst(1).With(s => s.Id = 12)
.TheNext(1).With(s => s.Id = 15)
.Build().ToList();
Mocker.GetMock<ISeriesRepository>()
.Setup(p => p.All())
.Returns(series);
Mocker.GetMock<IDiskScanService>()
.Setup(s => s.Scan(series[0]))
.Throws(new InvalidOperationException("Bad Job"));
Mocker.GetMock<IDiskScanService>()
.Setup(s => s.Scan(series[1]))
.Throws(new InvalidOperationException("Bad Job"));
Mocker.Resolve<DiskScanJob>().Start(new ProgressNotification("Test"), null);
Mocker.VerifyAllMocks();
ExceptionVerification.ExpectedErrors(2);
}
[Test]
public void job_with_no_target_should_scan_series_with_episodes()
{
var series = Builder<Series>.CreateListOfSize(2)
.TheFirst(1).With(s => s.Id = 12)
.TheNext(1).With(s => s.Id = 15)
.Build().ToList();
Mocker.GetMock<ISeriesRepository>()
.Setup(p => p.All())
.Returns(series);
Mocker.Resolve<DiskScanJob>().Start(new ProgressNotification("Test"), null);
Mocker.VerifyAllMocks();
Mocker.GetMock<IDiskScanService>().Verify(s => s.Scan(It.IsAny<Series>()), Times.Exactly(2));
}
}
}

@ -1,232 +0,0 @@
/*
using System.Linq;
using System;
using System.Collections.Generic;
using System.Threading;
using FluentAssertions;
using Moq;
using NCrunch.Framework;
using NUnit.Framework;
using NzbDrone.Core.Jobs;
using NzbDrone.Core.Jobs.Implementations;
using NzbDrone.Core.Model;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.JobTests
{
/* [TestFixture]
[ExclusivelyUses("JOB_PROVIDER")]
public class JobControllerFixture : CoreTest<JobController>
{
FakeJob _fakeJob;
SlowJob _slowJob;
SlowJob2 _slowJob2;
BrokenJob _brokenJob;
DisabledJob _disabledJob;
private JobDefinition _updatedJob = null;
[SetUp]
public void Setup()
{
_fakeJob = new FakeJob();
_slowJob = new SlowJob();
_slowJob2 = new SlowJob2();
_brokenJob = new BrokenJob();
_disabledJob = new DisabledJob();
_updatedJob = null;
IEnumerable<IJob> jobs = new List<IJob> { _fakeJob, _slowJob, _slowJob2, _brokenJob, _disabledJob };
Mocker.SetConstant(jobs);
Mocker.GetMock<IJobRepository>()
.Setup(c => c.Update(It.IsAny<JobDefinition>()))
.Callback<JobDefinition>(c => _updatedJob = c);
Mocker.GetMock<IJobRepository>()
.Setup(c => c.GetDefinition(It.IsAny<Type>()))
.Returns(new JobDefinition());
}
private void GivenPendingJob(IList<JobDefinition> jobDefinition)
{
Mocker.GetMock<IJobRepository>().Setup(c => c.GetPendingJobs()).Returns(jobDefinition);
}
[TearDown]
public void TearDown()
{
Subject.Queue.Should().BeEmpty();
}
private void WaitForQueue()
{
Console.WriteLine("Waiting for queue to clear.");
var queue = Mocker.Resolve<JobController>().Queue;
while (Subject.IsProcessing)
{
Thread.Sleep(100);
}
}
[Test]
public void running_scheduled_jobs_should_updates_last_execution_time()
{
GivenPendingJob(new List<JobDefinition> { new JobDefinition { Type = _fakeJob.GetType().FullName } });
Subject.EnqueueScheduled();
WaitForQueue();
_updatedJob.LastExecution.Should().BeWithin(TimeSpan.FromSeconds(10));
_updatedJob.LastExecution.Should().BeWithin(TimeSpan.FromSeconds(10));
_fakeJob.ExecutionCount.Should().Be(1);
}
[Test]
public void failing_scheduled_job_should_mark_job_as_failed()
{
GivenPendingJob(new List<JobDefinition> { new JobDefinition { Type = _brokenJob.GetType().FullName } });
Subject.EnqueueScheduled();
WaitForQueue();
_updatedJob.LastExecution.Should().BeWithin(TimeSpan.FromSeconds(10));
_updatedJob.Success.Should().BeFalse();
_brokenJob.ExecutionCount.Should().Be(1);
ExceptionVerification.ExpectedErrors(1);
}
[Test]
public void can_run_job_again()
{
Subject.Enqueue(typeof(FakeJob));
WaitForQueue();
Subject.Enqueue(typeof(FakeJob));
WaitForQueue();
Subject.Queue.Should().BeEmpty();
_fakeJob.ExecutionCount.Should().Be(2);
}
[Test]
public void should_ignore_job_with_same_arg()
{
Subject.Enqueue(typeof(SlowJob2), 1);
Subject.Enqueue(typeof(FakeJob), 1);
Subject.Enqueue(typeof(FakeJob), 1);
WaitForQueue();
Subject.Queue.Should().BeEmpty();
_fakeJob.ExecutionCount.Should().Be(1);
ExceptionVerification.AssertNoUnexcpectedLogs();
}
[Test]
public void can_run_broken_job_again()
{
Subject.Enqueue(typeof(BrokenJob));
WaitForQueue();
Subject.Enqueue(typeof(BrokenJob));
WaitForQueue();
_brokenJob.ExecutionCount.Should().Be(2);
ExceptionVerification.ExpectedErrors(2);
}
[Test]
public void schedule_hit_should_be_ignored_if_queue_is_running()
{
Subject.Enqueue(typeof(SlowJob));
Subject.EnqueueScheduled();
WaitForQueue();
_slowJob.ExecutionCount.Should().Be(1);
_fakeJob.ExecutionCount.Should().Be(0);
}
[Test]
public void can_queue_jobs_at_the_same_time()
{
Subject.Enqueue(typeof(SlowJob));
var thread1 = new Thread(() => Subject.Enqueue(typeof(FakeJob)));
var thread2 = new Thread(() => Subject.Enqueue(typeof(FakeJob)));
thread1.Start();
thread2.Start();
thread1.Join();
thread2.Join();
WaitForQueue();
_fakeJob.ExecutionCount.Should().Be(1);
_slowJob.ExecutionCount.Should().Be(1);
Subject.Queue.Should().BeEmpty();
}
[Test]
public void job_with_specific_target_should_not_update_status()
{
Subject.Enqueue(typeof(FakeJob), 10);
WaitForQueue();
Mocker.GetMock<IJobRepository>().Verify(c => c.Update(It.IsAny<JobDefinition>()), Times.Never());
_updatedJob.Should().BeNull();
}
[Test]
public void Item_added_to_queue_while_scheduler_runs_should_be_executed()
{
GivenPendingJob(new List<JobDefinition> { new JobDefinition { Type = _slowJob.GetType().FullName } });
var jobThread = new Thread(Subject.EnqueueScheduled);
jobThread.Start();
Thread.Sleep(200);
Subject.Enqueue(typeof(DisabledJob), 12);
WaitForQueue();
_slowJob.ExecutionCount.Should().Be(1);
_disabledJob.ExecutionCount.Should().Be(1);
}
[Test]
public void trygin_to_queue_unregistered_job_should_fail()
{
Subject.Enqueue(typeof(UpdateInfoJob));
WaitForQueue();
ExceptionVerification.ExpectedErrors(1);
}
[Test]
public void scheduled_job_should_have_scheduler_as_source()
{
GivenPendingJob(new List<JobDefinition> { new JobDefinition { Type = _slowJob.GetType().FullName }, new JobDefinition { Type = _slowJob2.GetType().FullName } });
Subject.EnqueueScheduled();
Subject.Queue.Should().OnlyContain(c => c.Source == JobQueueItem.JobSourceType.Scheduler);
WaitForQueue();
}#1#
}
}
*/

@ -1,4 +1,4 @@
using System.Linq;
/*
using System;
using System.Collections.Generic;
using FizzWare.NBuilder;
@ -42,11 +42,10 @@ namespace NzbDrone.Core.Test.JobTests
Storage.All().Should().HaveCount(1);
StoredModel.Interval.Should().Be((Int32)_fakeJob.DefaultInterval.TotalMinutes);
StoredModel.Name.Should().Be(_fakeJob.Name);
StoredModel.Type.Should().Be(_fakeJob.GetType().ToString());
StoredModel.Name.Should().Be(_fakeJob.GetType().ToString());
StoredModel.LastExecution.Should().HaveYear(DateTime.Now.Year);
StoredModel.LastExecution.Should().HaveMonth(DateTime.Now.Month);
StoredModel.LastExecution.Should().HaveDay(DateTime.Today.Day);
StoredModel.Enable.Should().BeTrue();
}
[Test]
@ -63,13 +62,13 @@ namespace NzbDrone.Core.Test.JobTests
//Make sure deleted job is stored
AllStoredModels.Should().HaveCount(1);
AllStoredModels.Should().Contain(c => c.Type == deletedJob.Type);
AllStoredModels.Should().Contain(c => c.Name == deletedJob.Name);
Initialize();
//Make sure init has cleaned up the deleted job
AllStoredModels.Should().HaveCount(1);
AllStoredModels.Should().NotContain(c => c.Type == deletedJob.Type);
AllStoredModels.Should().NotContain(c => c.Name == deletedJob.Name);
}
[Test]
@ -87,13 +86,13 @@ namespace NzbDrone.Core.Test.JobTests
//Make sure deleted job is stored
AllStoredModels.Should().HaveCount(1);
AllStoredModels.Should().Contain(c => c.Type == deletedJob.Type);
AllStoredModels.Should().Contain(c => c.Name == deletedJob.Name);
Initialize();
//Make sure init has cleaned up the deleted job
AllStoredModels.Should().HaveCount(1);
AllStoredModels.Should().NotContain(c => c.Type == deletedJob.Type);
AllStoredModels.Should().NotContain(c => c.Name == deletedJob.Name);
}
[Test]
@ -103,9 +102,8 @@ namespace NzbDrone.Core.Test.JobTests
var oldJob = Builder<JobDefinition>.CreateNew()
.With(c => c.Id = 0)
.With(c => c.Name = "OldName")
.With(c => c.Type = typeof(FakeJob).ToString())
.With(c => c.Name = typeof(FakeJob).ToString())
.With(c => c.Interval = 0)
.With(c => c.Enable = true)
.With(c => c.Success = true)
.With(c => c.LastExecution = DateTime.Now.AddDays(-7).Date)
.Build();
@ -121,27 +119,13 @@ namespace NzbDrone.Core.Test.JobTests
AllStoredModels.Should().HaveCount(1);
StoredModel.Type.Should().Be(newJob.GetType().FullName);
StoredModel.Name.Should().Be(newJob.GetType().FullName);
StoredModel.Name.Should().Be(newJob.Name);
StoredModel.Interval.Should().Be((int)newJob.DefaultInterval.TotalMinutes);
StoredModel.Enable.Should().Be(true);
StoredModel.Success.Should().Be(oldJob.Success);
StoredModel.LastExecution.Should().Be(oldJob.LastExecution);
}
[Test]
public void jobs_with_zero_interval_are_registered_as_disabled()
{
IEnumerable<IJob> fakeJobs = new List<IJob> { _disabledJob };
Mocker.SetConstant(fakeJobs);
Initialize();
Storage.All().Should().HaveCount(1);
Storage.All().First().Enable.Should().BeFalse();
}
[Test]
public void pending_job_should_get_jobs_that_have_matured()
@ -149,7 +133,6 @@ namespace NzbDrone.Core.Test.JobTests
var oldJob = Builder<JobDefinition>.CreateNew()
.With(c => c.Id = 0)
.With(c => c.Interval = 1)
.With(c => c.Enable = true)
.With(c => c.Success = true)
.With(c => c.LastExecution = DateTime.Now.AddMinutes(-5))
.Build();
@ -168,7 +151,6 @@ namespace NzbDrone.Core.Test.JobTests
var recent = Builder<JobDefinition>.CreateNew()
.With(c => c.Id = 0)
.With(c => c.Interval = 60)
.With(c => c.Enable = true)
.With(c => c.Success = true)
.With(c => c.LastExecution = DateTime.Now.AddMinutes(-5))
.Build();
@ -193,7 +175,8 @@ namespace NzbDrone.Core.Test.JobTests
disabledJob.ExecutionCount.Should().Be(0);
}*/
}#1#
}
}
*/

@ -1,65 +0,0 @@
using Moq;
using NUnit.Framework;
using NzbDrone.Common;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Jobs.Implementations;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.JobTests
{
[TestFixture]
public class PostDownloadScanJobFixture : CoreTest<PostDownloadScanJob>
{
[SetUp]
public void Setup()
{
Mocker.GetMock<DiskProvider>().Setup(s => s.FolderExists(It.IsAny<string>())).Returns(true);
}
[Test]
public void should_use_options_Path_when_provided()
{
var path = @"C:\Test\Unsorted TV";
Mocker.GetMock<IDropFolderImportService>().Setup(s => s.ProcessDropFolder(path));
Subject.Start(MockNotification, new { Path = path });
Mocker.GetMock<IDropFolderImportService>().Verify(s => s.ProcessDropFolder(path), Times.Once());
}
[Test]
public void should_not_get_sabDropDir_when_path_is_supplied()
{
var path = @"C:\Test\Unsorted TV";
Mocker.GetMock<IDropFolderImportService>().Setup(s => s.ProcessDropFolder(path));
Subject.Start(MockNotification, new { Path = path });
Mocker.GetMock<IConfigService>().Verify(s => s.DownloadClientTvDirectory, Times.Never());
}
[Test]
public void should_get_sabDropDir_when_path_is_not_supplied()
{
var path = @"C:\Test\Unsorted TV";
Mocker.GetMock<IConfigService>().SetupGet(s => s.DownloadClientTvDirectory).Returns(path);
Subject.Start(MockNotification, null);
Mocker.GetMock<IConfigService>().Verify(s => s.DownloadClientTvDirectory, Times.Once());
}
[Test]
public void should_use_sabDropDir_when_options_Path_is_not_provided()
{
var path = @"C:\Test\Unsorted TV";
Mocker.GetMock<IConfigService>().SetupGet(s => s.DownloadClientTvDirectory).Returns(path);
Subject.Start(MockNotification, null);
Mocker.GetMock<IDropFolderImportService>().Verify(s => s.ProcessDropFolder(path), Times.Once());
}
}
}

@ -1,70 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using FizzWare.NBuilder;
using NUnit.Framework;
using NzbDrone.Core.Jobs.Implementations;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Model.Notification;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.JobTests
{
[TestFixture]
public class RenameSeasonJobFixture : TestBase
{
private ProgressNotification _testNotification;
private Series _series;
private IList<EpisodeFile> _episodeFiles;
[SetUp]
public void Setup()
{
_testNotification = new ProgressNotification("TEST");
_series = Builder<Series>
.CreateNew()
.Build();
_episodeFiles = Builder<EpisodeFile>
.CreateListOfSize(5)
.All()
.With(e => e.SeasonNumber = 5)
.Build();
Mocker.GetMock<ISeriesRepository>()
.Setup(s => s.Get(_series.Id))
.Returns(_series);
Mocker.GetMock<IMediaFileService>()
.Setup(s => s.GetFilesBySeason(_series.Id, 5))
.Returns(_episodeFiles.ToList());
}
[Test]
public void should_throw_if_seriesId_is_zero()
{
Assert.Throws<ArgumentException>(() =>
Mocker.Resolve<RenameSeasonJob>().Start(_testNotification, new { SeriesId = 0, SeasonNumber = 10 }));
}
[Test]
public void should_throw_if_seasonId_is_less_than_zero()
{
Assert.Throws<ArgumentException>(() =>
Mocker.Resolve<RenameSeasonJob>().Start(_testNotification, new { SeriesId = _series.Id, SeasonNumber = -10 }));
}
[Test]
public void should_log_warning_if_no_episode_files_are_found()
{
Mocker.Resolve<RenameSeasonJob>().Start(_testNotification, new { SeriesId = _series.Id, SeasonNumber = 10 });
ExceptionVerification.ExpectedWarns(1);
}
}
}

@ -1,4 +1,5 @@
using System;
/*
using System;
using System.Linq;
using System.Threading;
using NzbDrone.Core.Jobs;
@ -66,3 +67,4 @@ namespace NzbDrone.Core.Test.JobTests
}
}
}
*/

@ -137,8 +137,8 @@
<Compile Include="IndexerTests\IntegrationTests\NzbClubIntegrationTests.cs" />
<Compile Include="IndexerTests\ParserTests\NzbxParserFixture.cs" />
<Compile Include="JobTests\JobRepositoryFixture.cs" />
<Compile Include="JobTests\RenameSeasonJobFixture.cs" />
<Compile Include="DecisionEngineTests\LanguageSpecificationFixture.cs" />
<Compile Include="JobTests\TestJobs.cs" />
<Compile Include="MediaCoverTests\MediaCoverServiceFixture.cs" />
<Compile Include="MediaFileTests\GhostFileCleanupFixture.cs" />
<Compile Include="MediaFileTests\MediaFileRepositoryFixture.cs" />
@ -148,7 +148,6 @@
<Compile Include="RootFolderTests\FreeSpaceOnDrivesFixture.cs" />
<Compile Include="Qualities\QualityFixture.cs" />
<Compile Include="EpisodeParseResultTest.cs" />
<Compile Include="JobTests\PostDownloadScanJobFixture.cs" />
<Compile Include="ParserTests\QualityParserFixture.cs" />
<Compile Include="Configuration\ConfigCachingFixture.cs" />
<Compile Include="DecisionEngineTests\AllowedReleaseGroupSpecificationFixture.cs" />
@ -174,7 +173,6 @@
<Compile Include="ProviderTests\GrowlProviderTest.cs" />
<Compile Include="ProviderTests\DiskProviderTests\ExtractArchiveFixture.cs" />
<Compile Include="ProviderTests\PostDownloadProviderTests\DropFolderImportServiceFixture.cs" />
<Compile Include="JobTests\TestJobs.cs" />
<Compile Include="SeriesStatsTests\SeriesStatisticsFixture.cs" />
<Compile Include="TvTests\SeriesRepositoryTests\QualityProfileRepositoryFixture.cs" />
<Compile Include="UpdateTests\UpdateServiceFixture.cs" />
@ -193,9 +191,7 @@
<Compile Include="OrganizerTests\GetNewFilenameFixture.cs" />
<Compile Include="DecisionEngineTests\MonitoredEpisodeSpecificationFixture.cs" />
<Compile Include="EpisodeStatusTest.cs" />
<Compile Include="JobTests\DiskScanJobTest.cs" />
<Compile Include="DecisionEngineTests\AllowedDownloadSpecificationFixture.cs" />
<Compile Include="JobTests\JobControllerFixture.cs" />
<Compile Include="TvTests\QualityModelFixture.cs" />
<Compile Include="RootFolderTests\RootFolderServiceFixture.cs" />
<Compile Include="HistoryTests\HistoryRepositoryFixture.cs" />

@ -4,6 +4,7 @@ using Moq;
using NUnit.Framework;
using NzbDrone.Common;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Test.Framework;

@ -11,6 +11,7 @@ using Moq;
using NUnit.Framework;
using NzbDrone.Common;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Model;
using NzbDrone.Core.Providers;

@ -11,6 +11,7 @@ using Moq;
using NUnit.Framework;
using NzbDrone.Common;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Model;
using NzbDrone.Core.Providers;

@ -11,6 +11,7 @@ using Moq;
using NUnit.Framework;
using NzbDrone.Common;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Model;
using NzbDrone.Core.Providers;

@ -4,6 +4,8 @@ namespace NzbDrone.Core.DataAugmentation.DailySeries
{
public class DailySeriesService
{
//TODO: add timer command
private readonly IDailySeriesDataProxy _proxy;
private readonly ISeriesService _seriesService;

@ -92,8 +92,6 @@ namespace NzbDrone.Core.Datastore.Migration
.WithColumn("Name").AsString().Unique();
Create.TableForModel("JobDefinitions")
.WithColumn("Enable").AsBoolean()
.WithColumn("Type").AsString().Unique()
.WithColumn("Name").AsString().Unique()
.WithColumn("Interval").AsInt32()
.WithColumn("LastExecution").AsDateTime()

@ -1,32 +0,0 @@
using System;
using System.Linq;
using NzbDrone.Core.Jobs;
using NzbDrone.Core.Model.Notification;
namespace NzbDrone.Core.Instrumentation
{
public class TrimLogsJob : IJob
{
private readonly LogService _logService;
public TrimLogsJob(LogService logService)
{
_logService = logService;
}
public string Name
{
get { return "Trim Logs Job"; }
}
public TimeSpan DefaultInterval
{
get { return TimeSpan.FromDays(1); }
}
public virtual void Start(ProgressNotification notification, dynamic options)
{
_logService.Trim();
}
}
}

@ -1,33 +0,0 @@
using System;
using System.Linq;
using NzbDrone.Core.Model.Notification;
namespace NzbDrone.Core.Jobs
{
public interface IJob
{
/// <summary>
/// Name of the timer.
/// This is the name that will be visible in all UI elements
/// </summary>\\\
string Name { get; }
/// <summary>
/// Default Interval that this job should run at. In seconds.
/// </summary>
/// <remarks>Setting this value to 0 means the job will not be
/// executed by the schedule and is only triggered manually.</remarks>
TimeSpan DefaultInterval { get; }
/// <summary>
/// Starts the job
/// </summary>
/// <param name="notification">Notification object that is passed in by JobProvider.
/// this object should be used to update the progress on the UI</param>
/// <param name="targetId">The that should be used to limit the target of this job</param>
/// /// <param name="secondaryTargetId">The that should be used to limit the target of this job</param>
void Start(ProgressNotification notification, dynamic options);
}
}

@ -1,32 +0,0 @@
using System;
using System.Linq;
using NzbDrone.Core.Model.Notification;
using NzbDrone.Core.Providers;
namespace NzbDrone.Core.Jobs.Implementations
{
public class CleanupRecycleBinJob : IJob
{
private readonly RecycleBinProvider _recycleBinProvider;
public CleanupRecycleBinJob(RecycleBinProvider recycleBinProvider)
{
_recycleBinProvider = recycleBinProvider;
}
public string Name
{
get { return "Cleanup Recycle Bin"; }
}
public TimeSpan DefaultInterval
{
get { return TimeSpan.FromDays(24); }
}
public void Start(ProgressNotification notification, dynamic options)
{
_recycleBinProvider.Cleanup();
}
}
}

@ -1,54 +0,0 @@
using System;
using System.Linq;
using NLog;
using NzbDrone.Core.Model.Notification;
using NzbDrone.Core.Providers.Converting;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Jobs.Implementations
{
public class ConvertEpisodeJob : IJob
{
private readonly HandbrakeProvider _handbrakeProvider;
private readonly AtomicParsleyProvider _atomicParsleyProvider;
private readonly IEpisodeService _episodeService;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public ConvertEpisodeJob(HandbrakeProvider handbrakeProvider, AtomicParsleyProvider atomicParsleyProvider,
IEpisodeService episodeService)
{
_handbrakeProvider = handbrakeProvider;
_atomicParsleyProvider = atomicParsleyProvider;
_episodeService = episodeService;
}
public string Name
{
get { return "Convert Episode"; }
}
public TimeSpan DefaultInterval
{
get { return TimeSpan.FromTicks(0); }
}
public void Start(ProgressNotification notification, dynamic options)
{
if (options == null || options.EpisodeId <= 0)
throw new ArgumentNullException(options);
Episode episode = _episodeService.GetEpisode((int)options.EpisodeId);
notification.CurrentMessage = String.Format("Starting Conversion for {0}", episode);
var outputFile = _handbrakeProvider.ConvertFile(episode, notification);
if (String.IsNullOrEmpty(outputFile))
notification.CurrentMessage = String.Format("Conversion failed for {0}", episode);
_atomicParsleyProvider.RunAtomicParsley(episode, outputFile);
notification.CurrentMessage = String.Format("Conversion completed for {0}", episode);
}
}
}

@ -1,69 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Helpers;
using NzbDrone.Core.Model.Notification;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Jobs.Implementations
{
public class DiskScanJob : IJob
{
private readonly IDiskScanService _diskScanService;
private readonly IConfigService _configService;
private readonly ISeriesRepository _seriesRepository;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public DiskScanJob(IDiskScanService diskScanService,
IConfigService configService, ISeriesRepository seriesRepository)
{
_diskScanService = diskScanService;
_configService = configService;
_seriesRepository = seriesRepository;
}
public string Name
{
get { return "Media File Scan"; }
}
public TimeSpan DefaultInterval
{
get { return TimeSpan.FromHours(6); }
}
public virtual void Start(ProgressNotification notification, dynamic options)
{
IList<Series> seriesToScan;
if (options == null || options.SeriesId == 0)
{
if (_configService.IgnoreArticlesWhenSortingSeries)
seriesToScan = _seriesRepository.All().OrderBy(o => o.Title.IgnoreArticles()).ToList();
else
seriesToScan = _seriesRepository.All().OrderBy(o => o.Title).ToList();
}
else
{
seriesToScan = new List<Series>() { _seriesRepository.Get((int)options.SeriesId) };
}
foreach (var series in seriesToScan)
{
try
{
notification.CurrentMessage = string.Format("Scanning disk for '{0}'", series.Title);
_diskScanService.Scan(series);
notification.CurrentMessage = string.Format("Disk Scan completed for '{0}'", series.Title);
}
catch (Exception e)
{
Logger.ErrorException("An error has occurred while scanning " + series.Title, e);
}
}
}
}
}

@ -1,32 +0,0 @@
using System;
using System.Linq;
using NzbDrone.Core.Model.Notification;
using NzbDrone.Core.Providers;
namespace NzbDrone.Core.Jobs.Implementations
{
public class EmptyRecycleBinJob : IJob
{
private readonly RecycleBinProvider _recycleBinProvider;
public EmptyRecycleBinJob(RecycleBinProvider recycleBinProvider)
{
_recycleBinProvider = recycleBinProvider;
}
public string Name
{
get { return "Empty Recycle Bin"; }
}
public TimeSpan DefaultInterval
{
get { return TimeSpan.FromTicks(0); }
}
public void Start(ProgressNotification notification, dynamic options)
{
_recycleBinProvider.Empty();
}
}
}

@ -1,61 +0,0 @@
using System;
using System.Linq;
using NLog;
using NzbDrone.Common;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Model.Notification;
using NzbDrone.Core.Providers;
namespace NzbDrone.Core.Jobs.Implementations
{
public class PostDownloadScanJob : IJob
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private readonly IDropFolderImportService _dropFolderImportService;
private readonly IConfigService _configService;
private readonly DiskProvider _diskProvider;
public PostDownloadScanJob(IDropFolderImportService dropFolderImportService,IConfigService configService, DiskProvider diskProvider)
{
_dropFolderImportService = dropFolderImportService;
_configService = configService;
_diskProvider = diskProvider;
}
public string Name
{
get { return "Drop folder monitor"; }
}
public TimeSpan DefaultInterval
{
get { return TimeSpan.FromMinutes(1); }
}
public virtual void Start(ProgressNotification notification, dynamic options)
{
string dropFolder;
if (options != null && !String.IsNullOrWhiteSpace(options.Path))
dropFolder = options.Path;
else
dropFolder = _configService.DownloadClientTvDirectory;
if (String.IsNullOrWhiteSpace(dropFolder))
{
Logger.Debug("No drop folder is defined. Skipping.");
return;
}
if (!_diskProvider.FolderExists(dropFolder))
{
Logger.Warn("Unable to Scan for New Downloads - folder Doesn't exist: [{0}]", dropFolder);
return;
}
_dropFolderImportService.ProcessDropFolder(dropFolder);
}
}
}

@ -1,66 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Model.Notification;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Jobs.Implementations
{
public class RefreshEpisodeMetadata : IJob
{
private readonly IMediaFileService _mediaFileService;
private readonly ISeriesRepository _seriesRepository;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public RefreshEpisodeMetadata(IMediaFileService mediaFileService, ISeriesRepository seriesRepository)
{
_mediaFileService = mediaFileService;
_seriesRepository = seriesRepository;
}
public string Name
{
get { return "Refresh Episode Metadata"; }
}
public TimeSpan DefaultInterval
{
get { return TimeSpan.FromTicks(0); }
}
public void Start(ProgressNotification notification, dynamic options)
{
List<Series> seriesToRefresh;
if (options == null || options.SeriesId <= 0)
seriesToRefresh = _seriesRepository.All().ToList();
else
seriesToRefresh = new List<Series> { _seriesRepository.Get(options.SeriesId) };
foreach (var series in seriesToRefresh)
{
RefreshMetadata(notification, series);
}
}
private void RefreshMetadata(ProgressNotification notification, Series series)
{
notification.CurrentMessage = String.Format("Refreshing episode metadata for '{0}'", series.Title);
Logger.Debug("Getting episodes from database for series: {0}", series.Id);
var episodeFiles = _mediaFileService.GetFilesBySeries(series.Id);
if (episodeFiles == null || episodeFiles.Count == 0)
{
Logger.Warn("No episodes in database found for series: {0}", series.Id);
return;
}
notification.CurrentMessage = String.Format("Episode metadata refresh completed for {0}", series.Title);
}
}
}

@ -1,98 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Common.Messaging;
using NzbDrone.Core.Download;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Model.Notification;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Jobs.Implementations
{
public class RenameSeasonJob : IJob
{
private readonly IMediaFileService _mediaFileService;
private readonly ISeriesRepository _seriesRepository;
private readonly IMessageAggregator _messageAggregator;
private readonly IMoveEpisodeFiles _episodeFilesMover;
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
public RenameSeasonJob(IMediaFileService mediaFileService, ISeriesRepository seriesRepository, IMessageAggregator messageAggregator, IMoveEpisodeFiles episodeFilesMover)
{
_mediaFileService = mediaFileService;
_seriesRepository = seriesRepository;
_messageAggregator = messageAggregator;
_episodeFilesMover = episodeFilesMover;
}
public string Name
{
get { return "Rename Season"; }
}
public TimeSpan DefaultInterval
{
get { return TimeSpan.FromTicks(0); }
}
public void Start(ProgressNotification notification, dynamic options)
{
if (options == null || options.SeriesId <= 0)
throw new ArgumentException("options");
if (options.SeasonNumber < 0)
throw new ArgumentException("options.SeasonNumber");
var series = _seriesRepository.Get((int)options.SeriesId);
notification.CurrentMessage = String.Format("Renaming episodes for {0} Season {1}", series.Title, options.SeasonNumber);
logger.Debug("Getting episodes from database for series: {0} and season: {1}", options.SeriesId, options.SeasonNumber);
IList<EpisodeFile> episodeFiles = _mediaFileService.GetFilesBySeason((int)options.SeriesId, (int)options.SeasonNumber);
if (episodeFiles == null || !episodeFiles.Any())
{
logger.Warn("No episodes in database found for series: {0} and season: {1}.", options.SeriesId, options.SeasonNumber);
return;
}
var newEpisodeFiles = new List<EpisodeFile>();
var oldEpisodeFiles = new List<EpisodeFile>();
foreach (var episodeFile in episodeFiles)
{
try
{
var oldFile = new EpisodeFile(episodeFile);
var newFile = _episodeFilesMover.MoveEpisodeFile(episodeFile);
if (newFile != null)
{
newEpisodeFiles.Add(newFile);
oldEpisodeFiles.Add(oldFile);
}
}
catch (Exception e)
{
logger.WarnException("An error has occurred while renaming file", e);
}
}
if (!oldEpisodeFiles.Any())
{
logger.Trace("No episodes were renamed for: {0} Season {1}, no changes were made", series.Title,
options.SeasonNumber);
notification.CurrentMessage = String.Format("Rename completed for: {0} Season {1}, no changes were made", series.Title, options.SeasonNumber);
return;
}
//Start AfterRename
_messageAggregator.PublishEvent(new SeriesRenamedEvent(series));
notification.CurrentMessage = String.Format("Rename completed for {0} Season {1}", series.Title, options.SeasonNumber);
}
}
}

@ -1,98 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Common.Messaging;
using NzbDrone.Core.Download;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Model.Notification;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Jobs.Implementations
{
public class RenameSeriesJob : IJob
{
private readonly IMediaFileService _mediaFileService;
private readonly ISeriesRepository _seriesRepository;
private readonly IMessageAggregator _messageAggregator;
private readonly IMoveEpisodeFiles _moveEpisodeFiles;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public RenameSeriesJob(IMediaFileService mediaFileService, ISeriesRepository seriesRepository, IMessageAggregator messageAggregator, IMoveEpisodeFiles moveEpisodeFiles)
{
_mediaFileService = mediaFileService;
_seriesRepository = seriesRepository;
_messageAggregator = messageAggregator;
_moveEpisodeFiles = moveEpisodeFiles;
}
public string Name
{
get { return "Rename Series"; }
}
public TimeSpan DefaultInterval
{
get { return TimeSpan.FromTicks(0); }
}
public void Start(ProgressNotification notification, dynamic options)
{
List<Series> seriesToRename;
if (options == null || options.SeriesId <= 0)
{
seriesToRename = _seriesRepository.All().ToList();
}
else
{
seriesToRename = new List<Series> { _seriesRepository.Get((int)options.SeriesId) };
}
foreach (var series in seriesToRename)
{
notification.CurrentMessage = String.Format("Renaming episodes for '{0}'", series.Title);
Logger.Debug("Getting episodes from database for series: {0}", series.Id);
var episodeFiles = _mediaFileService.GetFilesBySeries(series.Id);
if (episodeFiles == null || episodeFiles.Count == 0)
{
Logger.Warn("No episodes in database found for series: {0}", series.Id);
return;
}
var newEpisodeFiles = new List<EpisodeFile>();
var oldEpisodeFiles = new List<EpisodeFile>();
foreach (var episodeFile in episodeFiles)
{
try
{
var oldFile = new EpisodeFile(episodeFile);
var newFile = _moveEpisodeFiles.MoveEpisodeFile(episodeFile);
if (newFile != null)
{
newEpisodeFiles.Add(newFile);
oldEpisodeFiles.Add(oldFile);
}
}
catch (Exception e)
{
Logger.WarnException("An error has occurred while renaming file", e);
}
}
//Start AfterRename
_messageAggregator.PublishEvent(new SeriesRenamedEvent(series));
notification.CurrentMessage = String.Format("Rename completed for {0}", series.Title);
}
}
}
}

@ -1,35 +0,0 @@
using System;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Model.Notification;
namespace NzbDrone.Core.Jobs.Implementations
{
public class RssSyncJob : IJob
{
private readonly IRssSyncService _rssSyncServiceService;
private readonly IConfigService _configService;
public RssSyncJob(IRssSyncService rssSyncServiceService, IConfigService configService)
{
_rssSyncServiceService = rssSyncServiceService;
_configService = configService;
}
public string Name
{
get { return "RSS Sync"; }
}
public TimeSpan DefaultInterval
{
get { return TimeSpan.FromMinutes(_configService.RssSyncInterval); }
}
public void Start(ProgressNotification notification, dynamic options)
{
_rssSyncServiceService.Sync();
}
}
}

@ -1,87 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.DataAugmentation.DailySeries;
using NzbDrone.Core.Helpers;
using NzbDrone.Core.Model.Notification;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Jobs.Implementations
{
public class UpdateInfoJob : IJob
{
private readonly ISeriesService _seriesService;
private readonly IEpisodeService _episodeService;
private readonly DailySeriesService _dailySeriesService;
private readonly IConfigService _configService;
private readonly ISeriesRepository _seriesRepository;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public UpdateInfoJob(ISeriesService seriesService, IEpisodeService episodeService,
DailySeriesService dailySeriesService, IConfigService configService, ISeriesRepository seriesRepository)
{
_seriesService = seriesService;
_episodeService = episodeService;
_dailySeriesService = dailySeriesService;
_configService = configService;
_seriesRepository = seriesRepository;
}
public string Name
{
get { return "Update Episode Info"; }
}
public TimeSpan DefaultInterval
{
get { return TimeSpan.FromHours(12); }
}
public virtual void Start(ProgressNotification notification, dynamic options)
{
IList<Series> listOfSeriesToUpdate;
if (options == null || options.SeriesId == 0)
{
if (_configService.IgnoreArticlesWhenSortingSeries)
{
listOfSeriesToUpdate = _seriesRepository.All().OrderBy(o => o.Title.IgnoreArticles()).ToList();
}
else
{
listOfSeriesToUpdate = _seriesRepository.All().OrderBy(o => o.Title).ToList();
}
}
else
{
listOfSeriesToUpdate = new List<Series>
{
_seriesRepository.Get((int) options.SeriesId)
};
}
//Update any Daily Series in the DB with the IsDaily flag
_dailySeriesService.UpdateDailySeries();
foreach (var seriesToUpdate in listOfSeriesToUpdate)
{
var series = seriesToUpdate;
try
{
notification.CurrentMessage = "Updating " + series.Title;
series = _seriesService.UpdateSeriesInfo(series.Id);
_episodeService.RefreshEpisodeInfo(series);
notification.CurrentMessage = "Update completed for " + series.Title;
}
catch (Exception ex)
{
Logger.ErrorException("Failed to update episode info for series: " + series.Title, ex);
}
}
}
}
}

@ -1,47 +0,0 @@
using System;
using System.Linq;
using NLog;
using NzbDrone.Core.Model.Notification;
using NzbDrone.Core.Providers;
namespace NzbDrone.Core.Jobs.Implementations
{
public class XemUpdateJob : IJob
{
private readonly XemProvider _xemProvider;
private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
public XemUpdateJob(XemProvider xemProvider)
{
_xemProvider = xemProvider;
}
public string Name
{
get { return "XEM Update"; }
}
public TimeSpan DefaultInterval
{
get { return TimeSpan.FromHours(12); }
}
public virtual void Start(ProgressNotification notification, dynamic options)
{
if (options == null || options.SeriesId == 0)
{
_logger.Trace("Starting XEM Update for all series");
_xemProvider.UpdateMappings();
}
else
{
_logger.Trace("Starting XEM Update for series: {0}", options.SeriesId);
_xemProvider.UpdateMappings((int)options.SeriesId);
}
_logger.Trace("XEM Update complete");
}
}
}

@ -1,188 +0,0 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using NLog;
using NzbDrone.Common.Messaging;
using NzbDrone.Core.Lifecycle;
using NzbDrone.Core.Model.Notification;
using NzbDrone.Core.Providers;
namespace NzbDrone.Core.Jobs
{
public interface IJobController
{
bool IsProcessing { get; }
IEnumerable<JobQueueItem> Queue { get; }
void EnqueueScheduled();
void Enqueue(Type jobType, dynamic options = null, JobQueueItem.JobSourceType source = JobQueueItem.JobSourceType.User);
bool Enqueue(string jobTypeString);
}
public class JobController : IJobController, IHandle<ApplicationShutdownRequested>
{
private readonly NotificationProvider _notificationProvider;
private readonly IEnumerable<IJob> _jobs;
private readonly IJobRepository _jobRepository;
private readonly Logger _logger;
private readonly BlockingCollection<JobQueueItem> _queue = new BlockingCollection<JobQueueItem>();
private ProgressNotification _notification;
private readonly CancellationTokenSource _cancellationTokenSource;
public JobController(NotificationProvider notificationProvider, IEnumerable<IJob> jobs, IJobRepository jobRepository, Logger logger)
{
_notificationProvider = notificationProvider;
_jobs = jobs;
_jobRepository = jobRepository;
_logger = logger;
_cancellationTokenSource = new CancellationTokenSource();
Task.Factory.StartNew(ProcessQueue, _cancellationTokenSource.Token);
}
public bool IsProcessing { get; private set; }
public IEnumerable<JobQueueItem> Queue
{
get
{
return _queue;
}
}
public void EnqueueScheduled()
{
if (IsProcessing)
{
_logger.Trace("Queue is already running. Ignoring scheduler request.");
return;
}
var pendingJobs = _jobRepository.GetPendingJobs()
.Select(c => _jobs.Single(t => t.GetType().ToString() == c.Type)
.GetType()).ToList();
pendingJobs.ForEach(jobType => Enqueue(jobType, source: JobQueueItem.JobSourceType.Scheduler));
_logger.Trace("{0} Scheduled tasks have been added to the queue", pendingJobs.Count);
}
public void Enqueue(Type jobType, dynamic options = null, JobQueueItem.JobSourceType source = JobQueueItem.JobSourceType.User)
{
IsProcessing = true;
var queueItem = new JobQueueItem
{
JobType = jobType,
Options = options,
Source = source
};
_logger.Debug("Attempting to queue {0}", queueItem);
lock (_queue)
{
if (!_queue.Contains(queueItem))
{
_queue.Add(queueItem);
_logger.Trace("Job {0} added to the queue. current items in queue: {1}", queueItem, _queue.Count);
}
else
{
_logger.Info("{0} already exists in the queue. Skipping. current items in queue: {1}", queueItem, _queue.Count);
}
}
}
public bool Enqueue(string jobTypeString)
{
var type = Type.GetType(jobTypeString);
if (type == null)
return false;
Enqueue(type);
return true;
}
private void ProcessQueue()
{
while (true)
{
try
{
IsProcessing = false;
var item = _queue.Take();
Execute(item);
}
catch (ThreadAbortException e)
{
_logger.Warn(e.Message);
}
catch (Exception e)
{
_logger.ErrorException("Error has occurred in queue processor thread", e);
}
}
}
private void Execute(JobQueueItem queueItem)
{
IsProcessing = true;
var jobImplementation = _jobs.SingleOrDefault(t => t.GetType() == queueItem.JobType);
if (jobImplementation == null)
{
_logger.Error("Unable to locate implementation for '{0}'. Make sure it is properly registered.", queueItem.JobType);
return;
}
var jobDefinition = _jobRepository.GetDefinition(queueItem.JobType);
using (_notification = new ProgressNotification(jobImplementation.Name))
{
try
{
_logger.Debug("Starting {0}. Last execution {1}", queueItem, jobDefinition.LastExecution);
var sw = Stopwatch.StartNew();
_notificationProvider.Register(_notification);
jobImplementation.Start(_notification, queueItem.Options);
_notification.Status = ProgressNotificationStatus.Completed;
jobDefinition.LastExecution = DateTime.Now;
jobDefinition.Success = true;
sw.Stop();
_logger.Debug("Job {0} successfully completed in {1:0}.{2} seconds.", queueItem, sw.Elapsed.TotalSeconds, sw.Elapsed.Milliseconds / 100,
sw.Elapsed.Seconds);
}
catch (Exception e)
{
_logger.ErrorException("An error has occurred while executing job [" + jobImplementation.Name + "].", e);
_notification.Status = ProgressNotificationStatus.Failed;
_notification.CurrentMessage = jobImplementation.Name + " Failed.";
jobDefinition.LastExecution = DateTime.Now;
jobDefinition.Success = false;
}
}
//Only update last execution status if was triggered by the scheduler
if (queueItem.Options == null)
{
_jobRepository.Update(jobDefinition);
}
}
public void Handle(ApplicationShutdownRequested message)
{
_cancellationTokenSource.Cancel();
}
}
}

@ -5,8 +5,6 @@ namespace NzbDrone.Core.Jobs
{
public class JobDefinition : ModelBase
{
public Boolean Enable { get; set; }
public String Type { get; set; }
public String Name { get; set; }
public Int32 Interval { get; set; }
public DateTime LastExecution { get; set; }

@ -4,7 +4,9 @@ using System.Linq;
using NLog;
using NzbDrone.Common.Messaging;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Lifecycle;
using NzbDrone.Core.Providers;
namespace NzbDrone.Core.Jobs
{
@ -16,60 +18,60 @@ namespace NzbDrone.Core.Jobs
public class JobRepository : BasicRepository<JobDefinition>, IJobRepository, IHandle<ApplicationStartedEvent>
{
private readonly IEnumerable<IJob> _jobs;
private readonly Logger _logger;
public JobRepository(IDatabase database, IEnumerable<IJob> jobs, Logger logger, IMessageAggregator messageAggregator)
public JobRepository(IDatabase database, Logger logger, IMessageAggregator messageAggregator)
: base(database, messageAggregator)
{
_jobs = jobs;
_logger = logger;
}
public JobDefinition GetDefinition(Type type)
{
return Query.Single(c => c.Type == type.FullName);
return Query.Single(c => c.Name == type.FullName);
}
public IList<JobDefinition> GetPendingJobs()
{
return Query.Where(c => c.Enable == true && c.Interval != 2).ToList().Where(c => c.LastExecution < DateTime.Now.AddMinutes(-c.Interval)).ToList();
return Query.Where(c => c.Interval != 0).ToList().Where(c => c.LastExecution < DateTime.Now.AddMinutes(-c.Interval)).ToList();
}
public void Handle(ApplicationStartedEvent message)
{
var currentJobs = All().ToList();
_logger.Debug("Initializing jobs. Available: {0} Existing:{1}", _jobs.Count(), currentJobs.Count());
foreach (var currentJob in currentJobs)
var timers = new[]
{
new JobDefinition{ Interval = 25, Name = typeof(RssSyncCommand).FullName},
new JobDefinition{ Interval = 24*60, Name = typeof(UpdateXemMappings).FullName}
};
_logger.Debug("Initializing jobs. Available: {0} Existing:{1}", timers.Count(), currentJobs.Count());
foreach (var job in currentJobs)
{
if (_jobs.All(c => c.GetType().ToString() != currentJob.Type))
if (!timers.Any(c => c.Name == job.Name))
{
_logger.Debug("Removing job from database '{0}'", currentJob.Name);
Delete(currentJob.Id);
_logger.Debug("Removing job from database '{0}'", job.Name);
Delete(job.Id);
}
}
foreach (var job in _jobs)
foreach (var job in timers)
{
var jobDefinition = currentJobs.SingleOrDefault(c => c.Type == job.GetType().ToString());
var currentDefinition = currentJobs.SingleOrDefault(c => c.Name == job.GetType().ToString());
if (jobDefinition == null)
if (currentDefinition == null)
{
jobDefinition = new JobDefinition
{
Type = job.GetType().ToString(),
LastExecution = DateTime.Now
};
currentDefinition = job;
}
jobDefinition.Enable = job.DefaultInterval.TotalSeconds > 0;
jobDefinition.Name = job.Name;
jobDefinition.Interval = Convert.ToInt32(job.DefaultInterval.TotalMinutes);
currentDefinition.Interval = job.Interval;
Upsert(jobDefinition);
Upsert(currentDefinition);
}
}
}

@ -1,4 +1,5 @@
using System.Timers;
using System;
using System.Timers;
using NzbDrone.Common.Messaging;
using NzbDrone.Core.Lifecycle;
@ -8,23 +9,37 @@ namespace NzbDrone.Core.Jobs
IHandle<ApplicationStartedEvent>,
IHandle<ApplicationShutdownRequested>
{
private readonly IJobController _jobController;
private readonly IJobRepository _jobRepository;
private readonly IMessageAggregator _messageAggregator;
private readonly Timer _timer;
public JobTimer(IJobController jobController)
public JobTimer(IJobRepository jobRepository, IMessageAggregator messageAggregator)
{
_jobController = jobController;
_jobRepository = jobRepository;
_messageAggregator = messageAggregator;
_timer = new Timer();
}
public void Handle(ApplicationStartedEvent message)
{
_timer.Interval = 1000 * 30;
_timer.Elapsed += (o, args) => _jobController.EnqueueScheduled();
_timer.Elapsed += (o, args) => ExecuteCommands();
_timer.Start();
}
private void ExecuteCommands()
{
var jobs = _jobRepository.GetPendingJobs();
foreach (var jobDefinition in jobs)
{
var commandType = Type.GetType(jobDefinition.Name);
var command = (ICommand)Activator.CreateInstance(commandType);
_messageAggregator.PublishCommand(command);
}
}
public void Handle(ApplicationShutdownRequested message)
{
_timer.Stop();

@ -1,54 +0,0 @@
using System;
using NLog;
using NzbDrone.Common;
using NzbDrone.Core.Jobs;
using NzbDrone.Core.Model.Notification;
namespace NzbDrone.Core.Lifecycle
{
public class AppShutdownJob : IJob
{
private readonly ProcessProvider _processProvider;
private readonly ServiceProvider _serviceProvider;
private readonly Logger _logger;
public AppShutdownJob(ProcessProvider processProvider, ServiceProvider serviceProvider, Logger logger)
{
_processProvider = processProvider;
_serviceProvider = serviceProvider;
_logger = logger;
}
public string Name
{
get { return "Shutdown NzbDrone"; }
}
public TimeSpan DefaultInterval
{
get { return TimeSpan.FromTicks(0); }
}
public virtual void Start(ProgressNotification notification, dynamic options)
{
notification.CurrentMessage = "Shutting down NzbDrone";
_logger.Info("Shutting down NzbDrone");
if (_serviceProvider.ServiceExist(ServiceProvider.NZBDRONE_SERVICE_NAME)
&& _serviceProvider.IsServiceRunning(ServiceProvider.NZBDRONE_SERVICE_NAME))
{
_logger.Debug("Stopping NzbDrone Service");
_serviceProvider.Stop(ServiceProvider.NZBDRONE_SERVICE_NAME);
}
else
{
_logger.Debug("Stopping NzbDrone console");
var currentProcess = _processProvider.GetCurrentProcess();
_processProvider.Kill(currentProcess.Id);
}
}
}
}

@ -0,0 +1,8 @@
using NzbDrone.Common.Messaging;
namespace NzbDrone.Core.MediaFiles.Commands
{
public class CleanUpRecycleBinCommand : ICommand
{
}
}

@ -1,15 +1,15 @@
using System;
using System.IO;
using System.Linq;
using NLog;
using NzbDrone.Common;
using NzbDrone.Common.Messaging;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.MediaFiles.Commands;
using NzbDrone.Core.Tv.Events;
namespace NzbDrone.Core.Providers
namespace NzbDrone.Core.MediaFiles
{
public class RecycleBinProvider : IHandleAsync<SeriesDeletedEvent>
public class RecycleBinProvider : IHandleAsync<SeriesDeletedEvent>, IExecute<CleanUpRecycleBinCommand>
{
private readonly DiskProvider _diskProvider;
private readonly IConfigService _configService;
@ -139,7 +139,15 @@ namespace NzbDrone.Core.Providers
public void HandleAsync(SeriesDeletedEvent message)
{
DeleteDirectory(message.Series.Path);
if (message.DeleteFiles)
{
DeleteDirectory(message.Series.Path);
}
}
public void Execute(CleanUpRecycleBinCommand message)
{
Cleanup();
}
}
}

@ -244,6 +244,7 @@
<Compile Include="Indexers\IndexerWithSetting.cs" />
<Compile Include="Indexers\RssSyncCommand.cs" />
<Compile Include="Lifecycle\ApplicationShutdownRequested.cs" />
<Compile Include="MediaFiles\Commands\CleanUpRecycleBinCommand.cs" />
<Compile Include="MediaFiles\Events\EpisodeDownloadedEvent.cs" />
<Compile Include="Download\EpisodeGrabbedEvent.cs" />
<Compile Include="Download\SeriesRenamedEvent.cs" />
@ -283,24 +284,10 @@
<Compile Include="Indexers\Wombles\Wombles.cs" />
<Compile Include="Indexers\Wombles\WomblesParser.cs" />
<Compile Include="Instrumentation\LogRepository.cs" />
<Compile Include="Jobs\IJob.cs" />
<Compile Include="Jobs\Implementations\CleanupRecycleBinJob.cs" />
<Compile Include="Jobs\Implementations\ConvertEpisodeJob.cs" />
<Compile Include="Jobs\Implementations\DiskScanJob.cs" />
<Compile Include="Jobs\Implementations\EmptyRecycleBinJob.cs" />
<Compile Include="Jobs\Implementations\PostDownloadScanJob.cs" />
<Compile Include="Jobs\Implementations\RefreshEpisodeMetadata.cs" />
<Compile Include="Jobs\Implementations\RenameSeasonJob.cs" />
<Compile Include="Jobs\Implementations\RenameSeriesJob.cs" />
<Compile Include="Jobs\Implementations\RssSyncJob.cs" />
<Compile Include="Jobs\Implementations\UpdateInfoJob.cs" />
<Compile Include="Jobs\Implementations\XemUpdateJob.cs" />
<Compile Include="Jobs\JobController.cs" />
<Compile Include="Jobs\JobDefinition.cs" />
<Compile Include="Jobs\JobQueueItem.cs" />
<Compile Include="Jobs\JobRepository.cs" />
<Compile Include="Jobs\JobTimer.cs" />
<Compile Include="Lifecycle\AppShutdownJob.cs" />
<Compile Include="Lifecycle\ApplicationStartedEvent.cs" />
<Compile Include="MediaCover\MediaCover.cs" />
<Compile Include="MediaFiles\EpisodeFileMovingService.cs" />
@ -348,6 +335,7 @@
<Compile Include="Parser\Model\ReportInfo.cs" />
<Compile Include="Parser\Parser.cs" />
<Compile Include="Parser\ParsingService.cs" />
<Compile Include="Providers\UpdateXemMappings.cs" />
<Compile Include="Qualities\QualitySizeRepository.cs" />
<Compile Include="Qualities\QualityProfileRepository.cs" />
<Compile Include="SeriesStats\SeriesStatisticsService.cs" />
@ -386,13 +374,11 @@
<Compile Include="Download\Clients\Nzbget\NzbgetClient.cs" />
<Compile Include="Providers\VideoFileInfoReader.cs" />
<Compile Include="Download\Clients\PneumaticClient.cs" />
<Compile Include="Providers\RecycleBinProvider.cs" />
<Compile Include="MediaFiles\RecycleBinProvider.cs" />
<Compile Include="Tv\SeasonService.cs" />
<Compile Include="Instrumentation\TrimLogsJob.cs" />
<Compile Include="SeriesStats\SeriesStatistics.cs" />
<Compile Include="SeriesStats\SeriesStatisticsRepository.cs" />
<Compile Include="Tv\SeriesTypes.cs" />
<Compile Include="Update\AppUpdateJob.cs" />
<Compile Include="Model\Xbmc\TvShowResponse.cs" />
<Compile Include="Model\Xbmc\TvShow.cs" />
<Compile Include="Model\Xbmc\VersionResult.cs" />

@ -0,0 +1,8 @@
using NzbDrone.Common.Messaging;
namespace NzbDrone.Core.Providers
{
public class UpdateXemMappings : ICommand
{
}
}

@ -2,11 +2,12 @@
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Common.Messaging;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Providers
{
public class XemProvider
public class XemProvider :IExecute<UpdateXemMappings>
{
private readonly IEpisodeService _episodeService;
private readonly XemCommunicationProvider _xemCommunicationProvider;
@ -117,5 +118,10 @@ namespace NzbDrone.Core.Providers
_logger.WarnException("Error updating scene numbering mappings for: " + series, ex);
}
}
public void Execute(UpdateXemMappings message)
{
UpdateMappings();
}
}
}

@ -1,31 +0,0 @@
using System;
using NzbDrone.Core.Jobs;
using NzbDrone.Core.Model.Notification;
namespace NzbDrone.Core.Update
{
public class AppUpdateJob : IJob
{
private readonly IUpdateService _updateService;
public AppUpdateJob(IUpdateService updateService)
{
_updateService = updateService;
}
public string Name
{
get { return "Update Application Job"; }
}
public TimeSpan DefaultInterval
{
get { return TimeSpan.FromDays(2); }
}
public virtual void Start(ProgressNotification notification, dynamic options)
{
_updateService.InstallAvailableUpdate();
}
}
}

@ -25,8 +25,8 @@
layout="${date:format=yy-M-d HH\:mm\:ss.f}|${logger}}|${level}|${message}|${exception:format=ToString}"/>
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="consoleLogger"/>
<logger name="*" minlevel="Trace" writeTo="udpTarget"/>
<logger name="*" minlevel="Trace" writeTo="consoleLogger"/>
<logger name="*" minlevel="Off" writeTo="udpTarget"/>
<logger name="*" minlevel="Trace" writeTo="rollingFileLogger"/>
</rules>
</nlog>

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@ -92,7 +92,7 @@
<HintPath>..\packages\FluentMigrator.1.0.6.0\tools\FluentMigrator.Runner.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AspNet.SignalR.Core">
<HintPath>..\packages\Microsoft.AspNet.SignalR.Core.1.0.1\lib\net40\Microsoft.AspNet.SignalR.Core.dll</HintPath>
<HintPath>..\NzbDrone.Api\bin\x86\Debug\Microsoft.AspNet.SignalR.Core.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AspNet.SignalR.Owin">
<HintPath>..\packages\Microsoft.AspNet.SignalR.Owin.1.0.1\lib\net40\Microsoft.AspNet.SignalR.Owin.dll</HintPath>

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptLibraryMappings">
<file url="PROJECT" libraries="{jQuery-1.9.1, libraries}" />
<file url="PROJECT" libraries="{libraries}" />
</component>
</project>

Loading…
Cancel
Save