游标分页优化
This commit is contained in:
1 parent
f5db2f6e77
commit
0a0713e65b
17 files changed
+448
-156
No files matched your search
@@ -113,15 +113,17 @@ public sealed partial class AppUpdatesController(AppDbContext db) : ControllerBa
|
||||
|
||||
[Authorize(Roles = SystemRoles.SuperAdmin)]
|
||||
[HttpGet("releases")]
|
||||
public async Task<ActionResult<PagedResult<AppUpdateReleaseItem>>> GetReleases(
|
||||
[FromQuery] int page = 1,
|
||||
public async Task<ActionResult<CursorPagedResult<AppUpdateReleaseItem>>> GetReleases(
|
||||
[FromQuery] string? cursor = null,
|
||||
[FromQuery] int pageSize = 20,
|
||||
[FromQuery] string? platform = null,
|
||||
[FromQuery] string? channel = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (page < 1 || pageSize is < 1 or > 100)
|
||||
return ValidationProblem("页码必须大于零,每页数量必须在 1 到 100 之间。");
|
||||
if (pageSize is < 1 or > 100)
|
||||
return ValidationProblem("每批数量必须在 1 到 100 之间。");
|
||||
if (!CursorToken.TryDecode<ReleaseCursor>(cursor, out var after))
|
||||
return BadRequest("更新包游标无效。");
|
||||
|
||||
var query = db.AppUpdateReleases.AsNoTracking().AsQueryable();
|
||||
if (!string.IsNullOrWhiteSpace(platform))
|
||||
@@ -137,11 +139,21 @@ public sealed partial class AppUpdatesController(AppDbContext db) : ControllerBa
|
||||
query = query.Where(x => x.Channel == parsedChannel);
|
||||
}
|
||||
|
||||
var total = await query.CountAsync(cancellationToken);
|
||||
var rows = await query
|
||||
if (after is not null)
|
||||
{
|
||||
query = query.Where(x => (x.PublishedAt ?? x.CreatedAt) < after.SortAt ||
|
||||
(x.PublishedAt ?? x.CreatedAt) == after.SortAt && x.Id.CompareTo(after.Id) < 0);
|
||||
}
|
||||
var keys = await query
|
||||
.OrderByDescending(x => x.PublishedAt ?? x.CreatedAt)
|
||||
.Skip((page - 1) * pageSize)
|
||||
.Take(pageSize)
|
||||
.ThenByDescending(x => x.Id)
|
||||
.Take(pageSize + 1)
|
||||
.Select(x => new { x.Id, SortAt = x.PublishedAt ?? x.CreatedAt })
|
||||
.ToArrayAsync(cancellationToken);
|
||||
var hasMore = keys.Length > pageSize;
|
||||
var pageIds = keys.Take(pageSize).Select(x => x.Id).ToArray();
|
||||
var rows = await query.WhereIn(pageIds, x => x.Id)
|
||||
.OrderByDescending(x => x.PublishedAt ?? x.CreatedAt).ThenByDescending(x => x.Id)
|
||||
.Select(x => new AppUpdateReleaseItem(
|
||||
x.Id,
|
||||
x.Platform,
|
||||
@@ -158,13 +170,16 @@ public sealed partial class AppUpdatesController(AppDbContext db) : ControllerBa
|
||||
x.PublishedByUserName,
|
||||
x.PublishedAt))
|
||||
.ToArrayAsync(cancellationToken);
|
||||
return Ok(new PagedResult<AppUpdateReleaseItem>(
|
||||
var last = keys.Take(pageSize).LastOrDefault();
|
||||
return Ok(new CursorPagedResult<AppUpdateReleaseItem>(
|
||||
rows,
|
||||
total,
|
||||
page,
|
||||
hasMore && last is not null ? CursorToken.Encode(new ReleaseCursor(last.SortAt, last.Id)) : null,
|
||||
hasMore,
|
||||
pageSize));
|
||||
}
|
||||
|
||||
private sealed record ReleaseCursor(DateTime SortAt, Guid Id);
|
||||
|
||||
[Authorize(Roles = SystemRoles.SuperAdmin)]
|
||||
[Consumes("multipart/form-data")]
|
||||
[RequestSizeLimit(MaximumBundleBytes + 1024 * 1024)]
|
||||
|
||||
Reference in new issue
Block a user