feat(request-limits): Request limits are no longer a rolling date. But reset at the start of the week or month depending on the preference

pull/4312/head
tidusjar 3 years ago
parent 847873c307
commit 364b9f11af

@ -5,13 +5,16 @@ using NUnit.Framework;
using Ombi.Core.Authentication; using Ombi.Core.Authentication;
using Ombi.Core.Engine; using Ombi.Core.Engine;
using Ombi.Core.Models; using Ombi.Core.Models;
using Ombi.Helpers;
using Ombi.Store.Entities; using Ombi.Store.Entities;
using Ombi.Store.Entities.Requests; using Ombi.Store.Entities.Requests;
using Ombi.Store.Repository; using Ombi.Store.Repository;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization;
using System.Linq; using System.Linq;
using System.Security.Principal; using System.Security.Principal;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ombi.Core.Tests.Engine namespace Ombi.Core.Tests.Engine
@ -26,6 +29,7 @@ namespace Ombi.Core.Tests.Engine
[SetUp] [SetUp]
public void SetUp() public void SetUp()
{ {
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-GB");
_mocker = new AutoMocker(); _mocker = new AutoMocker();
var principleMock = new Mock<IPrincipal>(); var principleMock = new Mock<IPrincipal>();
var identityMock = new Mock<IIdentity>(); var identityMock = new Mock<IIdentity>();
@ -246,6 +250,7 @@ namespace Ombi.Core.Tests.Engine
MovieRequestLimitType = RequestLimitType.Day, MovieRequestLimitType = RequestLimitType.Day,
Id = "id1" Id = "id1"
}; };
var today = DateTime.Now; var today = DateTime.Now;
var log = new List<RequestLog> var log = new List<RequestLog>
{ {
@ -265,7 +270,7 @@ namespace Ombi.Core.Tests.Engine
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true) .With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2) .And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(1) .And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(1)
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(today.AddDays(1).AddHours(-1)) .And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(today.AddDays(1).Date)
); );
} }
@ -304,7 +309,7 @@ namespace Ombi.Core.Tests.Engine
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true) .With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2) .And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(0) .And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(0)
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(today.AddDays(1).AddHours(-2)) .And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(today.AddDays(1).Date)
); );
} }
@ -318,7 +323,7 @@ namespace Ombi.Core.Tests.Engine
MovieRequestLimitType = RequestLimitType.Week, MovieRequestLimitType = RequestLimitType.Week,
Id = "id1" Id = "id1"
}; };
var lastWeek = DateTime.Now.AddDays(-8); var lastWeek = DateTime.Now.FirstDateInWeek().AddDays(-1); // Day before reset
var log = new List<RequestLog> var log = new List<RequestLog>
{ {
new RequestLog new RequestLog
@ -350,7 +355,7 @@ namespace Ombi.Core.Tests.Engine
MovieRequestLimitType = RequestLimitType.Week, MovieRequestLimitType = RequestLimitType.Week,
Id = "id1" Id = "id1"
}; };
var today = DateTime.Now; var today = DateTime.UtcNow;
var log = new List<RequestLog> var log = new List<RequestLog>
{ {
new RequestLog new RequestLog
@ -369,7 +374,7 @@ namespace Ombi.Core.Tests.Engine
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true) .With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2) .And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(1) .And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(1)
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(today.AddDays(7)) .And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(today.FirstDateInWeek().AddDays(7).Date)
); );
} }
@ -408,7 +413,7 @@ namespace Ombi.Core.Tests.Engine
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true) .With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2) .And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(0) .And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(0)
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(today.AddDays(6)) .And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(today.FirstDateInWeek().AddDays(7).Date)
); );
} }
[Test] [Test]
@ -454,6 +459,7 @@ namespace Ombi.Core.Tests.Engine
Id = "id1" Id = "id1"
}; };
var today = DateTime.Now; var today = DateTime.Now;
var firstDayOfMonth = new DateTime(today.Year, today.Month, 1);
var log = new List<RequestLog> var log = new List<RequestLog>
{ {
new RequestLog new RequestLog
@ -472,7 +478,7 @@ namespace Ombi.Core.Tests.Engine
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true) .With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2) .And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(1) .And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(1)
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(today.AddMonths(1)) .And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(firstDayOfMonth.AddMonths(1).Date)
); );
} }
@ -487,6 +493,7 @@ namespace Ombi.Core.Tests.Engine
Id = "id1" Id = "id1"
}; };
var today = DateTime.Now; var today = DateTime.Now;
var firstDayOfMonth = new DateTime(today.Year, today.Month, 1);
var log = new List<RequestLog> var log = new List<RequestLog>
{ {
new RequestLog new RequestLog
@ -511,7 +518,7 @@ namespace Ombi.Core.Tests.Engine
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true) .With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2) .And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(0) .And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(0)
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(today.AddMonths(1).AddDays(-1)) .And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(firstDayOfMonth.AddMonths(1).Date)
); );
} }
} }

