You've already forked Sonarr
							
							
				mirror of
				https://github.com/Sonarr/Sonarr.git
				synced 2025-10-31 00:07:55 +02:00 
			
		
		
		
	Added completely awesome JobProvider. extremely easy to do async/timer tasks with ui status/notification already plugged in.
This commit is contained in:
		| @@ -30,8 +30,9 @@ namespace AutoMoq | ||||
|  | ||||
|         public virtual T Resolve<T>() | ||||
|         { | ||||
|             ResolveType = typeof (T); | ||||
|             ResolveType = typeof(T); | ||||
|             var result = container.Resolve<T>(); | ||||
|             SetConstant(result); | ||||
|             ResolveType = null; | ||||
|             return result; | ||||
|         } | ||||
| @@ -61,7 +62,7 @@ namespace AutoMoq | ||||
|                 registeredMocks.Add(type, mock); | ||||
|         } | ||||
|  | ||||
|         public virtual void SetConstant<T>(T instance) where T : class | ||||
|         public virtual void SetConstant<T>(T instance) | ||||
|         { | ||||
|             container.RegisterInstance(instance); | ||||
|             SetMock(instance.GetType(), null); | ||||
| @@ -125,7 +126,7 @@ namespace AutoMoq | ||||
|  | ||||
|         private Mock<T> TheRegisteredMockForThisType<T>(Type type) where T : class | ||||
|         { | ||||
|             return (Mock<T>) registeredMocks.Where(x => x.Key == type).First().Value; | ||||
|             return (Mock<T>)registeredMocks.Where(x => x.Key == type).First().Value; | ||||
|         } | ||||
|  | ||||
|         private void CreateANewMockAndRegisterIt<T>(Type type, MockBehavior behavior) where T : class | ||||
| @@ -142,7 +143,7 @@ namespace AutoMoq | ||||
|  | ||||
|         private static Type GetTheMockType<T>() where T : class | ||||
|         { | ||||
|             return typeof (T); | ||||
|             return typeof(T); | ||||
|         } | ||||
|  | ||||
|         #endregion | ||||
|   | ||||
| @@ -87,5 +87,25 @@ namespace NzbDrone.Core.Test | ||||
|  | ||||
|             //Assert | ||||
|         } | ||||
|  | ||||
|  | ||||
|         [Test] | ||||
|         public void Add_daily_show_episodes() | ||||
|         { | ||||
|             var mocker = new AutoMoqer(); | ||||
|             mocker.SetConstant(MockLib.GetEmptyRepository()); | ||||
|             mocker.Resolve<TvDbProvider>(); | ||||
|             const int tvDbSeriesId = 71256; | ||||
|             //act | ||||
|             var seriesProvider = mocker.Resolve<SeriesProvider>(); | ||||
|  | ||||
|             seriesProvider.AddSeries("c:\\test\\", tvDbSeriesId, 0); | ||||
|             var episodeProvider = mocker.Resolve<EpisodeProvider>(); | ||||
|             episodeProvider.RefreshEpisodeInfo(tvDbSeriesId); | ||||
|  | ||||
|             //assert | ||||
|             var episodes = episodeProvider.GetEpisodeBySeries(tvDbSeriesId); | ||||
|             Assert.IsNotEmpty(episodes); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										203
									
								
								NzbDrone.Core.Test/JobProviderTest.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										203
									
								
								NzbDrone.Core.Test/JobProviderTest.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,203 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Threading; | ||||
| using AutoMoq; | ||||
| using MbUnit.Framework; | ||||
| using NzbDrone.Core.Model.Notification; | ||||
| using NzbDrone.Core.Providers.Jobs; | ||||
|  | ||||
| namespace NzbDrone.Core.Test | ||||
| { | ||||
|     [TestFixture] | ||||
|     // ReSharper disable InconsistentNaming | ||||
|     public class JobProviderTest | ||||
|     { | ||||
|         [Test] | ||||
|         public void Run_Jobs() | ||||
|         { | ||||
|  | ||||
|             IEnumerable<IJob> fakeTimers = new List<IJob> { new FakeJob() }; | ||||
|             var mocker = new AutoMoqer(); | ||||
|  | ||||
|             mocker.SetConstant(MockLib.GetEmptyRepository()); | ||||
|             mocker.SetConstant(fakeTimers); | ||||
|  | ||||
|             var timerProvider = mocker.Resolve<JobProvider>(); | ||||
|             timerProvider.Initialize(); | ||||
|             timerProvider.RunScheduled(); | ||||
|  | ||||
|         } | ||||
|  | ||||
|  | ||||
|         [Test] | ||||
|         //This test will confirm that the concurrency checks are rest | ||||
|         //after execution so the job can successfully run. | ||||
|         public void can_run_job_again() | ||||
|         { | ||||
|             IEnumerable<IJob> fakeTimers = new List<IJob> { new FakeJob() }; | ||||
|             var mocker = new AutoMoqer(); | ||||
|  | ||||
|             mocker.SetConstant(MockLib.GetEmptyRepository()); | ||||
|             mocker.SetConstant(fakeTimers); | ||||
|  | ||||
|             var timerProvider = mocker.Resolve<JobProvider>(); | ||||
|             timerProvider.Initialize(); | ||||
|             var firstRun = timerProvider.RunScheduled(); | ||||
|             var secondRun = timerProvider.RunScheduled(); | ||||
|  | ||||
|             Assert.IsTrue(firstRun); | ||||
|             Assert.IsTrue(secondRun); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         [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> fakeTimers = new List<IJob> { new FakeJob() }; | ||||
|             var mocker = new AutoMoqer(); | ||||
|  | ||||
|             mocker.SetConstant(MockLib.GetEmptyRepository()); | ||||
|             mocker.SetConstant(fakeTimers); | ||||
|  | ||||
|             var timerProvider = mocker.Resolve<JobProvider>(); | ||||
|             timerProvider.Initialize(); | ||||
|             var firstRun = timerProvider.BeginExecute(typeof(FakeJob)); | ||||
|             Thread.Sleep(2000); | ||||
|             var secondRun = timerProvider.BeginExecute(typeof(FakeJob)); | ||||
|  | ||||
|             Assert.IsTrue(firstRun); | ||||
|             Assert.IsTrue(secondRun); | ||||
|  | ||||
|         } | ||||
|  | ||||
|  | ||||
|         [Test] | ||||
|         //This test will confirm that the concurrency checks are rest | ||||
|         //after execution so the job can successfully run. | ||||
|         public void can_run_two_jobs_at_the_same_time() | ||||
|         { | ||||
|             IEnumerable<IJob> fakeTimers = new List<IJob> { new SlowJob() }; | ||||
|             var mocker = new AutoMoqer(); | ||||
|  | ||||
|             mocker.SetConstant(MockLib.GetEmptyRepository()); | ||||
|             mocker.SetConstant(fakeTimers); | ||||
|  | ||||
|             var timerProvider = mocker.Resolve<JobProvider>(); | ||||
|             timerProvider.Initialize(); | ||||
|  | ||||
|             bool firstRun = false; | ||||
|             bool secondRun = false; | ||||
|  | ||||
|             var thread1 = new Thread(() => firstRun = timerProvider.RunScheduled()); | ||||
|             thread1.Start(); | ||||
|             Thread.Sleep(1000); | ||||
|             var thread2 = new Thread(() => secondRun = timerProvider.RunScheduled()); | ||||
|             thread2.Start(); | ||||
|  | ||||
|             thread1.Join(); | ||||
|             thread2.Join(); | ||||
|  | ||||
|             Assert.IsTrue(firstRun); | ||||
|             Assert.IsFalse(secondRun); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void Init_Jobs() | ||||
|         { | ||||
|             var fakeTimer = new FakeJob(); | ||||
|             IEnumerable<IJob> fakeTimers = new List<IJob> { fakeTimer }; | ||||
|             var mocker = new AutoMoqer(); | ||||
|  | ||||
|             mocker.SetConstant(MockLib.GetEmptyRepository()); | ||||
|             mocker.SetConstant(fakeTimers); | ||||
|  | ||||
|             var timerProvider = mocker.Resolve<JobProvider>(); | ||||
|             timerProvider.Initialize(); | ||||
|  | ||||
|             var timers = timerProvider.All(); | ||||
|  | ||||
|  | ||||
|             //Assert | ||||
|             Assert.Count(1, timers); | ||||
|             Assert.AreEqual(fakeTimer.DefaultInterval, timers[0].Interval); | ||||
|             Assert.AreEqual(fakeTimer.Name, timers[0].Name); | ||||
|             Assert.AreEqual(fakeTimer.GetType().ToString(), timers[0].TypeName); | ||||
|             Assert.AreEqual(DateTime.MinValue, timers[0].LastExecution); | ||||
|             Assert.IsTrue(timers[0].Enable); | ||||
|  | ||||
|  | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void Init_Timers_only_registers_once() | ||||
|         { | ||||
|             var repo = MockLib.GetEmptyRepository(); | ||||
|  | ||||
|             for (int i = 0; i < 2; i++) | ||||
|             { | ||||
|                 var fakeTimer = new FakeJob(); | ||||
|                 IEnumerable<IJob> fakeTimers = new List<IJob> { fakeTimer }; | ||||
|                 var mocker = new AutoMoqer(); | ||||
|  | ||||
|                 mocker.SetConstant(repo); | ||||
|                 mocker.SetConstant(fakeTimers); | ||||
|  | ||||
|                 var timerProvider = mocker.Resolve<JobProvider>(); | ||||
|                 timerProvider.Initialize(); | ||||
|             } | ||||
|  | ||||
|             var mocker2 = new AutoMoqer(); | ||||
|  | ||||
|             mocker2.SetConstant(repo); | ||||
|             var assertTimerProvider = mocker2.Resolve<JobProvider>(); | ||||
|  | ||||
|             var timers = assertTimerProvider.All(); | ||||
|  | ||||
|  | ||||
|             //Assert | ||||
|             Assert.Count(1, timers); | ||||
|         } | ||||
|  | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public class FakeJob : IJob | ||||
|     { | ||||
|         public string Name | ||||
|         { | ||||
|             get { return "FakeJob"; } | ||||
|         } | ||||
|  | ||||
|         public int DefaultInterval | ||||
|         { | ||||
|             get { return 15; } | ||||
|         } | ||||
|  | ||||
|         public void Start(ProgressNotification notification, int targetId) | ||||
|         { | ||||
|             throw new NotImplementedException(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public class SlowJob : IJob | ||||
|     { | ||||
|         public string Name | ||||
|         { | ||||
|             get { return "FakeJob"; } | ||||
|         } | ||||
|  | ||||
|         public int DefaultInterval | ||||
|         { | ||||
|             get { return 15; } | ||||
|         } | ||||
|  | ||||
|         public void Start(ProgressNotification notification, int targetId) | ||||
|         { | ||||
|             Thread.Sleep(10000); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -93,7 +93,7 @@ | ||||
|     <Compile Include="AutoMoq\Unity\AutoMockingContainerExtension.cs"> | ||||
|       <SubType>Code</SubType> | ||||
|     </Compile> | ||||
|     <Compile Include="TimerProviderTest.cs" /> | ||||
|     <Compile Include="JobProviderTest.cs" /> | ||||
|     <Compile Include="SyncProviderTest.cs" /> | ||||
|     <Compile Include="RootDirProviderTest.cs" /> | ||||
|     <Compile Include="IndexerProviderTest.cs" /> | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| using System.Threading; | ||||
| using System; | ||||
| using System.Threading; | ||||
| using MbUnit.Framework; | ||||
| using NzbDrone.Core.Repository.Quality; | ||||
|  | ||||
|   | ||||
| @@ -1,110 +0,0 @@ | ||||
| using System; | ||||
| using System.Linq; | ||||
| using System.Collections.Generic; | ||||
| using AutoMoq; | ||||
| using MbUnit.Framework; | ||||
| using Moq; | ||||
| using NzbDrone.Core.Providers; | ||||
| using NzbDrone.Core.Providers.Core; | ||||
| using NzbDrone.Core.Providers.Timers; | ||||
|  | ||||
| namespace NzbDrone.Core.Test | ||||
| { | ||||
|     [TestFixture] | ||||
|     // ReSharper disable InconsistentNaming | ||||
|     public class TimerProviderTest | ||||
|     { | ||||
|         [Test] | ||||
|         public void Run_Timers() | ||||
|         { | ||||
|  | ||||
|             IEnumerable<ITimer> fakeTimers = new List<ITimer> { new FakeTimer() }; | ||||
|             var mocker = new AutoMoqer(); | ||||
|  | ||||
|             mocker.SetConstant(MockLib.GetEmptyRepository()); | ||||
|             mocker.SetConstant(fakeTimers); | ||||
|  | ||||
|             var timerProvider = mocker.Resolve<TimerProvider>(); | ||||
|             timerProvider.Initialize(); | ||||
|             timerProvider.Run(); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void Init_Timers() | ||||
|         { | ||||
|             var fakeTimer = new FakeTimer(); | ||||
|             IEnumerable<ITimer> fakeTimers = new List<ITimer> { fakeTimer }; | ||||
|             var mocker = new AutoMoqer(); | ||||
|  | ||||
|             mocker.SetConstant(MockLib.GetEmptyRepository()); | ||||
|             mocker.SetConstant(fakeTimers); | ||||
|  | ||||
|             var timerProvider = mocker.Resolve<TimerProvider>(); | ||||
|             timerProvider.Initialize(); | ||||
|  | ||||
|             var timers = timerProvider.All(); | ||||
|  | ||||
|  | ||||
|             //Assert | ||||
|             Assert.Count(1, timers); | ||||
|             Assert.AreEqual(fakeTimer.DefaultInterval, timers[0].Interval); | ||||
|             Assert.AreEqual(fakeTimer.Name, timers[0].Name); | ||||
|             Assert.AreEqual(fakeTimer.GetType().ToString(), timers[0].TypeName); | ||||
|             Assert.AreEqual(DateTime.MinValue, timers[0].LastExecution); | ||||
|             Assert.IsTrue(timers[0].Enable); | ||||
|  | ||||
|  | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void Init_Timers_only_registers_once() | ||||
|         { | ||||
|             var repo = MockLib.GetEmptyRepository(); | ||||
|  | ||||
|             for (int i = 0; i < 2; i++) | ||||
|             { | ||||
|                 var fakeTimer = new FakeTimer(); | ||||
|                 IEnumerable<ITimer> fakeTimers = new List<ITimer> { fakeTimer }; | ||||
|                 var mocker = new AutoMoqer(); | ||||
|  | ||||
|                 mocker.SetConstant(repo); | ||||
|                 mocker.SetConstant(fakeTimers); | ||||
|  | ||||
|                 var timerProvider = mocker.Resolve<TimerProvider>(); | ||||
|                 timerProvider.Initialize(); | ||||
|             } | ||||
|  | ||||
|             var mocker2 = new AutoMoqer(); | ||||
|  | ||||
|             mocker2.SetConstant(repo); | ||||
|             var assertTimerProvider = mocker2.Resolve<TimerProvider>(); | ||||
|  | ||||
|             var timers = assertTimerProvider.All(); | ||||
|  | ||||
|  | ||||
|             //Assert | ||||
|             Assert.Count(1, timers); | ||||
|         } | ||||
|  | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public class FakeTimer : ITimer | ||||
|     { | ||||
|         public string Name | ||||
|         { | ||||
|             get { return "FakeTimer"; } | ||||
|         } | ||||
|  | ||||
|         public int DefaultInterval | ||||
|         { | ||||
|             get { return 15; } | ||||
|         } | ||||
|  | ||||
|         public void Start() | ||||
|         { | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -10,7 +10,7 @@ using NzbDrone.Core.Instrumentation; | ||||
| using NzbDrone.Core.Providers; | ||||
| using NzbDrone.Core.Providers.Core; | ||||
| using NzbDrone.Core.Providers.Indexer; | ||||
| using NzbDrone.Core.Providers.Timers; | ||||
| using NzbDrone.Core.Providers.Jobs; | ||||
| using NzbDrone.Core.Repository; | ||||
| using NzbDrone.Core.Repository.Quality; | ||||
| using SubSonic.DataProviders; | ||||
| @@ -77,7 +77,7 @@ namespace NzbDrone.Core | ||||
|                 dbProvider.Log = new NlogWriter(); | ||||
|  | ||||
|                 _kernel.Bind<QualityProvider>().ToSelf().InSingletonScope(); | ||||
|                 _kernel.Bind<TvDbProvider>().ToSelf().InSingletonScope(); | ||||
|                 _kernel.Bind<TvDbProvider>().ToSelf().InTransientScope(); | ||||
|                 _kernel.Bind<HttpProvider>().ToSelf().InSingletonScope(); | ||||
|                 _kernel.Bind<SeriesProvider>().ToSelf().InSingletonScope(); | ||||
|                 _kernel.Bind<SeasonProvider>().ToSelf().InSingletonScope(); | ||||
| @@ -96,7 +96,7 @@ namespace NzbDrone.Core | ||||
|                 _kernel.Bind<NotificationProvider>().ToSelf().InSingletonScope(); | ||||
|                 _kernel.Bind<LogProvider>().ToSelf().InSingletonScope(); | ||||
|                 _kernel.Bind<MediaFileProvider>().ToSelf().InSingletonScope(); | ||||
|                 _kernel.Bind<TimerProvider>().ToSelf().InSingletonScope(); | ||||
|                 _kernel.Bind<JobProvider>().ToSelf().InSingletonScope(); | ||||
|                 _kernel.Bind<IndexerProvider>().ToSelf().InSingletonScope(); | ||||
|                 _kernel.Bind<IRepository>().ToMethod( | ||||
|                     c => new SimpleRepository(dbProvider, SimpleRepositoryOptions.RunMigrations)).InSingletonScope(); | ||||
| @@ -109,7 +109,7 @@ namespace NzbDrone.Core | ||||
|                 SetupDefaultQualityProfiles(_kernel.Get<IRepository>()); //Setup the default QualityProfiles on start-up | ||||
|  | ||||
|                 BindIndexers(); | ||||
|                 BindTimers(); | ||||
|                 BindJobs(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -125,10 +125,12 @@ namespace NzbDrone.Core | ||||
|             _kernel.Get<IndexerProvider>().InitializeIndexers(indexers.ToList()); | ||||
|         } | ||||
|  | ||||
|         private static void BindTimers() | ||||
|         private static void BindJobs() | ||||
|         { | ||||
|             _kernel.Bind<ITimer>().To<RssSyncTimer>().InTransientScope(); | ||||
|             _kernel.Get<TimerProvider>().Initialize(); | ||||
|             _kernel.Bind<IJob>().To<RssSyncJob>().InTransientScope(); | ||||
|             _kernel.Bind<IJob>().To<NewSeriesUpdate>().InTransientScope(); | ||||
|             _kernel.Bind<IJob>().To<UpdateInfoJob>().InTransientScope(); | ||||
|             _kernel.Get<JobProvider>().Initialize(); | ||||
|         } | ||||
|  | ||||
|         private static void ForceMigration(IRepository repository) | ||||
|   | ||||
| @@ -169,12 +169,14 @@ | ||||
|     <Compile Include="Instrumentation\ExceptioneerTarget.cs" /> | ||||
|     <Compile Include="Instrumentation\NlogWriter.cs" /> | ||||
|     <Compile Include="Providers\Indexer\NzbMatrixProvider.cs" /> | ||||
|     <Compile Include="Providers\Timers\TimerProvider.cs" /> | ||||
|     <Compile Include="Providers\Jobs\NewSeriesUpdate.cs" /> | ||||
|     <Compile Include="Providers\Jobs\JobProvider.cs" /> | ||||
|     <Compile Include="Providers\Indexer\NewzbinProvider.cs" /> | ||||
|     <Compile Include="Providers\Indexer\NzbsRUsProvider.cs" /> | ||||
|     <Compile Include="Providers\Timers\ITimer.cs" /> | ||||
|     <Compile Include="Providers\Timers\RssSyncTimer.cs" /> | ||||
|     <Compile Include="Repository\TimerSetting.cs" /> | ||||
|     <Compile Include="Providers\Jobs\IJob.cs" /> | ||||
|     <Compile Include="Providers\Jobs\RssSyncJob.cs" /> | ||||
|     <Compile Include="Providers\Jobs\UpdateInfoJob.cs" /> | ||||
|     <Compile Include="Repository\JobSetting.cs" /> | ||||
|     <Compile Include="Repository\IndexerSetting.cs" /> | ||||
|     <Compile Include="Model\EpisodeParseResult.cs" /> | ||||
|     <Compile Include="Model\EpisodeRenameModel.cs" /> | ||||
|   | ||||
| @@ -129,7 +129,7 @@ namespace NzbDrone.Core.Providers | ||||
|             var newList = new List<Episode>(); | ||||
|  | ||||
|             Logger.Debug("Updating season info for series:{0}", targetSeries.SeriesName); | ||||
|             targetSeries.Episodes.Select(e => new {e.SeasonId, e.SeasonNumber}) | ||||
|             targetSeries.Episodes.Select(e => new { e.SeasonId, e.SeasonNumber }) | ||||
|                 .Distinct().ToList() | ||||
|                 .ForEach(s => _seasons.EnsureSeason(seriesId, s.SeasonId, s.SeasonNumber)); | ||||
|  | ||||
| @@ -144,8 +144,7 @@ namespace NzbDrone.Core.Providers | ||||
|                     if (episode.FirstAired < new DateTime(1753, 1, 1)) | ||||
|                         episode.FirstAired = new DateTime(1753, 1, 1); | ||||
|  | ||||
|                     Logger.Trace("Updating info for series:{0} - episode:{1}", targetSeries.SeriesName, | ||||
|                                  episode.EpisodeNumber); | ||||
|                     Logger.Trace("Updating info for [{0}] - S{1}E{2}", targetSeries.SeriesName, episode.SeasonNumber, episode.EpisodeNumber); | ||||
|                     var newEpisode = new Episode | ||||
|                                          { | ||||
|                                              AirDate = episode.FirstAired, | ||||
|   | ||||
							
								
								
									
										28
									
								
								NzbDrone.Core/Providers/Jobs/IJob.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								NzbDrone.Core/Providers/Jobs/IJob.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| using NzbDrone.Core.Model.Notification; | ||||
|  | ||||
| namespace NzbDrone.Core.Providers.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> | ||||
|         int 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> | ||||
|         void Start(ProgressNotification notification, int targetId); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										214
									
								
								NzbDrone.Core/Providers/Jobs/JobProvider.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										214
									
								
								NzbDrone.Core/Providers/Jobs/JobProvider.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,214 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Diagnostics; | ||||
| using System.Linq; | ||||
| using System.Threading; | ||||
| using NLog; | ||||
| using NzbDrone.Core.Model.Notification; | ||||
| using NzbDrone.Core.Repository; | ||||
| using SubSonic.Repository; | ||||
|  | ||||
| namespace NzbDrone.Core.Providers.Jobs | ||||
| { | ||||
|     public class JobProvider | ||||
|     { | ||||
|         private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); | ||||
|         private readonly IRepository _repository; | ||||
|         private readonly NotificationProvider _notificationProvider; | ||||
|         private readonly IEnumerable<IJob> _jobs; | ||||
|  | ||||
|         private static readonly object ExecutionLock = new object(); | ||||
|         private Thread _jobThread; | ||||
|         private static bool _isRunning; | ||||
|  | ||||
|         private ProgressNotification _notification; | ||||
|  | ||||
|         public JobProvider(IRepository repository, NotificationProvider notificationProvider, IEnumerable<IJob> jobs) | ||||
|         { | ||||
|             _repository = repository; | ||||
|             _notificationProvider = notificationProvider; | ||||
|             _jobs = jobs; | ||||
|         } | ||||
|  | ||||
|         public JobProvider() { } | ||||
|  | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Returns a list of all registered jobs | ||||
|         /// </summary> | ||||
|         /// <returns></returns> | ||||
|         public virtual List<JobSetting> All() | ||||
|         { | ||||
|             return _repository.All<JobSetting>().ToList(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Creates/Updates settings for a job | ||||
|         /// </summary> | ||||
|         /// <param name="settings">Settings to be created/updated</param> | ||||
|         public virtual void SaveSettings(JobSetting settings) | ||||
|         { | ||||
|             if (settings.Id == 0) | ||||
|             { | ||||
|                 Logger.Debug("Adding job settings for {0}", settings.Name); | ||||
|                 _repository.Add(settings); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 Logger.Debug("Updating job settings for {0}", settings.Name); | ||||
|                 _repository.Update(settings); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Iterates through all registered jobs and executed any that are due for an execution. | ||||
|         /// </summary> | ||||
|         /// <returns>True if ran, false if skipped</returns> | ||||
|         public virtual bool RunScheduled() | ||||
|         { | ||||
|             lock (ExecutionLock) | ||||
|             { | ||||
|                 if (_isRunning) | ||||
|                 { | ||||
|                     Logger.Info("Another instance of this job is already running. Ignoring request."); | ||||
|                     return false; | ||||
|                 } | ||||
|                 _isRunning = true; | ||||
|             } | ||||
|  | ||||
|             try | ||||
|             { | ||||
|                 Logger.Trace("Getting list of jobs needing to be executed"); | ||||
|  | ||||
|                 var pendingJobs = All().Where( | ||||
|                     t => t.Enable && | ||||
|                          (DateTime.Now - t.LastExecution) > TimeSpan.FromMinutes(t.Interval) | ||||
|                     ); | ||||
|  | ||||
|                 foreach (var pendingTimer in pendingJobs) | ||||
|                 { | ||||
|                     Logger.Info("Attempting to start job [{0}]. Last executing {1}", pendingTimer.Name, | ||||
|                                 pendingTimer.LastExecution); | ||||
|                     var timerClass = _jobs.Where(t => t.GetType().ToString() == pendingTimer.TypeName).FirstOrDefault(); | ||||
|                     Execute(timerClass.GetType(), 0); | ||||
|                 } | ||||
|             } | ||||
|             finally | ||||
|             { | ||||
|                 _isRunning = false; | ||||
|             } | ||||
|  | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|  | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Starts the execution of a job asynchronously | ||||
|         /// </summary> | ||||
|         /// <param name="jobType">Type of the job that should be executed.</param> | ||||
|         /// <param name="targetId">The targetId could be any Id parameter eg. SeriesId. it will be passed to the job implementation | ||||
|         /// to allow it to filter it's target of execution.</param> | ||||
|         /// <returns>True if ran, false if skipped</returns> | ||||
|         public bool BeginExecute(Type jobType, int targetId = 0) | ||||
|         { | ||||
|             lock (ExecutionLock) | ||||
|             { | ||||
|                 if (_isRunning) | ||||
|                 { | ||||
|                     Logger.Info("Another instance of this job is already running. Ignoring request."); | ||||
|                     return false; | ||||
|                 } | ||||
|                 _isRunning = true; | ||||
|             } | ||||
|  | ||||
|             Logger.Info("User has requested a manual execution of {0}", jobType.Name); | ||||
|             if (_jobThread == null || !_jobThread.IsAlive) | ||||
|             { | ||||
|                 Logger.Debug("Initializing background thread"); | ||||
|  | ||||
|                 ThreadStart starter = () => Execute(jobType, targetId); | ||||
|                 _jobThread = new Thread(starter) { Name = "TimerThread", Priority = ThreadPriority.BelowNormal }; | ||||
|                 _jobThread.Start(); | ||||
|  | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 Logger.Warn("Thread still active. Ignoring request."); | ||||
|             } | ||||
|  | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Executes the job | ||||
|         /// </summary> | ||||
|         /// <param name="jobType">Type of the job that should be executed</param> | ||||
|         /// <param name="targetId">The targetId could be any Id parameter eg. SeriesId. it will be passed to the timer implementation | ||||
|         /// to allow it to filter it's target of execution</param> | ||||
|         private void Execute(Type jobType, int targetId = 0) | ||||
|         { | ||||
|             var timerClass = _jobs.Where(t => t.GetType() == jobType).FirstOrDefault(); | ||||
|             if (timerClass == null) | ||||
|             { | ||||
|                 Logger.Error("Unable to locate implantation for [{0}]. Make sure its properly registered.", jobType.ToString()); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             try | ||||
|             { | ||||
|                 var sw = Stopwatch.StartNew(); | ||||
|                 using (_notification = new ProgressNotification(timerClass.Name)) | ||||
|                 { | ||||
|                     _notificationProvider.Register(_notification); | ||||
|                     timerClass.Start(_notification, targetId); | ||||
|                     _notification.Status = ProgressNotificationStatus.Completed; | ||||
|                 } | ||||
|                 sw.Stop(); | ||||
|                 Logger.Info("timer [{0}] finished executing successfully. Duration {1}", timerClass.Name, sw.Elapsed.ToString()); | ||||
|             } | ||||
|             catch (Exception e) | ||||
|             { | ||||
|                 Logger.ErrorException("An error has occurred while executing timer job" + timerClass.Name, e); | ||||
|             } | ||||
|             finally | ||||
|             { | ||||
|                 if (_jobThread == Thread.CurrentThread) | ||||
|                 { | ||||
|                     _isRunning = false; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes jobs in the database using the IJob instances that are | ||||
|         /// registered in CentralDispatch | ||||
|         /// </summary> | ||||
|         public virtual void Initialize() | ||||
|         { | ||||
|             Logger.Info("Initializing jobs. Count {0}", _jobs.Count()); | ||||
|             var currentTimer = All(); | ||||
|  | ||||
|             foreach (var timer in _jobs) | ||||
|             { | ||||
|                 var timerProviderLocal = timer; | ||||
|                 if (!currentTimer.Exists(c => c.TypeName == timerProviderLocal.GetType().ToString())) | ||||
|                 { | ||||
|                     var settings = new JobSetting() | ||||
|                                        { | ||||
|                                            Enable = true, | ||||
|                                            TypeName = timer.GetType().ToString(), | ||||
|                                            Name = timerProviderLocal.Name, | ||||
|                                            Interval = timerProviderLocal.DefaultInterval, | ||||
|                                            LastExecution = DateTime.MinValue | ||||
|  | ||||
|                                        }; | ||||
|  | ||||
|                     SaveSettings(settings); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										71
									
								
								NzbDrone.Core/Providers/Jobs/NewSeriesUpdate.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								NzbDrone.Core/Providers/Jobs/NewSeriesUpdate.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | ||||
| using System; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using NLog; | ||||
| using NzbDrone.Core.Model.Notification; | ||||
|  | ||||
| namespace NzbDrone.Core.Providers.Jobs | ||||
| { | ||||
|     public class NewSeriesUpdate : IJob | ||||
|     { | ||||
|         private readonly SeriesProvider _seriesProvider; | ||||
|         private readonly EpisodeProvider _episodeProvider; | ||||
|         private readonly MediaFileProvider _mediaFileProvider; | ||||
|  | ||||
|         private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); | ||||
|  | ||||
|         public NewSeriesUpdate(SeriesProvider seriesProvider, EpisodeProvider episodeProvider, MediaFileProvider mediaFileProvider) | ||||
|         { | ||||
|             _seriesProvider = seriesProvider; | ||||
|             _episodeProvider = episodeProvider; | ||||
|             _mediaFileProvider = mediaFileProvider; | ||||
|         } | ||||
|  | ||||
|         public string Name | ||||
|         { | ||||
|             get { return "New Series Update"; } | ||||
|         } | ||||
|  | ||||
|         public int DefaultInterval | ||||
|         { | ||||
|             get { return 1; } | ||||
|         } | ||||
|  | ||||
|         public void Start(ProgressNotification notification, int targetId) | ||||
|         { | ||||
|             ScanSeries(notification); | ||||
|         } | ||||
|  | ||||
|         private void ScanSeries(ProgressNotification notification) | ||||
|         { | ||||
|             var syncList = _seriesProvider.GetAllSeries().Where(s => s.LastInfoSync == null).ToList(); | ||||
|             if (syncList.Count == 0) return; | ||||
|  | ||||
|             foreach (var currentSeries in syncList) | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     notification.CurrentStatus = String.Format("Searching For: {0}", new DirectoryInfo(currentSeries.Path).Name); | ||||
|                     var updatedSeries = _seriesProvider.UpdateSeriesInfo(currentSeries.SeriesId); | ||||
|  | ||||
|                     notification.CurrentStatus = String.Format("Downloading episode info For: {0}", | ||||
|                                                                           updatedSeries.Title); | ||||
|                     _episodeProvider.RefreshEpisodeInfo(updatedSeries.SeriesId); | ||||
|  | ||||
|                     notification.CurrentStatus = String.Format("Scanning series folder {0}", | ||||
|                                                                           updatedSeries.Path); | ||||
|                     _mediaFileProvider.Scan(_seriesProvider.GetSeries(updatedSeries.SeriesId)); | ||||
|                 } | ||||
|  | ||||
|                 catch (Exception e) | ||||
|                 { | ||||
|                     Logger.ErrorException(e.Message, e); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             //Keep scanning until there no more shows left. | ||||
|             ScanSeries(notification); | ||||
|         } | ||||
|  | ||||
|     } | ||||
| } | ||||
| @@ -1,15 +1,16 @@ | ||||
| using System.Linq; | ||||
| using NLog; | ||||
| using NzbDrone.Core.Model.Notification; | ||||
| 
 | ||||
| namespace NzbDrone.Core.Providers.Timers | ||||
| namespace NzbDrone.Core.Providers.Jobs | ||||
| { | ||||
|     public class RssSyncTimer : ITimer | ||||
|     public class RssSyncJob : IJob | ||||
|     { | ||||
|         private readonly IndexerProvider _indexerProvider; | ||||
| 
 | ||||
|         private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); | ||||
| 
 | ||||
|         public RssSyncTimer(IndexerProvider indexerProvider) | ||||
|         public RssSyncJob(IndexerProvider indexerProvider) | ||||
|         { | ||||
|             _indexerProvider = indexerProvider; | ||||
|         } | ||||
| @@ -24,7 +25,7 @@ namespace NzbDrone.Core.Providers.Timers | ||||
|             get { return 15; } | ||||
|         } | ||||
| 
 | ||||
|         public void Start() | ||||
|         public void Start(ProgressNotification notification, int targetId) | ||||
|         { | ||||
|             Logger.Info("Doing Things!!!!"); | ||||
| 
 | ||||
| @@ -32,7 +33,7 @@ namespace NzbDrone.Core.Providers.Timers | ||||
| 
 | ||||
|             foreach (var indexerSetting in indexers) | ||||
|             { | ||||
|                  | ||||
| 
 | ||||
|             } | ||||
|         } | ||||
|     } | ||||
							
								
								
									
										50
									
								
								NzbDrone.Core/Providers/Jobs/UpdateInfoJob.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								NzbDrone.Core/Providers/Jobs/UpdateInfoJob.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| using System.Linq; | ||||
| using System.Collections.Generic; | ||||
| using NzbDrone.Core.Model.Notification; | ||||
| using NzbDrone.Core.Repository; | ||||
|  | ||||
| namespace NzbDrone.Core.Providers.Jobs | ||||
| { | ||||
|     public class UpdateInfoJob : IJob | ||||
|     { | ||||
|         private readonly SeriesProvider _seriesProvider; | ||||
|         private readonly EpisodeProvider _episodeProvider; | ||||
|  | ||||
|         public UpdateInfoJob(SeriesProvider seriesProvider, EpisodeProvider episodeProvider) | ||||
|         { | ||||
|             _seriesProvider = seriesProvider; | ||||
|             _episodeProvider = episodeProvider; | ||||
|         } | ||||
|  | ||||
|         public string Name | ||||
|         { | ||||
|             get { return "Update Info"; } | ||||
|         } | ||||
|  | ||||
|         public int DefaultInterval | ||||
|         { | ||||
|             get { return 1440; } //Daily | ||||
|         } | ||||
|  | ||||
|         public void Start(ProgressNotification notification, int targetId) | ||||
|         { | ||||
|             IList<Series> seriesToUpdate; | ||||
|             if (targetId == 0) | ||||
|             { | ||||
|                 seriesToUpdate = _seriesProvider.GetAllSeries().ToList(); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 seriesToUpdate = new List<Series>() { _seriesProvider.GetSeries(targetId) }; | ||||
|             } | ||||
|  | ||||
|             foreach (var series in seriesToUpdate) | ||||
|             { | ||||
|                 notification.CurrentStatus = "Updating series info for " + series.Title; | ||||
|                 _seriesProvider.UpdateSeriesInfo(series.SeriesId); | ||||
|                 notification.CurrentStatus = "Updating episode info for " + series.Title; | ||||
|                 _episodeProvider.RefreshEpisodeInfo(series.SeriesId); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -147,7 +147,7 @@ namespace NzbDrone.Core.Providers | ||||
|             } | ||||
|             catch (Exception e) | ||||
|             { | ||||
|                 Logger.Error("An error has occurred while deleting series.", e); | ||||
|                 Logger.ErrorException("An error has occurred while deleting series.", e); | ||||
|                 throw; | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -13,22 +13,11 @@ namespace NzbDrone.Core.Providers | ||||
|     { | ||||
|         private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); | ||||
|         private readonly DiskProvider _diskProvider; | ||||
|         private readonly EpisodeProvider _episodeProvider; | ||||
|         private readonly MediaFileProvider _mediaFileProvider; | ||||
|         private readonly NotificationProvider _notificationProvider; | ||||
|         private readonly SeriesProvider _seriesProvider; | ||||
|  | ||||
|         private ProgressNotification _seriesSyncNotification; | ||||
|         private Thread _seriesSyncThread; | ||||
|  | ||||
|         public SyncProvider(SeriesProvider seriesProvider, EpisodeProvider episodeProvider, | ||||
|                             MediaFileProvider mediaFileProvider, NotificationProvider notificationProvider, | ||||
|                             DiskProvider diskProvider) | ||||
|         public SyncProvider(SeriesProvider seriesProvider, DiskProvider diskProvider) | ||||
|         { | ||||
|             _seriesProvider = seriesProvider; | ||||
|             _episodeProvider = episodeProvider; | ||||
|             _mediaFileProvider = mediaFileProvider; | ||||
|             _notificationProvider = notificationProvider; | ||||
|             _diskProvider = diskProvider; | ||||
|         } | ||||
|  | ||||
| @@ -58,93 +47,5 @@ namespace NzbDrone.Core.Providers | ||||
|             Logger.Debug("{0} unmapped folders detected.", results.Count); | ||||
|             return results; | ||||
|         } | ||||
|  | ||||
|         public bool BeginUpdateNewSeries() | ||||
|         { | ||||
|             Logger.Debug("User has requested a scan of new series"); | ||||
|             if (_seriesSyncThread == null || !_seriesSyncThread.IsAlive) | ||||
|             { | ||||
|                 Logger.Debug("Initializing background scan thread"); | ||||
|                 _seriesSyncThread = new Thread(SyncNewSeries) | ||||
|                                         { | ||||
|                                             Name = "SyncNewSeries", | ||||
|                                             Priority = ThreadPriority.Lowest | ||||
|                                         }; | ||||
|  | ||||
|                 _seriesSyncThread.Start(); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 Logger.Warn("Series folder scan already in progress. Ignoring request."); | ||||
|  | ||||
|                 //return false if sync was already running, then we can tell the user to try again later | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|             //return true if sync has started | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         private void SyncNewSeries() | ||||
|         { | ||||
|             Logger.Info("Syncing new series"); | ||||
|  | ||||
|             try | ||||
|             { | ||||
|                 using (_seriesSyncNotification = new ProgressNotification("Series Scan")) | ||||
|                 { | ||||
|                     _notificationProvider.Register(_seriesSyncNotification); | ||||
|  | ||||
|                     _seriesSyncNotification.CurrentStatus = "Finding New Series"; | ||||
|                     ScanSeries(); | ||||
|  | ||||
|                     _seriesSyncNotification.CurrentStatus = "Series Scan Completed"; | ||||
|                     Logger.Info("Series folders scan has successfully completed."); | ||||
|                     Thread.Sleep(3000); | ||||
|                     _seriesSyncNotification.Status = ProgressNotificationStatus.Completed; | ||||
|                 } | ||||
|             } | ||||
|             catch (Exception e) | ||||
|             { | ||||
|                 Logger.ErrorException(e.Message, e); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private void ScanSeries() | ||||
|         { | ||||
|             var syncList = _seriesProvider.GetAllSeries().Where(s => s.LastInfoSync == null).ToList(); | ||||
|             if (syncList.Count == 0) return; | ||||
|  | ||||
|             _seriesSyncNotification.ProgressMax = syncList.Count; | ||||
|  | ||||
|             foreach (var currentSeries in syncList) | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     _seriesSyncNotification.CurrentStatus = String.Format("Searching For: {0}", currentSeries.Title); | ||||
|                     var updatedSeries = _seriesProvider.UpdateSeriesInfo(currentSeries.SeriesId); | ||||
|  | ||||
|                     _seriesSyncNotification.CurrentStatus = String.Format("Downloading episode info For: {0}", | ||||
|                                                                           updatedSeries.Title); | ||||
|                     _episodeProvider.RefreshEpisodeInfo(updatedSeries.SeriesId); | ||||
|  | ||||
|                     _seriesSyncNotification.CurrentStatus = String.Format("Scanning series folder {0}", | ||||
|                                                                           updatedSeries.Path); | ||||
|                     _mediaFileProvider.Scan(_seriesProvider.GetSeries(updatedSeries.SeriesId)); | ||||
|  | ||||
|                     //Todo: Launch Backlog search for this series _backlogProvider.StartSearch(mappedSeries.Id); | ||||
|                 } | ||||
|  | ||||
|                 catch (Exception e) | ||||
|                 { | ||||
|                     Logger.ErrorException(e.Message, e); | ||||
|                 } | ||||
|                 _seriesSyncNotification.ProgressValue++; | ||||
|             } | ||||
|  | ||||
|             //Keep scanning until there no more shows left. | ||||
|             ScanSeries(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,11 +0,0 @@ | ||||
| namespace NzbDrone.Core.Providers.Timers | ||||
| { | ||||
|     public interface ITimer | ||||
|     { | ||||
|         string Name { get; } | ||||
|  | ||||
|         int DefaultInterval { get; } | ||||
|  | ||||
|         void Start(); | ||||
|     } | ||||
| } | ||||
| @@ -1,123 +0,0 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Diagnostics; | ||||
| using System.Linq; | ||||
| using NLog; | ||||
| using NzbDrone.Core.Repository; | ||||
| using SubSonic.Repository; | ||||
|  | ||||
| namespace NzbDrone.Core.Providers.Timers | ||||
| { | ||||
|     public class TimerProvider | ||||
|     { | ||||
|         private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); | ||||
|         private readonly IRepository _repository; | ||||
|         private readonly IEnumerable<ITimer> _timerJobs; | ||||
|  | ||||
|         private static readonly object ExecutionLock = new object(); | ||||
|         private static bool _isRunning; | ||||
|  | ||||
|         public TimerProvider(IRepository repository, IEnumerable<ITimer> timerJobs) | ||||
|         { | ||||
|             _repository = repository; | ||||
|             _timerJobs = timerJobs; | ||||
|         } | ||||
|  | ||||
|         public TimerProvider() { } | ||||
|  | ||||
|         public virtual List<TimerSetting> All() | ||||
|         { | ||||
|             return _repository.All<TimerSetting>().ToList(); | ||||
|         } | ||||
|  | ||||
|         public virtual void SaveSettings(TimerSetting settings) | ||||
|         { | ||||
|             if (settings.Id == 0) | ||||
|             { | ||||
|                 Logger.Debug("Adding timer settings for {0}", settings.Name); | ||||
|                 _repository.Add(settings); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 Logger.Debug("Updating timer settings for {0}", settings.Name); | ||||
|                 _repository.Update(settings); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public virtual void Run() | ||||
|         { | ||||
|             lock (ExecutionLock) | ||||
|             { | ||||
|                 if (_isRunning) | ||||
|                 { | ||||
|                     Logger.Info("Another instance of timer is already running. Ignoring request."); | ||||
|                     return; | ||||
|                 } | ||||
|                 _isRunning = true; | ||||
|             } | ||||
|  | ||||
|             Logger.Trace("Getting list of timers needing to be executed"); | ||||
|  | ||||
|             var pendingTimers = All().Where( | ||||
|                                                      t => t.Enable && | ||||
|                                                      (DateTime.Now - t.LastExecution) > TimeSpan.FromMinutes(t.Interval) | ||||
|                 ); | ||||
|  | ||||
|             foreach (var pendingTimer in pendingTimers) | ||||
|             { | ||||
|                 Logger.Info("Attempting to start timer [{0}]. Last executing {1}", pendingTimer.Name, pendingTimer.LastExecution); | ||||
|                 var timerClass = _timerJobs.Where(t => t.GetType().ToString() == pendingTimer.TypeName).FirstOrDefault(); | ||||
|                 ForceExecute(timerClass.GetType()); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public void ForceExecute(Type timerType) | ||||
|         { | ||||
|             var timerClass = _timerJobs.Where(t => t.GetType() == timerType).FirstOrDefault(); | ||||
|             if (timerClass == null) | ||||
|             { | ||||
|                 Logger.Error("Unable to locate implantation for [{0}]. Make sure its properly registered.", timerType.ToString()); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             try | ||||
|             { | ||||
|                 var sw = Stopwatch.StartNew(); | ||||
|                 timerClass.Start(); | ||||
|                 sw.Stop(); | ||||
|                 Logger.Info("timer [{0}] finished executing successfully. Duration {1}", timerClass.Name, sw.Elapsed.ToString()); | ||||
|             } | ||||
|             catch (Exception e) | ||||
|             { | ||||
|                 Logger.Error("An error has occurred while executing timer job " + timerClass.Name, e); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public virtual void Initialize() | ||||
|         { | ||||
|             Logger.Info("Initializing timer jobs. Count {0}", _timerJobs.Count()); | ||||
|             var currentTimer = All(); | ||||
|  | ||||
|             foreach (var timer in _timerJobs) | ||||
|             { | ||||
|                 var timerProviderLocal = timer; | ||||
|                 if (!currentTimer.Exists(c => c.TypeName == timerProviderLocal.GetType().ToString())) | ||||
|                 { | ||||
|                     var settings = new TimerSetting() | ||||
|                                        { | ||||
|                                            Enable = true, | ||||
|                                            TypeName = timer.GetType().ToString(), | ||||
|                                            Name = timerProviderLocal.Name, | ||||
|                                            Interval = timerProviderLocal.DefaultInterval, | ||||
|                                            LastExecution = DateTime.MinValue | ||||
|  | ||||
|                                        }; | ||||
|  | ||||
|                     SaveSettings(settings); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|  | ||||
|     } | ||||
| } | ||||
| @@ -25,29 +25,35 @@ namespace NzbDrone.Core.Providers | ||||
|  | ||||
|         public virtual IList<TvdbSearchResult> SearchSeries(string title) | ||||
|         { | ||||
|             Logger.Debug("Searching TVDB for '{0}'", title); | ||||
|             var result = _handler.SearchSeries(title); | ||||
|             lock (_handler) | ||||
|             { | ||||
|                 Logger.Debug("Searching TVDB for '{0}'", title); | ||||
|  | ||||
|             Logger.Debug("Search for '{0}' returned {1} possible results", title, result.Count); | ||||
|             return result; | ||||
|                 var result = _handler.SearchSeries(title); | ||||
|  | ||||
|                 Logger.Debug("Search for '{0}' returned {1} possible results", title, result.Count); | ||||
|                 return result; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|  | ||||
|         public virtual TvdbSearchResult GetSeries(string title) | ||||
|         { | ||||
|             var searchResults = SearchSeries(title); | ||||
|             if (searchResults.Count == 0) | ||||
|                 return null; | ||||
|  | ||||
|             foreach (var tvdbSearchResult in searchResults) | ||||
|             lock (_handler) | ||||
|             { | ||||
|                 if (IsTitleMatch(tvdbSearchResult.SeriesName, title)) | ||||
|                 var searchResults = SearchSeries(title); | ||||
|                 if (searchResults.Count == 0) | ||||
|                     return null; | ||||
|  | ||||
|                 foreach (var tvdbSearchResult in searchResults) | ||||
|                 { | ||||
|                     Logger.Debug("Search for '{0}' was successful", title); | ||||
|                     return tvdbSearchResult; | ||||
|                     if (IsTitleMatch(tvdbSearchResult.SeriesName, title)) | ||||
|                     { | ||||
|                         Logger.Debug("Search for '{0}' was successful", title); | ||||
|                         return tvdbSearchResult; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
| @@ -70,8 +76,11 @@ namespace NzbDrone.Core.Providers | ||||
|  | ||||
|         public virtual TvdbSeries GetSeries(int id, bool loadEpisodes) | ||||
|         { | ||||
|             Logger.Debug("Fetching SeriesId'{0}' from tvdb", id); | ||||
|             return _handler.GetSeries(id, TvdbLanguage.DefaultLanguage, loadEpisodes, false, false); | ||||
|             lock (_handler) | ||||
|             { | ||||
|                 Logger.Debug("Fetching SeriesId'{0}' from tvdb", id); | ||||
|                 return _handler.GetSeries(id, TvdbLanguage.DefaultLanguage, loadEpisodes, false, false); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|   | ||||
| @@ -3,7 +3,7 @@ using SubSonic.SqlGeneration.Schema; | ||||
| 
 | ||||
| namespace NzbDrone.Core.Repository | ||||
| { | ||||
|     public class TimerSetting | ||||
|     public class JobSetting | ||||
|     { | ||||
|         [SubSonicPrimaryKey(true)] | ||||
|         public Int32 Id { get; set; } | ||||
| @@ -4,6 +4,7 @@ using System.IO; | ||||
| using System.Web.Mvc; | ||||
| using NzbDrone.Core.Providers; | ||||
| using NzbDrone.Core.Providers.Core; | ||||
| using NzbDrone.Core.Providers.Jobs; | ||||
| using NzbDrone.Web.Models; | ||||
|  | ||||
| namespace NzbDrone.Web.Controllers | ||||
| @@ -14,13 +15,14 @@ namespace NzbDrone.Web.Controllers | ||||
|         private readonly QualityProvider _qualityProvider; | ||||
|         private readonly RootDirProvider _rootFolderProvider; | ||||
|         private readonly SeriesProvider _seriesProvider; | ||||
|         private readonly JobProvider _jobProvider; | ||||
|         private readonly SyncProvider _syncProvider; | ||||
|         private readonly TvDbProvider _tvDbProvider; | ||||
|  | ||||
|         public AddSeriesController(SyncProvider syncProvider, RootDirProvider rootFolderProvider, | ||||
|                                    ConfigProvider configProvider, | ||||
|                                    QualityProvider qualityProvider, TvDbProvider tvDbProvider, | ||||
|                                    SeriesProvider seriesProvider) | ||||
|                                    SeriesProvider seriesProvider, JobProvider jobProvider) | ||||
|         { | ||||
|             _syncProvider = syncProvider; | ||||
|             _rootFolderProvider = rootFolderProvider; | ||||
| @@ -28,12 +30,13 @@ namespace NzbDrone.Web.Controllers | ||||
|             _qualityProvider = qualityProvider; | ||||
|             _tvDbProvider = tvDbProvider; | ||||
|             _seriesProvider = seriesProvider; | ||||
|             _jobProvider = jobProvider; | ||||
|         } | ||||
|  | ||||
|         [HttpPost] | ||||
|         public JsonResult ScanNewSeries() | ||||
|         { | ||||
|             _syncProvider.BeginUpdateNewSeries(); | ||||
|             _jobProvider.BeginExecute(typeof(NewSeriesUpdate)); | ||||
|             return new JsonResult(); | ||||
|         } | ||||
|  | ||||
| @@ -106,7 +109,7 @@ namespace NzbDrone.Web.Controllers | ||||
|                 path.Replace('|', Path.DirectorySeparatorChar).Replace('^', Path.VolumeSeparatorChar), seriesId, | ||||
|                 qualityProfileId); | ||||
|             ScanNewSeries(); | ||||
|             return new JsonResult {Data = "ok"}; | ||||
|             return new JsonResult { Data = "ok" }; | ||||
|         } | ||||
|  | ||||
|         [HttpPost] | ||||
|   | ||||
| @@ -4,7 +4,7 @@ using System.IO; | ||||
| using System.Linq; | ||||
| using System.Web.Mvc; | ||||
| using NzbDrone.Core.Providers; | ||||
| using NzbDrone.Core.Providers.Timers; | ||||
| using NzbDrone.Core.Providers.Jobs; | ||||
| using NzbDrone.Core.Repository; | ||||
| using NzbDrone.Web.Models; | ||||
| using Telerik.Web.Mvc; | ||||
| @@ -21,27 +21,25 @@ namespace NzbDrone.Web.Controllers | ||||
|         private readonly RenameProvider _renameProvider; | ||||
|         private readonly RootDirProvider _rootDirProvider; | ||||
|         private readonly SeriesProvider _seriesProvider; | ||||
|         private readonly SyncProvider _syncProvider; | ||||
|         private readonly TvDbProvider _tvDbProvider; | ||||
|         private readonly TimerProvider _timerProvider; | ||||
|         private readonly JobProvider _jobProvider; | ||||
|         // | ||||
|         // GET: /Series/ | ||||
|  | ||||
|         public SeriesController(SyncProvider syncProvider, SeriesProvider seriesProvider, | ||||
|         public SeriesController(SeriesProvider seriesProvider, | ||||
|                                 EpisodeProvider episodeProvider, | ||||
|                                 QualityProvider qualityProvider, MediaFileProvider mediaFileProvider, | ||||
|                                 RenameProvider renameProvider, RootDirProvider rootDirProvider, | ||||
|                                 TvDbProvider tvDbProvider, TimerProvider timerProvider) | ||||
|                                 TvDbProvider tvDbProvider, JobProvider jobProvider) | ||||
|         { | ||||
|             _seriesProvider = seriesProvider; | ||||
|             _episodeProvider = episodeProvider; | ||||
|             _syncProvider = syncProvider; | ||||
|             _qualityProvider = qualityProvider; | ||||
|             _mediaFileProvider = mediaFileProvider; | ||||
|             _renameProvider = renameProvider; | ||||
|             _rootDirProvider = rootDirProvider; | ||||
|             _tvDbProvider = tvDbProvider; | ||||
|             _timerProvider = timerProvider; | ||||
|             _jobProvider = jobProvider; | ||||
|         } | ||||
|  | ||||
|         public ActionResult Index() | ||||
| @@ -53,15 +51,10 @@ namespace NzbDrone.Web.Controllers | ||||
|  | ||||
|         public ActionResult RssSync() | ||||
|         { | ||||
|             _timerProvider.ForceExecute(typeof(RssSyncTimer)); | ||||
|             _jobProvider.BeginExecute(typeof(RssSyncJob)); | ||||
|             return RedirectToAction("Index"); | ||||
|         } | ||||
|  | ||||
|         public ActionResult UnMapped(string path) | ||||
|         { | ||||
|             return View(_syncProvider.GetUnmappedFolders(path).Select(c => new MappingModel { Id = 1, Path = c }).ToList()); | ||||
|         } | ||||
|  | ||||
|         public ActionResult LoadEpisodes(int seriesId) | ||||
|         { | ||||
|             _episodeProvider.RefreshEpisodeInfo(seriesId); | ||||
| @@ -108,37 +101,6 @@ namespace NzbDrone.Web.Controllers | ||||
|                             }); | ||||
|         } | ||||
|  | ||||
|         [GridAction] | ||||
|         public ActionResult _AjaxUnmappedFoldersGrid() | ||||
|         { | ||||
|             var unmappedList = new List<AddExistingSeriesModel>(); | ||||
|  | ||||
|             foreach (var folder in _rootDirProvider.GetAll()) | ||||
|             { | ||||
|                 foreach (var unmappedFolder in _syncProvider.GetUnmappedFolders(folder.Path)) | ||||
|                 { | ||||
|                     var tvDbSeries = _seriesProvider.MapPathToSeries(unmappedFolder); | ||||
|  | ||||
|                     //We still want to show this series as unmapped, but we don't know what it will be when mapped | ||||
|                     //Todo: Provide the user with a way to manually map a folder to a TvDb series (or make them rename the folder...) | ||||
|                     if (tvDbSeries == null) | ||||
|                         tvDbSeries = new TvdbSeries { Id = 0, SeriesName = String.Empty }; | ||||
|  | ||||
|                     unmappedList.Add(new AddExistingSeriesModel | ||||
|                                          { | ||||
|                                              IsWanted = true, | ||||
|                                              Path = unmappedFolder, | ||||
|                                              PathEncoded = Url.Encode(unmappedFolder), | ||||
|                                              TvDbId = tvDbSeries.Id, | ||||
|                                              TvDbName = tvDbSeries.SeriesName | ||||
|                                          }); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return View(new GridModel(unmappedList)); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         public ActionResult SearchForSeries(string seriesName) | ||||
|         { | ||||
|             var model = new List<SeriesSearchResultModel>(); | ||||
| @@ -267,6 +229,13 @@ namespace NzbDrone.Web.Controllers | ||||
|             return RedirectToAction("Details", new { seriesId }); | ||||
|         } | ||||
|  | ||||
|         public ActionResult UpdateInfo(int seriesId) | ||||
|         { | ||||
|             //Syncs the episodes on disk for the specified series | ||||
|             _jobProvider.BeginExecute(typeof(UpdateInfoJob), seriesId); | ||||
|             return RedirectToAction("Details", new { seriesId }); | ||||
|         } | ||||
|  | ||||
|         public ActionResult RenameAll() | ||||
|         { | ||||
|             _renameProvider.RenameAll(); | ||||
|   | ||||
| @@ -1,17 +1,17 @@ | ||||
| using System; | ||||
| using System.Web.Mvc; | ||||
| using NzbDrone.Core.Providers; | ||||
| using NzbDrone.Core.Providers.Timers; | ||||
| using NzbDrone.Core.Providers.Jobs; | ||||
|  | ||||
| namespace NzbDrone.Web.Controllers | ||||
| { | ||||
|     public class SharedController : Controller | ||||
|     { | ||||
|         private readonly TimerProvider _timerProvider; | ||||
|         private readonly JobProvider _jobProvider; | ||||
|  | ||||
|         public SharedController(TimerProvider timerProvider) | ||||
|         public SharedController(JobProvider jobProvider) | ||||
|         { | ||||
|             _timerProvider = timerProvider; | ||||
|             _jobProvider = jobProvider; | ||||
|         } | ||||
|  | ||||
|         public ActionResult Index() | ||||
|   | ||||
| @@ -3,22 +3,22 @@ using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Web; | ||||
| using System.Web.Mvc; | ||||
| using NzbDrone.Core.Providers.Timers; | ||||
| using NzbDrone.Core.Providers.Jobs; | ||||
|  | ||||
| namespace NzbDrone.Web.Controllers | ||||
| { | ||||
|     public class TimersController : Controller | ||||
|     { | ||||
|         private readonly TimerProvider _timerProvider; | ||||
|         private readonly JobProvider _jobProvider; | ||||
|  | ||||
|         public TimersController(TimerProvider timerProvider) | ||||
|         public TimersController(JobProvider jobProvider) | ||||
|         { | ||||
|             _timerProvider = timerProvider; | ||||
|             _jobProvider = jobProvider; | ||||
|         } | ||||
|  | ||||
|         public ActionResult Index() | ||||
|         { | ||||
|             return View(_timerProvider.All()); | ||||
|             return View(_jobProvider.All()); | ||||
|         } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -19,6 +19,9 @@ | ||||
|                                                                items.Add().Text("Scan For Episodes on Disk").Action( | ||||
|                                                                    "SyncEpisodesOnDisk", "Series", | ||||
|                                                                    new {seriesId = Model.SeriesId}); | ||||
|                                                                items.Add().Text("Update Info").Action( | ||||
|                                                                   "UpdateInfo", "Series", | ||||
|                                                                   new { seriesId = Model.SeriesId }); | ||||
|                                                                items.Add().Text("Rename Series").Action("RenameSeries", | ||||
|                                                                                                         "Series", | ||||
|                                                                                                         new | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| @model IEnumerable<NzbDrone.Core.Repository.TimerSetting> | ||||
| @model IEnumerable<NzbDrone.Core.Repository.JobSetting> | ||||
| @{ | ||||
|     Layout = null; | ||||
| } | ||||
|   | ||||
| @@ -51,7 +51,7 @@ namespace NzbDrone | ||||
|             } | ||||
|             catch (Exception e) | ||||
|             { | ||||
|                 Logger.Error("An error has occured while trying to update the config file.", e); | ||||
|                 Logger.ErrorException("An error has occurred while trying to update the config file.", e); | ||||
|             } | ||||
|  | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user