[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)
|
.EnsureNoteVisibilityFor(p => p.Note, user)
|
||||||
.FilterBlocked(p => p.Notifier, user)
|
.FilterBlocked(p => p.Notifier, user)
|
||||||
.FilterBlocked(p => p.Note, user)
|
.FilterBlocked(p => p.Note, user)
|
||||||
.Paginate(query, ControllerContext)
|
.Paginate(p => p.MastoId, query, ControllerContext)
|
||||||
.PrecomputeNoteVisibilities(user)
|
.PrecomputeNoteVisibilities(user)
|
||||||
.RenderAllForMastodonAsync(notificationRenderer, 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("IsRead");
|
||||||
|
|
||||||
|
b.HasIndex("MastoId");
|
||||||
|
|
||||||
b.HasIndex("NoteId");
|
b.HasIndex("NoteId");
|
||||||
|
|
||||||
b.HasIndex("NotifieeId");
|
b.HasIndex("NotifieeId");
|
||||||
|
|
|
@ -12,6 +12,7 @@ namespace Iceshrimp.Backend.Core.Database.Tables;
|
||||||
[Index("NotifieeId")]
|
[Index("NotifieeId")]
|
||||||
[Index("CreatedAt")]
|
[Index("CreatedAt")]
|
||||||
[Index("AppAccessTokenId")]
|
[Index("AppAccessTokenId")]
|
||||||
|
[Index("MastoId")]
|
||||||
public class Notification : IEntity
|
public class Notification : IEntity
|
||||||
{
|
{
|
||||||
[PgName("notification_type_enum")]
|
[PgName("notification_type_enum")]
|
||||||
|
|
|
@ -85,6 +85,60 @@ public static class QueryableExtensions
|
||||||
return query.Take(Math.Min(pq.Limit ?? defaultLimit, maxLimit));
|
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>(
|
public static IQueryable<T> Paginate<T>(
|
||||||
this IQueryable<T> query,
|
this IQueryable<T> query,
|
||||||
PaginationQuery pq,
|
PaginationQuery pq,
|
||||||
|
@ -140,6 +194,22 @@ public static class QueryableExtensions
|
||||||
return Paginate(query, predicate, pq, filter.DefaultLimit, filter.MaxLimit);
|
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>(
|
public static IQueryable<T> Paginate<T>(
|
||||||
this IQueryable<T> query,
|
this IQueryable<T> query,
|
||||||
PaginationQuery pq,
|
PaginationQuery pq,
|
||||||
|
|
Loading…
Add table
Reference in a new issue