[backend/masto-api] Move NoteRenderer prefetch objects into a DTO

This commit is contained in:
Laura Hausmann 2024-02-25 00:10:51 +01:00
parent 69360a8ad7
commit 404d8ae5b3
No known key found for this signature in database
GPG key ID: D044E84C5BE01605
2 changed files with 57 additions and 56 deletions

View file

@ -16,20 +16,14 @@ public class NoteRenderer(
DatabaseContext db DatabaseContext db
) )
{ {
public async Task<StatusEntity> RenderAsync( public async Task<StatusEntity> RenderAsync(Note note, User? user, NoteRendererDto? data = null, int recurse = 2)
Note note, User? user, List<AccountEntity>? accounts = null, List<MentionEntity>? mentions = null,
List<AttachmentEntity>? attachments = null, Dictionary<string, int>? likeCounts = null,
List<string>? likedNotes = null, List<string>? renotes = null, List<EmojiEntity>? emoji = null, int recurse = 2
)
{ {
var uri = note.Uri ?? note.GetPublicUri(config.Value); var uri = note.Uri ?? note.GetPublicUri(config.Value);
var renote = note is { Renote: not null, IsQuote: false } && recurse > 0 var renote = note is { Renote: not null, IsQuote: false } && recurse > 0
? await RenderAsync(note.Renote, user, accounts, mentions, attachments, likeCounts, likedNotes, ? await RenderAsync(note.Renote, user, data, 0)
renotes, emoji, 0)
: null; : null;
var quote = note is { Renote: not null, IsQuote: true } && recurse > 0 var quote = note is { Renote: not null, IsQuote: true } && recurse > 0
? await RenderAsync(note.Renote, user, accounts, mentions, attachments, likeCounts, likedNotes, ? await RenderAsync(note.Renote, user, data, --recurse)
renotes, emoji, --recurse)
: null; : null;
var text = note.Text; var text = note.Text;
if (note is { Renote: not null, IsQuote: true } && text != null) if (note is { Renote: not null, IsQuote: true } && text != null)
@ -39,28 +33,24 @@ public class NoteRenderer(
text += $"\n\nRE: {quoteUri}"; //TODO: render as inline quote text += $"\n\nRE: {quoteUri}"; //TODO: render as inline quote
} }
var likeCount = likeCounts?.GetValueOrDefault(note.Id, 0) ?? await db.NoteLikes.CountAsync(p => p.Note == note); var likeCount = data?.LikeCounts?.GetValueOrDefault(note.Id, 0) ??
var liked = likedNotes?.Contains(note.Id) ?? await db.NoteLikes.AnyAsync(p => p.Note == note && p.User == user); await db.NoteLikes.CountAsync(p => p.Note == note);
var renoted = renotes?.Contains(note.Id) ?? var liked = data?.LikedNotes?.Contains(note.Id) ??
await db.NoteLikes.AnyAsync(p => p.Note == note && p.User == user);
var renoted = data?.Renotes?.Contains(note.Id) ??
await db.Notes.AnyAsync(p => p.Renote == note && p.User == user && p.IsPureRenote); await db.Notes.AnyAsync(p => p.Renote == note && p.User == user && p.IsPureRenote);
var noteEmoji = emoji?.Where(p => note.Emojis.Contains(p.Id)).ToList() ?? await GetEmoji([note]); var noteEmoji = data?.Emoji?.Where(p => note.Emojis.Contains(p.Id)).ToList() ?? await GetEmoji([note]);
if (mentions == null) var mentions = data?.Mentions == null
{ ? await db.Users.IncludeCommonProperties()
mentions = await db.Users.IncludeCommonProperties()
.Where(p => note.Mentions.Contains(p.Id)) .Where(p => note.Mentions.Contains(p.Id))
.Select(u => new MentionEntity(u, config.Value.WebDomain)) .Select(u => new MentionEntity(u, config.Value.WebDomain))
.ToListAsync(); .ToListAsync()
} : [..data.Mentions.Where(p => note.Mentions.Contains(p.Id))];
else
{
mentions = [..mentions.Where(p => note.Mentions.Contains(p.Id))];
}
if (attachments == null) var attachments = data?.Attachments == null
{ ? await db.DriveFiles.Where(p => note.FileIds.Contains(p.Id))
attachments = await db.DriveFiles.Where(p => note.FileIds.Contains(p.Id))
.Select(f => new AttachmentEntity .Select(f => new AttachmentEntity
{ {
Id = f.Id, Id = f.Id,
@ -72,12 +62,9 @@ public class NoteRenderer(
RemoteUrl = f.Uri, RemoteUrl = f.Uri,
Type = AttachmentEntity.GetType(f.Type) Type = AttachmentEntity.GetType(f.Type)
}) })
.ToListAsync(); .ToListAsync()
} : [..data.Attachments.Where(p => note.FileIds.Contains(p.Id))];
else
{
attachments = [..attachments.Where(p => note.FileIds.Contains(p.Id))];
}
var mentionedUsers = mentions.Select(p => new Note.MentionedUser var mentionedUsers = mentions.Select(p => new Note.MentionedUser
{ {
@ -92,7 +79,8 @@ public class NoteRenderer(
? await mfmConverter.ToHtmlAsync(text, mentionedUsers, note.UserHost) ? await mfmConverter.ToHtmlAsync(text, mentionedUsers, note.UserHost)
: null; : null;
var account = accounts?.FirstOrDefault(p => p.Id == note.UserId) ?? await userRenderer.RenderAsync(note.User); var account = data?.Accounts?.FirstOrDefault(p => p.Id == note.UserId) ??
await userRenderer.RenderAsync(note.User);
var res = new StatusEntity var res = new StatusEntity
{ {
@ -215,15 +203,28 @@ public class NoteRenderer(
.DistinctBy(p => p.Id) .DistinctBy(p => p.Id)
.ToList(); .ToList();
accounts ??= await GetAccounts(noteList.Select(p => p.User)); var data = new NoteRendererDto
var mentions = await GetMentions(noteList); {
var attachments = await GetAttachments(noteList); Accounts = accounts ?? await GetAccounts(noteList.Select(p => p.User)),
var likeCounts = await GetLikeCounts(noteList); Mentions = await GetMentions(noteList),
var likedNotes = await GetLikedNotes(noteList, user); Attachments = await GetAttachments(noteList),
var renotes = await GetRenotes(noteList, user); LikeCounts = await GetLikeCounts(noteList),
var emoji = await GetEmoji(noteList); LikedNotes = await GetLikedNotes(noteList, user),
return await noteList.Select(p => RenderAsync(p, user, accounts, mentions, attachments, likeCounts, likedNotes, Renotes = await GetRenotes(noteList, user),
renotes, emoji)) Emoji = await GetEmoji(noteList)
.AwaitAllAsync(); };
return await noteList.Select(p => RenderAsync(p, user, data)).AwaitAllAsync();
}
public class NoteRendererDto
{
public List<AccountEntity>? Accounts;
public List<MentionEntity>? Mentions;
public List<AttachmentEntity>? Attachments;
public Dictionary<string, int>? LikeCounts;
public List<string>? LikedNotes;
public List<string>? Renotes;
public List<EmojiEntity>? Emoji;
} }
} }

View file

@ -20,7 +20,7 @@ public class NotificationRenderer(NoteRenderer noteRenderer, UserRenderer userRe
var note = targetNote != null var note = targetNote != null
? statuses?.FirstOrDefault(p => p.Id == targetNote.Id) ?? ? statuses?.FirstOrDefault(p => p.Id == targetNote.Id) ??
await noteRenderer.RenderAsync(targetNote, user, accounts) await noteRenderer.RenderAsync(targetNote, user, new NoteRenderer.NoteRendererDto { Accounts = accounts })
: null; : null;
var notifier = accounts?.FirstOrDefault(p => p.Id == dbNotifier.Id) ?? var notifier = accounts?.FirstOrDefault(p => p.Id == dbNotifier.Id) ??