Files
plba/requirements/architecture.md

4.9 KiB

Architecture

Overview

The runtime is built as a platform layer for business applications.

It consists of four logical layers:

  • platform core
  • platform contracts
  • infrastructure adapters
  • business applications

Layers

Platform core

The core contains long-lived runtime services:

  • RuntimeManager
  • ConfigurationManager
  • WorkerSupervisor
  • TraceService
  • HealthRegistry
  • ControlPlaneService
  • ServiceContainer

The core is responsible for orchestration, not domain behavior.

Platform contracts

Contracts define how business applications integrate with the runtime.

Main contracts:

  • ApplicationModule
  • TaskSource
  • TaskQueue
  • Worker
  • TaskHandler
  • ConfigProvider
  • HealthContributor
  • TraceFactory

These contracts must remain domain-agnostic.

Infrastructure adapters

Adapters implement concrete runtime capabilities:

  • in-memory queue
  • Redis queue
  • file config loader
  • database config loader
  • polling source
  • IMAP IDLE source
  • HTTP control plane
  • trace transport adapters

Adapters may change between applications and deployments.

Business applications

Applications are built on top of the contracts and adapters.

Examples:

  • mail_order_bot
  • future event-driven business services

Applications contain:

  • domain models
  • domain handlers
  • application-specific configuration schema
  • source/handler composition

Core runtime components

RuntimeManager

The main platform facade.

Responsibilities:

  • bootstrap runtime
  • initialize services
  • register application modules
  • start and stop all runtime-managed components
  • expose status
  • coordinate graceful shutdown

ConfigurationManager

Responsibilities:

  • load configuration
  • validate configuration
  • publish config updates
  • provide typed config access
  • notify subscribers on reload

Configuration should be divided into:

  • platform config
  • application config
  • environment/runtime overrides

WorkerSupervisor

Responsibilities:

  • register worker definitions
  • start worker pools
  • monitor worker health
  • restart failed workers when appropriate
  • manage parallelism and backpressure
  • expose worker-level status

TraceService

Responsibilities:

  • create traces for operations
  • propagate trace context across source -> queue -> worker -> handler boundaries
  • provide trace factories to applications
  • remain transport-agnostic

HealthRegistry

Responsibilities:

  • collect health from registered contributors
  • aggregate health into liveness/readiness/status views
  • expose structured runtime health

ControlPlaneService

Responsibilities:

  • control endpoints
  • runtime state visibility
  • administrative actions
  • later authentication and user/session-aware access

Main runtime model

The runtime should operate on this conceptual flow:

  1. runtime starts
  2. configuration is loaded
  3. services are initialized
  4. application modules register sources, queues, handlers, and workers
  5. task sources start producing tasks
  6. tasks are published into queues
  7. workers consume tasks
  8. handlers execute business logic
  9. traces and health are updated throughout the flow
  10. runtime stops gracefully on request

Contracts

ApplicationModule

Describes a business application to the runtime.

Responsibilities:

  • register domain services
  • register task sources
  • register queues
  • register worker pools
  • register handlers
  • declare config requirements
  • optionally register health contributors

TaskSource

Produces tasks into queues.

Examples:

  • IMAP polling source
  • IMAP IDLE source
  • webhook source
  • scheduled source

Responsibilities:

  • start
  • stop
  • publish tasks
  • expose source status

TaskQueue

A queue abstraction.

Expected operations:

  • publish(task)
  • consume()
  • ack(task)
  • nack(task, retry_delay=None)
  • stats()

The first implementation may be in-memory, but the interface should support future backends.

Worker

Consumes tasks from a queue and passes them to a handler.

Responsibilities:

  • obtain task from queue
  • open or resume trace context
  • call business handler
  • ack or nack the task
  • expose worker state

TaskHandler

Executes business logic for one task.

The runtime should not know what the handler does. It only knows that a task is processed.

Mail Order Bot as first application

Phase 1

  • source: IMAP polling
  • queue: in-memory queue
  • workers: parallel email processing workers
  • handler: domain email processing handler
  • mark message as read only after successful processing

Phase 2

  • source changes from polling to IMAP IDLE
  • queue and workers remain the same

This demonstrates one of the architectural goals: the source can change without redesigning the rest of the processing pipeline.

Suggested package structure

src/
  app_runtime/
    core/
    contracts/
    config/
    workers/
    queue/
    tracing/
    health/
    control/
    container/
    adapters/
  mail_order_bot_app/
    module/
    sources/
    handlers/
    services/
    domain/