Retry a failed self-check on another validator; add the self-check failure ceiling

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>
This commit is contained in:
ayurishchevandClaude Sonnet 5.5 committed 2026-10-04 09:50:12 +03:00
1 parent b7669c9e41
commit e95b5eb7d5
34 files changed
+1092 -82

No files matched your search

+28 -7
View File
@@ -198,8 +198,13 @@ self-check способом `control_api` (`self_check.methods` в
```
Ответ: `{"ok": true}`. При `success: false` control-api сам решает —
повторить попытку назначения FIP или пометить IP как `failed` (после
исчерпания `orchestrator.max_self_check_retries`).
вернуть адрес в очередь или пометить IP как `failed`. Сбой записывается в
историю адреса; повтор **не отдаётся этому валидатору** (он остаётся в
работе и берёт остальные адреса). Итог `fail` ставится, когда число
проваленных self-check у адреса достигло потолка `self_check_max_attempts`
(по умолчанию 5, см. [«Настройки оркестратора»](#настройки-оркестратора-apiv1adminconfigorchestrator));
`orchestrator.max_self_check_retries` не используется. Сбой привязки FIP и
истечение лизинга идут по `max_retries`, как раньше.
### `POST /api/v1/agents/{id}/events`
@@ -415,10 +420,14 @@ IP на данном проходе". До этого момента control-api
{
"ip": { "ID": 42, "IPAddress": "203.0.113.10", "State": "done", "OverallResult": "pass", "...": "..." },
"checks": [ {"Source": "egress", "CheckType": "https", "Target": "https://github.com", "Success": true, "...": "..."} ],
"events": [ {"EventType": "fip_associated", "OccurredAt": "...", "...": "..."} ]
"events": [ {"EventType": "fip_associated", "OccurredAt": "...", "...": "..."} ],
"self_check_failed_on": ["vkiplab-v17"]
}
```
`self_check_failed_on` — валидаторы, у которых self-check на этом адресе не
прошёл в текущем запуске (по алфавиту; `[]`, если сбоев не было).
> Обратите внимание: вложенные объекты `ip`/`checks`/`events` сериализуются
> без переопределения имён полей (используются имена Go-структур, например
> `IPAddress`, `State`, `Success`) — в отличие от методов для
@@ -722,10 +731,14 @@ curl -s -X POST http://<control-api>:8080/api/v1/admin/auto-cycle/stop
"checks": [
{"CycleID": 4, "Source": "egress", "CheckType": "https", "Success": true, "...": "..."},
{"CycleID": 3, "Source": "egress", "CheckType": "https", "Success": false, "...": "..."}
]
],
"self_check_failed_on": ["vkiplab-v17"]
}
```
`self_check_failed_on` — валидаторы, у которых self-check на этом адресе не
прошёл, по всем запускам (по алфавиту; `[]`, если сбоев не было).
`404`, если адрес никогда не ставился на проверку.
**Глубина хранения.** Сколько последних циклов на адрес хранится в
@@ -797,7 +810,7 @@ curl -s -X POST "$BASE/api/v1/admin/ips/clear"
### Настройки оркестратора: `/api/v1/admin/config/orchestrator`
Два параметра:
Три параметра:
- `fip_settle_seconds` — пауза между привязкой Floating IP к валидатору и
моментом, когда self-check по этому адресу становится доступен агенту
@@ -811,11 +824,19 @@ curl -s -X POST "$BASE/api/v1/admin/ips/clear"
на адрес в реестре (`GET /api/v1/admin/registry/{ip}`, см.
[«Реестр адресов»](#реестр-адресов-и-история-проверок)). `0` — без
ограничения (поведение по умолчанию).
- `self_check_max_attempts` — потолок провалов self-check на один адрес
(1…50, по умолчанию 5). Когда у адреса провалено столько self-check,
он получает итог `fail`. Не зависит от числа валидаторов. Валидатор,
проваливший self-check на адресе, этому адресу больше не выдаётся (на
остальные адреса это не влияет); если все рабочие валидаторы уже
провалили адрес, исключения сбрасываются и повторы продолжаются до
потолка. Значение действует на следующих повторах без перезапуска.
В `PUT` поле необязательно: если не передано, не меняется.
| Метод | Путь | Тело | Успех | Ошибки |
|---|---|---|---|---|
| GET | `/api/v1/admin/config/orchestrator` | — | `{"fip_settle_seconds":N,"history_retention_cycles":M}` | |
| PUT | `/api/v1/admin/config/orchestrator` | `{"fip_settle_seconds":N,"history_retention_cycles":M}` | `200` | `400`, если `N < 0` или `M < 0`, или если `fip_settle_seconds + self_check_timeout_seconds >= lease_ttl_seconds` (пауза не должна съедать весь лизинг адреса — иначе self-check не успеет пройти до истечения `lease_ttl_seconds`, и адрес будет вечно возвращаться в очередь) |
| GET | `/api/v1/admin/config/orchestrator` | — | `{"fip_settle_seconds":N,"history_retention_cycles":M,"self_check_max_attempts":K}` | |
| PUT | `/api/v1/admin/config/orchestrator` | `{"fip_settle_seconds":N,"history_retention_cycles":M,"self_check_max_attempts":K}` | `200` | `400`, если `N < 0`, `M < 0` или `K` вне 1…50, или если `fip_settle_seconds + self_check_timeout_seconds >= lease_ttl_seconds` (пауза не должна съедать весь лизинг адреса — иначе self-check не успеет пройти до истечения `lease_ttl_seconds`, и адрес будет вечно возвращаться в очередь) |
Как и остальные разделы этой группы, YAML-поле `orchestrator.
fip_settle_seconds` в `control-api.yaml` — только одноразовый bootstrap