# Согласование Links дёргает привилегированный процесс каждые 30 секунд - **Кому:** `antigravity` - **Дата:** 2026-08-20 - **От кого:** главный агент (`claude`) - **Ветка:** `antigravity/reconciliation-poll-interval` - **Файл отчёта:** `../done/2026-08-20-reconciliation-poll-interval.md` ## Что происходит `LinkReconciliationBackgroundService` тикает с периодом `Math.Min(LinkReconciliationSeconds, 30)` (строка 117), то есть **не реже раза в 30 секунд при любой настройке**. На каждом тике первым делом безусловно вызывается `applier.GetReconciliationRequestAsync(...)` (строка 30) — а это запуск внешнего процесса `/usr/bin/sudo` + `ochenstarik-smm-policy-apply` (`LinkPolicyApplier.RunAsync`, строка 143). Отсюда два следствия. **1. Настройка не ограничивает привилегированные вызовы.** `LinkReconciliationSeconds` валидируется в диапазоне 30…3600, и оператор, поставивший 3600, вправе ожидать примерно одну активность в час. Фактически он получает около **120 запусков sudo в час** — интервал управляет только полным проходом `ReconcileAllAsync`, но не инспекцией маркера. **2. Backoff не подавляет эти вызовы.** Проверка `_backoffUntil` (строки 35–38) стоит **после** обращения к маркеру. Когда firewall недоступен и служба ушла в backoff, она всё равно продолжает запускать sudo каждые 30 секунд — ровно в той ситуации, когда предполагалось притормозить. Каждая неудачная инспекция пишет предупреждение с полным стеком. ## Измерение Control запущен локально с `--Control:LinkReconciliationSeconds=3600`. Журнал приложений Windows, провайдер `.NET Runtime`, категория `ServerMonitorManager.Control.LinkReconciliationBackgroundService`: ``` 17:29:16 17:29:46 17:30:16 17:30:46 17:31:16 ``` Ровно каждые 30 секунд при заданных 3600. Записи идут непрерывно, службы в этот момент нечем было заниматься: узлов ноль, связей ноль. ## Что нужно сделать Привести поведение в соответствие с настройкой, **не потеряв быструю реакцию на маркер** — она и есть смысл 30-секундного опроса, её ломать нельзя. Как минимум: 1. Не обращаться к маркеру, пока действует `_backoffUntil`. Сейчас backoff не защищает ни от чего. 2. Решить и обосновать в отчёте, каким должен быть контракт `LinkReconciliationSeconds`. Либо это интервал полного прохода, и тогда частота опроса маркера должна настраиваться отдельным параметром с собственной валидацией и описанием. Либо это верхняя граница любой активности, и тогда опрос обязан её соблюдать. 3. Сделать так, чтобы повторяющаяся недоступность helper'а не писала полный стек на каждом тике. Выбор между вариантами пункта 2 — за тобой, но он должен быть **выбором с обоснованием**, а не молчаливым изменением поведения. ## Границы `src/ServerMonitorManager.Control/LinkReconciliationBackgroundService.cs`, при необходимости `ControlOptions` и валидация в `Program.cs`, плюс тесты `tests/ServerMonitorManager.Control.Tests/LinkReconciliationTests.cs`. Не трогать `LinkService.ReconcileAllAsync`, helper в `deploy/**`, консоль и Desktop. ## Как проверить результат - `dotnet test tests/ServerMonitorManager.Control.Tests/...` — все 158 существующих тестов зелёные, с выводом. Маркерные тесты трогать только если меняется контракт, и тогда объяснить каждое изменение; - новый тест на то, что во время backoff обращения к маркеру **не происходит**: подменить `ILinkPolicyApplier` и сосчитать вызовы; - новый тест на соблюдение настроенного интервала по выбранному контракту; - предъявить число вызовов applier за фиксированное время до и после правки — как в измерении выше, числами. ## Контекст и ограничения Дефект найден на живом прогоне Control на Windows, где helper'а нет вовсе, поэтому каждая инспекция падает. На настоящем Hub helper есть и вызовы успешны — значит там это не ошибки в журнале, а тихая нагрузка: запуск sudo и внешнего процесса дважды в минуту круглосуточно. Оценить, насколько это существенно на настоящем Hub, я не могу: живого Hub под рукой нет. Если при проверке окажется, что нагрузка пренебрежима и контракт менять не нужно, — так и напиши с числами, это допустимый результат. Пункт 1 про backoff при этом всё равно остаётся к исправлению.