Show egress/ingress levels in the registry; freeze checks at the verdict
Registry: the "last result" column now also shows, per level (egress,
ingress), how many of the recorded checks of the latest cycle succeeded, split
by check family (tcp-22 and tcp-443 are both "tcp"). One grouped query per
chunk of addresses; new fields last_cycle_id, egress, ingress in
GET /admin/registry; the dashboard renders them under the verdict.
Verdict integrity (migration 0010):
- the prober is handed an address once per site and attempt, not on every
poll, so results are no longer overwritten by later probe rounds;
- UpsertCheckIfOpen refuses writes once the address is aggregating or has its
verdict, or for an older attempt; senders get {"ok":true,"ignored":N} and a
result_dropped event is recorded;
- the checking window counts from checking_started_at, not from assigned_at;
- checks.recorded_at (server clock) and checks.after_verdict (flag for rows
written after the verdict in existing data);
- the verdict rule is a pure function (computeVerdict) and the aggregated
event carries the egress/ingress check counts.
Rebuilt bin/control-api and bin/admin-dashboard to match. Plans and summaries
are in docs/changes; README, API, USAGE, DASHBOARD and DIAGRAMS are updated.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
db73409e8f
commit
864208238f
34 files changed
+1570
-72
No files matched your search
+43
-5
@@ -218,6 +218,19 @@ self-check способом `control_api` (`self_check.methods` в
|
||||
|
||||
Ответ: `{"ok": true}`.
|
||||
|
||||
### Результаты после вердикта
|
||||
|
||||
Проверки фиксируются в момент вердикта: `POST /agents/{id}/results` и
|
||||
`POST /probers/{site_id}/results` принимают результат только пока адрес
|
||||
проверяется (состояния до `aggregating`) и только для его текущей попытки.
|
||||
Результат, пришедший после начала агрегации или после вердикта, а также
|
||||
результат прежней попытки не сохраняется и не меняет сохранённые проверки.
|
||||
Ответ остаётся `200`, чтобы отправитель не повторял запрос:
|
||||
`{"ok": true, "ignored": N}`, где `N` — число отброшенных проверок. На каждый
|
||||
такой запрос по адресу пишется событие `result_dropped`
|
||||
(`{"source": "egress"|"inbound-site-N", "dropped": N}`). Благодаря этому вердикт
|
||||
всегда совпадает с сохранёнными проверками и пересчитывается из них.
|
||||
|
||||
### `POST /api/v1/agents/{id}/results`
|
||||
|
||||
Отчёт о результатах исходящих (egress) проверок. Можно отправлять по
|
||||
@@ -286,13 +299,17 @@ USAGE.md про состояния площадки).
|
||||
|
||||
Запрос: тело не требуется.
|
||||
|
||||
Ответ: `{"ok": true}`. `404`, если `site_id` не сконфигурирован.
|
||||
Ответ: `{"ok": true}`, либо `{"ok": true, "ignored": N}`, если часть результатов
|
||||
отброшена (см. «Результаты после вердикта» ниже). `404`, если `site_id` не сконфигурирован.
|
||||
|
||||
### `GET /api/v1/probers/{site_id}/assignments`
|
||||
|
||||
Список всех IP, которые сейчас находятся в состоянии `checking` — то есть
|
||||
всё, что нужно прозондировать на этом цикле опроса (валидаторов может
|
||||
работать несколько параллельно, поэтому список, а не один IP).
|
||||
Список IP в состоянии `checking`, которые эта площадка ещё не зондировала
|
||||
в текущей попытке (валидаторов может работать несколько параллельно,
|
||||
поэтому список, а не один IP). Адрес выдаётся площадке, пока она не
|
||||
пришлёт для него результат с `complete: true`; после этого этой площадке он
|
||||
больше не выдаётся (другим площадкам выдаётся). Новая попытка (повтор после
|
||||
сбоя) выдаёт адрес снова. Так каждая площадка зондирует адрес один раз за попытку.
|
||||
|
||||
Ответ:
|
||||
```json
|
||||
@@ -659,7 +676,16 @@ curl -s -X POST http://<control-api>:8080/api/v1/admin/auto-cycle/stop
|
||||
"last_result": "pass",
|
||||
"last_checked_at": "2026-02-01T09:05:00Z",
|
||||
"in_queue": true,
|
||||
"current_state": "done"
|
||||
"current_state": "done",
|
||||
"last_cycle_id": 4,
|
||||
"egress": {"total": 5, "ok": 5, "by_type": [
|
||||
{"type": "https", "total": 3, "ok": 3},
|
||||
{"type": "icmp", "total": 2, "ok": 2}
|
||||
]},
|
||||
"ingress": {"total": 4, "ok": 3, "by_type": [
|
||||
{"type": "icmp", "total": 1, "ok": 1},
|
||||
{"type": "tcp", "total": 3, "ok": 2}
|
||||
]}
|
||||
}
|
||||
]
|
||||
```
|
||||
@@ -667,6 +693,18 @@ curl -s -X POST http://<control-api>:8080/api/v1/admin/auto-cycle/stop
|
||||
`in_queue`/`current_state` отражают, есть ли у адреса сейчас живая строка в
|
||||
`ip_queue`, а не только в реестре.
|
||||
|
||||
**Уровни `egress` и `ingress`.** Результат последнего цикла (`last_cycle_id` —
|
||||
наибольший цикл с записанными проверками, `0` — проверок нет), разделённый
|
||||
на выходные проверки валидатора (`egress`) и входные проверки пробера со всех
|
||||
площадок (`ingress`). В каждом уровне: `total` — сколько проверок записано,
|
||||
`ok` — сколько успешных, `by_type` — то же по типам, по алфавиту. Тип — это
|
||||
`check_type` до первого дефиса: `tcp-22` и `tcp-443` дают `tcp`, `tls-443` —
|
||||
`tls`; `https`, `icmp`, `ssh` остаются как есть, новый тип проверки появляется
|
||||
в `by_type` сам. Без проверок на уровне: `{"total": 0, "ok": 0, "by_type": []}`.
|
||||
Счёт идёт по записанным проверкам, а `last_result` учитывает ещё и недостающие
|
||||
результаты, поэтому при неполном наборе вердикт может быть хуже, чем «`ok` из
|
||||
`total`».
|
||||
|
||||
### `GET /api/v1/admin/registry/{ip}`
|
||||
|
||||
Реестровая запись по одному адресу плюс вся сохранённая история проверок
|
||||
|
||||
Reference in new issue
Block a user