[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 =>
{
entity.Property(e => e.CaughtAt).HasComment("The caught date of the Instance.");
entity.Property(e => e.FollowersCount).HasDefaultValue(0);
entity.Property(e => e.FollowingCount).HasDefaultValue(0);
entity.Property(e => e.OutgoingFollows).HasDefaultValue(0);
entity.Property(e => e.IncomingFollows).HasDefaultValue(0);
entity.Property(e => e.Host).HasComment("The host of the Instance.");
entity.Property(e => e.IsNotResponding).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()
.HasColumnType("integer")
.HasDefaultValue(0)
.HasColumnName("followersCount");
.HasColumnName("outgoingFollows");
b.Property<int>("FollowingCount")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasDefaultValue(0)
.HasColumnName("followingCount");
.HasColumnName("incomingFollows");
b.Property<string>("Host")
.IsRequired()

View file

@ -41,9 +41,9 @@ public class Instance
[Column("notesCount")]
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; }

View file

@ -335,14 +335,13 @@ public class ActivityHandlerService(
follower.FollowingCount++;
followee.FollowersCount++;
_ = followupTaskSvc.ExecuteTask("UpdateInstanceFollowingCounter", async provider =>
_ = followupTaskSvc.ExecuteTask("IncrementInstanceIncomingFollowsCounter", async provider =>
{
var bgDb = provider.GetRequiredService<DatabaseContext>();
var bgInstanceSvc = provider.GetRequiredService<InstanceService>();
var dbInstance = await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(follower.Host,
new Uri(follower.Uri!).Host);
var dbInstance = await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(follower);
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);
@ -367,7 +366,15 @@ public class ActivityHandlerService(
db.RemoveRange(followings);
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
.Where(p => p.Type == Notification.NotificationType.Follow &&
p.Notifiee == followee &&
@ -413,14 +420,13 @@ public class ActivityHandlerService(
actor.FollowersCount++;
request.Follower.FollowingCount++;
_ = followupTaskSvc.ExecuteTask("UpdateInstanceFollowersCounter", async provider =>
_ = followupTaskSvc.ExecuteTask("IncrementInstanceOutgoingFollowsCounter", async provider =>
{
var bgDb = provider.GetRequiredService<DatabaseContext>();
var bgInstanceSvc = provider.GetRequiredService<InstanceService>();
var dbInstance = await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(request.Followee.Host!,
new Uri(request.Followee.Uri!).Host);
var dbInstance = await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(request.Followee);
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);

View file

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

View file

@ -58,6 +58,12 @@ public class InstanceService(DatabaseContext db, HttpClient httpClient)
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)
{
try

View file

@ -113,19 +113,15 @@ public class NoteService(
await notificationSvc.GenerateRenoteNotification(note);
if (user.Host != null)
{
if (user.Uri != null)
{
_ = followupTaskSvc.ExecuteTask("UpdateInstanceNoteCounter", async provider =>
{
var bgDb = provider.GetRequiredService<DatabaseContext>();
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)
.ExecuteUpdateAsync(p => p.SetProperty(i => i.NotesCount, i => i.NotesCount + 1));
});
}
return note;
}
@ -256,8 +252,7 @@ public class NoteService(
{
var bgDb = provider.GetRequiredService<DatabaseContext>();
var bgInstanceSvc = provider.GetRequiredService<InstanceService>();
var dbInstance =
await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(note.UserHost, new Uri(note.User.Uri).Host);
var dbInstance = await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(note.User);
await bgDb.Instances.Where(p => p.Id == dbInstance.Id)
.ExecuteUpdateAsync(p => p.SetProperty(i => i.NotesCount, i => i.NotesCount - 1));
});
@ -320,8 +315,7 @@ public class NoteService(
var bgDb = provider.GetRequiredService<DatabaseContext>();
var bgInstanceSvc = provider.GetRequiredService<InstanceService>();
// ReSharper disable once EntityFramework.NPlusOne.IncompleteDataUsage (same reason as above)
var dbInstance =
await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(dbNote.UserHost, new Uri(dbNote.User.Uri).Host);
var dbInstance = await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(dbNote.User);
await bgDb.Instances.Where(p => p.Id == dbInstance.Id)
.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 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)
.ExecuteUpdateAsync(p => p.SetProperty(i => i.UsersCount, i => i.UsersCount + 1));
});
@ -449,7 +449,7 @@ public class UserService(
{
var bgDb = provider.GetRequiredService<DatabaseContext>();
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)
.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 })
{
_ = followupTaskSvc.ExecuteTask("UpdateInstanceFollowingCounter", async provider =>
_ = followupTaskSvc.ExecuteTask("IncrementInstanceIncomingFollowsCounter", async provider =>
{
var bgDb = provider.GetRequiredService<DatabaseContext>();
var bgInstanceSvc = provider.GetRequiredService<InstanceService>();
var dbInstance = await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(request.Follower.Host,
new Uri(request.Follower.Uri!).Host);
var dbInstance = await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(request.Follower);
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)
{
_ = followupTaskSvc.ExecuteTask("UpdateInstanceFollowersCounter", async provider =>
_ = followupTaskSvc.ExecuteTask("DecrementInstanceOutgoingFollowsCounter", async provider =>
{
var bgDb = provider.GetRequiredService<DatabaseContext>();
var bgInstanceSvc = provider.GetRequiredService<InstanceService>();
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)
.ExecuteUpdateAsync(p => p.SetProperty(i => i.FollowersCount, i => i.FollowersCount - 1));
.ExecuteUpdateAsync(p => p.SetProperty(i => i.OutgoingFollows,
i => i.OutgoingFollows - 1));
});
}