# Config Manager ## Описание Пакет предназначен для запуска приложений. Класс ConfigManager реализует точку входа программы и предоставляет актуальную конфигурацию приложения, а также упрощает настройку логирования. ## ConfigManager v2: устройство и взаимосвязи **ConfigManager v2** — точка входа приложения. Он наследует внутреннюю логику от **\_RuntimeController** (циклы воркера и обновления конфига, запуск/остановка каналов управления). **Ядро (core):** - **ConfigLoader** — читает конфиг из файла (YAML/JSON), считает хеш и отдаёт конфиг только при изменении; при ошибке парсинга возвращает последний валидный конфиг. - **WorkerLoop** — в отдельном потоке циклически вызывает ваш метод `execute()` с паузой между вызовами; реагирует на событие остановки и колбэки успеха/ошибки. - **LogManager** (v1) — применяет секцию `log` из конфига к логированию (dictConfig). - **HealthAggregator** — собирает состояние: жизненный цикл (idle/starting/running/…), время последнего успешного `execute()` и таймаут здоровья; формирует единый ответ для health (ok/unhealthy). - **ControlChannelBridge** — один мост для всех каналов: обработчики on_start/on_stop/on_status (сброс/установка halt, текст статуса). **Каналы управления (control):** - **ControlChannel** — абстрактный контракт: `start(on_start, on_stop, on_status)`, `stop()`. - **HttpControlChannel** — HTTP API (`/health`, `/actions/start`, `/actions/stop`, `/actions/status`); использует **UvicornServerRunner**; для `/health` вызывает **HealthAggregator.collect()**, для действий — переданные обработчики из **ControlChannelBridge**. - **TelegramControlChannel** — реализация через long polling Telegram; команды `/start`, `/stop`, `/status` вызывают переданные обработчики. **Поток работы:** при `start()` менеджер собирает список каналов (при `management_settings.enabled` — **HttpControlChannel**, плюс опционально **control_channel** / **control_channels**), поднимает все каналы с одним **ControlChannelBridge**, затем запускает два цикла: **WorkerLoop** и периодическое обновление конфига через **ConfigLoader**. Остановка по halt (через любой канал) завершает оба цикла; в конце останавливаются все каналы. ## Диаграмма классов (v1 и v2) ```mermaid classDiagram direction TB class ConfigManager { +str path +Any config +float update_interval +float work_interval -Event _halt -Task _task +start() async +stop() async +execute()* -_worker_loop() async -_periodic_update_loop() async -_update_config() async } class ConfigManagerV2 { +str path +Any config +float update_interval +float work_interval -ConfigLoader _loader -LifecycleState _state +start() async +stop() async +execute()* +get_health_status() HealthPayload -_run() async -_worker_loop() async -_periodic_update_loop() async } class _RuntimeController { <<внутренний>> -_on_execute_success() -_on_execute_error(exc) -_worker_loop() async -_periodic_update_loop() async -_start_control_channels() async -_stop_control_channels() async -_run() async } class ConfigLoader { +str path +Any config +Any last_valid_config +load_if_changed() async +parse_config(data) Any -_read_file_sync() str -read_file_async() async } class WorkerLoop { -Callable execute -Callable get_interval -Event halt_event +run() async } class LogManager { +apply_config(config) None } class ControlChannel { <<абстрактный>> +start(on_start, on_stop, on_status) async* +stop() async* } class TelegramControlChannel { -str _token -int _chat_id +start(on_start, on_stop, on_status) async +stop() async -_poll_loop() async } class HttpControlChannel { -UvicornServerRunner _runner -Callable _health_provider +start(on_start, on_stop, on_status) async +stop() async +int port } class HealthAggregator { -Callable get_state -Callable get_app_health +collect() async HealthPayload } class ControlChannelBridge { -Event _halt -Callable _get_state -Callable _get_status +on_start() async str +on_stop() async str +on_status() async str } class UvicornServerRunner { -Server _server -Task _serve_task +start(app) async +stop() async +int port } ConfigManager --> LogManager : использует ConfigManagerV2 --|> _RuntimeController : наследует ConfigManagerV2 --> ConfigLoader : использует ConfigManagerV2 --> LogManager : использует ConfigManagerV2 --> HealthAggregator : использует ConfigManagerV2 --> ControlChannelBridge : использует ConfigManagerV2 ..> ControlChannel : список каналов _RuntimeController ..> WorkerLoop : создаёт в _worker_loop TelegramControlChannel --|> ControlChannel : реализует HttpControlChannel --|> ControlChannel : реализует HttpControlChannel --> UvicornServerRunner : использует HttpControlChannel ..> HealthAggregator : health_provider ControlChannelBridge ..> ControlChannel : on_start, on_stop, on_status ``` ## Логирование (v2) Логирование настраивается из конфигурационного файла только если в нём есть секция **`log`** в формате [dictConfig](https://docs.python.org/3/library/logging.config.html#logging.config.dictConfig). Если секции `log` нет, менеджер пишет предупреждение в лог, а уровень Python по умолчанию (WARNING) сохраняется — сообщения INFO/DEBUG могут не отображаться. **Как проверить, что конфигурация логирования применилась:** - Убедитесь, что путь к файлу конфига верный и файл загружается при старте (в логах нет ошибки чтения конфига). - Убедитесь, что в конфиге есть ключ `log` с `version: 1`, `handlers` и `loggers` (пример — `tests/config.yaml`). - После старта в логе должно появиться сообщение уровня INFO: `"Logging configuration applied"` (из `config_manager.v1.log_manager`). Если его нет, либо секция `log` отсутствует (будет предупреждение), либо уровень root/пакета выше INFO. ## Установка ``pip install git+https://git.lesha.spb.ru/alex/config_manager.git`` ## Контакты - **e-mail**: lesha.spb@gmail.com - **telegram**: https://t.me/lesha_spb