1
0
mirror of https://github.com/Radarr/Radarr.git synced 2024-11-04 10:02:40 +01:00

splited jobprovider into jobrepo, jobcontroller, moved to object db.

This commit is contained in:
kay.one 2013-02-17 23:59:43 -08:00
parent 97398f604b
commit 40f3a8663d
38 changed files with 635 additions and 634 deletions

View File

@ -16,9 +16,9 @@ namespace NzbDrone.Api.Series
public class SeriesModule : NzbDroneApiModule
{
private readonly SeriesProvider _seriesProvider;
private readonly JobProvider _jobProvider;
private readonly JobController _jobProvider;
public SeriesModule(SeriesProvider seriesProvider, JobProvider jobProvider)
public SeriesModule(SeriesProvider seriesProvider, JobController jobProvider)
: base("/Series")
{
_seriesProvider = seriesProvider;

View File

@ -104,7 +104,7 @@ public void All_metadata_clients_should_be_registered()
[Test]
public void jobs_are_initialized()
{
kernel.Resolve<JobProvider>().All().Should().HaveSameCount(jobs);
kernel.Resolve<IJobRepository>().All().Should().HaveSameCount(jobs);
}
[Test]
@ -134,8 +134,8 @@ public void quality_profile_initialized()
[Test]
public void JobProvider_should_be_singletone()
{
var first = kernel.Resolve<JobProvider>();
var second = kernel.Resolve<JobProvider>();
var first = kernel.Resolve<JobController>();
var second = kernel.Resolve<JobController>();
first.Should().BeSameAs(second);
}

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Test.Framework;
@ -215,7 +216,7 @@ public void Truncate_should_truncate_strings_to_max_specified_number_of_bytes()
var resultString = str.Truncate(1000);
//Resolve
var result = new System.Text.UTF8Encoding().GetBytes(resultString);
var result = new UTF8Encoding().GetBytes(resultString);
result.Length.Should().BeLessOrEqualTo(1000);
}
@ -229,7 +230,7 @@ public void Truncate_should_not_truncate_string_shorter_than_max_bytes()
var resultString = str.Truncate(1000);
//Resolve
var result = new System.Text.UTF8Encoding().GetBytes(resultString);
var result = new UTF8Encoding().GetBytes(resultString);
result.Length.Should().Be(11);
}

View File

@ -28,14 +28,28 @@ protected FileStream OpenRead(params string[] path)
}
}
public abstract class CoreTest<TSubject> : CoreTest
public abstract class CoreTest<TSubject> : CoreTest where TSubject: class
{
private TSubject _subject;
[SetUp]
public void CoreTestSetup()
{
Subject = Mocker.Resolve<TSubject>();
_subject = null;
}
protected TSubject Subject
{
get
{
if (_subject == null)
{
_subject = Mocker.Resolve<TSubject>();
}
return _subject;
}
protected TSubject Subject { get; set; }
}
}
}

View File

