diff --git a/Iceshrimp.Backend/Core/Federation/ActivityPub/ActivityHandlerService.cs b/Iceshrimp.Backend/Core/Federation/ActivityPub/ActivityHandlerService.cs index fc06a46f..6c5200ed 100644 --- a/Iceshrimp.Backend/Core/Federation/ActivityPub/ActivityHandlerService.cs +++ b/Iceshrimp.Backend/Core/Federation/ActivityPub/ActivityHandlerService.cs @@ -105,7 +105,8 @@ public class ActivityHandlerService( activity.Object = await objectResolver.ResolveObject(activity.Object, actor.Uri) as ASNote ?? throw GracefulException.UnprocessableEntity("Failed to resolve create object"); - await noteSvc.ProcessNoteAsync(activity.Object, actor, inboxUser); + using (await NoteService.GetNoteProcessLockAsync(activity.Object.Id)) + await noteSvc.ProcessNoteAsync(activity.Object, actor, inboxUser); } private async Task HandleDelete(ASDelete activity, User resolvedActor) @@ -335,7 +336,8 @@ public class ActivityHandlerService( await userSvc.UpdateUserAsync(resolvedActor, actor); break; case ASNote note: - await noteSvc.ProcessNoteUpdateAsync(note, resolvedActor); + using (await NoteService.GetNoteProcessLockAsync(note.Id)) + await noteSvc.ProcessNoteUpdateAsync(note, resolvedActor); break; default: logger.LogDebug("Like activity object is unknown, skipping"); diff --git a/Iceshrimp.Backend/Core/Services/NoteService.cs b/Iceshrimp.Backend/Core/Services/NoteService.cs index 36f1c5f4..9c3ea1a0 100644 --- a/Iceshrimp.Backend/Core/Services/NoteService.cs +++ b/Iceshrimp.Backend/Core/Services/NoteService.cs @@ -715,6 +715,8 @@ public class NoteService( eventSvc.RaiseNoteDeleted(this, hit); } + public static ValueTask GetNoteProcessLockAsync(string uri) => KeyedLocker.LockAsync(uri); + public async Task ProcessNoteAsync(ASNote note, User actor, User? user = null) { var dbHit = await db.Notes.IncludeCommonProperties().FirstOrDefaultAsync(p => p.Uri == note.Id);