From 093abe82b80b93589e8d78eb09b6af864567a746 Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Sun, 18 Aug 2024 00:22:09 +0200 Subject: [PATCH] [backend/core] Also use the NoteService KeyedLocker when it's called from ActivityHandlerService This fixes sporadic "Unique constraint violation" exceptions on the "IX_note_uri" index. --- .../Core/Federation/ActivityPub/ActivityHandlerService.cs | 6 ++++-- Iceshrimp.Backend/Core/Services/NoteService.cs | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) 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);