@ -813,23 +813,26 @@ namespace Ombi.Core.Engine
.OrderBy(x => x.RequestDate) .OrderBy(x => x.RequestDate)
.Select(x => x.RequestDate) .Select(x => x.RequestDate)
.FirstOrDefaultAsync(); .FirstOrDefaultAsync();
nextRequest = oldestRequestedAt.AddDays(1); nextRequest = oldestRequestedAt.AddDays(1).Date;
break; break;
case RequestLimitType.Week: case RequestLimitType.Week:
count = limit - await log.CountAsync(x => x.RequestDate >= DateTime.UtcNow.Date.AddDays(-7)); var fdow = DateTime.UtcNow.FirstDateInWeek();
oldestRequestedAt = await log.Where(x => x.RequestDate >= DateTime.UtcNow.Date.AddDays(-7)) count = limit - await log.CountAsync(x => x.RequestDate >= fdow);
oldestRequestedAt = await log.Where(x => x.RequestDate >= fdow)
.OrderBy(x => x.RequestDate) .OrderBy(x => x.RequestDate)
.Select(x => x.RequestDate) .Select(x => x.RequestDate)
.FirstOrDefaultAsync(); .FirstOrDefaultAsync();
nextRequest = oldestRequestedAt.AddDays(7); nextRequest = fdow.AddDays(7).Date;
break; break;
case RequestLimitType.Month: case RequestLimitType.Month:
count = limit - await log.CountAsync(x => x.RequestDate >= DateTime.UtcNow.Date.AddMonths(-1)); var now = DateTime.UtcNow;
oldestRequestedAt = await log.Where(x => x.RequestDate >= DateTime.UtcNow.Date.AddMonths(-1)) var firstDayOfMonth = new DateTime(now.Year, now.Month, 1);
count = limit - await log.CountAsync(x => x.RequestDate >= firstDayOfMonth);
oldestRequestedAt = await log.Where(x => x.RequestDate >= firstDayOfMonth)
.OrderBy(x => x.RequestDate) .OrderBy(x => x.RequestDate)
.Select(x => x.RequestDate) .Select(x => x.RequestDate)
.FirstOrDefaultAsync(); .FirstOrDefaultAsync();
nextRequest = oldestRequestedAt.AddMonths(1); nextRequest = firstDayOfMonth.AddMonths(1).Date;
break; break;
default: default:
break; break;

@ -1071,8 +1071,6 @@ namespace Ombi.Core.Engine
Remaining = count < 0 ? 0 : count, Remaining = count < 0 ? 0 : count,
NextRequest = DateTime.SpecifyKind(nextRequest, DateTimeKind.Utc), NextRequest = DateTime.SpecifyKind(nextRequest, DateTimeKind.Utc),
}; };
return null;
} }
public async Task<RequestEngineResult> UpdateAdvancedOptions(MediaAdvancedOptions options) public async Task<RequestEngineResult> UpdateAdvancedOptions(MediaAdvancedOptions options)

