207 lines
No EOL
7 KiB
Text
207 lines
No EOL
7 KiB
Text
@page "/queue/{queue?}/{pagination:int?}/{status?}"
|
||
@inject QueueService QueueSvc
|
||
@using Iceshrimp.Backend.Core.Database.Tables
|
||
@using Iceshrimp.Backend.Core.Extensions
|
||
@using Iceshrimp.Backend.Core.Services
|
||
@model QueueModel
|
||
|
||
@{
|
||
ViewData["title"] = $"Queue dashboard - {Model.InstanceName}";
|
||
}
|
||
|
||
@section head {
|
||
<link rel="stylesheet" href="~/css/queue.css"/>
|
||
}
|
||
|
||
@section scripts {
|
||
<script src="~/js/queue.js"></script>
|
||
@if (Model.Queue == null)
|
||
{
|
||
<script src="~/js/queue-index.js"></script>
|
||
}
|
||
}
|
||
|
||
<h1>Queue Dashboard</h1>
|
||
<button role="link" data-target="/queue" onclick="navigate(event)">overview</button>
|
||
@foreach (var queue in QueueSvc.QueueNames)
|
||
{
|
||
<button role="link" data-target="/queue/@queue" onclick="navigate(event)">@queue</button>
|
||
}
|
||
<br/>
|
||
|
||
@if (Model.Queue == null)
|
||
{
|
||
<p>Please pick a queue.</p>
|
||
|
||
<form onsubmit="return lookupJob(event)">
|
||
<input type="text" id="lookup" placeholder="Lookup job by id" minlength="36" maxlength="36" class="inline"/>
|
||
<button type="submit">Submit</button>
|
||
</form>
|
||
|
||
<h3>Queue status — <span id="update-status" class="status-delayed">Connecting...</span></h3>
|
||
<table class="auto-table" id="queue-status">
|
||
<thead>
|
||
<th>Name</th>
|
||
@foreach (var status in Enum.GetValues<Job.JobStatus>())
|
||
{
|
||
<th class="justify-right">@Enum.GetName(status)</th>
|
||
}
|
||
</thead>
|
||
<tbody>
|
||
@foreach (var queue in Model.QueueStatuses ?? throw new Exception("Model.QueueStatuses must not be null here"))
|
||
{
|
||
<tr>
|
||
<td>@queue.Name</td>
|
||
@foreach (var status in Enum.GetValues<Job.JobStatus>())
|
||
{
|
||
<td class="status-@Enum.GetName(status)!.ToLowerInvariant() justify-right">@queue.JobCounts[status]</td>
|
||
}
|
||
</tr>
|
||
}
|
||
</tbody>
|
||
</table>
|
||
|
||
<h3>Recent jobs</h3>
|
||
<table class="auto-table" id="recent-jobs">
|
||
<thead>
|
||
<th class="width0">ID</th>
|
||
<th>Queue</th>
|
||
<th>Status</th>
|
||
<th>Actions</th>
|
||
</thead>
|
||
<tbody>
|
||
@foreach (var job in Model.Jobs)
|
||
{
|
||
await RenderJob(job, true);
|
||
}
|
||
</tbody>
|
||
</table>
|
||
|
||
var last = Model.Jobs.FirstOrDefault();
|
||
var lastUpdated = last != null ? new DateTimeOffset(last.LastUpdatedAt).ToUnixTimeMilliseconds() : 0;
|
||
|
||
<div class="display-none" id="last-updated">@lastUpdated</div>
|
||
}
|
||
|
||
else
|
||
{
|
||
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>
|
||
}
|
||
else
|
||
{
|
||
<p>Listing @Model.TotalCount <span class="status-@Model.Filter.Value.ToString().ToLowerInvariant()">@Model.Filter.Value.ToString().ToLowerInvariant()</span> <b>@Model.Queue</b> jobs.</p>
|
||
}
|
||
|
||
<table class="auto-table">
|
||
<thead>
|
||
<th class="width0">ID</th>
|
||
<th>Status</th>
|
||
<th>Actions</th>
|
||
</thead>
|
||
<tbody>
|
||
@foreach (var job in Model.Jobs)
|
||
{
|
||
await RenderJob(job);
|
||
}
|
||
</tbody>
|
||
</table>
|
||
|
||
<div class="flex">
|
||
@if (Model.PrevPage != null)
|
||
{
|
||
if (Model.Filter.HasValue)
|
||
{
|
||
<button role="link" data-target="/queue/@Model.Queue/@Model.PrevPage/@Model.Filter.Value.ToString().ToLowerInvariant()" onclick="navigate">❮ Previous page</button>
|
||
}
|
||
else
|
||
{
|
||
<button role="link" data-target="/queue/@Model.Queue/@Model.PrevPage" onclick="navigate(event)">❮ Previous page</button>
|
||
}
|
||
}
|
||
else
|
||
{
|
||
<button disabled>❮ Previous page</button>
|
||
}
|
||
|
||
@if (Model.NextPage != null)
|
||
{
|
||
if (Model.Filter.HasValue)
|
||
{
|
||
<button role="link" data-target="/queue/@Model.Queue/@Model.NextPage/@Model.Filter.Value.ToString().ToLowerInvariant()" onclick="navigate(event)">Next page ❯</button>
|
||
}
|
||
else
|
||
{
|
||
<button role="link" data-target="/queue/@Model.Queue/@Model.NextPage" onclick="navigate(event)">Next page ❯</button>
|
||
}
|
||
}
|
||
else
|
||
{
|
||
<button disabled>Next page ❯</button>
|
||
}
|
||
|
||
<select onchange="filter('@Model.Queue')" id="filter" class="inline-flex">
|
||
@if (Model.Filter == null)
|
||
{
|
||
<option value="all" selected>All</option>
|
||
}
|
||
else
|
||
{
|
||
<option value="all">All</option>
|
||
}
|
||
@foreach (var status in Enum.GetValues<Job.JobStatus>())
|
||
{
|
||
if (Model.Filter.Equals(status))
|
||
{
|
||
<option value="@status.ToString().ToLowerInvariant()" selected>@status.ToString()</option>
|
||
}
|
||
else
|
||
{
|
||
<option value="@status.ToString().ToLowerInvariant()">@status.ToString()</option>
|
||
}
|
||
}
|
||
</select>
|
||
|
||
<form onsubmit="return lookupJob(event)" class="inline-flex flex-grow">
|
||
<input type="text" id="lookup" placeholder="Lookup job by id" minlength="36" maxlength="36" class="flex-grow"/>
|
||
</form>
|
||
</div>
|
||
}
|
||
|
||
@{
|
||
async Task RenderJob(Job job, bool withQueue = false)
|
||
{
|
||
var id = job.Id.ToStringLower();
|
||
var additional = job.Status switch
|
||
{
|
||
Job.JobStatus.Queued => $"for {job.QueueDuration.ToDurationDisplayString()}",
|
||
Job.JobStatus.Running => $"for {job.Duration.ToDurationDisplayString()}",
|
||
Job.JobStatus.Delayed => $"until {job.DelayedUntil?.ToLocalTime().ToDisplayStringTz() ?? "<unknown>"}",
|
||
Job.JobStatus.Completed => $"at {job.FinishedAt?.ToLocalTime().ToDisplayStringTz() ?? "<unknown>"}",
|
||
Job.JobStatus.Failed => $"at {job.FinishedAt?.ToLocalTime().ToDisplayStringTz() ?? "<unknown>"}",
|
||
_ => throw new ArgumentOutOfRangeException()
|
||
};
|
||
|
||
var classes = Model.Last != null && new DateTimeOffset(job.LastUpdatedAt).ToUnixTimeMilliseconds() > Model.Last
|
||
? "new-item"
|
||
: "";
|
||
|
||
<tr class="@classes">
|
||
@if (withQueue)
|
||
{
|
||
<td class="uuid-abbrev">@id[..8]...@id[24..]</td>
|
||
<td>@job.Queue</td>
|
||
}
|
||
else
|
||
{
|
||
<td class="uuid">@id</td>
|
||
}
|
||
<td class="status-@job.Status.ToString().ToLowerInvariant()">
|
||
<b>@job.Status</b> <small>@additional</small>
|
||
<td>
|
||
<a href="/queue/job/@id">View details</a>
|
||
</td>
|
||
</tr>
|
||
}
|
||
} |