[backend/razor] Indicate scheduled jobs in the queue dashboard

Calling both scheduled and delayed jobs delayed is confusing, even if there's no queue system-internal distinction.
This commit is contained in:
Laura Hausmann 2024-10-14 22:40:20 +02:00
parent 85d9bc597f
commit 4a3cf7c2d5
No known key found for this signature in database
GPG key ID: D044E84C5BE01605
4 changed files with 49 additions and 9 deletions

View file

@ -50,11 +50,26 @@
<tbody> <tbody>
@foreach (var queue in Model.QueueStatuses ?? throw new Exception("Model.QueueStatuses must not be null here")) @foreach (var queue in Model.QueueStatuses ?? throw new Exception("Model.QueueStatuses must not be null here"))
{ {
var isScheduled = QueueModel.ScheduledQueues.Contains(queue.Name);
var scheduled = isScheduled ? queue.JobCounts[Job.JobStatus.Delayed].ToString() : "-";
var delayed = !isScheduled ? queue.JobCounts[Job.JobStatus.Delayed].ToString() : "-";
<tr> <tr>
<td>@queue.Name</td> <td>@queue.Name</td>
@foreach (var status in Enum.GetValues<Job.JobStatus>()) @foreach (var status in Enum.GetValues<Job.JobStatus>())
{ {
<td class="status-@Enum.GetName(status)!.ToLowerInvariant() justify-right">@queue.JobCounts[status]</td> if (status == Job.JobStatus.Delayed)
{
<td class="status-delayed justify-right">@delayed</td>
}
else if (status == Job.JobStatus.Queued && isScheduled)
{
<td class="justify-right">(<span class="status-scheduled">@scheduled</span>) <span class="status-queued">@queue.JobCounts[status]</span></td>
}
else
{
<td class="status-@Enum.GetName(status)!.ToLowerInvariant() justify-right">@queue.JobCounts[status]</td>
}
} }
</tr> </tr>
} }
@ -85,14 +100,19 @@
else else
{ {
var delayedStr = QueueModel.ScheduledQueues.Contains(Model.Queue) ? "scheduled" : "delayed";
if (Model.Filter == null) if (Model.Filter == null)
{ {
<p>Listing @Model.TotalCount <b>@Model.Queue</b> jobs, out of which <span class="status-running">@Model.RunningCount</span> are <span class="status-running">running</span>, <span class="status-queued">@Model.QueuedCount</span> are <span class="status-queued">queued</span> and <span class="status-delayed">@Model.DelayedCount</span> are <span class="status-delayed">delayed</span>.</p> <p>Listing @Model.TotalCount <b>@Model.Queue</b> jobs, out of which <span class="status-running">@Model.RunningCount</span> are <span class="status-running">running</span>, <span class="status-queued">@Model.QueuedCount</span> are <span class="status-queued">queued</span> and <span class="status-delayed">@Model.DelayedCount</span> are <span class="status-@delayedStr">@delayedStr</span>.</p>
} }
else else
{ {
var filterStr = Model.Filter.Value == Job.JobStatus.Delayed && QueueModel.ScheduledQueues.Contains(Model.Queue)
? "scheduled"
: Model.Filter.Value.ToString().ToLowerInvariant();
<p> <p>
Listing @Model.TotalCount <span class="status-@Model.Filter.Value.ToString().ToLowerInvariant()">@Model.Filter.Value.ToString().ToLowerInvariant()</span> <b>@Model.Queue</b> jobs. Listing @Model.TotalCount <span class="status-@filterStr">@filterStr</span> <b>@Model.Queue</b> jobs.
@if (Model.Filter is Job.JobStatus.Failed) @if (Model.Filter is Job.JobStatus.Failed)
{ {
<span>Batch retry: <a class="fake-link" onclick="retryAllFailed('@Model.Queue')">all failed</a> / <a class="fake-link" onclick="retryAllOnPage('@Model.Queue')">all on this page</a></span> <span>Batch retry: <a class="fake-link" onclick="retryAllFailed('@Model.Queue')">all failed</a> / <a class="fake-link" onclick="retryAllOnPage('@Model.Queue')">all on this page</a></span>
@ -158,13 +178,17 @@ else
} }
@foreach (var status in Enum.GetValues<Job.JobStatus>()) @foreach (var status in Enum.GetValues<Job.JobStatus>())
{ {
var statusStr = status == Job.JobStatus.Delayed && QueueModel.ScheduledQueues.Contains(Model.Queue)
? "Scheduled"
: status.ToString();
if (Model.Filter.Equals(status)) if (Model.Filter.Equals(status))
{ {
<option value="@status.ToString().ToLowerInvariant()" selected>@status.ToString()</option> <option value="@status.ToString().ToLowerInvariant()" selected>@statusStr</option>
} }
else else
{ {
<option value="@status.ToString().ToLowerInvariant()">@status.ToString()</option> <option value="@status.ToString().ToLowerInvariant()">@statusStr</option>
} }
} }
</select> </select>
@ -181,6 +205,8 @@ else
var id = job.Id.ToStringLower(); var id = job.Id.ToStringLower();
var additional = job.Status switch var additional = job.Status switch
{ {
Job.JobStatus.Delayed when job.RetryCount is 0 => $"for {job.DelayedUntil?.ToLocalTime().ToDisplayStringTz() ?? "<unknown>"}",
// Separated for readability
Job.JobStatus.Queued => $"for {job.QueueDuration.ToDurationDisplayString()}", Job.JobStatus.Queued => $"for {job.QueueDuration.ToDurationDisplayString()}",
Job.JobStatus.Running => $"for {job.Duration.ToDurationDisplayString()}", Job.JobStatus.Running => $"for {job.Duration.ToDurationDisplayString()}",
Job.JobStatus.Delayed => $"until {job.DelayedUntil?.ToLocalTime().ToDisplayStringTz() ?? "<unknown>"}", Job.JobStatus.Delayed => $"until {job.DelayedUntil?.ToLocalTime().ToDisplayStringTz() ?? "<unknown>"}",
@ -193,6 +219,8 @@ else
? "new-item" ? "new-item"
: ""; : "";
var status = job is { Status: Job.JobStatus.Delayed, RetryCount: 0 } ? "Scheduled" : job.Status.ToString();
<tr class="@classes"> <tr class="@classes">
@if (withQueue) @if (withQueue)
{ {
@ -203,8 +231,8 @@ else
{ {
<td class="uuid">@id</td> <td class="uuid">@id</td>
} }
<td class="status-@job.Status.ToString().ToLowerInvariant()"> <td class="status-@status.ToLowerInvariant()">
<b>@job.Status</b> <small>@additional</small> <b>@status</b> <small>@additional</small>
<td> <td>
<a href="/queue/job/@id">View details</a> <a href="/queue/job/@id">View details</a>
</td> </td>

View file

@ -1,3 +1,4 @@
using System.Collections.Immutable;
using Iceshrimp.Backend.Core.Database; using Iceshrimp.Backend.Core.Database;
using Iceshrimp.Backend.Core.Database.Tables; using Iceshrimp.Backend.Core.Database.Tables;
using Iceshrimp.Backend.Core.Middleware; using Iceshrimp.Backend.Core.Middleware;
@ -23,6 +24,8 @@ public class QueueModel(DatabaseContext db, QueueService queueSvc, MetaService m
public long? Last; public long? Last;
public string InstanceName = "Iceshrimp.NET"; public string InstanceName = "Iceshrimp.NET";
public static readonly ImmutableArray<string> ScheduledQueues = ["background-task", "backfill"];
public async Task<IActionResult> OnGet( public async Task<IActionResult> OnGet(
[FromRoute] string? queue, [FromRoute(Name = "pagination")] int? page, [FromRoute] string? status [FromRoute] string? queue, [FromRoute(Name = "pagination")] int? page, [FromRoute] string? status
) )

View file

@ -35,8 +35,11 @@
<td>@Model.Job.Queue</td> <td>@Model.Job.Queue</td>
</tr> </tr>
<tr> <tr>
@{
var status = Model.Job is { Status: Job.JobStatus.Delayed, RetryCount: 0 } ? "Scheduled" : Model.Job.Status.ToString();
}
<td>Status</td> <td>Status</td>
<td class="status-@Model.Job.Status.ToString().ToLowerInvariant()">@Model.Job.Status</td> <td class="status-@status.ToLowerInvariant()">@status</td>
</tr> </tr>
@if (Model.Job.Status.Equals(Job.JobStatus.Failed)) @if (Model.Job.Status.Equals(Job.JobStatus.Failed))
{ {
@ -49,10 +52,11 @@
} }
else if (Model.Job.Status.Equals(Job.JobStatus.Delayed)) else if (Model.Job.Status.Equals(Job.JobStatus.Delayed))
{ {
var abandonName = Model.Job.RetryCount == 0 ? "Deschedule" : "Abandon";
<tr> <tr>
<td>Actions</td> <td>Actions</td>
<td> <td>
<a class="fake-link" onclick="abandon('@Model.Job.Id.ToStringLower()')">Abandon</a> <a class="fake-link" onclick="abandon('@Model.Job.Id.ToStringLower()')">@abandonName</a>
</td> </td>
</tr> </tr>
} }

View file

@ -1,6 +1,7 @@
:root { :root {
--queued-color: #9958FC; --queued-color: #9958FC;
--delayed-color: #FFCD59; --delayed-color: #FFCD59;
--scheduled-color: #FFE4A5;
--running-color: #59D5FF; --running-color: #59D5FF;
--completed-color: #92EF5F; --completed-color: #92EF5F;
--failed-color: #FF5151; --failed-color: #FF5151;
@ -14,6 +15,10 @@
color: var(--delayed-color); color: var(--delayed-color);
} }
.status-scheduled {
color: var(--scheduled-color);
}
.status-running { .status-running {
color: var(--running-color); color: var(--running-color);
} }