[backend/masto-client] Fix slow notifications endpoint response time
This commit is contained in:
parent
f1a1ed9039
commit
1af21062fb
1 changed files with 29 additions and 25 deletions
|
@ -5,6 +5,7 @@ using Iceshrimp.Backend.Core.Database;
|
||||||
using Iceshrimp.Backend.Core.Database.Tables;
|
using Iceshrimp.Backend.Core.Database.Tables;
|
||||||
using Iceshrimp.Backend.Core.Extensions;
|
using Iceshrimp.Backend.Core.Extensions;
|
||||||
using Iceshrimp.Backend.Core.Services;
|
using Iceshrimp.Backend.Core.Services;
|
||||||
|
using Iceshrimp.EntityFrameworkCore.Extensions;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
|
@ -28,13 +29,13 @@ public class NotificationRenderer(
|
||||||
var targetNote = notification.Note;
|
var targetNote = notification.Note;
|
||||||
|
|
||||||
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, Filter.FilterContext.Notifications,
|
?? await noteRenderer.RenderAsync(targetNote, user, Filter.FilterContext.Notifications,
|
||||||
new NoteRenderer.NoteRendererDto { Accounts = accounts })
|
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)
|
||||||
await userRenderer.RenderAsync(dbNotifier, user);
|
?? await userRenderer.RenderAsync(dbNotifier, user);
|
||||||
|
|
||||||
string? emojiUrl = null;
|
string? emojiUrl = null;
|
||||||
if (notification.Reaction != null)
|
if (notification.Reaction != null)
|
||||||
|
@ -63,7 +64,9 @@ public class NotificationRenderer(
|
||||||
CreatedAt = notification.CreatedAt.ToStringIso8601Like(),
|
CreatedAt = notification.CreatedAt.ToStringIso8601Like(),
|
||||||
Emoji = notification.Reaction,
|
Emoji = notification.Reaction,
|
||||||
EmojiUrl = emojiUrl,
|
EmojiUrl = emojiUrl,
|
||||||
Pleroma = flags.IsPleroma.Value ? new PleromaNotificationExtensions { IsSeen = notification.IsRead } : null
|
Pleroma = flags.IsPleroma.Value
|
||||||
|
? new PleromaNotificationExtensions { IsSeen = notification.IsRead }
|
||||||
|
: null
|
||||||
};
|
};
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
@ -98,27 +101,28 @@ public class NotificationRenderer(
|
||||||
.Select(p =>
|
.Select(p =>
|
||||||
{
|
{
|
||||||
var parts = p.Reaction!.Trim(':').Split('@');
|
var parts = p.Reaction!.Trim(':').Split('@');
|
||||||
return new { Name = parts[0], Host = parts.Length > 1 ? parts[1] : null };
|
return (name: parts[0], host: parts.Length > 1 ? parts[1] : null);
|
||||||
});
|
})
|
||||||
|
.Distinct()
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
var expr = ExpressionExtensions.False<Emoji>();
|
||||||
|
expr = parts.Aggregate(expr, (current, part) => current.Or(p => p.Name == part.name && p.Host == part.host));
|
||||||
|
|
||||||
// https://github.com/dotnet/efcore/issues/31492
|
// https://github.com/dotnet/efcore/issues/31492
|
||||||
//TODO: is there a better way of expressing this using LINQ?
|
var emojiUrls = await db.Emojis
|
||||||
IQueryable<Emoji> urlQ = db.Emojis;
|
.Where(expr)
|
||||||
foreach (var part in parts)
|
.Select(e => new
|
||||||
urlQ = urlQ.Concat(db.Emojis.Where(e => e.Name == part.Name && e.Host == part.Host));
|
{
|
||||||
|
Name = $":{e.Name}{(e.Host != null ? "@" + e.Host : "")}:",
|
||||||
|
Url = e.GetAccessUrl(instance.Value)
|
||||||
|
})
|
||||||
|
.ToDictionaryAsync(e => e.Name, e => e.Url);
|
||||||
|
|
||||||
//TODO: can we somehow optimize this to do the dedupe database side?
|
var res = await notificationList
|
||||||
var emojiUrls = await urlQ.Select(e => new
|
.Select(p => RenderAsync(p, user, isPleroma, accounts, notes, emojiUrls))
|
||||||
{
|
.AwaitAllAsync();
|
||||||
Name = $":{e.Name}{(e.Host != null ? "@" + e.Host : "")}:",
|
|
||||||
Url = e.GetAccessUrl(instance.Value)
|
|
||||||
})
|
|
||||||
.ToArrayAsync()
|
|
||||||
.ContinueWithResult(res => res.DistinctBy(e => e.Name)
|
|
||||||
.ToDictionary(e => e.Name, e => e.Url));
|
|
||||||
|
|
||||||
return await notificationList
|
return res;
|
||||||
.Select(p => RenderAsync(p, user, isPleroma, accounts, notes, emojiUrls))
|
|
||||||
.AwaitAllAsync();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue