parent
d10e60587b
commit
b1fd924188
@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.HealthCheck.Checks;
|
||||
using NzbDrone.Core.NetImport;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.HealthCheck.Checks
|
||||
{
|
||||
[TestFixture]
|
||||
public class NetImportStatusCheckFixture : CoreTest<NetImportStatusCheck>
|
||||
{
|
||||
private List<INetImport> _lists = new List<INetImport>();
|
||||
private List<NetImportStatus> _blockedLists = new List<NetImportStatus>();
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
Mocker.GetMock<INetImportFactory>()
|
||||
.Setup(v => v.GetAvailableProviders())
|
||||
.Returns(_lists);
|
||||
|
||||
Mocker.GetMock<INetImportStatusService>()
|
||||
.Setup(v => v.GetBlockedProviders())
|
||||
.Returns(_blockedLists);
|
||||
}
|
||||
|
||||
private Mock<INetImport> GivenList(int i, double backoffHours, double failureHours)
|
||||
{
|
||||
var id = i;
|
||||
|
||||
var mockList = new Mock<INetImport>();
|
||||
mockList.SetupGet(s => s.Definition).Returns(new NetImportDefinition { Id = id });
|
||||
mockList.SetupGet(s => s.EnableAuto).Returns(true);
|
||||
|
||||
_lists.Add(mockList.Object);
|
||||
|
||||
if (backoffHours != 0.0)
|
||||
{
|
||||
_blockedLists.Add(new NetImportStatus
|
||||
{
|
||||
ProviderId = id,
|
||||
InitialFailure = DateTime.UtcNow.AddHours(-failureHours),
|
||||
MostRecentFailure = DateTime.UtcNow.AddHours(-0.1),
|
||||
EscalationLevel = 5,
|
||||
DisabledTill = DateTime.UtcNow.AddHours(backoffHours)
|
||||
});
|
||||
}
|
||||
|
||||
return mockList;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_return_error_when_no_indexers()
|
||||
{
|
||||
Subject.Check().ShouldBeOk();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_warning_if_indexer_unavailable()
|
||||
{
|
||||
GivenList(1, 10.0, 24.0);
|
||||
GivenList(2, 0.0, 0.0);
|
||||
|
||||
Subject.Check().ShouldBeWarning();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_error_if_all_indexers_unavailable()
|
||||
{
|
||||
GivenList(1, 10.0, 24.0);
|
||||
|
||||
Subject.Check().ShouldBeError();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_warning_if_few_indexers_unavailable()
|
||||
{
|
||||
GivenList(1, 10.0, 24.0);
|
||||
GivenList(2, 10.0, 24.0);
|
||||
GivenList(3, 0.0, 0.0);
|
||||
|
||||
Subject.Check().ShouldBeWarning();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Core.NetImport;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.NetImport
|
||||
{
|
||||
public class NetImportStatusServiceFixture : CoreTest<NetImportStatusService>
|
||||
{
|
||||
private DateTime _epoch;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_epoch = DateTime.UtcNow;
|
||||
|
||||
Mocker.GetMock<IRuntimeInfo>()
|
||||
.SetupGet(v => v.StartTime)
|
||||
.Returns(_epoch - TimeSpan.FromHours(1));
|
||||
}
|
||||
|
||||
private void WithStatus(NetImportStatus status)
|
||||
{
|
||||
Mocker.GetMock<INetImportStatusRepository>()
|
||||
.Setup(v => v.FindByProviderId(1))
|
||||
.Returns(status);
|
||||
|
||||
Mocker.GetMock<INetImportStatusRepository>()
|
||||
.Setup(v => v.All())
|
||||
.Returns(new[] { status });
|
||||
}
|
||||
|
||||
private void VerifyUpdate()
|
||||
{
|
||||
Mocker.GetMock<INetImportStatusRepository>()
|
||||
.Verify(v => v.Upsert(It.IsAny<NetImportStatus>()), Times.Once());
|
||||
}
|
||||
|
||||
private void VerifyNoUpdate()
|
||||
{
|
||||
Mocker.GetMock<INetImportStatusRepository>()
|
||||
.Verify(v => v.Upsert(It.IsAny<NetImportStatus>()), Times.Never());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_cancel_backoff_on_success()
|
||||
{
|
||||
WithStatus(new NetImportStatus { EscalationLevel = 2 });
|
||||
|
||||
Subject.RecordSuccess(1);
|
||||
|
||||
VerifyUpdate();
|
||||
|
||||
var status = Subject.GetBlockedProviders().FirstOrDefault();
|
||||
status.Should().BeNull();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_store_update_if_already_okay()
|
||||
{
|
||||
WithStatus(new NetImportStatus { EscalationLevel = 0 });
|
||||
|
||||
Subject.RecordSuccess(1);
|
||||
|
||||
VerifyNoUpdate();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(173)]
|
||||
public class net_import_status : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Create.TableForModel("NetImportStatus")
|
||||
.WithColumn("ProviderId").AsInt32().NotNullable().Unique()
|
||||
.WithColumn("InitialFailure").AsDateTime().Nullable()
|
||||
.WithColumn("MostRecentFailure").AsDateTime().Nullable()
|
||||
.WithColumn("EscalationLevel").AsInt32().NotNullable()
|
||||
.WithColumn("DisabledTill").AsDateTime().Nullable()
|
||||
.WithColumn("LastSyncListInfo").AsString().Nullable();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
using System.Linq;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.NetImport;
|
||||
using NzbDrone.Core.ThingiProvider.Events;
|
||||
|
||||
namespace NzbDrone.Core.HealthCheck.Checks
|
||||
{
|
||||
[CheckOn(typeof(ProviderUpdatedEvent<INetImport>))]
|
||||
[CheckOn(typeof(ProviderDeletedEvent<INetImport>))]
|
||||
[CheckOn(typeof(ProviderStatusChangedEvent<INetImport>))]
|
||||
public class NetImportStatusCheck : HealthCheckBase
|
||||
{
|
||||
private readonly INetImportFactory _providerFactory;
|
||||
private readonly INetImportStatusService _providerStatusService;
|
||||
|
||||
public NetImportStatusCheck(INetImportFactory providerFactory, INetImportStatusService providerStatusService)
|
||||
{
|
||||
_providerFactory = providerFactory;
|
||||
_providerStatusService = providerStatusService;
|
||||
}
|
||||
|
||||
public override HealthCheck Check()
|
||||
{
|
||||
var enabledProviders = _providerFactory.GetAvailableProviders();
|
||||
var backOffProviders = enabledProviders.Join(_providerStatusService.GetBlockedProviders(),
|
||||
i => i.Definition.Id,
|
||||
s => s.ProviderId,
|
||||
(i, s) => new { Provider = i, Status = s })
|
||||
.ToList();
|
||||
|
||||
if (backOffProviders.Empty())
|
||||
{
|
||||
return new HealthCheck(GetType());
|
||||
}
|
||||
|
||||
if (backOffProviders.Count == enabledProviders.Count)
|
||||
{
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Error, "All lists are unavailable due to failures", "#lists-are-unavailable-due-to-failures");
|
||||
}
|
||||
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Warning, string.Format("Lists unavailable due to failures: {0}", string.Join(", ", backOffProviders.Select(v => v.Provider.Definition.Name))), "#lists-are-unavailable-due-to-failures");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
using NzbDrone.Core.Movies;
|
||||
using NzbDrone.Core.ThingiProvider.Status;
|
||||
|
||||
namespace NzbDrone.Core.NetImport
|
||||
{
|
||||
public class NetImportStatus : ProviderStatusBase
|
||||
{
|
||||
public Movie LastSyncListInfo { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.ThingiProvider.Status;
|
||||
|
||||
namespace NzbDrone.Core.NetImport
|
||||
{
|
||||
public interface INetImportStatusRepository : IProviderStatusRepository<NetImportStatus>
|
||||
{
|
||||
}
|
||||
|
||||
public class NetImportStatusRepository : ProviderStatusRepository<NetImportStatus>, INetImportStatusRepository
|
||||
{
|
||||
public NetImportStatusRepository(IMainDatabase database, IEventAggregator eventAggregator)
|
||||
: base(database, eventAggregator)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
using NLog;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Movies;
|
||||
using NzbDrone.Core.ThingiProvider.Status;
|
||||
|
||||
namespace NzbDrone.Core.NetImport
|
||||
{
|
||||
public interface INetImportStatusService : IProviderStatusServiceBase<NetImportStatus>
|
||||
{
|
||||
Movie GetLastSyncListInfo(int importListId);
|
||||
|
||||
void UpdateListSyncStatus(int importListId, Movie listItemInfo);
|
||||
}
|
||||
|
||||
public class NetImportStatusService : ProviderStatusServiceBase<INetImport, NetImportStatus>, INetImportStatusService
|
||||
{
|
||||
public NetImportStatusService(INetImportStatusRepository providerStatusRepository, IEventAggregator eventAggregator, IRuntimeInfo runtimeInfo, Logger logger)
|
||||
: base(providerStatusRepository, eventAggregator, runtimeInfo, logger)
|
||||
{
|
||||
}
|
||||
|
||||
public Movie GetLastSyncListInfo(int importListId)
|
||||
{
|
||||
return GetProviderStatus(importListId).LastSyncListInfo;
|
||||
}
|
||||
|
||||
public void UpdateListSyncStatus(int importListId, Movie listItemInfo)
|
||||
{
|
||||
lock (_syncRoot)
|
||||
{
|
||||
var status = GetProviderStatus(importListId);
|
||||
|
||||
status.LastSyncListInfo = listItemInfo;
|
||||
|
||||
_providerStatusRepository.Upsert(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in new issue