Add periodic garbage collection of webhook rate limit cache

This commit is contained in:
Ske 2020-04-16 18:18:08 +02:00
parent 93e53be7db
commit 93bf7c6543
2 changed files with 28 additions and 2 deletions

View File

@ -102,13 +102,16 @@ namespace PluralKit.Bot
private IMetrics _metrics; private IMetrics _metrics;
private PeriodicStatCollector _collector; private PeriodicStatCollector _collector;
private ILogger _logger; private ILogger _logger;
private WebhookRateLimitService _webhookRateLimit;
private int _periodicUpdateCount;
public Bot(ILifetimeScope services, IDiscordClient client, IMetrics metrics, PeriodicStatCollector collector, ILogger logger) public Bot(ILifetimeScope services, IDiscordClient client, IMetrics metrics, PeriodicStatCollector collector, ILogger logger, WebhookRateLimitService webhookRateLimit)
{ {
_services = services; _services = services;
_client = client as DiscordShardedClient; _client = client as DiscordShardedClient;
_metrics = metrics; _metrics = metrics;
_collector = collector; _collector = collector;
_webhookRateLimit = webhookRateLimit;
_logger = logger.ForContext<Bot>(); _logger = logger.ForContext<Bot>();
} }
@ -162,6 +165,12 @@ namespace PluralKit.Bot
// Change bot status // Change bot status
await _client.SetGameAsync($"pk;help | in {_client.Guilds.Count} servers"); await _client.SetGameAsync($"pk;help | in {_client.Guilds.Count} servers");
// Run webhook rate limit GC every 10 minutes
if (_periodicUpdateCount++ % 10 == 0)
{
var _ = Task.Run(() => _webhookRateLimit.GarbageCollect());
}
await _collector.CollectStats(); await _collector.CollectStats();
_logger.Information("Submitted metrics to backend"); _logger.Information("Submitted metrics to backend");

View File

@ -87,6 +87,23 @@ namespace PluralKit.Bot
} }
} }
public void GarbageCollect()
{
_logger.Information("Garbage-collecting webhook rate limit buckets...");
var collected = 0;
foreach (var channel in _info.Keys)
{
if (!_info.TryGetValue(channel, out var info)) continue;
// Remove all keys that expired more than an hour ago (and of course, haven't been reset)
if (info.resetTime < SystemClock.Instance.GetCurrentInstant() - Duration.FromHours(1))
if (_info.TryRemove(channel, out _)) collected++;
}
_logger.Information("Garbage-collected {ChannelCount} channels from the webhook rate limit buckets.", collected);
}
private string GetHeader(HttpResponseMessage response, string key) private string GetHeader(HttpResponseMessage response, string key)
{ {
var firstPair = response.Headers.FirstOrDefault(pair => pair.Key.Equals(key, StringComparison.InvariantCultureIgnoreCase)); var firstPair = response.Headers.FirstOrDefault(pair => pair.Key.Equals(key, StringComparison.InvariantCultureIgnoreCase));