< Summary

Information
Class: AspNetCoreGeneratedDocument.Areas_Studio2_Views_HangfireQueue_Index
Assembly: OzonOrdersWeb
File(s): /home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/Studio2/Views/HangfireQueue/Index.cshtml
Line coverage
0%
Covered lines: 0
Uncovered lines: 30
Coverable lines: 30
Total lines: 154
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 48
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
ExecuteAsync()0%1332360%
TabHint()0%7280%
<ExecuteAsync()0%2040%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/Studio2/Views/HangfireQueue/Index.cshtml

#LineLine coverage
 1@model OzonOrdersWeb.Areas.Studio2.ViewModels.HangfireQueue.HangfireJobsViewModel
 2@{
 03    ViewData["Title"] = "Статистика Hangfire";
 04    Layout = "~/Views/Shared/_Layout.cshtml";
 05    var tab = Model.ActiveTab ?? "enqueued";
 06    string TabHint() => tab switch
 07    {
 08        "processing" => "Задания, которые воркер выполняет прямо сейчас. «Остановить» снимает job с воркера (удаление из
 09        "succeeded" => "Последние успешно завершённые задачи: время, длительность и текстовый результат. Клик по результ
 010        "deleted" => "Задачи, удалённые вручную или системой, с причиной и аргументами вызова.",
 011        "statistics" => "График длительности succeeded-задач по времени завершения. Цвет — тип метода. Колёсико — zoom п
 012        _ => "Задачи в очереди ожидают свободного воркера. Удаление снимает job до начала выполнения."
 013    };
 14}
 15
 16<link rel="stylesheet" href="~/css/Studio2/HangfireQueue/hangfire-queue-index.css" asp-append-version="true"/>
 17<link rel="stylesheet" href="~/css/Studio2/HangfireQueue/hangfire-jobs-partials.css" asp-append-version="true"/>
 18
 019@await Html.PartialAsync("_BsxGridShell")
 20
 21<div class="container-fluid py-3 bsx-surface hq-page">
 022    @Html.AntiForgeryToken()
 23
 24    <div class="app-section-hero app-section-hero--import d-flex flex-wrap justify-content-between align-items-start gap
 25        <div>
 26            <h1><i class="fas fa-server me-2 text-primary"></i>Статистика Hangfire</h1>
 27            <div class="subtitle">Мониторинг очередей <code>main</code> и <code>ozon-webhook</code></div>
 28            <div class="subtitle-help">
 29                Упрощённый UI поверх Hangfire storage: что в очереди, что выполняется, что завершилось.
 30                Для retry, recurring jobs и полного stack trace — <strong>Hangfire Dashboard</strong>.
 31                Очередь <code>default</code> не обрабатывается воркерами (см. repair при старте приложения).
 32            </div>
 33            <div class="app-section-hero__quick-links">
 34                <a href="/hangfire" target="_blank" rel="noopener"><i class="fas fa-external-link-alt"></i>Hangfire Dash
 35                <a asp-area="Studio2" asp-controller="Job" asp-action="Index" asp-route-pageTab="queue"><i class="fas fa
 36                <a asp-area="Studio2" asp-controller="JobLogs" asp-action="Index"><i class="fas fa-list-alt"></i>Логи за
 37            </div>
 38        </div>
 039        <div class="bsx-dir-stats"><span class="bsx-dir-stat">Очередь <b>@(Model.QueueName)</b></span></div>
 40    </div>
 41
 42    <div class="hq-intro">
 43        <i class="fas fa-circle-info"></i>
 44        <div class="hq-intro-text">
 45            <strong>Очереди:</strong> <code>main</code> — загрузка заказов, BitrixStock, транзакции, статусы;
 46            <code>ozon-webhook</code> — входящие webhook Ozon. Переключите очередь и вкладку — данные обновятся с сервер
 47        </div>
 48    </div>
 49
 50    <div class="hq-workflow">
 51        <div class="hq-workflow-step"><span class="num">1</span>Выберите очередь</div>
 52        <div class="hq-workflow-step"><span class="num">2</span>Вкладка: очередь / выполнение</div>
 53        <div class="hq-workflow-step"><span class="num">3</span>Детали в модалке</div>
 54        <div class="hq-workflow-step"><span class="num">4</span>При необходимости — /hangfire</div>
 55    </div>
 56
 57    <div class="hq-card">
 58        <div class="hq-card-body pb-2">
 59            <div class="hq-queue-selector">
 60                <form method="get" class="row g-2 align-items-end">
 61                    <div class="col-sm-5 col-md-4">
 62                        <label for="queueName" class="form-label small fw-semibold text-secondary mb-1">Очередь Hangfire
 63                        <select name="queueName" id="queueName" class="form-select form-select-sm custom-select-init">
 064                            @foreach (var queue in Model.AvailableQueues)
 65                            {
 066                                <option value="@queue" selected="@(queue == Model.QueueName)">@queue</option>
 67                            }
 68                        </select>
 69                        <div class="hq-field-hint">Воркеры слушают main и ozon-webhook</div>
 70                    </div>
 71                    <div class="col-sm-4 col-md-3">
 72                        <input type="hidden" name="tab" value="@tab"/>
 73                        <button type="submit" class="btn btn-primary btn-sm w-100">
 74                            <i class="fas fa-sync-alt me-1"></i>Обновить
 75                        </button>
 76                    </div>
 77                </form>
 78                <div class="hq-queue-legend mt-2">
 79                    <span><code>main</code> — основные фоновые задачи</span>
 80                    <span><code>ozon-webhook</code> — webhook Ozon</span>
 81                </div>
 82            </div>
 83        </div>
 84
 085        <div class="hq-tab-hint">@TabHint()</div>
 86
 87        <div class="hq-tabs-wrap">
 88            <ul class="nav nav-tabs">
 89                <li class="nav-item">
 90                    <a class="nav-link @(tab == "enqueued" ? "active" : "")"
 91                       href="@Url.Action("Index", new { queueName = Model.QueueName, tab = "enqueued" })">
 92                        <i class="fas fa-clock me-1"></i>В очереди
 093                        <span class="hq-job-count-badge">@Model.EnqueuedJobs.Count</span>
 94                    </a>
 95                </li>
 96                <li class="nav-item">
 97                    <a class="nav-link @(tab == "processing" ? "active" : "")"
 98                       href="@Url.Action("Index", new { queueName = Model.QueueName, tab = "processing" })">
 99                        <i class="fas fa-sync-alt me-1"></i>Выполняются
 0100                        <span class="hq-job-count-badge">@Model.ProcessingJobs.Count</span>
 101                    </a>
 102                </li>
 103                <li class="nav-item">
 104                    <a class="nav-link @(tab == "succeeded" ? "active" : "")"
 105                       href="@Url.Action("Index", new { queueName = Model.QueueName, tab = "succeeded" })">
 106                        <i class="fas fa-check-circle me-1"></i>Выполненные
 0107                        <span class="hq-job-count-badge">@Model.SucceededJobs.Count</span>
 108                    </a>
 109                </li>
 110                <li class="nav-item">
 111                    <a class="nav-link @(tab == "deleted" ? "active" : "")"
 112                       href="@Url.Action("Index", new { queueName = Model.QueueName, tab = "deleted" })">
 113                        <i class="fas fa-trash me-1"></i>Удалённые
 0114                        <span class="hq-job-count-badge">@Model.DeletedJobs.Count</span>
 115                    </a>
 116                </li>
 117                <li class="nav-item">
 118                    <a class="nav-link @(tab == "statistics" ? "active" : "")"
 119                       href="@Url.Action("Index", new { queueName = Model.QueueName, tab = "statistics" })">
 120                        <i class="fas fa-chart-bar me-1"></i>Статистика
 121                    </a>
 122                </li>
 123            </ul>
 124
 125            <div class="hq-tab-content">
 0126                @if (tab == "enqueued")
 127                {
 0128                    @await Html.PartialAsync("_HangfireJobsGrid", ("enqueued", Model.EnqueuedJobs))
 129                }
 0130                else if (tab == "processing")
 131                {
 0132                    @await Html.PartialAsync("_HangfireJobsGrid", ("processing", Model.ProcessingJobs))
 133                }
 0134                else if (tab == "succeeded")
 135                {
 0136                    @await Html.PartialAsync("_HangfireJobsGrid", ("succeeded", Model.SucceededJobs))
 137                }
 0138                else if (tab == "deleted")
 139                {
 0140                    @await Html.PartialAsync("_HangfireJobsGrid", ("deleted", Model.DeletedJobs))
 141                }
 0142                else if (tab == "statistics")
 143                {
 144                    <partial name="_StatisticsPartial" model="Model.SucceededJobs"/>
 145                }
 146            </div>
 147        </div>
 148    </div>
 149</div>
 150
 151@section Scripts {
 152<script src="~/js/Studio2/Grid/bsx-directory.js" asp-append-version="true"></script>
 153<script src="~/js/Studio2/HangfireQueue/hangfire-jobs-grid.js" asp-append-version="true"></script>
 154}