[backend/masto-client] Fix notification pagination (ISH-204)
This commit is contained in:
parent
174064416a
commit
715f47cafc
6 changed files with 6131 additions and 1 deletions
|
@ -50,7 +50,7 @@ public class NotificationController(DatabaseContext db, NotificationRenderer not
|
|||
.EnsureNoteVisibilityFor(p => p.Note, user)
|
||||
.FilterBlocked(p => p.Notifier, user)
|
||||
.FilterBlocked(p => p.Note, user)
|
||||
.Paginate(query, ControllerContext)
|
||||
.Paginate(p => p.MastoId, query, ControllerContext)
|
||||
.PrecomputeNoteVisibilities(user)
|
||||
.RenderAllForMastodonAsync(notificationRenderer, user);
|
||||
|
||||
|
|
6030
Iceshrimp.Backend/Core/Database/Migrations/20240326191000_AddNotificationMastoIdIndex.Designer.cs
generated
Normal file
6030
Iceshrimp.Backend/Core/Database/Migrations/20240326191000_AddNotificationMastoIdIndex.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,27 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Iceshrimp.Backend.Core.Database.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddNotificationMastoIdIndex : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_notification_masto_id",
|
||||
table: "notification",
|
||||
column: "masto_id");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_notification_masto_id",
|
||||
table: "notification");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2926,6 +2926,8 @@ namespace Iceshrimp.Backend.Core.Database.Migrations
|
|||
|
||||
b.HasIndex("IsRead");
|
||||
|
||||
b.HasIndex("MastoId");
|
||||
|
||||
b.HasIndex("NoteId");
|
||||
|
||||
b.HasIndex("NotifieeId");
|
||||
|
|
|
@ -12,6 +12,7 @@ namespace Iceshrimp.Backend.Core.Database.Tables;
|
|||
[Index("NotifieeId")]
|
||||
[Index("CreatedAt")]
|
||||
[Index("AppAccessTokenId")]
|
||||
[Index("MastoId")]
|
||||
public class Notification : IEntity
|
||||
{
|
||||
[PgName("notification_type_enum")]
|
||||
|
|
|
@ -85,6 +85,60 @@ public static class QueryableExtensions
|
|||
return query.Take(Math.Min(pq.Limit ?? defaultLimit, maxLimit));
|
||||
}
|
||||
|
||||
public static IQueryable<T> Paginate<T>(
|
||||
this IQueryable<T> query,
|
||||
Expression<Func<T, long>> predicate,
|
||||
MastodonPaginationQuery pq,
|
||||
int defaultLimit,
|
||||
int maxLimit
|
||||
) where T : IEntity
|
||||
{
|
||||
if (pq.Limit is < 1)
|
||||
throw GracefulException.BadRequest("Limit cannot be less than 1");
|
||||
|
||||
if (pq is { SinceId: not null, MinId: not null })
|
||||
throw GracefulException.BadRequest("Can't use sinceId and minId params simultaneously");
|
||||
|
||||
long? sinceId = null;
|
||||
long? minId = null;
|
||||
long? maxId = null;
|
||||
|
||||
if (pq.SinceId != null)
|
||||
{
|
||||
if (!long.TryParse(pq.SinceId, out var res))
|
||||
throw GracefulException.BadRequest("sinceId must be an integer");
|
||||
sinceId = res;
|
||||
}
|
||||
|
||||
if (pq.MinId != null)
|
||||
{
|
||||
if (!long.TryParse(pq.MinId, out var res))
|
||||
throw GracefulException.BadRequest("minId must be an integer");
|
||||
minId = res;
|
||||
}
|
||||
|
||||
if (pq.MaxId != null)
|
||||
{
|
||||
if (!long.TryParse(pq.MaxId, out var res))
|
||||
throw GracefulException.BadRequest("maxId must be an integer");
|
||||
maxId = res;
|
||||
}
|
||||
|
||||
query = pq switch
|
||||
{
|
||||
{ SinceId: not null, MaxId: not null } => query.Where(predicate.Compose(id => id > sinceId && id < maxId))
|
||||
.OrderByDescending(predicate),
|
||||
{ MinId: not null, MaxId: not null } => query.Where(predicate.Compose(id => id > minId && id < maxId))
|
||||
.OrderBy(predicate),
|
||||
{ SinceId: not null } => query.Where(predicate.Compose(id => id > sinceId)).OrderByDescending(predicate),
|
||||
{ MinId: not null } => query.Where(predicate.Compose(id => id > minId)).OrderBy(predicate),
|
||||
{ MaxId: not null } => query.Where(predicate.Compose(id => id < maxId)).OrderByDescending(predicate),
|
||||
_ => query.OrderByDescending(predicate)
|
||||
};
|
||||
|
||||
return query.Take(Math.Min(pq.Limit ?? defaultLimit, maxLimit));
|
||||
}
|
||||
|
||||
public static IQueryable<T> Paginate<T>(
|
||||
this IQueryable<T> query,
|
||||
PaginationQuery pq,
|
||||
|
@ -140,6 +194,22 @@ public static class QueryableExtensions
|
|||
return Paginate(query, predicate, pq, filter.DefaultLimit, filter.MaxLimit);
|
||||
}
|
||||
|
||||
public static IQueryable<T> Paginate<T>(
|
||||
this IQueryable<T> query,
|
||||
Expression<Func<T, long>> predicate,
|
||||
MastodonPaginationQuery pq,
|
||||
ControllerContext context
|
||||
) where T : IEntity
|
||||
{
|
||||
var filter = context.ActionDescriptor.FilterDescriptors.Select(p => p.Filter)
|
||||
.OfType<LinkPaginationAttribute>()
|
||||
.FirstOrDefault();
|
||||
if (filter == null)
|
||||
throw new GracefulException("Route doesn't have a LinkPaginationAttribute");
|
||||
|
||||
return Paginate(query, predicate, pq, filter.DefaultLimit, filter.MaxLimit);
|
||||
}
|
||||
|
||||
public static IQueryable<T> Paginate<T>(
|
||||
this IQueryable<T> query,
|
||||
PaginationQuery pq,
|
||||
|
|
Loading…
Add table
Reference in a new issue