[backend/core] Add instance counters (ISH-107)
This commit is contained in:
parent
ad21897928
commit
a719fc722e
6 changed files with 129 additions and 4 deletions
|
@ -88,10 +88,11 @@ public static class WebApplicationExtensions
|
|||
|
||||
if (args.Contains("--recompute-counters"))
|
||||
{
|
||||
app.Logger.LogInformation("Recomputing note & user counters, this will take a while...");
|
||||
app.Logger.LogInformation("Recomputing note, user & instance counters, this will take a while...");
|
||||
var maintenanceSvc = provider.GetRequiredService<DatabaseMaintenanceService>();
|
||||
await maintenanceSvc.RecomputeNoteCountersAsync();
|
||||
await maintenanceSvc.RecomputeUserCountersAsync();
|
||||
await maintenanceSvc.RecomputeInstanceCountersAsync();
|
||||
}
|
||||
|
||||
app.Logger.LogInformation("Verifying redis connection...");
|
||||
|
|
|
@ -335,6 +335,16 @@ public class ActivityHandlerService(
|
|||
follower.FollowingCount++;
|
||||
followee.FollowersCount++;
|
||||
|
||||
_ = followupTaskSvc.ExecuteTask("UpdateInstanceFollowingCounter", async provider =>
|
||||
{
|
||||
var bgDb = provider.GetRequiredService<DatabaseContext>();
|
||||
var bgInstanceSvc = provider.GetRequiredService<InstanceService>();
|
||||
var dbInstance = await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(follower.Host,
|
||||
new Uri(follower.Uri!).Host);
|
||||
await bgDb.Instances.Where(p => p.Id == dbInstance.Id)
|
||||
.ExecuteUpdateAsync(p => p.SetProperty(i => i.FollowingCount, i => i.FollowingCount + 1));
|
||||
});
|
||||
|
||||
await db.AddAsync(following);
|
||||
await db.SaveChangesAsync();
|
||||
await notificationSvc.GenerateFollowNotification(follower, followee);
|
||||
|
@ -403,6 +413,16 @@ public class ActivityHandlerService(
|
|||
actor.FollowersCount++;
|
||||
request.Follower.FollowingCount++;
|
||||
|
||||
_ = followupTaskSvc.ExecuteTask("UpdateInstanceFollowersCounter", 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);
|
||||
await bgDb.Instances.Where(p => p.Id == dbInstance.Id)
|
||||
.ExecuteUpdateAsync(p => p.SetProperty(i => i.FollowersCount, i => i.FollowersCount + 1));
|
||||
});
|
||||
|
||||
db.Remove(request);
|
||||
await db.AddAsync(following);
|
||||
await db.SaveChangesAsync();
|
||||
|
|
|
@ -23,4 +23,18 @@ public class DatabaseMaintenanceService(DatabaseContext db)
|
|||
.SetProperty(u => u.NotesCount,
|
||||
u => db.Notes.Count(n => n.User == u && !n.IsPureRenote)));
|
||||
}
|
||||
|
||||
public async Task RecomputeInstanceCountersAsync()
|
||||
{
|
||||
await db.Instances.ExecuteUpdateAsync(p => p.SetProperty(i => i.NotesCount,
|
||||
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,
|
||||
i => db.Followings
|
||||
.Count(n => n.FolloweeHost == i.Host))
|
||||
.SetProperty(i => i.FollowingCount,
|
||||
i => db.Followings
|
||||
.Count(n => n.FollowerHost == i.Host)));
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@ public class InstanceService(DatabaseContext db, HttpClient httpClient)
|
|||
o.PoolInitialFill = 5;
|
||||
});
|
||||
|
||||
private async Task<Instance> GetUpdatedInstanceMetadataAsync(string host, string webDomain)
|
||||
public async Task<Instance> GetUpdatedInstanceMetadataAsync(string host, string webDomain)
|
||||
{
|
||||
host = host.ToLowerInvariant();
|
||||
var instance = db.Instances.FirstOrDefault(p => p.Host == host);
|
||||
|
|
|
@ -37,7 +37,8 @@ public class NoteService(
|
|||
NotificationService notificationSvc,
|
||||
EventService eventSvc,
|
||||
ActivityPub.ActivityRenderer activityRenderer,
|
||||
EmojiService emojiSvc
|
||||
EmojiService emojiSvc,
|
||||
FollowupTaskService followupTaskSvc
|
||||
)
|
||||
{
|
||||
private readonly List<string> _resolverHistory = [];
|
||||
|
@ -111,7 +112,23 @@ public class NoteService(
|
|||
await notificationSvc.GenerateReplyNotifications(note, mentionedLocalUserIds);
|
||||
await notificationSvc.GenerateRenoteNotification(note);
|
||||
|
||||
if (user.Host != null) return 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);
|
||||
await bgDb.Instances.Where(p => p.Id == dbInstance.Id)
|
||||
.ExecuteUpdateAsync(p => p.SetProperty(i => i.NotesCount, i => i.NotesCount + 1));
|
||||
});
|
||||
}
|
||||
|
||||
return note;
|
||||
}
|
||||
|
||||
var actor = userRenderer.RenderLite(user);
|
||||
ASActivity activity = note is { IsPureRenote: true, Renote: not null }
|
||||
|
@ -232,7 +249,22 @@ public class NoteService(
|
|||
await db.SaveChangesAsync();
|
||||
|
||||
if (note.UserHost != null)
|
||||
{
|
||||
if (note.User.Uri != null)
|
||||
{
|
||||
_ = followupTaskSvc.ExecuteTask("UpdateInstanceNoteCounter", async provider =>
|
||||
{
|
||||
var bgDb = provider.GetRequiredService<DatabaseContext>();
|
||||
var bgInstanceSvc = provider.GetRequiredService<InstanceService>();
|
||||
var dbInstance =
|
||||
await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(note.UserHost, new Uri(note.User.Uri).Host);
|
||||
await bgDb.Instances.Where(p => p.Id == dbInstance.Id)
|
||||
.ExecuteUpdateAsync(p => p.SetProperty(i => i.NotesCount, i => i.NotesCount - 1));
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var recipients = await db.Users.Where(p => note.Mentions.Concat(note.VisibleUserIds).Distinct().Contains(p.Id))
|
||||
.Select(p => new User { Host = p.Host, Inbox = p.Inbox })
|
||||
|
@ -279,6 +311,21 @@ public class NoteService(
|
|||
db.Remove(dbNote);
|
||||
eventSvc.RaiseNoteDeleted(this, dbNote);
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
// ReSharper disable once EntityFramework.NPlusOne.IncompleteDataUsage (same reason as above)
|
||||
if (dbNote.User.Uri != null && dbNote.UserHost != null)
|
||||
{
|
||||
_ = followupTaskSvc.ExecuteTask("UpdateInstanceNoteCounter", async provider =>
|
||||
{
|
||||
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);
|
||||
await bgDb.Instances.Where(p => p.Id == dbInstance.Id)
|
||||
.ExecuteUpdateAsync(p => p.SetProperty(i => i.NotesCount, i => i.NotesCount - 1));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public async Task UndoAnnounceAsync(ASNote note, User actor)
|
||||
|
|
|
@ -185,6 +185,14 @@ public class UserService(
|
|||
await db.SaveChangesAsync();
|
||||
await processPendingDeletes();
|
||||
user = await UpdateProfileMentions(user, actor);
|
||||
_ = followupTaskSvc.ExecuteTask("UpdateInstanceUserCounter", async provider =>
|
||||
{
|
||||
var bgDb = provider.GetRequiredService<DatabaseContext>();
|
||||
var bgInstanceSvc = provider.GetRequiredService<InstanceService>();
|
||||
var dbInstance = await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(host, new Uri(uri).Host);
|
||||
await bgDb.Instances.Where(p => p.Id == dbInstance.Id)
|
||||
.ExecuteUpdateAsync(p => p.SetProperty(i => i.UsersCount, i => i.UsersCount + 1));
|
||||
});
|
||||
return user;
|
||||
}
|
||||
catch (UniqueConstraintException)
|
||||
|
@ -437,6 +445,15 @@ public class UserService(
|
|||
db.Remove(user);
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
_ = followupTaskSvc.ExecuteTask("UpdateInstanceUserCounter", async provider =>
|
||||
{
|
||||
var bgDb = provider.GetRequiredService<DatabaseContext>();
|
||||
var bgInstanceSvc = provider.GetRequiredService<InstanceService>();
|
||||
var dbInstance = 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.UsersCount, i => i.UsersCount - 1));
|
||||
});
|
||||
|
||||
if (user.Avatar != null)
|
||||
await driveSvc.RemoveFile(user.Avatar);
|
||||
if (user.Banner != null)
|
||||
|
@ -511,6 +528,19 @@ public class UserService(
|
|||
await db.AddAsync(following);
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
if (request.Follower is { Host: not null })
|
||||
{
|
||||
_ = followupTaskSvc.ExecuteTask("UpdateInstanceFollowingCounter", 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);
|
||||
await bgDb.Instances.Where(p => p.Id == dbInstance.Id)
|
||||
.ExecuteUpdateAsync(p => p.SetProperty(i => i.FollowingCount, i => i.FollowingCount + 1));
|
||||
});
|
||||
}
|
||||
|
||||
await notificationSvc.GenerateFollowNotification(request.Follower, request.Followee);
|
||||
await notificationSvc.GenerateFollowRequestAcceptedNotification(request);
|
||||
|
||||
|
@ -627,6 +657,19 @@ public class UserService(
|
|||
db.RemoveRange(followings);
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
if (followee.Host != null)
|
||||
{
|
||||
_ = followupTaskSvc.ExecuteTask("UpdateInstanceFollowersCounter", 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 bgDb.Instances.Where(p => p.Id == dbInstance.Id)
|
||||
.ExecuteUpdateAsync(p => p.SetProperty(i => i.FollowersCount, i => i.FollowersCount - 1));
|
||||
});
|
||||
}
|
||||
|
||||
followee.PrecomputedIsFollowedBy = false;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue