Files
plba/README.md

445 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PLBA
## 1. Общее описание сервиса и его назначение
`PLBA` (`Platform Runtime for Business Applications`) - это платформенный runtime для бизнес-приложений. Библиотека выносит из прикладного кода типовые инфраструктурные задачи: жизненный цикл приложения, запуск и остановку фоновых воркеров, загрузку конфигурации, health-check, tracing, логирование и control plane.
Назначение сервиса:
- дать единый каркас для запуска бизнес-модулей;
- отделить платформенные обязанности от предметной логики;
- упростить разработку сервисов с очередями, polling-обработчиками и фоновыми процессами;
- обеспечить наблюдаемость и управляемость runtime через health/status и HTTP control endpoints.
Текущая модель работы выглядит так:
1. приложение создаёт `RuntimeManager`;
2. runtime загружает конфигурацию;
3. применяется logging-конфигурация;
4. модуль приложения регистрирует очереди, обработчики, воркеры и health contributors;
5. `WorkerSupervisor` запускает все рабочие компоненты;
6. runtime агрегирует состояние, health и tracing;
7. control plane предоставляет снимок состояния и команды запуска/остановки.
`PLBA` особенно полезен для:
- почтовых ботов и интеграционных сервисов;
- event-driven и queue-driven приложений;
- фоновых бизнес-процессов;
- внутренних платформенных сервисов с единым operational-контуром.
## 2. Архитектура - диаграмма классов
```mermaid
classDiagram
class RuntimeManager {
+register_module(module)
+add_config_file(path)
+start()
+stop(timeout, force, stop_control_plane)
+status()
+current_health()
}
class ConfigurationManager {
+add_provider(provider)
+load()
+reload()
+get()
+section(name, default)
}
class ServiceContainer {
+register(name, service)
+get(name)
+require(name, expected_type)
+snapshot()
}
class ModuleRegistry {
+register_module(name)
+add_queue(name, queue)
+add_handler(name, handler)
+add_worker(worker)
+add_health_contributor(contributor)
}
class ApplicationModule {
<<abstract>>
+name
+register(registry)
}
class WorkerSupervisor {
+register(worker)
+start()
+stop(timeout, force)
+snapshot()
+healths()
+statuses()
}
class Worker {
<<abstract>>
+start()
+stop(force)
+health()
+status()
}
class QueueWorker {
+name
+critical
+start()
+stop(force)
+health()
+status()
}
class TaskQueue {
<<abstract>>
+publish(task)
+consume(timeout)
+ack(task)
+nack(task, retry_delay)
+stats()
}
class InMemoryTaskQueue {
+publish(task)
+consume(timeout)
+ack(task)
+nack(task, retry_delay)
+stats()
}
class TaskHandler {
<<abstract>>
+handle(task)
}
class TraceService {
+create_context(...)
+open_context(...)
+resume(task_metadata, operation)
+attach(task_metadata, context)
+info(message, status, attrs)
+warning(message, status, attrs)
+error(message, status, attrs)
}
class HealthRegistry {
+register(contributor)
+snapshot(worker_healths)
+payload(state, worker_healths)
}
class ControlPlaneService {
+register_channel(channel)
+start(runtime)
+stop()
+snapshot(runtime)
}
class LogManager {
+apply_config(config)
}
class FileConfigProvider {
+load()
}
RuntimeManager --> ConfigurationManager
RuntimeManager --> ServiceContainer
RuntimeManager --> ModuleRegistry
RuntimeManager --> WorkerSupervisor
RuntimeManager --> TraceService
RuntimeManager --> HealthRegistry
RuntimeManager --> ControlPlaneService
RuntimeManager --> LogManager
RuntimeManager --> ApplicationModule
ModuleRegistry --> ServiceContainer
ModuleRegistry --> Worker
ModuleRegistry --> TaskQueue
ModuleRegistry --> TaskHandler
WorkerSupervisor --> Worker
QueueWorker --|> Worker
QueueWorker --> TaskQueue
QueueWorker --> TaskHandler
QueueWorker --> TraceService
InMemoryTaskQueue --|> TaskQueue
ConfigurationManager --> FileConfigProvider
```
### Архитектурные слои
- `app_runtime.core` - оркестрация runtime, контейнер сервисов, регистрация модулей, типы состояния.
- `app_runtime.contracts` - абстракции для интеграции бизнес-приложений.
- `app_runtime.workers`, `queue`, `config`, `logging`, `health`, `tracing`, `control` - инфраструктурные адаптеры и платформенные сервисы.
- `plba` - публичный фасад, который реэкспортирует ключевые классы как API пакета.
## 3. Описание доступных модулей, их назначение, краткое устройство, примеры применения в бизнес приложениях
### `plba`
Публичный API пакета. Реэкспортирует `RuntimeManager`, `ApplicationModule`, `QueueWorker`, `InMemoryTaskQueue`, `TraceService`, `HealthRegistry`, `ControlPlaneService` и другие классы.
Краткое устройство:
- служит фасадом над `app_runtime`;
- упрощает импорт для прикладного кода;
- позволяет использовать пакет как библиотеку без знания внутренней структуры.
Пример применения:
- бизнес-сервис импортирует `create_runtime` и `ApplicationModule`, собирает свой модуль и запускает runtime.
### `app_runtime.core`
Основной orchestration-слой.
Ключевые классы:
- `RuntimeManager` - центральная точка запуска и остановки;
- `ConfigurationManager` - загрузка и merge конфигурации;
- `ServiceContainer` - DI-like контейнер платформенных сервисов;
- `ModuleRegistry` - регистрация очередей, обработчиков, воркеров и health contributors.
Краткое устройство:
- `RuntimeManager` создаёт и связывает инфраструктурные сервисы;
- при старте регистрирует health contributors, воркеры и поднимает control plane;
- `ModuleRegistry` связывает бизнес-модуль с runtime без жёсткой зависимости на конкретные реализации.
Примеры применения в бизнес-приложениях:
- CRM-интеграция с несколькими фоновых воркерами;
- сервис обработки заявок, где один модуль регистрирует очередь, handler и worker pool;
- back-office процесс с управляемым graceful shutdown.
### `app_runtime.contracts`
Набор абстракций для расширения платформы.
Ключевые контракты:
- `ApplicationModule`;
- `Worker`;
- `TaskQueue`;
- `TaskHandler`;
- `ConfigProvider`;
- `HealthContributor`;
- trace-related контракты.
Краткое устройство:
- бизнес-код реализует интерфейсы, а runtime работает только через контракты;
- это позволяет менять инфраструктуру без переписывания прикладной логики.
Примеры применения в бизнес-приложениях:
- реализовать свой `ApplicationModule` для почтового бота;
- подключить собственный `ConfigProvider` для БД или secrets storage;
- реализовать кастомный `Worker` для long-running polling процесса.
### `app_runtime.workers`
Модуль управления рабочими процессами.
Ключевые классы:
- `WorkerSupervisor` - запускает и останавливает набор воркеров;
- `QueueWorker` - стандартный worker для обработки задач из очереди.
Краткое устройство:
- `WorkerSupervisor` агрегирует health/status всех воркеров;
- `QueueWorker` поднимает нужное число потоков, читает задачи из `TaskQueue`, вызывает `TaskHandler`, делает `ack/nack` и обновляет operational-метрики.
Примеры применения в бизнес-приложениях:
- параллельная обработка входящих писем;
- обработка очереди заказов;
- фоновая генерация документов или актов.
### `app_runtime.queue`
Очереди задач.
Ключевой класс:
- `InMemoryTaskQueue`.
Краткое устройство:
- использует стандартный `Queue` из Python;
- хранит счётчики `published`, `acked`, `nacked`, `queued`;
- подходит как базовая реализация для разработки, тестов и простых сценариев.
Примеры применения в бизнес-приложениях:
- локальная очередь задач в небольшом внутреннем сервисе;
- тестовая среда без внешнего брокера;
- staging-сценарии для отладки worker pipeline.
### `app_runtime.config`
Подсистема загрузки конфигурации.
Ключевые классы:
- `FileConfigProvider`;
- `ConfigFileLoader`.
Краткое устройство:
- `ConfigurationManager` собирает данные из провайдеров;
- текущая штатная реализация читает YAML-файл;
- поддерживается глубокое слияние секций конфигурации.
Примеры применения в бизнес-приложениях:
- конфигурация платформы и прикладных модулей из `config.yml`;
- раздельное хранение `platform`, `log` и app-specific секций;
- подключение нескольких источников конфигурации с последующим merge.
### `app_runtime.logging`
Управление логированием.
Ключевой класс:
- `LogManager`.
Краткое устройство:
- применяет `dictConfig` из секции `log`;
- хранит последнюю валидную конфигурацию и пытается восстановиться при ошибке.
Примеры применения в бизнес-приложениях:
- единообразная настройка JSON-логов;
- переключение уровней логирования между окружениями;
- централизованная logging-конфигурация для нескольких модулей.
### `app_runtime.health`
Подсистема health aggregation.
Ключевой класс:
- `HealthRegistry`.
Краткое устройство:
- собирает health от воркеров и дополнительных contributors;
- агрегирует статус в `ok`, `degraded`, `unhealthy`;
- формирует payload для readiness/liveness и operational snapshot.
Примеры применения в бизнес-приложениях:
- показывать degraded, если обработка идёт с ошибками;
- маркировать сервис unhealthy при падении критичного worker;
- добавлять health внешней зависимости, например IMAP или ERP API.
### `app_runtime.tracing`
Подсистема трассировки выполнения.
Ключевые классы:
- `TraceService`;
- `TraceContextStore`;
- `NoOpTraceTransport`.
Краткое устройство:
- создаёт trace contexts;
- связывает source/queue/worker/handler через metadata;
- пишет контексты и сообщения через транспортный слой.
Примеры применения в бизнес-приложениях:
- трассировка обработки письма от polling до бизнес-handler;
- аудит прохождения заказа по pipeline;
- отладка проблемных задач в фоне.
### `app_runtime.control`
Control plane и HTTP-канал управления.
Ключевые классы:
- `ControlPlaneService`;
- `HttpControlChannel`;
- `ControlActionSet`.
Краткое устройство:
- публикует health/status и команды управления runtime;
- может поднимать HTTP endpoints для start/stop/status;
- строит snapshot состояния на основе `RuntimeManager`.
Примеры применения в бизнес-приложениях:
- административный endpoint для оператора;
- health endpoint для Kubernetes/nomad;
- runtime status для monitoring dashboard.
## 4. Установка - `git@git.lesha.spb.ru:alex/plba.git`
### Требования
- Python `3.12+`
- `pip`
- SSH-доступ к `git.lesha.spb.ru`
### Установка напрямую через `pip` из Git-репозитория
```bash
pip install "plba @ git+ssh://git@git.lesha.spb.ru/alex/plba.git"
```
Если нужна установка из конкретной ветки:
```bash
pip install "plba @ git+ssh://git@git.lesha.spb.ru/alex/plba.git@main"
```
Если нужна установка из конкретного тега или commit hash:
```bash
pip install "plba @ git+ssh://git@git.lesha.spb.ru/alex/plba.git@v0.1.0"
```
или
```bash
pip install "plba @ git+ssh://git@git.lesha.spb.ru/alex/plba.git@<commit-hash>"
```
### Установка в виртуальное окружение
```bash
python -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install "plba @ git+ssh://git@git.lesha.spb.ru/alex/plba.git"
```
### Локальная разработка
Если пакет нужно не только использовать, но и разрабатывать:
```bash
git clone git@git.lesha.spb.ru:alex/plba.git
cd plba
python -m venv .venv
source .venv/bin/activate
pip install -e .
```
### Быстрая проверка
```bash
python -c "import plba; print(plba.__all__[:5])"
```
### Минимальный пример использования
```python
from plba import ApplicationModule, InMemoryTaskQueue, QueueWorker, RuntimeManager, Task, TaskHandler
class PrintHandler(TaskHandler):
def handle(self, task: Task) -> None:
print(task.payload)
class DemoModule(ApplicationModule):
@property
def name(self) -> str:
return "demo"
def register(self, registry) -> None:
queue = InMemoryTaskQueue()
traces = registry.services.get("traces")
handler = PrintHandler()
queue.publish(Task(name="demo-task", payload={"id": 1}, metadata={}))
registry.add_worker(QueueWorker("demo-worker", queue, handler, traces))
runtime = RuntimeManager()
runtime.register_module(DemoModule())
runtime.start()
runtime.stop()
```