[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.
This commit is contained in:
Laura Hausmann 2024-08-18 00:22:09 +02:00
parent 4be51a0cad
commit 093abe82b8
No known key found for this signature in database
GPG key ID: D044E84C5BE01605
2 changed files with 6 additions and 2 deletions

View file

@ -105,7 +105,8 @@ public class ActivityHandlerService(
activity.Object = await objectResolver.ResolveObject(activity.Object, actor.Uri) as ASNote ?? activity.Object = await objectResolver.ResolveObject(activity.Object, actor.Uri) as ASNote ??
throw GracefulException.UnprocessableEntity("Failed to resolve create object"); 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) private async Task HandleDelete(ASDelete activity, User resolvedActor)
@ -335,7 +336,8 @@ public class ActivityHandlerService(
await userSvc.UpdateUserAsync(resolvedActor, actor); await userSvc.UpdateUserAsync(resolvedActor, actor);
break; break;
case ASNote note: case ASNote note:
await noteSvc.ProcessNoteUpdateAsync(note, resolvedActor); using (await NoteService.GetNoteProcessLockAsync(note.Id))
await noteSvc.ProcessNoteUpdateAsync(note, resolvedActor);
break; break;
default: default:
logger.LogDebug("Like activity object is unknown, skipping"); logger.LogDebug("Like activity object is unknown, skipping");

View file

@ -715,6 +715,8 @@ public class NoteService(
eventSvc.RaiseNoteDeleted(this, hit); eventSvc.RaiseNoteDeleted(this, hit);
} }
public static ValueTask<IDisposable> GetNoteProcessLockAsync(string uri) => KeyedLocker.LockAsync(uri);
public async Task<Note?> ProcessNoteAsync(ASNote note, User actor, User? user = null) public async Task<Note?> ProcessNoteAsync(ASNote note, User actor, User? user = null)
{ {
var dbHit = await db.Notes.IncludeCommonProperties().FirstOrDefaultAsync(p => p.Uri == note.Id); var dbHit = await db.Notes.IncludeCommonProperties().FirstOrDefaultAsync(p => p.Uri == note.Id);