Рефакторинг канала управления
This commit is contained in:
169
README.md
169
README.md
@@ -1,20 +1,167 @@
|
||||
# Config Manager
|
||||
## Description
|
||||
This package was created to run my applications.
|
||||
The ConfigManager class implements the entry point for the program and provides the actual application configuration. It also simplifies logging setup.
|
||||
## Описание
|
||||
Пакет предназначен для запуска приложений.
|
||||
Класс ConfigManager реализует точку входа программы и предоставляет актуальную конфигурацию приложения, а также упрощает настройку логирования.
|
||||
|
||||
## Logging (v2)
|
||||
Logging is configured from the config file only if it contains a **`log`** section in [dictConfig](https://docs.python.org/3/library/logging.config.html#logging.config.dictConfig) format. If there is no `log` section, the manager logs a warning and the default Python level (WARNING) remains, so INFO/DEBUG messages may not appear.
|
||||
## ConfigManager v2: устройство и взаимосвязи
|
||||
|
||||
**How to verify that logging config is applied:**
|
||||
- Ensure your config file path is correct and the file is loaded on startup (no error in logs about reading config).
|
||||
- Ensure the config has a `log` key with `version: 1`, `handlers`, and `loggers` (see `tests/config.yaml` for an example).
|
||||
- After startup you should see an INFO message: `"Logging configuration applied"` (from `config_manager.v1.log_manager`). If you do not see it, either the `log` section is missing (you will see a warning) or the root/package log level is above INFO.
|
||||
**ConfigManager v2** — точка входа приложения. Он наследует внутреннюю логику от **\_RuntimeController** (циклы воркера и обновления конфига, запуск/остановка каналов управления).
|
||||
|
||||
## Installation
|
||||
**Ядро (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``
|
||||
|
||||
## Contacts
|
||||
## Контакты
|
||||
- **e-mail**: lesha.spb@gmail.com
|
||||
- **telegram**: https://t.me/lesha_spb
|
||||
|
||||
|
||||
Reference in New Issue
Block a user