[backend/core] Fix note & user counters (ISH-109)
This commit is contained in:
parent
c87fa00864
commit
52519f3b69
4 changed files with 73 additions and 33 deletions
|
@ -139,6 +139,7 @@ public class StatusController(
|
||||||
throw GracefulException.BadRequest("Renote visibility must be one of: public, unlisted, private");
|
throw GracefulException.BadRequest("Renote visibility must be one of: public, unlisted, private");
|
||||||
|
|
||||||
await noteSvc.CreateNoteAsync(user, renoteVisibility, renote: note);
|
await noteSvc.CreateNoteAsync(user, renoteVisibility, renote: note);
|
||||||
|
note.RenoteCount++; // we do not want to call save changes after this point
|
||||||
}
|
}
|
||||||
|
|
||||||
return await GetNote(id);
|
return await GetNote(id);
|
||||||
|
@ -158,14 +159,10 @@ public class StatusController(
|
||||||
.IncludeCommonProperties()
|
.IncludeCommonProperties()
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
if (renotes.Count > 0)
|
|
||||||
{
|
|
||||||
renotes[0].Renote!.RenoteCount--;
|
|
||||||
await db.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var renote in renotes) await noteSvc.DeleteNoteAsync(renote);
|
foreach (var renote in renotes) await noteSvc.DeleteNoteAsync(renote);
|
||||||
|
|
||||||
|
renotes[0].Renote!.RenoteCount--; // we do not want to call save changes after this point
|
||||||
|
|
||||||
return await GetNote(id);
|
return await GetNote(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -332,8 +332,10 @@ public class ActivityHandlerService(
|
||||||
FollowerSharedInbox = follower.SharedInbox
|
FollowerSharedInbox = follower.SharedInbox
|
||||||
};
|
};
|
||||||
|
|
||||||
follower.FollowingCount++;
|
await db.Users.Where(p => p.Id == follower.Id)
|
||||||
followee.FollowersCount++;
|
.ExecuteUpdateAsync(p => p.SetProperty(i => i.FollowingCount, i => i.FollowingCount + 1));
|
||||||
|
await db.Users.Where(p => p.Id == followee.Id)
|
||||||
|
.ExecuteUpdateAsync(p => p.SetProperty(i => i.FollowersCount, i => i.FollowersCount + 1));
|
||||||
|
|
||||||
_ = followupTaskSvc.ExecuteTask("IncrementInstanceIncomingFollowsCounter", async provider =>
|
_ = followupTaskSvc.ExecuteTask("IncrementInstanceIncomingFollowsCounter", async provider =>
|
||||||
{
|
{
|
||||||
|
@ -361,8 +363,12 @@ public class ActivityHandlerService(
|
||||||
var followings = await db.Followings.Where(p => p.Follower == follower && p.Followee == followee).ToListAsync();
|
var followings = await db.Followings.Where(p => p.Follower == follower && p.Followee == followee).ToListAsync();
|
||||||
if (followings.Count > 0)
|
if (followings.Count > 0)
|
||||||
{
|
{
|
||||||
followee.FollowersCount -= followings.Count;
|
await db.Users.Where(p => p.Id == follower.Id)
|
||||||
follower.FollowingCount -= followings.Count;
|
.ExecuteUpdateAsync(p => p.SetProperty(i => i.FollowingCount,
|
||||||
|
i => i.FollowingCount - followings.Count));
|
||||||
|
await db.Users.Where(p => p.Id == followee.Id)
|
||||||
|
.ExecuteUpdateAsync(p => p.SetProperty(i => i.FollowersCount,
|
||||||
|
i => i.FollowersCount - followings.Count));
|
||||||
db.RemoveRange(followings);
|
db.RemoveRange(followings);
|
||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
|
@ -417,8 +423,10 @@ public class ActivityHandlerService(
|
||||||
FolloweeSharedInbox = request.FolloweeSharedInbox
|
FolloweeSharedInbox = request.FolloweeSharedInbox
|
||||||
};
|
};
|
||||||
|
|
||||||
actor.FollowersCount++;
|
await db.Users.Where(p => p.Id == request.Follower.Id)
|
||||||
request.Follower.FollowingCount++;
|
.ExecuteUpdateAsync(p => p.SetProperty(i => i.FollowingCount, i => i.FollowingCount + 1));
|
||||||
|
await db.Users.Where(p => p.Id == actor.Id)
|
||||||
|
.ExecuteUpdateAsync(p => p.SetProperty(i => i.FollowersCount, i => i.FollowersCount + 1));
|
||||||
|
|
||||||
_ = followupTaskSvc.ExecuteTask("IncrementInstanceOutgoingFollowsCounter", async provider =>
|
_ = followupTaskSvc.ExecuteTask("IncrementInstanceOutgoingFollowsCounter", async provider =>
|
||||||
{
|
{
|
||||||
|
@ -450,8 +458,10 @@ public class ActivityHandlerService(
|
||||||
.ExecuteDeleteAsync();
|
.ExecuteDeleteAsync();
|
||||||
if (count > 0)
|
if (count > 0)
|
||||||
{
|
{
|
||||||
actor.FollowersCount -= count;
|
await db.Users.Where(p => p.Id == resolvedFollower.Id)
|
||||||
resolvedFollower.FollowingCount -= count;
|
.ExecuteUpdateAsync(p => p.SetProperty(i => i.FollowingCount, i => i.FollowingCount - count));
|
||||||
|
await db.Users.Where(p => p.Id == actor.Id)
|
||||||
|
.ExecuteUpdateAsync(p => p.SetProperty(i => i.FollowersCount, i => i.FollowersCount - count));
|
||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,7 @@ public class NoteService(
|
||||||
Renote = renote,
|
Renote = renote,
|
||||||
RenoteUserId = renote?.UserId,
|
RenoteUserId = renote?.UserId,
|
||||||
RenoteUserHost = renote?.UserHost,
|
RenoteUserHost = renote?.UserHost,
|
||||||
UserId = user.Id,
|
User = user,
|
||||||
CreatedAt = DateTime.UtcNow,
|
CreatedAt = DateTime.UtcNow,
|
||||||
UserHost = null,
|
UserHost = null,
|
||||||
Visibility = visibility,
|
Visibility = visibility,
|
||||||
|
@ -99,11 +99,7 @@ public class NoteService(
|
||||||
ThreadId = reply?.ThreadId ?? reply?.Id
|
ThreadId = reply?.ThreadId ?? reply?.Id
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!note.IsPureRenote) user.NotesCount++;
|
await UpdateNoteCountersAsync(note, true);
|
||||||
if (reply != null) reply.RepliesCount++;
|
|
||||||
if (renote != null && !note.IsQuote)
|
|
||||||
if (!db.Notes.Any(p => p.UserId == user.Id && p.RenoteId == renote.Id && p.IsPureRenote))
|
|
||||||
renote.RenoteCount++;
|
|
||||||
|
|
||||||
await db.AddAsync(note);
|
await db.AddAsync(note);
|
||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
|
@ -151,6 +147,34 @@ public class NoteService(
|
||||||
return note;
|
return note;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <remarks>
|
||||||
|
/// This needs to be called before SaveChangesAsync on create & after on delete
|
||||||
|
/// </remarks>
|
||||||
|
private async Task UpdateNoteCountersAsync(Note note, bool create)
|
||||||
|
{
|
||||||
|
var diff = create ? 1 : -1;
|
||||||
|
|
||||||
|
if (note is { Renote.Id: not null, IsPureRenote: true })
|
||||||
|
{
|
||||||
|
if (!db.Notes.Any(p => p.UserId == note.User.Id && p.RenoteId == note.Renote.Id && p.IsPureRenote))
|
||||||
|
{
|
||||||
|
await db.Notes.Where(p => p.Id == note.Renote.Id)
|
||||||
|
.ExecuteUpdateAsync(p => p.SetProperty(n => n.RenoteCount, n => n.RenoteCount + diff));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await db.Users.Where(p => p.Id == note.User.Id)
|
||||||
|
.ExecuteUpdateAsync(p => p.SetProperty(u => u.NotesCount, u => u.NotesCount + diff));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (note.Reply != null)
|
||||||
|
{
|
||||||
|
await db.Notes.Where(p => p.Id == note.Reply.Id)
|
||||||
|
.ExecuteUpdateAsync(p => p.SetProperty(n => n.RepliesCount, n => n.RepliesCount + diff));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<Note> UpdateNoteAsync(
|
public async Task<Note> UpdateNoteAsync(
|
||||||
Note note, string? text = null, string? cw = null, IReadOnlyCollection<DriveFile>? attachments = null
|
Note note, string? text = null, string? cw = null, IReadOnlyCollection<DriveFile>? attachments = null
|
||||||
)
|
)
|
||||||
|
@ -238,11 +262,11 @@ public class NoteService(
|
||||||
|
|
||||||
public async Task DeleteNoteAsync(Note note)
|
public async Task DeleteNoteAsync(Note note)
|
||||||
{
|
{
|
||||||
note.User.NotesCount--;
|
|
||||||
db.Update(note.User);
|
db.Update(note.User);
|
||||||
db.Remove(note);
|
db.Remove(note);
|
||||||
eventSvc.RaiseNoteDeleted(this, note);
|
eventSvc.RaiseNoteDeleted(this, note);
|
||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
|
await UpdateNoteCountersAsync(note, false);
|
||||||
|
|
||||||
if (note.UserHost != null)
|
if (note.UserHost != null)
|
||||||
{
|
{
|
||||||
|
@ -301,11 +325,10 @@ public class NoteService(
|
||||||
|
|
||||||
logger.LogDebug("Deleting note '{id}' owned by {userId}", note.Id, actor.Id);
|
logger.LogDebug("Deleting note '{id}' owned by {userId}", note.Id, actor.Id);
|
||||||
|
|
||||||
actor.NotesCount--;
|
|
||||||
if (dbNote.IsPureRenote) dbNote.RenoteCount--;
|
|
||||||
db.Remove(dbNote);
|
db.Remove(dbNote);
|
||||||
eventSvc.RaiseNoteDeleted(this, dbNote);
|
eventSvc.RaiseNoteDeleted(this, dbNote);
|
||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
|
await UpdateNoteCountersAsync(dbNote, false);
|
||||||
|
|
||||||
// ReSharper disable once EntityFramework.NPlusOne.IncompleteDataUsage (same reason as above)
|
// ReSharper disable once EntityFramework.NPlusOne.IncompleteDataUsage (same reason as above)
|
||||||
if (dbNote.User.Uri != null && dbNote.UserHost != null)
|
if (dbNote.User.Uri != null && dbNote.UserHost != null)
|
||||||
|
@ -331,9 +354,10 @@ public class NoteService(
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
if (notes.Count == 0) return;
|
if (notes.Count == 0) return;
|
||||||
renote.RenoteCount--;
|
|
||||||
db.RemoveRange(notes);
|
db.RemoveRange(notes);
|
||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
|
await db.Notes.Where(p => p.Id == note.Id)
|
||||||
|
.ExecuteUpdateAsync(p => p.SetProperty(n => n.RenoteCount, n => n.RenoteCount - 1));
|
||||||
|
|
||||||
foreach (var hit in notes)
|
foreach (var hit in notes)
|
||||||
eventSvc.RaiseNoteDeleted(this, hit);
|
eventSvc.RaiseNoteDeleted(this, hit);
|
||||||
|
@ -388,7 +412,7 @@ public class NoteService(
|
||||||
Url = note.Url?.Id, //FIXME: this doesn't seem to work yet
|
Url = note.Url?.Id, //FIXME: this doesn't seem to work yet
|
||||||
Text = note.MkContent ?? await MfmConverter.FromHtmlAsync(note.Content, mentions),
|
Text = note.MkContent ?? await MfmConverter.FromHtmlAsync(note.Content, mentions),
|
||||||
Cw = note.Summary,
|
Cw = note.Summary,
|
||||||
UserId = actor.Id,
|
User = actor,
|
||||||
CreatedAt = createdAt,
|
CreatedAt = createdAt,
|
||||||
UserHost = actor.Host,
|
UserHost = actor.Host,
|
||||||
Visibility = note.GetVisibility(actor),
|
Visibility = note.GetVisibility(actor),
|
||||||
|
@ -449,8 +473,7 @@ public class NoteService(
|
||||||
var emoji = await emojiSvc.ProcessEmojiAsync(note.Tags?.OfType<ASEmoji>().ToList(), actor.Host);
|
var emoji = await emojiSvc.ProcessEmojiAsync(note.Tags?.OfType<ASEmoji>().ToList(), actor.Host);
|
||||||
dbNote.Emojis = emoji.Select(p => p.Id).ToList();
|
dbNote.Emojis = emoji.Select(p => p.Id).ToList();
|
||||||
|
|
||||||
actor.NotesCount++;
|
await UpdateNoteCountersAsync(dbNote, true);
|
||||||
if (dbNote.Reply != null) dbNote.Reply.RepliesCount++;
|
|
||||||
await db.Notes.AddAsync(dbNote);
|
await db.Notes.AddAsync(dbNote);
|
||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
eventSvc.RaiseNotePublished(this, dbNote);
|
eventSvc.RaiseNotePublished(this, dbNote);
|
||||||
|
|
|
@ -521,8 +521,10 @@ public class UserService(
|
||||||
FolloweeSharedInbox = request.FolloweeSharedInbox
|
FolloweeSharedInbox = request.FolloweeSharedInbox
|
||||||
};
|
};
|
||||||
|
|
||||||
request.Followee.FollowersCount++;
|
await db.Users.Where(p => p.Id == request.Follower.Id)
|
||||||
request.Follower.FollowingCount++;
|
.ExecuteUpdateAsync(p => p.SetProperty(i => i.FollowingCount, i => i.FollowingCount + 1));
|
||||||
|
await db.Users.Where(p => p.Id == request.Followee.Id)
|
||||||
|
.ExecuteUpdateAsync(p => p.SetProperty(i => i.FollowersCount, i => i.FollowersCount + 1));
|
||||||
|
|
||||||
db.Remove(request);
|
db.Remove(request);
|
||||||
await db.AddAsync(following);
|
await db.AddAsync(following);
|
||||||
|
@ -624,8 +626,10 @@ public class UserService(
|
||||||
// otherwise we'll do it when receiving the Accept activity / the local followee accepts the request
|
// otherwise we'll do it when receiving the Accept activity / the local followee accepts the request
|
||||||
if (followee.Host == null && !followee.IsLocked)
|
if (followee.Host == null && !followee.IsLocked)
|
||||||
{
|
{
|
||||||
followee.FollowersCount++;
|
await db.Users.Where(p => p.Id == user.Id)
|
||||||
user.FollowingCount++;
|
.ExecuteUpdateAsync(p => p.SetProperty(i => i.FollowingCount, i => i.FollowingCount + 1));
|
||||||
|
await db.Users.Where(p => p.Id == followee.Id)
|
||||||
|
.ExecuteUpdateAsync(p => p.SetProperty(i => i.FollowersCount, i => i.FollowersCount + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
|
@ -651,8 +655,14 @@ public class UserService(
|
||||||
if (followee.PrecomputedIsFollowedBy ?? false)
|
if (followee.PrecomputedIsFollowedBy ?? false)
|
||||||
{
|
{
|
||||||
var followings = await db.Followings.Where(p => p.Follower == user && p.Followee == followee).ToListAsync();
|
var followings = await db.Followings.Where(p => p.Follower == user && p.Followee == followee).ToListAsync();
|
||||||
user.FollowingCount -= followings.Count;
|
|
||||||
followee.FollowersCount -= followings.Count;
|
await db.Users.Where(p => p.Id == user.Id)
|
||||||
|
.ExecuteUpdateAsync(p => p.SetProperty(i => i.FollowingCount,
|
||||||
|
i => i.FollowingCount - followings.Count));
|
||||||
|
await db.Users.Where(p => p.Id == followee.Id)
|
||||||
|
.ExecuteUpdateAsync(p => p.SetProperty(i => i.FollowersCount,
|
||||||
|
i => i.FollowersCount - followings.Count));
|
||||||
|
|
||||||
db.RemoveRange(followings);
|
db.RemoveRange(followings);
|
||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue