[backend/core] Cleanup instance counters code

This commit is contained in:
Laura Hausmann 2024-02-29 19:40:22 +01:00
parent 6b0328f7aa
commit c87fa00864
No known key found for this signature in database
GPG key ID: D044E84C5BE01605
10 changed files with 6325 additions and 42 deletions

View file

@ -484,8 +484,8 @@ public class DatabaseContext(DbContextOptions<DatabaseContext> options)
modelBuilder.Entity<Instance>(entity => modelBuilder.Entity<Instance>(entity =>
{ {
entity.Property(e => e.CaughtAt).HasComment("The caught date of the Instance."); entity.Property(e => e.CaughtAt).HasComment("The caught date of the Instance.");
entity.Property(e => e.FollowersCount).HasDefaultValue(0); entity.Property(e => e.OutgoingFollows).HasDefaultValue(0);
entity.Property(e => e.FollowingCount).HasDefaultValue(0); entity.Property(e => e.IncomingFollows).HasDefaultValue(0);
entity.Property(e => e.Host).HasComment("The host of the Instance."); entity.Property(e => e.Host).HasComment("The host of the Instance.");
entity.Property(e => e.IsNotResponding).HasDefaultValue(false); entity.Property(e => e.IsNotResponding).HasDefaultValue(false);
entity.Property(e => e.IsSuspended).HasDefaultValue(false); entity.Property(e => e.IsSuspended).HasDefaultValue(false);

View file

@ -0,0 +1,38 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Iceshrimp.Backend.Core.Database.Migrations
{
/// <inheritdoc />
public partial class RenameInstanceFollowsColumns : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(
name: "followingCount",
table: "instance",
newName: "incomingFollows");
migrationBuilder.RenameColumn(
name: "followersCount",
table: "instance",
newName: "outgoingFollows");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(
name: "outgoingFollows",
table: "instance",
newName: "followersCount");
migrationBuilder.RenameColumn(
name: "incomingFollows",
table: "instance",
newName: "followingCount");
}
}
}

View file

@ -1654,13 +1654,13 @@ namespace Iceshrimp.Backend.Core.Database.Migrations
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasColumnType("integer") .HasColumnType("integer")
.HasDefaultValue(0) .HasDefaultValue(0)
.HasColumnName("followersCount"); .HasColumnName("outgoingFollows");
b.Property<int>("FollowingCount") b.Property<int>("FollowingCount")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasColumnType("integer") .HasColumnType("integer")
.HasDefaultValue(0) .HasDefaultValue(0)
.HasColumnName("followingCount"); .HasColumnName("incomingFollows");
b.Property<string>("Host") b.Property<string>("Host")
.IsRequired() .IsRequired()

View file

@ -41,9 +41,9 @@ public class Instance
[Column("notesCount")] [Column("notesCount")]
public int NotesCount { get; set; } public int NotesCount { get; set; }
[Column("followingCount")] public int FollowingCount { get; set; } [Column("incomingFollows")] public int IncomingFollows { get; set; }
[Column("followersCount")] public int FollowersCount { get; set; } [Column("outgoingFollows")] public int OutgoingFollows { get; set; }
[Column("latestRequestSentAt")] public DateTime? LatestRequestSentAt { get; set; } [Column("latestRequestSentAt")] public DateTime? LatestRequestSentAt { get; set; }

View file

@ -335,14 +335,13 @@ public class ActivityHandlerService(
follower.FollowingCount++; follower.FollowingCount++;
followee.FollowersCount++; followee.FollowersCount++;
_ = followupTaskSvc.ExecuteTask("UpdateInstanceFollowingCounter", async provider => _ = followupTaskSvc.ExecuteTask("IncrementInstanceIncomingFollowsCounter", async provider =>
{ {
var bgDb = provider.GetRequiredService<DatabaseContext>(); var bgDb = provider.GetRequiredService<DatabaseContext>();
var bgInstanceSvc = provider.GetRequiredService<InstanceService>(); var bgInstanceSvc = provider.GetRequiredService<InstanceService>();
var dbInstance = await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(follower.Host, var dbInstance = await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(follower);
new Uri(follower.Uri!).Host);
await bgDb.Instances.Where(p => p.Id == dbInstance.Id) await bgDb.Instances.Where(p => p.Id == dbInstance.Id)
.ExecuteUpdateAsync(p => p.SetProperty(i => i.FollowingCount, i => i.FollowingCount + 1)); .ExecuteUpdateAsync(p => p.SetProperty(i => i.IncomingFollows, i => i.IncomingFollows + 1));
}); });
await db.AddAsync(following); await db.AddAsync(following);
@ -367,7 +366,15 @@ public class ActivityHandlerService(
db.RemoveRange(followings); db.RemoveRange(followings);
await db.SaveChangesAsync(); await db.SaveChangesAsync();
if (followee.Host != null) return; _ = followupTaskSvc.ExecuteTask("DecrementInstanceIncomingFollowsCounter", async provider =>
{
var bgDb = provider.GetRequiredService<DatabaseContext>();
var bgInstanceSvc = provider.GetRequiredService<InstanceService>();
var dbInstance = await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(follower);
await bgDb.Instances.Where(p => p.Id == dbInstance.Id)
.ExecuteUpdateAsync(p => p.SetProperty(i => i.IncomingFollows, i => i.IncomingFollows + 1));
});
await db.Notifications await db.Notifications
.Where(p => p.Type == Notification.NotificationType.Follow && .Where(p => p.Type == Notification.NotificationType.Follow &&
p.Notifiee == followee && p.Notifiee == followee &&
@ -413,14 +420,13 @@ public class ActivityHandlerService(
actor.FollowersCount++; actor.FollowersCount++;
request.Follower.FollowingCount++; request.Follower.FollowingCount++;
_ = followupTaskSvc.ExecuteTask("UpdateInstanceFollowersCounter", async provider => _ = followupTaskSvc.ExecuteTask("IncrementInstanceOutgoingFollowsCounter", async provider =>
{ {
var bgDb = provider.GetRequiredService<DatabaseContext>(); var bgDb = provider.GetRequiredService<DatabaseContext>();
var bgInstanceSvc = provider.GetRequiredService<InstanceService>(); var bgInstanceSvc = provider.GetRequiredService<InstanceService>();
var dbInstance = await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(request.Followee.Host!, var dbInstance = await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(request.Followee);
new Uri(request.Followee.Uri!).Host);
await bgDb.Instances.Where(p => p.Id == dbInstance.Id) await bgDb.Instances.Where(p => p.Id == dbInstance.Id)
.ExecuteUpdateAsync(p => p.SetProperty(i => i.FollowersCount, i => i.FollowersCount + 1)); .ExecuteUpdateAsync(p => p.SetProperty(i => i.OutgoingFollows, i => i.OutgoingFollows + 1));
}); });
db.Remove(request); db.Remove(request);

View file

@ -30,10 +30,10 @@ public class DatabaseMaintenanceService(DatabaseContext db)
i => db.Notes.Count(n => n.UserHost == i.Host)) i => db.Notes.Count(n => n.UserHost == i.Host))
.SetProperty(i => i.UsersCount, .SetProperty(i => i.UsersCount,
i => db.Users.Count(u => u.Host == i.Host)) i => db.Users.Count(u => u.Host == i.Host))
.SetProperty(i => i.FollowersCount, .SetProperty(i => i.OutgoingFollows,
i => db.Followings i => db.Followings
.Count(n => n.FolloweeHost == i.Host)) .Count(n => n.FolloweeHost == i.Host))
.SetProperty(i => i.FollowingCount, .SetProperty(i => i.IncomingFollows,
i => db.Followings i => db.Followings
.Count(n => n.FollowerHost == i.Host))); .Count(n => n.FollowerHost == i.Host)));
} }

View file

@ -58,6 +58,12 @@ public class InstanceService(DatabaseContext db, HttpClient httpClient)
return instance; return instance;
} }
public async Task<Instance> GetUpdatedInstanceMetadataAsync(User user)
{
if (user.Host == null || user.Uri == null) throw new Exception("Can't fetch instance metadata for local user");
return await GetUpdatedInstanceMetadataAsync(user.Host, new Uri(user.Uri).Host);
}
private async Task<NodeInfoResponse?> GetNodeInfoAsync(string webDomain) private async Task<NodeInfoResponse?> GetNodeInfoAsync(string webDomain)
{ {
try try

View file

@ -114,18 +114,14 @@ public class NoteService(
if (user.Host != null) if (user.Host != null)
{ {
if (user.Uri != null) _ = followupTaskSvc.ExecuteTask("UpdateInstanceNoteCounter", async provider =>
{ {
_ = followupTaskSvc.ExecuteTask("UpdateInstanceNoteCounter", async provider => var bgDb = provider.GetRequiredService<DatabaseContext>();
{ var bgInstanceSvc = provider.GetRequiredService<InstanceService>();
var bgDb = provider.GetRequiredService<DatabaseContext>(); var dbInstance = await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(user);
var bgInstanceSvc = provider.GetRequiredService<InstanceService>(); await bgDb.Instances.Where(p => p.Id == dbInstance.Id)
var dbInstance = .ExecuteUpdateAsync(p => p.SetProperty(i => i.NotesCount, i => i.NotesCount + 1));
await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(user.Host, new Uri(user.Uri).Host); });
await bgDb.Instances.Where(p => p.Id == dbInstance.Id)
.ExecuteUpdateAsync(p => p.SetProperty(i => i.NotesCount, i => i.NotesCount + 1));
});
}
return note; return note;
} }
@ -256,8 +252,7 @@ public class NoteService(
{ {
var bgDb = provider.GetRequiredService<DatabaseContext>(); var bgDb = provider.GetRequiredService<DatabaseContext>();
var bgInstanceSvc = provider.GetRequiredService<InstanceService>(); var bgInstanceSvc = provider.GetRequiredService<InstanceService>();
var dbInstance = var dbInstance = await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(note.User);
await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(note.UserHost, new Uri(note.User.Uri).Host);
await bgDb.Instances.Where(p => p.Id == dbInstance.Id) await bgDb.Instances.Where(p => p.Id == dbInstance.Id)
.ExecuteUpdateAsync(p => p.SetProperty(i => i.NotesCount, i => i.NotesCount - 1)); .ExecuteUpdateAsync(p => p.SetProperty(i => i.NotesCount, i => i.NotesCount - 1));
}); });
@ -320,8 +315,7 @@ public class NoteService(
var bgDb = provider.GetRequiredService<DatabaseContext>(); var bgDb = provider.GetRequiredService<DatabaseContext>();
var bgInstanceSvc = provider.GetRequiredService<InstanceService>(); var bgInstanceSvc = provider.GetRequiredService<InstanceService>();
// ReSharper disable once EntityFramework.NPlusOne.IncompleteDataUsage (same reason as above) // ReSharper disable once EntityFramework.NPlusOne.IncompleteDataUsage (same reason as above)
var dbInstance = var dbInstance = await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(dbNote.User);
await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(dbNote.UserHost, new Uri(dbNote.User.Uri).Host);
await bgDb.Instances.Where(p => p.Id == dbInstance.Id) await bgDb.Instances.Where(p => p.Id == dbInstance.Id)
.ExecuteUpdateAsync(p => p.SetProperty(i => i.NotesCount, i => i.NotesCount - 1)); .ExecuteUpdateAsync(p => p.SetProperty(i => i.NotesCount, i => i.NotesCount - 1));
}); });

View file

@ -189,7 +189,7 @@ public class UserService(
{ {
var bgDb = provider.GetRequiredService<DatabaseContext>(); var bgDb = provider.GetRequiredService<DatabaseContext>();
var bgInstanceSvc = provider.GetRequiredService<InstanceService>(); var bgInstanceSvc = provider.GetRequiredService<InstanceService>();
var dbInstance = await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(host, new Uri(uri).Host); var dbInstance = await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(user);
await bgDb.Instances.Where(p => p.Id == dbInstance.Id) await bgDb.Instances.Where(p => p.Id == dbInstance.Id)
.ExecuteUpdateAsync(p => p.SetProperty(i => i.UsersCount, i => i.UsersCount + 1)); .ExecuteUpdateAsync(p => p.SetProperty(i => i.UsersCount, i => i.UsersCount + 1));
}); });
@ -447,9 +447,9 @@ public class UserService(
_ = followupTaskSvc.ExecuteTask("UpdateInstanceUserCounter", async provider => _ = followupTaskSvc.ExecuteTask("UpdateInstanceUserCounter", async provider =>
{ {
var bgDb = provider.GetRequiredService<DatabaseContext>(); var bgDb = provider.GetRequiredService<DatabaseContext>();
var bgInstanceSvc = provider.GetRequiredService<InstanceService>(); var bgInstanceSvc = provider.GetRequiredService<InstanceService>();
var dbInstance = await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(user.Host!, new Uri(user.Uri!).Host); var dbInstance = await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(user);
await bgDb.Instances.Where(p => p.Id == dbInstance.Id) await bgDb.Instances.Where(p => p.Id == dbInstance.Id)
.ExecuteUpdateAsync(p => p.SetProperty(i => i.UsersCount, i => i.UsersCount - 1)); .ExecuteUpdateAsync(p => p.SetProperty(i => i.UsersCount, i => i.UsersCount - 1));
}); });
@ -530,14 +530,13 @@ public class UserService(
if (request.Follower is { Host: not null }) if (request.Follower is { Host: not null })
{ {
_ = followupTaskSvc.ExecuteTask("UpdateInstanceFollowingCounter", async provider => _ = followupTaskSvc.ExecuteTask("IncrementInstanceIncomingFollowsCounter", async provider =>
{ {
var bgDb = provider.GetRequiredService<DatabaseContext>(); var bgDb = provider.GetRequiredService<DatabaseContext>();
var bgInstanceSvc = provider.GetRequiredService<InstanceService>(); var bgInstanceSvc = provider.GetRequiredService<InstanceService>();
var dbInstance = await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(request.Follower.Host, var dbInstance = await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(request.Follower);
new Uri(request.Follower.Uri!).Host);
await bgDb.Instances.Where(p => p.Id == dbInstance.Id) await bgDb.Instances.Where(p => p.Id == dbInstance.Id)
.ExecuteUpdateAsync(p => p.SetProperty(i => i.FollowingCount, i => i.FollowingCount + 1)); .ExecuteUpdateAsync(p => p.SetProperty(i => i.IncomingFollows, i => i.IncomingFollows + 1));
}); });
} }
@ -659,14 +658,15 @@ public class UserService(
if (followee.Host != null) if (followee.Host != null)
{ {
_ = followupTaskSvc.ExecuteTask("UpdateInstanceFollowersCounter", async provider => _ = followupTaskSvc.ExecuteTask("DecrementInstanceOutgoingFollowsCounter", async provider =>
{ {
var bgDb = provider.GetRequiredService<DatabaseContext>(); var bgDb = provider.GetRequiredService<DatabaseContext>();
var bgInstanceSvc = provider.GetRequiredService<InstanceService>(); var bgInstanceSvc = provider.GetRequiredService<InstanceService>();
var dbInstance = var dbInstance =
await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(followee.Host, new Uri(followee.Uri!).Host); await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(followee);
await bgDb.Instances.Where(p => p.Id == dbInstance.Id) await bgDb.Instances.Where(p => p.Id == dbInstance.Id)
.ExecuteUpdateAsync(p => p.SetProperty(i => i.FollowersCount, i => i.FollowersCount - 1)); .ExecuteUpdateAsync(p => p.SetProperty(i => i.OutgoingFollows,
i => i.OutgoingFollows - 1));
}); });
} }