@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Threading;
using NUnit.Framework;
using NUnit.Framework.Internal;
namespace Ombi.Helpers.Tests
{
[TestFixture]
public class DateTimeExtensionsTests
{
[TestCaseSource(nameof(DayOfWeekData))]
public DateTime FirstDateInWeekTests(DateTime input, string culture)
{
Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(culture);
return input.FirstDateInWeek();
}
public static IEnumerable<TestCaseData> DayOfWeekData
{
get
{
yield return new TestCaseData(new DateTime(2021, 09, 20), "en-GB").Returns(new DateTime(2021, 09, 20)).SetName("en-GB Monday, FDOW is Monday");
yield return new TestCaseData(new DateTime(2021, 09, 21), "en-GB").Returns(new DateTime(2021, 09, 20)).SetName("en-GB Tuesday, FDOW is Monday");
yield return new TestCaseData(new DateTime(2021, 09, 22), "en-GB").Returns(new DateTime(2021, 09, 20)).SetName("en-GB Wednesday, FDOW is Monday");
yield return new TestCaseData(new DateTime(2021, 09, 23), "en-GB").Returns(new DateTime(2021, 09, 20)).SetName("en-GB Thursday, FDOW is Monday");
yield return new TestCaseData(new DateTime(2021, 09, 24), "en-GB").Returns(new DateTime(2021, 09, 20)).SetName("en-GB Friday, FDOW is Monday");
yield return new TestCaseData(new DateTime(2021, 09, 25), "en-GB").Returns(new DateTime(2021, 09, 20)).SetName("en-GB Sat, FDOW is Monday");
yield return new TestCaseData(new DateTime(2021, 09, 26), "en-GB").Returns(new DateTime(2021, 09, 20)).SetName("en-GB Sun, FDOW is Monday");
yield return new TestCaseData(new DateTime(2021, 09, 20), "en-US").Returns(new DateTime(2021, 09, 19)).SetName("en-US Monday, FDOW is Sunday");
yield return new TestCaseData(new DateTime(2021, 09, 21), "en-US").Returns(new DateTime(2021, 09, 19)).SetName("en-US Tuesday, FDOW is Sunday");
yield return new TestCaseData(new DateTime(2021, 09, 22), "en-US").Returns(new DateTime(2021, 09, 19)).SetName("en-US Wednesday, FDOW is Sunday");
yield return new TestCaseData(new DateTime(2021, 09, 23), "en-US").Returns(new DateTime(2021, 09, 19)).SetName("en-US Thursday, FDOW is Sunday");
yield return new TestCaseData(new DateTime(2021, 09, 24), "en-US").Returns(new DateTime(2021, 09, 19)).SetName("en-US Friday, FDOW is Sunday");
yield return new TestCaseData(new DateTime(2021, 09, 25), "en-US").Returns(new DateTime(2021, 09, 19)).SetName("en-US Sat, FDOW is Sunday");
yield return new TestCaseData(new DateTime(2021, 09, 26), "en-US").Returns(new DateTime(2021, 09, 26)).SetName("en-US Sun, FDOW is Sunday");
}
}
}
}

@ -0,0 +1,18 @@
using System;
using System.Threading;
namespace Ombi.Helpers
{
public static class DateTimeExtensions
{
public static DateTime FirstDateInWeek(this DateTime dt)
{
while (dt.DayOfWeek != Thread.CurrentThread.CurrentCulture.DateTimeFormat.FirstDayOfWeek)
{
dt = dt.AddDays(-1);
}
return dt;
}
}
}

@ -32,7 +32,7 @@ namespace Ombi.Helpers
} }
// Not in the cache, so add this Key into our MediaServiceCache // Not in the cache, so add this Key into our MediaServiceCache
await UpdateLocalCache(cacheKey); UpdateLocalCache(cacheKey);
return await _memoryCache.GetOrCreateAsync<T>(cacheKey, entry => return await _memoryCache.GetOrCreateAsync<T>(cacheKey, entry =>
{ {
@ -41,7 +41,7 @@ namespace Ombi.Helpers
}); });
} }
private async Task UpdateLocalCache(string cacheKey) private void UpdateLocalCache(string cacheKey)
{ {
var mediaServiceCache = _memoryCache.Get<List<string>>(CacheKey); var mediaServiceCache = _memoryCache.Get<List<string>>(CacheKey);
if (mediaServiceCache == null) if (mediaServiceCache == null)

@ -12,6 +12,7 @@
], ],
"discord.enabled": true, "discord.enabled": true,
"conventionalCommits.scopes": [ "conventionalCommits.scopes": [
"discover" "discover",
"request-limits"
] ]
} }

Loading…
Cancel
Save