mirror of
https://github.com/Readarr/Readarr.git
synced 2026-04-26 22:46:37 -04:00
Generalized RateLimit logic to all indexers based on indexer id
This commit is contained in:
@@ -107,7 +107,7 @@ namespace NzbDrone.Common.Http
|
||||
|
||||
if (request.RateLimit != TimeSpan.Zero)
|
||||
{
|
||||
_rateLimitService.WaitAndPulse(HttpRateLimitKeyFactory.GetRateLimitKey(request), request.RateLimit);
|
||||
_rateLimitService.WaitAndPulse(request.Url.Host, request.RateLimitKey, request.RateLimit);
|
||||
}
|
||||
|
||||
_logger.Trace(request);
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NzbDrone.Common.Http
|
||||
{
|
||||
public static class HttpRateLimitKeyFactory
|
||||
{
|
||||
// Use a different key for jackett instances to prevent hitting the ratelimit for multiple separate indexers.
|
||||
private static readonly Regex _regex = new Regex(@"^https?://(.+/jackett/api/v2.0/indexers/\w+)/", RegexOptions.Compiled);
|
||||
|
||||
public static string GetRateLimitKey(HttpRequest request)
|
||||
{
|
||||
var match = _regex.Match(request.Url.ToString());
|
||||
|
||||
if (match.Success)
|
||||
{
|
||||
return match.Groups[1].Value;
|
||||
}
|
||||
|
||||
return request.Url.Host;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,7 @@ namespace NzbDrone.Common.Http
|
||||
public bool StoreResponseCookie { get; set; }
|
||||
public TimeSpan RequestTimeout { get; set; }
|
||||
public TimeSpan RateLimit { get; set; }
|
||||
public string RateLimitKey { get; set; }
|
||||
public Stream ResponseStream { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Cache;
|
||||
using NzbDrone.Common.Extensions;
|
||||
|
||||
namespace NzbDrone.Common.TPL
|
||||
{
|
||||
public interface IRateLimitService
|
||||
{
|
||||
void WaitAndPulse(string key, TimeSpan interval);
|
||||
void WaitAndPulse(string key, string subKey, TimeSpan interval);
|
||||
}
|
||||
|
||||
public class RateLimitService : IRateLimitService
|
||||
@@ -23,9 +25,37 @@ namespace NzbDrone.Common.TPL
|
||||
|
||||
public void WaitAndPulse(string key, TimeSpan interval)
|
||||
{
|
||||
var waitUntil = _rateLimitStore.AddOrUpdate(key,
|
||||
(s) => DateTime.UtcNow + interval,
|
||||
(s, i) => new DateTime(Math.Max(DateTime.UtcNow.Ticks, i.Ticks), DateTimeKind.Utc) + interval);
|
||||
WaitAndPulse(key, null, interval);
|
||||
}
|
||||
|
||||
public void WaitAndPulse(string key, string subKey, TimeSpan interval)
|
||||
{
|
||||
var waitUntil = DateTime.UtcNow.Add(interval);
|
||||
|
||||
if (subKey.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
// Expand the base key timer, but don't extend it beyond now+interval.
|
||||
var baseUntil = _rateLimitStore.AddOrUpdate(key,
|
||||
(s) => waitUntil,
|
||||
(s, i) => new DateTime(Math.Max(waitUntil.Ticks, i.Ticks), DateTimeKind.Utc));
|
||||
|
||||
if (baseUntil > waitUntil)
|
||||
{
|
||||
waitUntil = baseUntil;
|
||||
}
|
||||
|
||||
// Wait for the full key
|
||||
var combinedKey = key + "-" + subKey;
|
||||
waitUntil = _rateLimitStore.AddOrUpdate(combinedKey,
|
||||
(s) => waitUntil,
|
||||
(s, i) => new DateTime(Math.Max(waitUntil.Ticks, i.Add(interval).Ticks), DateTimeKind.Utc));
|
||||
}
|
||||
else
|
||||
{
|
||||
waitUntil = _rateLimitStore.AddOrUpdate(key,
|
||||
(s) => waitUntil,
|
||||
(s, i) => new DateTime(Math.Max(waitUntil.Ticks, i.Add(interval).Ticks), DateTimeKind.Utc));
|
||||
}
|
||||
|
||||
waitUntil -= interval;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user