2021-10-15 10:27:38 +00:00
|
|
|
using System;
|
|
|
|
using System.Diagnostics;
|
|
|
|
using System.Threading;
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
|
|
using NodaTime;
|
|
|
|
using NodaTime.Extensions;
|
|
|
|
|
2021-11-27 02:10:56 +00:00
|
|
|
using PluralKit.Core;
|
|
|
|
|
2021-10-15 10:27:38 +00:00
|
|
|
using Serilog;
|
|
|
|
|
2021-11-27 02:10:56 +00:00
|
|
|
namespace PluralKit.ScheduledTasks;
|
2021-10-15 10:27:38 +00:00
|
|
|
|
2021-11-27 02:10:56 +00:00
|
|
|
public class TaskHandler
|
2021-10-15 10:27:38 +00:00
|
|
|
{
|
2021-11-27 02:10:56 +00:00
|
|
|
private static readonly Duration CommandMessageRetention = Duration.FromHours(24);
|
|
|
|
private readonly IDatabase _db;
|
2021-10-15 10:27:38 +00:00
|
|
|
|
2021-11-27 02:10:56 +00:00
|
|
|
private readonly ILogger _logger;
|
|
|
|
private readonly ModelRepository _repo;
|
|
|
|
private Timer _periodicTask;
|
2021-10-15 10:27:38 +00:00
|
|
|
|
2021-11-27 02:10:56 +00:00
|
|
|
public TaskHandler(ILogger logger, IDatabase db, ModelRepository repo)
|
|
|
|
{
|
|
|
|
_logger = logger;
|
|
|
|
_db = db;
|
|
|
|
_repo = repo;
|
|
|
|
}
|
2021-10-15 10:27:38 +00:00
|
|
|
|
2021-11-27 02:10:56 +00:00
|
|
|
public void Run()
|
|
|
|
{
|
|
|
|
_logger.Information("Starting scheduled task runner...");
|
|
|
|
var timeNow = SystemClock.Instance.GetCurrentInstant();
|
|
|
|
var timeTillNextWholeMinute =
|
|
|
|
TimeSpan.FromMilliseconds(60000 - timeNow.ToUnixTimeMilliseconds() % 60000 + 250);
|
|
|
|
_periodicTask = new Timer(_ =>
|
2021-10-15 10:27:38 +00:00
|
|
|
{
|
2021-11-27 02:10:56 +00:00
|
|
|
var __ = UpdatePeriodic();
|
|
|
|
}, null, timeTillNextWholeMinute, TimeSpan.FromMinutes(1));
|
|
|
|
}
|
2021-10-15 10:27:38 +00:00
|
|
|
|
2021-11-27 02:10:56 +00:00
|
|
|
private async Task UpdatePeriodic()
|
|
|
|
{
|
|
|
|
_logger.Information("Running per-minute scheduled tasks.");
|
|
|
|
var stopwatch = new Stopwatch();
|
|
|
|
stopwatch.Start();
|
2021-10-15 10:27:38 +00:00
|
|
|
|
2021-11-27 02:10:56 +00:00
|
|
|
_logger.Information("Updating database stats...");
|
|
|
|
await _repo.UpdateStats();
|
2021-10-15 10:27:38 +00:00
|
|
|
|
2021-11-27 02:10:56 +00:00
|
|
|
// Clean up message cache in postgres
|
|
|
|
await CleanupOldMessages();
|
2021-10-15 10:27:38 +00:00
|
|
|
|
2021-11-27 02:10:56 +00:00
|
|
|
stopwatch.Stop();
|
|
|
|
_logger.Information("Ran scheduled tasks in {Time}", stopwatch.ElapsedDuration());
|
|
|
|
}
|
2021-10-15 10:27:38 +00:00
|
|
|
|
2021-11-27 02:10:56 +00:00
|
|
|
private async Task CleanupOldMessages()
|
|
|
|
{
|
|
|
|
var deleteThresholdInstant = SystemClock.Instance.GetCurrentInstant() - CommandMessageRetention;
|
|
|
|
var deleteThresholdSnowflake = InstantToSnowflake(deleteThresholdInstant);
|
2021-10-15 10:27:38 +00:00
|
|
|
|
2021-11-27 02:10:56 +00:00
|
|
|
var deletedRows = await _repo.DeleteCommandMessagesBefore(deleteThresholdSnowflake);
|
2021-10-15 10:27:38 +00:00
|
|
|
|
2021-11-27 02:10:56 +00:00
|
|
|
_logger.Information(
|
|
|
|
"Pruned {DeletedRows} command messages older than retention {Retention} (older than {DeleteThresholdInstant} / {DeleteThresholdSnowflake})",
|
|
|
|
deletedRows, CommandMessageRetention, deleteThresholdInstant, deleteThresholdSnowflake);
|
2021-10-15 10:27:38 +00:00
|
|
|
}
|
2021-11-27 02:10:56 +00:00
|
|
|
|
|
|
|
// we don't have access to PluralKit.Bot here, so this needs to be vendored
|
|
|
|
public static ulong InstantToSnowflake(Instant time) =>
|
|
|
|
(ulong)(time - Instant.FromUtc(2015, 1, 1, 0, 0, 0)).TotalMilliseconds << 22;
|
2021-10-15 10:27:38 +00:00
|
|
|
}
|