feature: Prometheus Metrics, Supervisor Dashboard, and Promotion Retry Job

This commit is contained in:
voltsrage
2026-06-27 13:29:04 +08:00
parent e22d33b654
commit 04bdb7e85c
31 changed files with 4482 additions and 259 deletions
@@ -0,0 +1,15 @@
/// <summary>
/// A single audit trail event for a digitization batch.
/// Includes the actor's username and full name for display
/// without requiring a separate user lookup.
/// </summary>
public record BatchEventResponse(
Guid Id,
Guid BatchId,
string EventType,
Guid ActorUserId,
string ActorUsername,
string ActorFullName,
DateTimeOffset OccurredAt,
string? MetadataJson
);
@@ -0,0 +1,15 @@
/// <summary>
/// Cursor-paginated result set. The cursor is the OccurredAt timestamp
/// of the last item in this page. Pass it as the "after" query parameter
/// to get the next page.
///
/// This uses the N+1 fetch pattern: fetch pageSize+1 rows, return pageSize,
/// and use the existence of the extra row to determine HasMore without
/// a separate COUNT query.
/// </summary>
public record CursorPagedResult<T>(
IReadOnlyList<T> Items,
int PageSize,
string? NextCursor,
bool HasMore
);
@@ -3,8 +3,28 @@
/// Returned by GET /api/v1/work-queue/overview.
/// </summary>
public record WorkQueueOverviewResponse(
/// <summary>
/// Count of batches per status. Key is the DB status string
/// (e.g. "UPLOADED", "IN_ENTRY", "PENDING_VERIFICATION").
/// All 8 statuses are always present, even if count is 0.
/// </summary>
Dictionary<string, int> StatusCounts,
/// <summary>
/// Average time in minutes that batches currently in PendingVerification
/// have been waiting. Zero if no batches are pending.
/// </summary>
double AverageTimeInQueueMinutes,
/// <summary>
/// Rejection rate as a decimal (0.0 to 1.0). Calculated as
/// rejections / (rejections + verifications) over the last 24 hours.
/// </summary>
double RejectRate,
/// <summary>
/// Age in minutes of the oldest batch in PendingVerification status.
/// Zero if no batches are pending.
/// </summary>
double OldestPendingVerificationMinutes
);
);