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:
RuntimeManagerConfigurationManagerWorkerSupervisorTraceServiceHealthRegistryControlPlaneServiceServiceContainer
The core is responsible for orchestration, not domain behavior.
Platform contracts
Contracts define how business applications integrate with the runtime.
Main contracts:
ApplicationModuleTaskSourceTaskQueueWorkerTaskHandlerConfigProviderHealthContributorTraceFactory
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:
- runtime starts
- configuration is loaded
- services are initialized
- application modules register sources, queues, handlers, and workers
- task sources start producing tasks
- tasks are published into queues
- workers consume tasks
- handlers execute business logic
- traces and health are updated throughout the flow
- 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/