A strongly-typed cybernetic kernel for building durable event-driven systems in Python.
Project description
BussDCC
bussdcc is a strongly-typed cybernetic kernel for building durable, event-driven systems in Python.
It provides a minimal but complete coordination core for systems that manage:
- Devices (hardware, boundaries, external resources)
- Processes (event-driven logic)
- Interfaces (human/network adapters)
- Services (time-driven supervised workers)
The kernel defines contracts, lifecycle, dispatch authority, and supervision — but leaves application policy to you.
Why BussDCC?
Modern Python systems often grow into tangled combinations of:
- Threads
- Callbacks
- Background loops
- Signal handlers
- Implicit global state
bussdcc enforces:
- Explicit lifecycles
- Authoritative message dispatch
- Typed events
- Supervised background services
- Deterministic boot and shutdown
It is not a framework.
It is a coordination kernel.
Quick Start
from bussdcc import Runtime
from bussdcc.device import Device
from bussdcc.process import Process
from bussdcc.service import Service
class MySensor(Device):
kind = "sensor"
def connect(self):
print("Sensor online")
def disconnect(self):
print("Sensor offline")
class Logger(Process):
name = "logger"
def handle_event(self, ctx, evt):
print(evt.payload.name, evt.payload.to_dict())
class Heartbeat(Service):
name = "heartbeat"
interval = 2.0
def tick(self, ctx):
ctx.emit(message.SystemSignal(signal=0, action="heartbeat"))
rt = Runtime()
rt.attach_device(MySensor(id="sensor-1"))
rt.register_process(Logger())
rt.register_service(Heartbeat())
rt.boot()
Architectural Model
At its core, bussdcc is built around a single invariant:
All coordination flows through typed
Messageevents. TheRuntimeis the authoritative dispatcher.
Everything else supports that invariant.
Core Concepts
Runtime
The Runtime is the coordination authority.
It:
-
Owns the
Context -
Owns the event dispatch loop
-
Controls boot and shutdown order
-
Supervises services
-
Routes every
Messageto:- Processes
- Interfaces
- Services (event-driven side)
Boot order is deterministic:
- Devices attach
- Processes attach and start
- Interfaces attach and start
- Services attach and begin supervised execution
Shutdown reverses this order.
The runtime emits lifecycle messages:
runtime.bootingruntime.bootedruntime.shutting_downruntime.shutdown
The runtime is also usable as a context manager:
with Runtime() as rt:
...
Context
The Context is a minimal capability container.
It exposes:
clock— time abstractionevents— event busstate— thread-safe hierarchical stateruntime— runtime accessemit(message)— authoritative message emission
The context is intentionally small and infrastructure-focused.
Messages
Messages are:
- Frozen dataclasses
- Strictly typed
- Assigned a severity level
Example:
@dataclass(slots=True, frozen=True)
class ProcessError(Message):
name = "process.error"
severity = Severity.ERROR
Every message becomes an Event[Message] when emitted.
Severity levels:
DEBUGINFOWARNINGERRORCRITICAL
Severity protects the system from infinite error recursion during failure cascades.
Event Engine
The EventBus is:
- Synchronous
- Thread-safe
- In-process
- Typed
Handlers run in the emitter’s thread.
Subscriber failures are isolated and converted into event.subscriber_error messages (unless already error-level).
This is coordination — not distributed messaging middleware.
Devices
Devices represent hardware or external boundaries.
Lifecycle:
attach(ctx) → connect()
detach() → disconnect()
Devices emit:
device.attacheddevice.detacheddevice.failed
Devices are expected to fail honestly.
Processes
Processes are synchronous, event-driven logic units.
They:
- Attach to the runtime
- Start during boot
- Receive every emitted
Message - React via
handle_event
Lifecycle:
attach(ctx)start(ctx)handle_event(ctx, evt)stop(ctx)detach()
Errors are isolated and converted into process.error.
Interfaces
Interfaces are processes by role.
They typically:
- Translate external input (HTTP, CLI, UI, network) into
Messages - Present system state outward
They follow the same lifecycle as processes but are registered separately for clarity.
Services
Services are supervised, time-driven components.
They:
- Run in dedicated threads
- Execute
tick(ctx)on an interval - May restart automatically
- May be marked
critical
Execution model:
start()
loop:
tick()
sleep(interval)
stop()
Supervisor messages:
service.startedservice.stoppedservice.errorservice.restartservice.failure
Critical failures can halt the supervisor.
State
The StateStore is:
- Thread-safe
- Hierarchical
- Dot-path addressable
Example:
ctx.state.set("system.clock.uptime", 42)
value = ctx.state.get("system.clock.uptime")
It intentionally provides:
- No schema
- No persistence
- No policy
It is coordination state — not storage.
Clock Abstraction
Time is abstracted via ClockProtocol.
Default: SystemClock
Provides:
now_utc()monotonic()sleep(seconds, cancel=Event)
Custom clocks (simulated, deterministic, test clocks) can be injected.
Runtime Variants
Runtime
Standard synchronous kernel.
ThreadedRuntime
Owns a background execution thread.
Provides .run() which blocks until shutdown.
SignalRuntime
Adds POSIX signal supervision:
SIGINT→ shutdownSIGTERM→ shutdownSIGHUP→ reloadSIGUSR1,SIGUSR2→ user-defined message events
Signals are converted into typed system messages.
Design Principles
- Authoritative dispatch — only the runtime routes messages.
- Typed contracts over inheritance depth
- Infrastructure replaceable by protocol
- Explicit lifecycle ordering
- Failure isolation
- mypy --strict compatibility
What BussDCC Is
-
A cybernetic coordination kernel
-
A durable event-driven runtime
-
Suitable for:
- IoT systems
- Robotics
- Hardware control
- Automation engines
- Control planes
- Edge services
What BussDCC Is Not
- Not Django
- Not FastAPI
- Not Celery
- Not a rules engine
- Not a persistence layer
- Not a distributed system
It is the thing you build those systems on top of.
Status
Alpha
Core architecture is stabilizing. APIs may evolve, but the dispatch model and lifecycle ordering are solidifying.
Installation
pip install bussdcc
Requires Python 3.11+
License
MIT License
Durable systems start with explicit contracts, supervised execution, and honest failure boundaries.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file bussdcc-0.34.0.tar.gz.
File metadata
- Download URL: bussdcc-0.34.0.tar.gz
- Upload date:
- Size: 27.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
db76dcc0cb61cdb86e7ca599d2431af5c850fcaaabc2bc634772a5c3f6f5c174
|
|
| MD5 |
e2148f800e0e1a06a502c3ed531acb3c
|
|
| BLAKE2b-256 |
72f0c62a737ab5eff2c2bbab0b73c71bcdfd43e90961d86d1cac2b96a322c3d8
|
File details
Details for the file bussdcc-0.34.0-py3-none-any.whl.
File metadata
- Download URL: bussdcc-0.34.0-py3-none-any.whl
- Upload date:
- Size: 29.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
edda84e31041ba6e40c16138dbae4e9893291d59f683aed31f6ed44266b92355
|
|
| MD5 |
17babc1b34f7311100f2f636363a81a3
|
|
| BLAKE2b-256 |
681d01022f7cc85de2746ccff7ebbe13219b0ee09e4f9d2e2abec7dc288689da
|