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. Архитектура - диаграмма классов

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-репозитория

pip install "plba @ git+ssh://git@git.lesha.spb.ru/alex/plba.git"

При такой установке pip ставит не только сам пакет plba, но и все его зависимости, объявленные в pyproject.toml, например fastapi, uvicorn и PyYAML.

Если нужна установка из конкретной ветки:

pip install "plba @ git+ssh://git@git.lesha.spb.ru/alex/plba.git@main"

Если нужна установка из конкретного тега или commit hash:

pip install "plba @ git+ssh://git@git.lesha.spb.ru/alex/plba.git@v0.1.0"

или

pip install "plba @ git+ssh://git@git.lesha.spb.ru/alex/plba.git@<commit-hash>"

Установка в виртуальное окружение

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"

Подключение plba в бизнес-приложении

Чтобы при установке бизнес-приложения автоматически подтягивались зависимости plba, нужно добавить plba в зависимости самого бизнес-приложения как Git dependency.

Пример для requirements.txt:

plba @ git+ssh://git@git.lesha.spb.ru/alex/plba.git

Пример для pyproject.toml:

[project]
dependencies = [
    "plba @ git+ssh://git@git.lesha.spb.ru/alex/plba.git",
]

Если бизнес-приложение собирается в Docker, достаточно чтобы на этапе сборки выполнялся обычный pip install, например:

COPY pyproject.toml .
RUN pip install .

или при использовании requirements.txt:

COPY requirements.txt .
RUN pip install -r requirements.txt

В обоих случаях pip установит plba из Git и автоматически подтянет его транзитивные зависимости.

Локальная разработка

Если пакет нужно не только использовать, но и разрабатывать:

git clone git@git.lesha.spb.ru:alex/plba.git
cd plba
python -m venv .venv
source .venv/bin/activate
pip install -e .

Быстрая проверка

python -c "import plba; print(plba.__all__[:5])"

Минимальный пример использования

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()
Description
No description provided
Readme 260 KiB
Languages
Python 100%