mirror of
https://github.com/Radarr/Radarr.git
synced 2024-08-16 23:39:44 +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:
parent
b86dac57e1
commit
9028e498ca
@ -30,8 +30,9 @@ internal AutoMoqer(IUnityContainer container)
|
||||
|
||||
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 @@ internal virtual void SetMock(Type type, Mock mock)
|
||||
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 @@ private static void AddTheAutoMockingContainerExtensionToTheContainer(IUnityCont
|
||||
|
||||
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 @@ private bool GetMockHasNotBeenCalledForThisType(Type type)
|
||||
|
||||
private static Type GetTheMockType<T>() where T : class
|
||||
{
|
||||
return typeof (T);
|
||||
return typeof(T);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -87,5 +87,25 @@ public void IsNeededTrue()
|
||||
|
||||
//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.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 @@ public static void BindKernel()
|
||||
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 @@ public static void BindKernel()
|
||||
_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 @@ public static void BindKernel()
|
||||
SetupDefaultQualityProfiles(_kernel.Get<IRepository>()); //Setup the default QualityProfiles on start-up
|
||||
|
||||
BindIndexers();
|
||||
BindTimers();
|
||||
BindJobs();
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,10 +125,12 @@ private static void BindIndexers()
|
||||
_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 @@ public virtual void RefreshEpisodeInfo(int seriesId)
|
||||
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 @@ public virtual void RefreshEpisodeInfo(int seriesId)
|
||||
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 @@ public int DefaultInterval
|
||||
get { return 15; }
|
||||
}
|
||||
|
||||
public void Start()
|
||||
public void Start(ProgressNotification notification, int targetId)
|
||||
{
|
||||
Logger.Info("Doing Things!!!!");
|
||||
|
||||
@ -32,7 +33,7 @@ public void Start()
|
||||
|
||||
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 @@ public virtual void DeleteSeries(int seriesId)
|
||||
}
|
||||
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 @@ public class SyncProvider
|
||||
{
|
||||
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 @@ public List<String> GetUnmappedFolders(string path)
|
||||
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 @@ public TvDbProvider()
|
||||
|
||||
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 @@ public virtual int GetBestMatch(List<TvdbSearchResult> searchResults, string tit
|
||||
|
||||
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 @@
|
||||
|
||||
namespace NzbDrone.Core.Repository
|
||||
{
|
||||
public class TimerSetting
|
||||
public class JobSetting
|
||||
{
|
||||
[SubSonicPrimaryKey(true)]
|
||||
public Int32 Id { get; set; }
|
@ -4,6 +4,7 @@
|
||||
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 @@ public class AddSeriesController : Controller
|
||||
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 @@ public AddSeriesController(SyncProvider syncProvider, RootDirProvider rootFolder
|
||||
_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 @@ public JsonResult AddSeries(string path, int seriesId, int qualityProfileId)
|
||||
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.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 @@ public class SeriesController : Controller
|
||||
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 @@ public ActionResult Index()
|
||||
|
||||
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 @@ public ActionResult _CustomBinding(GridCommand command, int seasonId)
|
||||
});
|
||||
}
|
||||
|
||||
[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 @@ public ActionResult SyncEpisodesOnDisk(int seriesId)
|
||||
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.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 @@ internal static Process StartIIS()
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user