@ -8,6 +8,23 @@
namespace NzbDrone.Core.Test.Framework
{
public abstract class RepositoryTest<TRepository, TModel> : ObjectDbTest<TRepository>
where TRepository : class, IBasicRepository<TModel>
where TModel : ModelBase, new()
{
protected BasicRepository<TModel> Storage { get; private set; }
[SetUp]
public void RepositoryTestSetup()
{
WithObjectDb();
Storage = Mocker.Resolve<BasicRepository<TModel>>();
}
}
public abstract class ObjectDbTest<TSubject> : ObjectDbTest where TSubject : class
{
private TSubject _subject;

View File

@ -8,6 +8,7 @@
using NUnit.Framework;
using NzbDrone.Common;
using NzbDrone.Core.Jobs;
using NzbDrone.Core.Lifecycle;
using NzbDrone.Core.Model;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Core;

View File

@ -0,0 +1,228 @@
using System.Linq;
using System;
using System.Collections.Generic;
using System.Threading;
using FluentAssertions;
using Moq;
using NCrunch.Framework;
using NUnit.Framework;
using NzbDrone.Common;
using NzbDrone.Core.Jobs;
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;
BrokenJob _brokenJob;
DisabledJob _disabledJob;
private JobDefinition _updatedJob = null;
[SetUp]
public void Setup()
{
_fakeJob = new FakeJob();
_slowJob = new SlowJob();
_brokenJob = new BrokenJob();
_disabledJob = new DisabledJob();
_updatedJob = null;
IEnumerable<IJob> jobs = new List<IJob> { _fakeJob, _slowJob, _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 stopWatch = Mocker.Resolve<JobController>().StopWatch;
while (stopWatch.IsRunning)
{
Thread.Sleep(10);
}
}
[Test]
public void running_scheduled_jobs_should_updates_last_execution_time()
{
GivenPendingJob(new List<JobDefinition> { new JobDefinition { TypeName = _fakeJob.GetType().FullName } });
Subject.QueueScheduled();
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 { TypeName = _brokenJob.GetType().FullName } });
Subject.QueueScheduled();
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_async_job_again()
{
Subject.QueueJob(typeof(FakeJob));
WaitForQueue();
Subject.QueueJob(typeof(FakeJob));
WaitForQueue();
Subject.Queue.Should().BeEmpty();
_fakeJob.ExecutionCount.Should().Be(2);
}
[Test]
public void no_concurent_jobs()
{
Subject.QueueJob(typeof(SlowJob), 1);
Subject.QueueJob(typeof(SlowJob), 2);
Subject.QueueJob(typeof(SlowJob), 3);
WaitForQueue();
Subject.Queue.Should().BeEmpty();
_slowJob.ExecutionCount.Should().Be(3);
ExceptionVerification.AssertNoUnexcpectedLogs();
}
[Test]
public void can_run_broken_job_again()
{
Subject.QueueJob(typeof(BrokenJob));
WaitForQueue();
Subject.QueueJob(typeof(BrokenJob));
WaitForQueue();
_brokenJob.ExecutionCount.Should().Be(2);
ExceptionVerification.ExpectedErrors(2);
}
[Test]
public void schedule_hit_should_be_ignored_if_queue_is_running()
{
Subject.QueueJob(typeof(SlowJob));
Subject.QueueScheduled();
WaitForQueue();
_slowJob.ExecutionCount.Should().Be(1);
_fakeJob.ExecutionCount.Should().Be(0);
}
[Test]
public void can_queue_jobs_at_the_same_time()
{
Subject.QueueJob(typeof(SlowJob));
var thread1 = new Thread(() => Subject.QueueJob(typeof(FakeJob)));
var thread2 = new Thread(() => Subject.QueueJob(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.QueueJob(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 { TypeName = _slowJob.GetType().FullName } });
var jobThread = new Thread(Subject.QueueScheduled);
jobThread.Start();
Thread.Sleep(200);
Subject.QueueJob(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.QueueJob(typeof(UpdateInfoJob));
WaitForQueue();
ExceptionVerification.ExpectedErrors(1);
}
[Test]
public void scheduled_job_should_have_scheduler_as_source()
{
GivenPendingJob(new List<JobDefinition> { new JobDefinition { TypeName = _slowJob.GetType().FullName }, new JobDefinition { TypeName = _slowJob.GetType().FullName } });
Subject.QueueScheduled();
Subject.Queue.Should().OnlyContain(c => c.Source == JobQueueItem.JobSourceType.Scheduler);
WaitForQueue();
}
}
}

View File

@ -0,0 +1,161 @@
// ReSharper disable RedundantUsingDirective
using System.Linq;
using System;
using System.Collections.Generic;
using System.Threading;
using FizzWare.NBuilder;
using FluentAssertions;
using NCrunch.Framework;
using NUnit.Framework;
using NzbDrone.Common;
using NzbDrone.Core.Jobs;
using NzbDrone.Core.Model;
using NzbDrone.Core.Repository;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.JobTests
{
[TestFixture]
public class JobRepositoryFixture : RepositoryTest<JobRepository, JobDefinition>
{
FakeJob _fakeJob;
DisabledJob _disabledJob;
[SetUp]
public void Setup()
{
_fakeJob = new FakeJob();
_disabledJob = new DisabledJob();
}
[Test]
public void Init_should_add_defintaions()
{
IEnumerable<IJob> baseFakeJobs = new List<IJob> { _fakeJob };
Mocker.SetConstant(baseFakeJobs);
Subject.Init();
Storage.All().Should().HaveCount(1);
Storage.All()[0].Interval.Should().Be((Int32)_fakeJob.DefaultInterval.TotalMinutes);
Storage.All()[0].Name.Should().Be(_fakeJob.Name);
Storage.All()[0].TypeName.Should().Be(_fakeJob.GetType().ToString());
Storage.All()[0].LastExecution.Should().HaveYear(DateTime.Now.Year);
Storage.All()[0].LastExecution.Should().HaveMonth(DateTime.Now.Month);
Storage.All()[0].LastExecution.Should().HaveDay(DateTime.Today.Day);
Storage.All()[0].Enable.Should().BeTrue();
}
[Test]
public void inti_should_removed_jobs_that_no_longer_exist()
{
IEnumerable<IJob> fakeJobs = new List<IJob> { _fakeJob };
Mocker.SetConstant(fakeJobs);
Subject.Init();
var deletedJob = Builder<JobDefinition>.CreateNew()
.With(c => c.OID = 0)
.Build();
Db.Insert(deletedJob);
Subject.Init();
var registeredJobs = Storage.All();
registeredJobs.Should().HaveCount(1);
registeredJobs.Should().NotContain(c => c.TypeName == deletedJob.TypeName);
}
[Test]
public void inti_should_removed_jobs_that_no_longer_exist_even_with_same_name()
{
IEnumerable<IJob> fakeJobs = new List<IJob> { _fakeJob };
Mocker.SetConstant(fakeJobs);
Subject.Init();
var deletedJob = Builder<JobDefinition>.CreateNew()
.With(c => c.Name = _fakeJob.Name)
.With(c => c.OID = 0)
.Build();
Db.Insert(deletedJob);
Subject.Init();
var registeredJobs = Storage.All();
registeredJobs.Should().HaveCount(1);
registeredJobs.Should().NotContain(c => c.TypeName == deletedJob.TypeName);
}
[Test]
public void init_should_update_existing_job()
{
var oldJob = Builder<JobDefinition>.CreateNew()
.With(c => c.OID = 0)
.With(c => c.Name = "OldName")
.With(c => c.TypeName = 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();
Storage.Add(oldJob);
var newJob = new FakeJob();
IEnumerable<IJob> fakeJobs = new List<IJob> { newJob };
Mocker.SetConstant(fakeJobs);
Subject.Init();
var registeredJobs = Storage.All();
registeredJobs.Should().HaveCount(1);
registeredJobs.First().TypeName.Should().Be(newJob.GetType().FullName);
registeredJobs.First().Name.Should().Be(newJob.Name);
registeredJobs.First().Interval.Should().Be((int)newJob.DefaultInterval.TotalMinutes);
registeredJobs.First().Enable.Should().Be(true);
registeredJobs.First().Success.Should().Be(oldJob.Success);
registeredJobs.First().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);
Subject.Init();
Storage.All().Should().HaveCount(1);
Storage.All().First().Enable.Should().BeFalse();
}
/* [Test]
public void disabled_jobs_arent_run_by_scheduler()
{
IEnumerable<IJob> BaseFakeJobs = new List<IJob> { disabledJob };
Mocker.SetConstant(BaseFakeJobs);
var jobProvider = Mocker.Resolve<JobController>();
jobProvider.QueueScheduled();
WaitForQueue();
disabledJob.ExecutionCount.Should().Be(0);
}*/
}
}

View File

@ -4,7 +4,7 @@
using NzbDrone.Core.Jobs;
using NzbDrone.Core.Model.Notification;
namespace NzbDrone.Core.Test.ProviderTests.JobProviderTests
namespace NzbDrone.Core.Test.JobTests
{
public class FakeJob : IJob

View File

@ -141,6 +141,7 @@
<Compile Include="Framework\ObjectDbTest.cs" />
<Compile Include="HelperTests\XElementHelperTests\ConvertToTFixture.cs" />
<Compile Include="IndexerTests\NzbxFixture.cs" />
<Compile Include="JobTests\JobRepositoryFixture.cs" />
<Compile Include="JobTests\RenameSeasonJobFixture.cs" />
<Compile Include="ProviderTests\DecisionEngineTests\LanguageSpecificationFixture.cs" />
<Compile Include="ProviderTests\DownloadClientTests\NzbgetProviderTests\DownloadNzbFixture.cs" />
@ -212,7 +213,7 @@
<Compile Include="ProviderTests\PostDownloadProviderTests\GetFolderNameWithStatusFixture.cs" />
<Compile Include="JobTests\EpisodeSearchJobTest.cs" />
<Compile Include="ProviderTests\PostDownloadProviderTests\ProcessDownloadFixture.cs" />
<Compile Include="ProviderTests\JobProviderTests\TestJobs.cs" />
<Compile Include="JobTests\TestJobs.cs" />
<Compile Include="JobTests\AppUpdateJobFixture.cs" />
<Compile Include="ProviderTests\UpdateProviderTests\GetUpdateLogFixture.cs" />
<Compile Include="ProviderTests\UpdateProviderTests\GetAvilableUpdateFixture.cs" />
@ -245,7 +246,7 @@
<Compile Include="JobTests\DiskScanJobTest.cs" />
<Compile Include="IndexerTests\IndexerFixture.cs" />
<Compile Include="ProviderTests\DecisionEngineTests\AllowedDownloadSpecificationFixture.cs" />
<Compile Include="ProviderTests\JobProviderTests\JobProviderFixture.cs" />
<Compile Include="JobTests\JobControllerFixture.cs" />
<Compile Include="QualityTest.cs" />
<Compile Include="RootFolderTests\RootFolderServiceFixture.cs" />
<Compile Include="ProviderTests\IndexerProviderTest.cs" />

View File

@ -1,463 +0,0 @@
// ReSharper disable RedundantUsingDirective
using System.Linq;
using System;
using System.Collections.Generic;
using System.Threading;
using FizzWare.NBuilder;
using FluentAssertions;
using NCrunch.Framework;
using NUnit.Framework;
using NzbDrone.Common;
using NzbDrone.Core.Jobs;
using NzbDrone.Core.Model;
using NzbDrone.Core.Repository;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common;
using NzbDrone.Test.Common.AutoMoq;
namespace NzbDrone.Core.Test.ProviderTests.JobProviderTests
{
[TestFixture]
[ExclusivelyUses("JOB_PROVIDER")]
public class JobProviderFixture : SqlCeTest
{
FakeJob fakeJob;
SlowJob slowJob;
BrokenJob brokenJob;
DisabledJob disabledJob;
[SetUp]
public void Setup()
{
WithRealDb();
fakeJob = new FakeJob();
slowJob = new SlowJob();
brokenJob = new BrokenJob();
disabledJob = new DisabledJob();
}
[TearDown]
public void TearDown()
{
if(!EnvironmentProvider.IsMono)
{
Mocker.Resolve<JobProvider>().Queue.Should().BeEmpty();
}
}
private void ResetLastExecution()
{
var jobProvider = Mocker.Resolve<JobProvider>();
var jobs = jobProvider.All();
foreach (var jobDefinition in jobs)
{
jobDefinition.LastExecution = new DateTime(2000, 1, 1);
jobProvider.SaveDefinition(jobDefinition);
}
}
private void WaitForQueue()
{
Console.WriteLine("Waiting for queue to clear.");
var stopWatch = Mocker.Resolve<JobProvider>().StopWatch;
while (stopWatch.IsRunning)
{
Thread.Sleep(10);
}
}
[Test]
public void running_scheduled_jobs_should_updates_last_execution_time()
{
IEnumerable<IJob> BaseFakeJobs = new List<IJob> { fakeJob };
Mocker.SetConstant(BaseFakeJobs);
ResetLastExecution();
Mocker.Resolve<JobProvider>().QueueScheduled();
WaitForQueue();
var settings = Mocker.Resolve<JobProvider>().All();
settings.First().LastExecution.Should().BeWithin(TimeSpan.FromSeconds(10));
fakeJob.ExecutionCount.Should().Be(1);
}
[Test]
public void failing_scheduled_job_should_mark_job_as_failed()
{
IEnumerable<IJob> BaseFakeJobs = new List<IJob> { brokenJob };
Mocker.SetConstant(BaseFakeJobs);
ResetLastExecution();
Mocker.Resolve<JobProvider>().QueueScheduled();
WaitForQueue();
var settings = Mocker.Resolve<JobProvider>().All();
settings.First().LastExecution.Should().BeWithin(TimeSpan.FromSeconds(10));
settings.First().Success.Should().BeFalse();
brokenJob.ExecutionCount.Should().Be(1);
ExceptionVerification.ExpectedErrors(1);
}
[Test]
public void scheduler_skips_jobs_that_arent_mature_yet()
{
IEnumerable<IJob> BaseFakeJobs = new List<IJob> { fakeJob };
Mocker.SetConstant(BaseFakeJobs);
ResetLastExecution();
Mocker.Resolve<JobProvider>().QueueScheduled();
WaitForQueue();
Mocker.Resolve<JobProvider>().QueueScheduled();
WaitForQueue();
fakeJob.ExecutionCount.Should().Be(1);
}
[Test]
//This test will confirm that the concurrency checks are rest
//after execution so the job can successfully run.
public void can_run_async_job_again()
{
IEnumerable<IJob> BaseFakeJobs = new List<IJob> { fakeJob };
Mocker.SetConstant(BaseFakeJobs);
var jobProvider = Mocker.Resolve<JobProvider>();
jobProvider.QueueJob(typeof(FakeJob));
WaitForQueue();
jobProvider.QueueJob(typeof(FakeJob));
WaitForQueue();
jobProvider.Queue.Should().BeEmpty();
fakeJob.ExecutionCount.Should().Be(2);
}
[Test]
public void no_concurent_jobs()
{
IEnumerable<IJob> BaseFakeJobs = new List<IJob> { slowJob };
Mocker.SetConstant(BaseFakeJobs);
var jobProvider = Mocker.Resolve<JobProvider>();
jobProvider.QueueJob(typeof(SlowJob), 1);
jobProvider.QueueJob(typeof(SlowJob), 2);
jobProvider.QueueJob(typeof(SlowJob), 3);
WaitForQueue();
jobProvider.Queue.Should().BeEmpty();
slowJob.ExecutionCount.Should().Be(3);
ExceptionVerification.AssertNoUnexcpectedLogs();
}
[Test]
public void can_run_broken_job_again()
{
IEnumerable<IJob> BaseFakeJobs = new List<IJob> { brokenJob };
Mocker.SetConstant(BaseFakeJobs);
var jobProvider = Mocker.Resolve<JobProvider>();
jobProvider.QueueJob(typeof(BrokenJob));
WaitForQueue();
jobProvider.QueueJob(typeof(BrokenJob));
WaitForQueue();
brokenJob.ExecutionCount.Should().Be(2);
ExceptionVerification.ExpectedErrors(2);
}
[Test]
public void schedule_hit_should_be_ignored_if_queue_is_running()
{
IEnumerable<IJob> fakeJobs = new List<IJob> { slowJob, fakeJob };
Mocker.SetConstant(fakeJobs);
var jobProvider = Mocker.Resolve<JobProvider>();
jobProvider.QueueJob(typeof(SlowJob));
jobProvider.QueueScheduled();
WaitForQueue();
slowJob.ExecutionCount.Should().Be(1);
fakeJob.ExecutionCount.Should().Be(0);
}
[Test]
public void can_queue_jobs_at_the_same_time()
{
IEnumerable<IJob> BaseFakeJobs = new List<IJob> { slowJob, fakeJob };
Mocker.SetConstant(BaseFakeJobs);
var jobProvider = Mocker.Resolve<JobProvider>();
jobProvider.QueueJob(typeof(SlowJob));
var thread1 = new Thread(() => jobProvider.QueueJob(typeof(FakeJob)));
var thread2 = new Thread(() => jobProvider.QueueJob(typeof(FakeJob)));
thread1.Start();
thread2.Start();
thread1.Join();
thread2.Join();
WaitForQueue();
fakeJob.ExecutionCount.Should().Be(1);
slowJob.ExecutionCount.Should().Be(1);
jobProvider.Queue.Should().BeEmpty();
}
[Test]
public void Init_Jobs()
{
IEnumerable<IJob> BaseFakeJobs = new List<IJob> { fakeJob };
Mocker.SetConstant(BaseFakeJobs);
var jobProvider = Mocker.Resolve<JobProvider>();
var timers = jobProvider.All();
timers.Should().HaveCount(1);
timers[0].Interval.Should().Be((Int32)fakeJob.DefaultInterval.TotalMinutes);
timers[0].Name.Should().Be(fakeJob.Name);
timers[0].TypeName.Should().Be(fakeJob.GetType().ToString());
timers[0].LastExecution.Should().HaveYear(DateTime.Now.Year);
timers[0].LastExecution.Should().HaveMonth(DateTime.Now.Month);
timers[0].LastExecution.Should().HaveDay(DateTime.Today.Day);
timers[0].Enable.Should().BeTrue();
}
[Test]
public void inti_should_removed_jobs_that_no_longer_exist()
{
IEnumerable<IJob> fakeJobs = new List<IJob> { fakeJob };
Mocker.SetConstant(fakeJobs);
WithRealDb();
var deletedJob = Builder<JobDefinition>.CreateNew().Build();
Db.Insert(deletedJob);
var jobProvider = Mocker.Resolve<JobProvider>();
var registeredJobs = Db.Fetch<JobDefinition>();
registeredJobs.Should().HaveCount(1);
registeredJobs.Should().NotContain(c => c.TypeName == deletedJob.TypeName);
}
[Test]
public void inti_should_removed_jobs_that_no_longer_exist_even_with_same_name()
{
IEnumerable<IJob> fakeJobs = new List<IJob> { fakeJob };
Mocker.SetConstant(fakeJobs);
WithRealDb();
var deletedJob = Builder<JobDefinition>.CreateNew()
.With(c => c.Name = fakeJob.Name).Build();
Db.Insert(deletedJob);
var jobProvider = Mocker.Resolve<JobProvider>();
var registeredJobs = Db.Fetch<JobDefinition>();
registeredJobs.Should().HaveCount(1);
registeredJobs.Should().NotContain(c => c.TypeName == deletedJob.TypeName);
}
[Test]
public void init_should_update_existing_job()
{
IEnumerable<IJob> fakeJobs = new List<IJob> { fakeJob };
Mocker.SetConstant(fakeJobs);
WithRealDb();
var initialFakeJob = Builder<JobDefinition>.CreateNew()
.With(c => c.Name = "NewName")
.With(c => c.TypeName = fakeJob.GetType().ToString())
.With(c => c.Interval = 0)
.With(c => c.Enable = false)
.With(c => c.Success = true)
.With(c => c.LastExecution = DateTime.Now.AddDays(-7).Date)
.Build();
var id = Convert.ToInt32(Db.Insert(initialFakeJob));
Mocker.Resolve<JobProvider>();
var registeredJobs = Db.Fetch<JobDefinition>();
registeredJobs.Should().HaveCount(1);
registeredJobs.First().TypeName.Should().Be(fakeJob.GetType().ToString());
registeredJobs.First().Name.Should().Be(fakeJob.Name);
registeredJobs.First().Interval.Should().Be((Int32)fakeJob.DefaultInterval.TotalMinutes);
registeredJobs.First().Enable.Should().Be(true);
registeredJobs.First().Success.Should().Be(initialFakeJob.Success);
registeredJobs.First().LastExecution.Should().Be(initialFakeJob.LastExecution);
}
[Test]
public void jobs_with_zero_interval_are_registered_as_disabled()
{
IEnumerable<IJob> fakeJobs = new List<IJob> { disabledJob };
Mocker.SetConstant(fakeJobs);
var jobProvider = Mocker.Resolve<JobProvider>();
jobProvider.All().Should().HaveCount(1);
jobProvider.All().First().Enable.Should().BeFalse();
}
[Test]
public void disabled_jobs_arent_run_by_scheduler()
{
IEnumerable<IJob> BaseFakeJobs = new List<IJob> { disabledJob };
Mocker.SetConstant(BaseFakeJobs);
var jobProvider = Mocker.Resolve<JobProvider>();
jobProvider.QueueScheduled();
WaitForQueue();
disabledJob.ExecutionCount.Should().Be(0);
}
[Test]
public void job_with_specific_target_should_not_update_last_execution()
{
IEnumerable<IJob> BaseFakeJobs = new List<IJob> { fakeJob };
Mocker.SetConstant(BaseFakeJobs);
var jobProvider = Mocker.Resolve<JobProvider>();
ResetLastExecution();
jobProvider.QueueJob(typeof(FakeJob), 10);
WaitForQueue();
jobProvider.All().First().LastExecution.Should().HaveYear(2000);
}
[Test]
public void job_with_specific_target_should_not_set_success_flag()
{
IEnumerable<IJob> BaseFakeJobs = new List<IJob> { fakeJob };
Mocker.SetConstant(BaseFakeJobs);
var jobProvider = Mocker.Resolve<JobProvider>();
jobProvider.QueueJob(typeof(FakeJob), 10);
WaitForQueue();
jobProvider.All().First().Success.Should().BeFalse();
}
[Test]
public void duplicated_queue_item_should_start_queue_if_its_not_running()
{
IEnumerable<IJob> BaseFakeJobs = new List<IJob> { fakeJob };
Mocker.SetConstant(BaseFakeJobs);
var stuckQueueItem = new JobQueueItem
{
JobType = fakeJob.GetType(),
Options = new { TargetId = 12 }
};
var jobProvider = Mocker.Resolve<JobProvider>();
jobProvider.Queue.Add(stuckQueueItem);
WaitForQueue();
jobProvider.QueueJob(stuckQueueItem.JobType, stuckQueueItem.Options);
WaitForQueue();
fakeJob.ExecutionCount.Should().Be(1);
}
[Test]
public void Item_added_to_queue_while_scheduler_runs_should_be_executed()
{
IEnumerable<IJob> BaseFakeJobs = new List<IJob> { slowJob, disabledJob };
Mocker.SetConstant(BaseFakeJobs);
ResetLastExecution();
var _jobThread = new Thread(Mocker.Resolve<JobProvider>().QueueScheduled);
_jobThread.Start();
Thread.Sleep(200);
Mocker.Resolve<JobProvider>().QueueJob(typeof(DisabledJob), 12);
WaitForQueue();
slowJob.ExecutionCount.Should().Be(1);
disabledJob.ExecutionCount.Should().Be(1);
}
[Test]
public void trygin_to_queue_unregistered_job_should_fail()
{
IEnumerable<IJob> BaseFakeJobs = new List<IJob> { slowJob, disabledJob };
Mocker.SetConstant(BaseFakeJobs);
var jobProvider = Mocker.Resolve<JobProvider>();
jobProvider.QueueJob(typeof(string));
WaitForQueue();
ExceptionVerification.ExpectedErrors(1);
}
[Test]
public void scheduled_job_should_have_scheduler_as_source()
{
IEnumerable<IJob> BaseFakeJobs = new List<IJob> { slowJob, fakeJob};
Mocker.SetConstant(BaseFakeJobs);
var jobProvider = Mocker.Resolve<JobProvider>();
ResetLastExecution();
jobProvider.QueueScheduled();
jobProvider.Queue.Should().OnlyContain(c => c.Source == JobQueueItem.JobSourceType.Scheduler);
WaitForQueue();
}
}
}

View File

@ -8,6 +8,8 @@ public interface IBasicRepository<TModel>
List<TModel> All();
TModel Get(int id);
TModel Add(TModel model);
TModel Update(TModel model);
TModel Upsert(TModel model);
void Delete(int id);
}
@ -18,7 +20,7 @@ public BasicRepository(IObjectDatabase objectDatabase)
ObjectDatabase = objectDatabase;
}
protected IObjectDatabase ObjectDatabase { get; private set; }
public IObjectDatabase ObjectDatabase { get; private set; }
protected IEnumerable<TModel> Queryable { get { return ObjectDatabase.AsQueryable<TModel>(); } }
@ -37,6 +39,20 @@ public TModel Add(TModel model)
return ObjectDatabase.Insert(model);
}
public TModel Update(TModel model)
{
return ObjectDatabase.Update(model);
}
public TModel Upsert(TModel model)
{
if(model.OID == 0)
{
return ObjectDatabase.Insert(model);
}
return ObjectDatabase.Update(model);
}
public void Delete(int id)
{
var itemToDelete = Get(id);

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.Common;
using System.Reflection;
using NLog;
@ -21,7 +22,7 @@ static ConnectionFactory()
if (EnvironmentProvider.IsMono) return;
var dataSet = (System.Data.DataSet)ConfigurationManager.GetSection("system.data");
var dataSet = (DataSet)ConfigurationManager.GetSection("system.data");
dataSet.Tables[0].Rows.Add("Microsoft SQL Server Compact Data Provider 4.0"
, "System.Data.SqlServerCe.4.0"
, ".NET Framework Data Provider for Microsoft SQL Server Compact"

View File

@ -2,6 +2,7 @@
using System.Linq;
using NzbDrone.Core.Repository;
// ReSharper disable CheckNamespace
namespace PetaPoco
{
public class EpisodeSeasonRelator

View File

@ -1,9 +1,9 @@
using System;
using System.Linq;
using NzbDrone.Core.Instrumentation;
using NzbDrone.Core.Jobs;
using NzbDrone.Core.Model.Notification;
namespace NzbDrone.Core.Jobs
namespace NzbDrone.Core.Instrumentation
{
public class TrimLogsJob : IJob
{

View File

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Threading;
@ -8,21 +7,24 @@
using NzbDrone.Core.Model;
using NzbDrone.Core.Model.Notification;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Repository;
using PetaPoco;
namespace NzbDrone.Core.Jobs
{
/// <summary>
/// Provides a background task runner, tasks could be queue either by the scheduler using QueueScheduled()
/// or by explicitly calling QueueJob(type,int)
/// </summary>
public class JobProvider
public interface IJobController
{
Stopwatch StopWatch { get; }
List<JobQueueItem> Queue { get; }
void QueueScheduled();
void QueueJob(Type jobType, dynamic options = null, JobQueueItem.JobSourceType source = JobQueueItem.JobSourceType.User);
bool QueueJob(string jobTypeString);
}
public class JobController : IJobController
{
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
private readonly IDatabase _database;
private readonly NotificationProvider _notificationProvider;
private readonly IEnumerable<IJob> _jobs;
private readonly IJobRepository _jobRepository;
private readonly Logger logger;
private Thread _jobThread;
public Stopwatch StopWatch { get; private set; }
@ -33,26 +35,16 @@ public class JobProvider
private ProgressNotification _notification;
public JobProvider(IDatabase database, NotificationProvider notificationProvider, IEnumerable<IJob> jobs)
public JobController(NotificationProvider notificationProvider, IEnumerable<IJob> jobs, IJobRepository jobRepository, Logger logger)
{
StopWatch = new Stopwatch();
_database = database;
_notificationProvider = notificationProvider;
_jobs = jobs;
_jobRepository = jobRepository;
this.logger = logger;
ResetThread();
Initialize();
}
/// <summary>
/// Initializes a new instance of the <see cref="JobProvider"/> class. by AutoMoq
/// </summary>
/// <remarks>Should only be used by AutoMoq</remarks>
[EditorBrowsable(EditorBrowsableState.Never)]
public JobProvider() { }
/// <summary>
/// Gets the active queue.
/// </summary>
public List<JobQueueItem> Queue
{
get
@ -61,62 +53,6 @@ public List<JobQueueItem> Queue
}
}
public virtual List<JobDefinition> All()
{
return _database.Fetch<JobDefinition>().ToList();
}
private void Initialize()
{
var currentJobs = All();
logger.Debug("Initializing jobs. Available: {0} Existing:{1}", _jobs.Count(), currentJobs.Count);
foreach (var currentJob in currentJobs)
{
if (!_jobs.Any(c => c.GetType().ToString() == currentJob.TypeName))
{
logger.Debug("Removing job from database '{0}'", currentJob.Name);
_database.Delete(currentJob);
}
}
foreach (var job in _jobs)
{
var jobDefinition = currentJobs.SingleOrDefault(c => c.TypeName == job.GetType().ToString());
if (jobDefinition == null)
{
jobDefinition = new JobDefinition();
jobDefinition.TypeName = job.GetType().ToString();
jobDefinition.LastExecution = DateTime.Now;
}
jobDefinition.Enable = job.DefaultInterval.TotalSeconds > 0;
jobDefinition.Name = job.Name;
jobDefinition.Interval = Convert.ToInt32(job.DefaultInterval.TotalMinutes);
SaveDefinition(jobDefinition);
}
}
/// <summary>
/// Adds/Updates definitions for a job
/// </summary>
/// <param name="definitions">Settings to be added/updated</param>
public virtual void SaveDefinition(JobDefinition definitions)
{
if (definitions.Id == 0)
{
logger.Trace("Adding job definitions for {0}", definitions.Name);
_database.Insert(definitions);
}
else
{
logger.Trace("Updating job definitions for {0}", definitions.Name);
_database.Update(definitions);
}
}
public virtual void QueueScheduled()
{
@ -131,14 +67,13 @@ public virtual void QueueScheduled()
}
}
var pendingJobTypes = All().Where(
t => t.Enable &&
(DateTime.Now - t.LastExecution) > TimeSpan.FromMinutes(t.Interval)
).Select(c => _jobs.Single(t => t.GetType().ToString() == c.TypeName).GetType()).ToList();
var pendingJobs = _jobRepository.GetPendingJobs()
.Select(c => _jobs.Single(t => t.GetType().ToString() == c.TypeName)
.GetType()).ToList();
pendingJobTypes.ForEach(jobType => QueueJob(jobType, source: JobQueueItem.JobSourceType.Scheduler));
logger.Trace("{0} Scheduled tasks have been added to the queue", pendingJobTypes.Count);
pendingJobs.ForEach(jobType => QueueJob(jobType, source: JobQueueItem.JobSourceType.Scheduler));
logger.Trace("{0} Scheduled tasks have been added to the queue", pendingJobs.Count);
}
public virtual void QueueJob(Type jobType, dynamic options = null, JobQueueItem.JobSourceType source = JobQueueItem.JobSourceType.User)
@ -193,11 +128,6 @@ public virtual bool QueueJob(string jobTypeString)
return true;
}
public virtual JobDefinition GetDefinition(Type type)
{
return _database.Single<JobDefinition>("WHERE TypeName = @0", type.ToString());
}
private void ProcessQueue()
{
try
@ -261,13 +191,12 @@ private void Execute(JobQueueItem queueItem)
return;
}
var settings = All().Single(j => j.TypeName == queueItem.JobType.ToString());
var jobDefinition = _jobRepository.GetDefinition(queueItem.JobType);
using (_notification = new ProgressNotification(jobImplementation.Name))
{
try
{
logger.Debug("Starting {0}. Last execution {1}", queueItem, settings.LastExecution);
logger.Debug("Starting {0}. Last execution {1}", queueItem, jobDefinition.LastExecution);
var sw = Stopwatch.StartNew();
@ -275,8 +204,8 @@ private void Execute(JobQueueItem queueItem)
jobImplementation.Start(_notification, queueItem.Options);
_notification.Status = ProgressNotificationStatus.Completed;
settings.LastExecution = DateTime.Now;
settings.Success = true;
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,
@ -292,15 +221,15 @@ private void Execute(JobQueueItem queueItem)
_notification.Status = ProgressNotificationStatus.Failed;
_notification.CurrentMessage = jobImplementation.Name + " Failed.";
settings.LastExecution = DateTime.Now;
settings.Success = false;
jobDefinition.LastExecution = DateTime.Now;
jobDefinition.Success = false;
}
}
//Only update last execution status if was triggered by the scheduler
if (queueItem.Options == null)
{
SaveDefinition(settings);
_jobRepository.Update(jobDefinition);
}
}

View File

@ -1,14 +1,11 @@
using System;
using PetaPoco;
using System.Linq;
using System;
using NzbDrone.Core.Datastore;
namespace NzbDrone.Core.Repository
namespace NzbDrone.Core.Jobs
{
[TableName("JobDefinitions")]
[PrimaryKey("Id", autoIncrement = true)]
public class JobDefinition
public class JobDefinition : ModelBase
{
public Int32 Id { get; set; }
public Boolean Enable { get; set; }
public String TypeName { get; set; }

View File

@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Lifecycle;
namespace NzbDrone.Core.Jobs
{
public interface IJobRepository : IInitializable, IBasicRepository<JobDefinition>
{
IList<JobDefinition> GetPendingJobs();
JobDefinition GetDefinition(Type type);
}
public class JobRepository : BasicRepository<JobDefinition>, IJobRepository
{
private readonly IEnumerable<IJob> _jobs;
private readonly Logger _logger;
public JobRepository(IObjectDatabase objectDatabase, IEnumerable<IJob> jobs, Logger logger)
: base(objectDatabase)
{
_jobs = jobs;
_logger = logger;
}
public JobDefinition GetDefinition(Type type)
{
return Queryable.Single(c => c.TypeName == type.FullName);
}
public IList<JobDefinition> GetPendingJobs()
{
return Queryable.Where(c => c.Enable && c.LastExecution < DateTime.UtcNow.AddMinutes(c.Interval)).ToList();
}
public void Init()
{
var currentJobs = All();
_logger.Debug("Initializing jobs. Available: {0} Existing:{1}", _jobs.Count(), currentJobs.Count);
foreach (var currentJob in currentJobs)
{
if (_jobs.All(c => c.GetType().ToString() != currentJob.TypeName))
{
_logger.Debug("Removing job from database '{0}'", currentJob.Name);
Delete(currentJob.OID);
}
}
foreach (var job in _jobs)
{
var jobDefinition = currentJobs.SingleOrDefault(c => c.TypeName == job.GetType().ToString());
if (jobDefinition == null)
{
jobDefinition = new JobDefinition
{
TypeName = job.GetType().ToString(),
LastExecution = DateTime.Now
};
}
jobDefinition.Enable = job.DefaultInterval.TotalSeconds > 0;
jobDefinition.Name = job.Name;
jobDefinition.Interval = Convert.ToInt32(job.DefaultInterval.TotalMinutes);
Upsert(jobDefinition);
}
}
}
}

View File

@ -2,9 +2,10 @@
using System.Linq;
using NLog;
using NzbDrone.Common;
using NzbDrone.Core.Jobs;
using NzbDrone.Core.Model.Notification;
namespace NzbDrone.Core.Jobs
namespace NzbDrone.Core.Lifecycle
{
public class AppRestartJob : IJob
{

View File

@ -1,12 +1,11 @@
using System;
using System.Linq;
using System.Diagnostics;
using System.IO;
using NLog;
using NzbDrone.Common;
using NzbDrone.Core.Jobs;
using NzbDrone.Core.Model.Notification;
namespace NzbDrone.Core.Jobs
namespace NzbDrone.Core.Lifecycle
{
public class AppShutdownJob : IJob
{

View File

@ -4,11 +4,12 @@
using System.IO;
using NLog;
using NzbDrone.Common;
using NzbDrone.Core.Jobs;
using NzbDrone.Core.Model.Notification;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Core;
namespace NzbDrone.Core.Jobs
namespace NzbDrone.Core.Lifecycle
{
public class AppUpdateJob : IJob
{

View File

@ -0,0 +1,7 @@
namespace NzbDrone.Core.Lifecycle
{
public interface IInitializable
{
void Init();
}
}

View File

@ -270,13 +270,15 @@
<Compile Include="Helpers\XElementHelper.cs" />
<Compile Include="Instrumentation\LogInjectionModule.cs" />
<Compile Include="Jobs\CleanupRecycleBinJob.cs" />
<Compile Include="Jobs\AppShutdownJob.cs" />
<Compile Include="Jobs\AppRestartJob.cs" />
<Compile Include="Jobs\JobRepository.cs" />
<Compile Include="Lifecycle\AppShutdownJob.cs" />
<Compile Include="Lifecycle\AppRestartJob.cs" />
<Compile Include="Jobs\XemUpdateJob.cs" />
<Compile Include="Jobs\EmptyRecycleBinJob.cs" />
<Compile Include="Jobs\RefreshEpsiodeMetadata.cs" />
<Compile Include="Jobs\PastWeekBacklogSearchJob.cs" />
<Compile Include="Jobs\SearchHistoryCleanupJob.cs" />
<Compile Include="Lifecycle\IInitilizable.cs" />
<Compile Include="Model\HistoryQueryModel.cs" />
<Compile Include="Model\DownloadClientType.cs" />
<Compile Include="Instrumentation\LogProvider.cs" />
@ -353,11 +355,11 @@
<Compile Include="Providers\Search\SearchBase.cs" />
<Compile Include="Providers\SeasonProvider.cs" />
<Compile Include="Jobs\RecentBacklogSearchJob.cs" />
<Compile Include="Jobs\TrimLogsJob.cs" />
<Compile Include="Jobs\JobProvider.cs" />
<Compile Include="Instrumentation\TrimLogsJob.cs" />
<Compile Include="Jobs\JobController.cs" />
<Compile Include="Jobs\RenameSeasonJob.cs" />
<Compile Include="Jobs\RenameSeriesJob.cs" />
<Compile Include="Jobs\AppUpdateJob.cs" />
<Compile Include="Lifecycle\AppUpdateJob.cs" />
<Compile Include="Jobs\BacklogSearchJob.cs" />
<Compile Include="Jobs\BannerDownloadJob.cs" />
<Compile Include="Jobs\ConvertEpisodeJob.cs" />
@ -570,7 +572,7 @@
</Compile>
<Compile Include="Repository\NewznabDefinition.cs" />
<Compile Include="Repository\ExternalNotificationDefinition.cs" />
<Compile Include="Repository\JobDefinition.cs" />
<Compile Include="Jobs\JobDefinition.cs" />
<Compile Include="Repository\IndexerDefinition.cs" />
<Compile Include="Model\EpisodeParseResult.cs" />
<Compile Include="Model\EpisodeSortingType.cs" />

View File

@ -29,7 +29,7 @@ public virtual bool RunAtomicParsley(Episode episode, string outputFile)
throw new NotImplementedException();
var atomicParsleyLocation = _configProvider.GetValue("AtomicParsleyLocation", "");
var atomicParsleyTitleType = (AtomicParsleyTitleType) System.Convert.ToInt32(_configProvider.GetValue("AtomicParsley", 0));
var atomicParsleyTitleType = (AtomicParsleyTitleType) Convert.ToInt32(_configProvider.GetValue("AtomicParsley", 0));
var atomicParsleyCommand = String.Format("\"{0}\" --overWrite --title \"{1}\" --genre \"TV Shows\" --stik \"TV Show\" --TVShowName \"{2}\" --TVEpisodeNum \"{3}\" --TVSeason \"{4}\"",
outputFile, episode.Title, episode.Series.Title, episode.EpisodeNumber, episode.SeasonNumber);

View File

@ -81,7 +81,7 @@ private void HandBrakeOutputDataReceived(object obj, DataReceivedEventArgs args)
_currentEpisode.SeasonNumber,
_currentEpisode.EpisodeNumber);
var percent = System.Convert.ToDecimal(match[0].Groups["percent"].Value);
var percent = Convert.ToDecimal(match[0].Groups["percent"].Value);
int hours;
int minutes;
int seconds;

View File

@ -1,18 +1,21 @@
namespace NzbDrone.Core.Providers.Xbmc
using System.Drawing;
using System.IO;
namespace NzbDrone.Core.Providers.Xbmc
{
public class ResourceManager
{
public static System.Drawing.Icon GetIcon(string Name)
public static Icon GetIcon(string Name)
{
System.IO.Stream stm = typeof(ResourceManager).Assembly.GetManifestResourceStream(string.Format("NzbDrone.Core.{0}.ico", Name));
Stream stm = typeof(ResourceManager).Assembly.GetManifestResourceStream(string.Format("NzbDrone.Core.{0}.ico", Name));
if (stm == null) return null;
return new System.Drawing.Icon(stm);
return new Icon(stm);
}
public static byte[] GetRawData(string Name)
{
byte[] data;
using (System.IO.Stream stm = typeof(ResourceManager).Assembly.GetManifestResourceStream(string.Format("NzbDrone.Core.{0}.ico", Name)))
using (Stream stm = typeof(ResourceManager).Assembly.GetManifestResourceStream(string.Format("NzbDrone.Core.{0}.ico", Name)))
{
if (stm == null) return null;
data = new byte[stm.Length];
@ -25,7 +28,7 @@ public static byte[] GetRawData(string Name)
public static byte[] GetRawLogo(string Name)
{
byte[] data;
using (System.IO.Stream stm = typeof(ResourceManager).Assembly.GetManifestResourceStream(string.Format("NzbDrone.Core.{0}", Name)))
using (Stream stm = typeof(ResourceManager).Assembly.GetManifestResourceStream(string.Format("NzbDrone.Core.{0}", Name)))
{
if (stm == null) return null;
data = new byte[stm.Length];
@ -35,15 +38,15 @@ public static byte[] GetRawLogo(string Name)
return data;
}
public static System.Drawing.Bitmap GetIconAsImage(string Name)
public static Bitmap GetIconAsImage(string Name)
{
System.IO.Stream stm = typeof(ResourceManager).Assembly.GetManifestResourceStream(string.Format("NzbDrone.Core.{0}.ico", Name));
Stream stm = typeof(ResourceManager).Assembly.GetManifestResourceStream(string.Format("NzbDrone.Core.{0}.ico", Name));
if (stm == null) return null;
System.Drawing.Bitmap bmp;
using (System.Drawing.Icon ico = new System.Drawing.Icon(stm))
Bitmap bmp;
using (Icon ico = new Icon(stm))
{
bmp = new System.Drawing.Bitmap(ico.Width, ico.Height);
using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bmp))
bmp = new Bitmap(ico.Width, ico.Height);
using (Graphics g = Graphics.FromImage(bmp))
{
g.DrawIcon(ico, 0, 0);
}

View File

@ -8,7 +8,7 @@ namespace NzbDrone.Core
{
public class WebTimer
{
private readonly JobProvider _jobProvider;
private readonly JobController _jobProvider;
private static CacheItemRemovedCallback _onCacheRemove;
private static bool _stop;
@ -17,7 +17,7 @@ public class WebTimer
public WebTimer(JobProvider jobProvider)
public WebTimer(JobController jobProvider)
{
_jobProvider = jobProvider;
}

View File

@ -2,6 +2,7 @@
using System.Linq;
using System.IO;
using Moq;
using NLog;
using NUnit.Framework;
using NzbDrone.Common;
using NzbDrone.Test.Common.AutoMoq;
@ -45,6 +46,8 @@ private string VirtualPath
public void TestBaseSetup()
{
Mocker.SetConstant(LogManager.GetLogger("TestLogger"));
TempFolder = Path.Combine(Directory.GetCurrentDirectory(), "_temp_" + DateTime.Now.Ticks);
MockedRestProvider = new Mock<RestProvider>();

View File

@ -11,7 +11,7 @@ namespace NzbDrone.Web.Controllers
{
public class CommandController : Controller
{
private readonly JobProvider _jobProvider;
private readonly JobController _jobProvider;
private readonly SabProvider _sabProvider;
private readonly SmtpProvider _smtpProvider;
private readonly TwitterProvider _twitterProvider;
@ -25,7 +25,7 @@ public class CommandController : Controller
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
public CommandController(JobProvider jobProvider, SabProvider sabProvider,
public CommandController(JobController jobProvider, SabProvider sabProvider,
SmtpProvider smtpProvider, TwitterProvider twitterProvider,
EpisodeProvider episodeProvider, GrowlProvider growlProvider,
SeasonProvider seasonProvider, ProwlProvider prowlProvider,

View File

@ -9,10 +9,10 @@ namespace NzbDrone.Web.Controllers
{
public class EpisodeController : Controller
{
private readonly JobProvider _jobProvider;
private readonly JobController _jobProvider;
private readonly MediaFileProvider _mediaFileProvider;
public EpisodeController(JobProvider jobProvider, MediaFileProvider mediaFileProvider)
public EpisodeController(JobController jobProvider, MediaFileProvider mediaFileProvider)
{
_jobProvider = jobProvider;
_mediaFileProvider = mediaFileProvider;

View File

@ -16,10 +16,10 @@ namespace NzbDrone.Web.Controllers
public class HistoryController : Controller
{
private readonly HistoryProvider _historyProvider;
private readonly JobProvider _jobProvider;
private readonly JobController _jobProvider;
private readonly ConfigProvider _configProvider;
public HistoryController(HistoryProvider historyProvider, JobProvider jobProvider,
public HistoryController(HistoryProvider historyProvider, JobController jobProvider,
ConfigProvider configProvider)
{
_historyProvider = historyProvider;

View File

@ -24,14 +24,14 @@ public class SeriesController : Controller
{
private readonly QualityProvider _qualityProvider;
private readonly SeriesProvider _seriesProvider;
private readonly JobProvider _jobProvider;
private readonly JobController _jobProvider;
private readonly SeasonProvider _seasonProvider;
private readonly ConfigProvider _configProvider;
//
// GET: /Series/
public SeriesController(SeriesProvider seriesProvider, QualityProvider qualityProvider,
JobProvider jobProvider, SeasonProvider seasonProvider,
JobController jobProvider, SeasonProvider seasonProvider,
ConfigProvider configProvider)
{
_seriesProvider = seriesProvider;

View File

@ -34,7 +34,7 @@ public class SettingsController : Controller
private readonly ConfigFileProvider _configFileProvider;
private readonly NewznabProvider _newznabProvider;
private readonly MetadataProvider _metadataProvider;
private readonly JobProvider _jobProvider;
private readonly JobController _jobProvider;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
@ -43,7 +43,7 @@ public SettingsController(ConfigProvider configProvider, IndexerProvider indexer
SeriesProvider seriesProvider, ExternalNotificationProvider externalNotificationProvider,
QualityTypeProvider qualityTypeProvider, ConfigFileProvider configFileProvider,
NewznabProvider newznabProvider, MetadataProvider metadataProvider,
JobProvider jobProvider)
JobController jobProvider)
{
_externalNotificationProvider = externalNotificationProvider;
_qualityTypeProvider = qualityTypeProvider;
@ -439,9 +439,9 @@ public JsonResult SaveIndexers(IndexerSettingsModel data)
//Save the interval to config and immediately apply it the the job (to avoid a restart)
_configProvider.RssSyncInterval = data.RssSyncInterval;
var rssSyncJob = _jobProvider.GetDefinition(typeof(RssSyncJob));
/* var rssSyncJob = _jobProvider.GetDefinition(typeof(RssSyncJob));
rssSyncJob.Interval = data.RssSyncInterval;
_jobProvider.SaveDefinition(rssSyncJob);
_jobProvider.SaveDefinition(rssSyncJob);*/
try
{

View File

@ -8,6 +8,7 @@
using NzbDrone.Core;
using NzbDrone.Core.Helpers;
using NzbDrone.Core.Jobs;
using NzbDrone.Core.Lifecycle;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Providers.DownloadClients;
@ -17,16 +18,17 @@ namespace NzbDrone.Web.Controllers
{
public class SystemController : Controller
{
private readonly JobProvider _jobProvider;
private readonly JobController _jobProvider;
private readonly IndexerProvider _indexerProvider;
private readonly ConfigProvider _configProvider;
private readonly DiskProvider _diskProvider;
private readonly BackupProvider _backupProvider;
private readonly StatsProvider _statsProvider;
private readonly IJobRepository _jobRepository;
public SystemController(JobProvider jobProvider, IndexerProvider indexerProvider,
public SystemController(JobController jobProvider, IndexerProvider indexerProvider,
ConfigProvider configProvider, DiskProvider diskProvider,
BackupProvider backupProvider, StatsProvider statsProvider)
BackupProvider backupProvider, StatsProvider statsProvider,IJobRepository jobRepository)
{
_jobProvider = jobProvider;
_indexerProvider = indexerProvider;
@ -34,6 +36,7 @@ public SystemController(JobProvider jobProvider, IndexerProvider indexerProvider
_diskProvider = diskProvider;
_backupProvider = backupProvider;
_statsProvider = statsProvider;
_jobRepository = jobRepository;
}
public ActionResult Index()
@ -58,9 +61,9 @@ public ActionResult Jobs()
ViewData["Queue"] = serializedQueue;
var jobs = _jobProvider.All().Select(j => new JobModel
var jobs = _jobRepository.All().Select(j => new JobModel
{
Id = j.Id,
Id = j.OID,
Enable = j.Enable,
TypeName = j.TypeName,
Name = j.Name,

View File

@ -3,6 +3,7 @@
using System.Web.Mvc;
using NzbDrone.Common;
using NzbDrone.Core.Jobs;
using NzbDrone.Core.Lifecycle;
using NzbDrone.Core.Providers;
using NzbDrone.Web.Models;
@ -11,11 +12,11 @@ namespace NzbDrone.Web.Controllers
public class UpdateController : Controller
{
private readonly UpdateProvider _updateProvider;
private readonly JobProvider _jobProvider;
private readonly JobController _jobProvider;
private readonly EnvironmentProvider _environmentProvider;
private readonly DiskProvider _diskProvider;
public UpdateController(UpdateProvider updateProvider, JobProvider jobProvider,
public UpdateController(UpdateProvider updateProvider, JobController jobProvider,
EnvironmentProvider environmentProvider, DiskProvider diskProvider)
{
_updateProvider = updateProvider;

View File

@ -1,6 +1,6 @@
<SolutionConfiguration>
<FileVersion>1</FileVersion>
<AutoEnableOnStartup>False</AutoEnableOnStartup>
<AutoEnableOnStartup>True</AutoEnableOnStartup>
<AllowParallelTestExecution>true</AllowParallelTestExecution>
<AllowTestsToRunInParallelWithThemselves>true</AllowTestsToRunInParallelWithThemselves>
<FrameworkUtilisationTypeForNUnit>UseDynamicAnalysis</FrameworkUtilisationTypeForNUnit>

View File

@ -1,4 +1,6 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=CheckNamespace/@EntryIndexedValue">ERROR</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertIfStatementToReturnStatement/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FPARAMETER/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb"&gt;&lt;ExtraRule Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/Environment/Editor/MatchingBraceHighlighting/Position/@EntryValue">BOTH_SIDES</s:String>
<s:String x:Key="/Default/Environment/Editor/MatchingBraceHighlighting/Style/@EntryValue">OUTLINE</s:String>

Binary file not shown.