Upgrade EFCore, switch to bulk operations

This commit is contained in:
Noi 2022-11-21 21:20:48 -08:00
parent fbd7305818
commit 2c920e9794
2 changed files with 27 additions and 28 deletions

View file

@ -1,4 +1,5 @@
using BirthdayBot.Data; using BirthdayBot.Data;
using Microsoft.EntityFrameworkCore;
using System.Text; using System.Text;
namespace BirthdayBot.BackgroundServices; namespace BirthdayBot.BackgroundServices;
@ -31,34 +32,32 @@ class DataRetention : BackgroundService {
private async Task RemoveStaleEntriesAsync() { private async Task RemoveStaleEntriesAsync() {
using var db = new BotDatabaseContext(); using var db = new BotDatabaseContext();
var now = DateTimeOffset.UtcNow; var now = DateTimeOffset.UtcNow;
int updatedGuilds = 0, updatedUsers = 0;
// Update guilds
var localGuilds = ShardInstance.DiscordClient.Guilds.Select(g => (long)g.Id).ToList();
var updatedGuilds = await db.GuildConfigurations
.Where(g => localGuilds.Contains(g.GuildId))
.ExecuteUpdateAsync(upd => upd.SetProperty(p => p.LastSeen, now));
// Update guild users
var updatedUsers = 0;
foreach (var guild in ShardInstance.DiscordClient.Guilds) { foreach (var guild in ShardInstance.DiscordClient.Guilds) {
// Update guild, fetch users from database var localUsers = guild.Users.Select(u => (long)u.Id).ToList();
var dbGuild = db.GuildConfigurations.Where(s => s.GuildId == (long)guild.Id).FirstOrDefault(); updatedUsers += await db.UserEntries
if (dbGuild == null) continue; .Where(gu => gu.GuildId == (long)guild.Id)
dbGuild.LastSeen = now; .Where(gu => localUsers.Contains(gu.UserId))
updatedGuilds++; .ExecuteUpdateAsync(upd => upd.SetProperty(p => p.LastSeen, now));
// 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++;
}
} }
// And let go of old data // And let go of old data
var staleGuilds = db.GuildConfigurations.Where(s => now - TimeSpan.FromDays(StaleGuildThreshold) > s.LastSeen); var staleGuildCount = await db.GuildConfigurations
var staleUsers = db.UserEntries.Where(e => now - TimeSpan.FromDays(StaleUserThreashold) > e.LastSeen); .Where(g => now - TimeSpan.FromDays(StaleGuildThreshold) > g.LastSeen)
int staleGuildCount = staleGuilds.Count(), staleUserCount = staleUsers.Count(); .ExecuteDeleteAsync();
db.GuildConfigurations.RemoveRange(staleGuilds); var staleUserCount = await db.UserEntries
db.UserEntries.RemoveRange(staleUsers); .Where(gu => now - TimeSpan.FromDays(StaleUserThreashold) > gu.LastSeen)
.ExecuteDeleteAsync();
await db.SaveChangesAsync(CancellationToken.None);
// Build report
var resultText = new StringBuilder(); var resultText = new StringBuilder();
resultText.Append($"Updated {updatedGuilds} guilds, {updatedUsers} users."); resultText.Append($"Updated {updatedGuilds} guilds, {updatedUsers} users.");
if (staleGuildCount != 0 || staleUserCount != 0) { if (staleGuildCount != 0 || staleUserCount != 0) {

View file

@ -5,7 +5,7 @@
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<Version>3.4.5</Version> <Version>3.4.6</Version>
<Authors>NoiTheCat</Authors> <Authors>NoiTheCat</Authors>
</PropertyGroup> </PropertyGroup>
@ -23,16 +23,16 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="CommandLineParser" Version="2.9.1" /> <PackageReference Include="CommandLineParser" Version="2.9.1" />
<PackageReference Include="Discord.Net" Version="3.8.1" /> <PackageReference Include="Discord.Net" Version="3.8.1" />
<PackageReference Include="EFCore.NamingConventions" Version="6.0.0" /> <PackageReference Include="EFCore.NamingConventions" Version="7.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.9"> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.0">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="NodaTime" Version="3.1.3" /> <PackageReference Include="NodaTime" Version="3.1.3" />
<PackageReference Include="Npgsql" Version="6.0.6" /> <PackageReference Include="Npgsql" Version="7.0.0" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.6" /> <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.0" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.Design" Version="1.1.0" /> <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.Design" Version="1.1.0" />
</ItemGroup> </ItemGroup>