2020-10-10 06:48:43 +00:00
|
|
|
|
using BirthdayBot.Data;
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
2021-10-15 01:55:04 +00:00
|
|
|
|
namespace BirthdayBot.BackgroundServices;
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Automatically removes database information for guilds that have not been accessed in a long time.
|
|
|
|
|
/// </summary>
|
|
|
|
|
class DataRetention : BackgroundService {
|
2021-11-22 19:49:55 +00:00
|
|
|
|
const int ProcessInterval = 5400 / ShardBackgroundWorker.Interval; // Process about once per hour and a half
|
2022-08-10 00:04:24 +00:00
|
|
|
|
|
2021-11-22 19:49:55 +00:00
|
|
|
|
// Amount of days without updates before data is considered stale and up for deletion.
|
|
|
|
|
const int StaleGuildThreshold = 180;
|
|
|
|
|
const int StaleUserThreashold = 360;
|
2020-10-10 06:48:43 +00:00
|
|
|
|
|
2021-10-15 01:55:04 +00:00
|
|
|
|
public DataRetention(ShardInstance instance) : base(instance) { }
|
2020-10-10 06:48:43 +00:00
|
|
|
|
|
2021-10-15 01:55:04 +00:00
|
|
|
|
public override async Task OnTick(int tickCount, CancellationToken token) {
|
|
|
|
|
// On each tick, run only a set group of guilds, each group still processed every ProcessInterval ticks.
|
2021-11-22 19:49:55 +00:00
|
|
|
|
if ((tickCount + ShardInstance.ShardId) % ProcessInterval != 0) return;
|
2021-10-15 01:55:04 +00:00
|
|
|
|
|
2022-08-10 00:04:24 +00:00
|
|
|
|
try {
|
|
|
|
|
await DbConcurrentOperationsLock.WaitAsync(token);
|
|
|
|
|
await RemoveStaleEntriesAsync();
|
|
|
|
|
} finally {
|
|
|
|
|
try {
|
|
|
|
|
DbConcurrentOperationsLock.Release();
|
|
|
|
|
} catch (ObjectDisposedException) { }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task RemoveStaleEntriesAsync() {
|
2022-03-21 19:11:30 +00:00
|
|
|
|
using var db = new BotDatabaseContext();
|
|
|
|
|
var now = DateTimeOffset.UtcNow;
|
|
|
|
|
int updatedGuilds = 0, updatedUsers = 0;
|
2020-10-10 06:48:43 +00:00
|
|
|
|
|
2022-03-21 19:11:30 +00:00
|
|
|
|
foreach (var guild in ShardInstance.DiscordClient.Guilds) {
|
|
|
|
|
// Update guild, fetch users from database
|
|
|
|
|
var dbGuild = db.GuildConfigurations.Where(s => s.GuildId == (long)guild.Id).FirstOrDefault();
|
|
|
|
|
if (dbGuild == null) continue;
|
|
|
|
|
dbGuild.LastSeen = now;
|
|
|
|
|
updatedGuilds++;
|
2020-10-10 06:48:43 +00:00
|
|
|
|
|
2022-03-21 19:11:30 +00:00
|
|
|
|
// Update users
|
|
|
|
|
var localIds = guild.Users.Select(u => (long)u.Id);
|
|
|
|
|
var dbSavedIds = db.UserEntries.Where(e => e.GuildId == (long)guild.Id).Select(e => e.UserId);
|
|
|
|
|
var usersToUpdate = localIds.Intersect(dbSavedIds).ToHashSet();
|
|
|
|
|
foreach (var user in db.UserEntries.Where(e => e.GuildId == (long)guild.Id && usersToUpdate.Contains(e.UserId))) {
|
|
|
|
|
user.LastSeen = now;
|
|
|
|
|
updatedUsers++;
|
2021-10-15 01:55:04 +00:00
|
|
|
|
}
|
2022-03-21 19:11:30 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// And let go of old data
|
|
|
|
|
var staleGuilds = db.GuildConfigurations.Where(s => now - TimeSpan.FromDays(StaleGuildThreshold) > s.LastSeen);
|
|
|
|
|
var staleUsers = db.UserEntries.Where(e => now - TimeSpan.FromDays(StaleUserThreashold) > e.LastSeen);
|
|
|
|
|
int staleGuildCount = staleGuilds.Count(), staleUserCount = staleUsers.Count();
|
|
|
|
|
db.GuildConfigurations.RemoveRange(staleGuilds);
|
|
|
|
|
db.UserEntries.RemoveRange(staleUsers);
|
2020-10-10 06:48:43 +00:00
|
|
|
|
|
2022-03-21 19:11:30 +00:00
|
|
|
|
await db.SaveChangesAsync(CancellationToken.None);
|
|
|
|
|
|
|
|
|
|
var resultText = new StringBuilder();
|
|
|
|
|
resultText.Append($"Updated {updatedGuilds} guilds, {updatedUsers} users.");
|
|
|
|
|
if (staleGuildCount != 0 || staleUserCount != 0) {
|
|
|
|
|
resultText.Append(" Discarded ");
|
|
|
|
|
if (staleGuildCount != 0) {
|
|
|
|
|
resultText.Append($"{staleGuildCount} guilds");
|
|
|
|
|
if (staleUserCount != 0) resultText.Append(", ");
|
2021-10-15 01:55:04 +00:00
|
|
|
|
}
|
2022-03-21 19:11:30 +00:00
|
|
|
|
if (staleUserCount != 0) {
|
|
|
|
|
resultText.Append($"{staleUserCount} users");
|
2020-10-10 06:48:43 +00:00
|
|
|
|
}
|
2022-03-21 19:11:30 +00:00
|
|
|
|
resultText.Append('.');
|
2020-10-10 06:48:43 +00:00
|
|
|
|
}
|
2022-03-21 19:11:30 +00:00
|
|
|
|
Log(resultText.ToString());
|
2020-10-10 06:48:43 +00:00
|
|
|
|
}
|
|
|
|
|
}
|