A validator that failed the self-check of an address no longer gets that address
again in the current round (ClaimNextQueued skips it); the validator itself stays
in service and takes all other addresses. The verdict fail is set when the number
of failed self-checks of an address reaches settings.self_check_max_attempts
(1..50, default 5, independent of the number of validators); max_retries and
retry_count are no longer used for self-check. If every working validator has
already failed the address, a new round starts and the exclusions lapse.
Migration 0012: ip_self_check_failures (permanent history per registry address),
ip_queue.sc_failures and sc_round_start_cycle (cycle_id is used instead of
attempt_number, which restarts when a queue row is recreated), the setting.
db.FailSelfCheck does it in one transaction; re-submission starts a new series.
API: self_check_max_attempts in GET/PUT /admin/config/orchestrator,
self_check_failed_on in /admin/ips/{ip} and /admin/registry/{ip}. Dashboard: the
field on /settings and the line "Self-check не прошёл на: ..." on the address
pages. Docs, plan and summary in docs/changes/.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
75 lines
3.0 KiB
HTML
75 lines
3.0 KiB
HTML
{{define "ip_detail_page"}}
|
||
<!doctype html>
|
||
<html lang="ru">
|
||
<head>{{template "html_head" .}}</head>
|
||
<body>
|
||
<div class="bg-grid"></div>
|
||
<input type="checkbox" id="nav-toggle" class="nav-toggle">
|
||
<div class="shell">
|
||
{{template "sidebar_nav" .}}
|
||
<div>
|
||
{{template "topbar_mobile" .}}
|
||
<main class="main">
|
||
<div id="error-banner">{{template "banner_inner" .Banner}}</div>
|
||
{{template "ip_detail_content" .}}
|
||
</main>
|
||
</div>
|
||
</div>
|
||
</body>
|
||
</html>
|
||
{{end}}
|
||
|
||
{{define "ip_detail_content"}}
|
||
<p><a href="/ips">← К очереди</a></p>
|
||
{{$b := ipBadge .Detail.IP.State .Detail.IP.OverallResult .Detail.IP.FIPAssociatedAt 0}}
|
||
<div class="topbar">
|
||
<h1 class="mono" style="display:flex;align-items:center;gap:10px">{{.Detail.IP.IPAddress}} <span class="pill {{$b.Class}}">{{$b.Label}}</span></h1>
|
||
</div>
|
||
<p class="muted"><a href="/registry/{{.Detail.IP.IPAddress}}">Полная история проверок этого адреса за всё время →</a></p>
|
||
<p class="muted">
|
||
попытка {{.Detail.IP.AttemptNumber}} (повторов: {{.Detail.IP.RetryCount}})
|
||
· валидатор {{deref .Detail.IP.OwnerValidatorID}}
|
||
</p>
|
||
<p class="muted">
|
||
создан: {{fmtTime .Detail.IP.CreatedAt}} · назначен: {{fmtTime .Detail.IP.AssignedAt}} ·
|
||
агрегирован: {{fmtTime .Detail.IP.AggregatedAt}} · FIP освобождён: {{fmtTime .Detail.IP.FIPReleasedAt}}
|
||
</p>
|
||
{{if .Detail.SelfCheckFailedOn}}<p class="muted">Self-check не прошёл на: {{join .Detail.SelfCheckFailedOn ", "}}</p>{{end}}
|
||
|
||
<h2 class="section-title">Проверки (попытка {{.Detail.IP.AttemptNumber}})</h2>
|
||
{{if .Detail.Checks}}
|
||
<div class="panel">
|
||
<div class="table-scroll">
|
||
<table>
|
||
<thead><tr><th>Источник</th><th>Тип</th><th>Цель</th><th>Успех</th><th>Задержка, мс</th><th>Время</th><th>Детали</th></tr></thead>
|
||
<tbody>
|
||
{{range .Detail.Checks}}
|
||
<tr>
|
||
<td data-label="Источник">{{.Source}}</td><td data-label="Тип">{{.CheckType}}</td><td class="addr" data-label="Цель">{{.Target}}</td>
|
||
<td data-label="Успех">{{if .Success}}<span class="pill pill-success">ok</span>{{else}}<span class="pill pill-danger">fail</span>{{end}}</td>
|
||
<td class="num" data-label="Задержка, мс">{{.LatencyMS}}</td><td class="num" data-label="Время">{{fmtTime .CheckedAt}}</td><td data-label="Детали">{{.Detail}}</td>
|
||
</tr>
|
||
{{end}}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
{{else}}<p class="muted">Проверок пока нет.</p>{{end}}
|
||
|
||
<h2 class="section-title">События</h2>
|
||
{{if .Detail.Events}}
|
||
<div class="panel">
|
||
<div class="table-scroll">
|
||
<table>
|
||
<thead><tr><th>Время</th><th>Тип</th><th>Источник</th><th>Данные</th></tr></thead>
|
||
<tbody>
|
||
{{range .Detail.Events}}
|
||
<tr><td class="num" data-label="Время">{{fmtTime .OccurredAt}}</td><td data-label="Тип">{{.EventType}}</td><td data-label="Источник">{{.SourceType}} {{.SourceID}}</td><td data-label="Данные">{{.Payload}}</td></tr>
|
||
{{end}}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
{{else}}<p class="muted">Событий нет.</p>{{end}}
|
||
{{end}}
|