ControllerBus is a framework for building modular, decoupled applications where independent components called Controllers communicate through a central Bus using declarative Directives. This documentation covers the complete system architecture, from core components to advanced features like hot-loadable plugins and cross-language integration.
ControllerBus enables:
For information about specific subsystems, see: Core Architecture, Bus System, Directive System, Controller System, Configuration System, and Plugin System.
The following diagram maps the primary architectural components to their code entities:
Sources: bus/bus.go bus/inmem/inmem.go14-28 core/core.go48-101 controller/controller.go directive/directive.go controller/factory.go
The following table defines the fundamental concepts with their code representations:
| Concept | Definition | Primary Interface | Key Implementation |
|---|---|---|---|
| Bus | Central communication hub managing controllers and dispatching directives | bus.Bus bus/bus.go12-39 | inmem.Bus bus/inmem/inmem.go14-28 |
| Controller | Stateful component that handles directives and executes long-running logic | controller.Controller controller/controller.go | Base: bus.BusController |
| Directive | Declarative request for data or desired state with reference counting | directive.Directive directive/directive.go | Various directive types in controller packages |
| Resolver | Goroutine that produces values to satisfy a directive | directive.Resolver directive/resolver.go | directive.ValueResolver, directive.GetterResolver, etc. |
| Factory | Constructor providing metadata and instantiation for controllers | controller.Factory controller/factory.go | bus.BusFactory, per-controller factories |
| Config | Protobuf configuration object for controller instantiation | config.Config config/config.go | Controller-specific config messages |
| Reference | Handle representing interest in a directive with lifecycle management | directive.Reference directive/directive.go | Returned by AddDirective() |
Sources: bus/bus.go12-39 controller/controller.go directive/directive.go directive/resolver.go controller/factory.go config/config.go
The bus.Bus interface bus/bus.go12-39 embeds directive.Controller and adds controller lifecycle management:
The in-memory implementation inmem.Bus bus/inmem/inmem.go14-28 embeds a directive controller for communication infrastructure while maintaining a list of attached controllers bus/inmem/inmem.go20-23
Sources: bus/bus.go12-39 bus/inmem/inmem.go14-28
Controllers implement the controller.Controller interface controller/controller.go with four key methods:
| Method | Purpose | Return Value |
|---|---|---|
GetControllerInfo() | Returns static metadata (*controller.Info) | Controller ID, version, description |
HandleDirective(ctx, di) | Inspects directive and returns resolvers | []directive.Resolver or nil |
Execute(ctx) | Main execution loop | error (nil = success) |
Close() | Cleanup on shutdown | None |
The base implementation bus.BusController[T] bus/controller.go handles common boilerplate like storing the logger, bus reference, and configuration.
Sources: controller/controller.go bus/controller.go
Directives are identified by type and parameters. The directive.Directive interface directive/directive.go requires:
GetDirectiveType(): Returns unique type stringIsEquivalent(directive.Directive): Enables deduplicationGetValueOptions(): Specifies value collection behaviorKey options in directive.ValueOptions directive/directive.go:
| Field | Type | Purpose |
|---|---|---|
MaxValueCount | uint32 | Maximum values to collect (0 = unbounded) |
MaxValueHardCap | bool | Whether limit is strict |
UnrefDisposeDur | time.Duration | Delay before disposing unreferenced directives |
UnrefDisposeEmptyImmediate | bool | Immediate disposal if no values |
Sources: directive/directive.go
Factories implement controller.Factory controller/factory.go and provide:
The static resolver static.Resolver controller/resolver/static maintains a registry of factories and implements controller.FactoryResolver for factory lookup.
Sources: controller/factory.go controller/resolver/static
The following diagram shows the bootstrap sequence with actual function calls:
Sources: core/core.go48-101 directive/controller bus/inmem/inmem.go26-28 controller/loader controller/resolver/static controller/resolver
The initialization order is critical:
ExecController directiveLoadConfigConstructorByID and LoadFactoryByConfig directivesSources: core/core.go48-101
ControllerBus supports both Go and TypeScript/JavaScript through shared protocol definitions:
Sources: go.mod14-15 package.json59-60
| Layer | Go Package | TypeScript Package | Purpose |
|---|---|---|---|
| Serialization | github.com/aperturerobotics/protobuf-go-lite | @aptre/protobuf-es-lite | Lightweight Protobuf encoding/decoding |
| RPC | github.com/aperturerobotics/starpc | starpc | Streaming RPC over multiplexed connections |
| Bus API | controllerbus/bus/api | - | gRPC service exposing bus operations |
The system uses:
Sources: go.mod1-31 package.json1-65
The CLI is structured as both daemon and client:
Sources: cmd/controllerbus README.md39-65 README.md142-181
ControllerBus uses YAML/JSON configuration with the ConfigSet structure controller/configset:
Each entry maps a controller instance ID to:
config: Controller-specific configuration objectid: Configuration type identifier (maps to a Factory)rev: Revision number for conflict resolutionSources: README.md73-86 controller/configset
ControllerBus provides multiple extension points:
| Mechanism | Location | Purpose | Hot-Reloadable |
|---|---|---|---|
| Controller Factories | Implement controller.Factory | Add new controller types | Via plugins |
| Plugin System | plugin/ plugin/README.md | Bundle factories into loadable modules | Yes (.cbus.so) |
| Bus API | bus/api/ | Remote control via gRPC | Configuration |
| Custom Resolvers | Implement directive.Resolver | Custom directive resolution strategies | Via controllers |
The plugin system plugin/README.md scans Go packages, discovers factories, generates wrapper code, and compiles to shared libraries (.cbus.so) plugin/loader/shared-library/shared-library.go17 The filesystem loader plugin/loader/filesystem watches for file changes and hot-reloads plugins.
Sources: plugin/README.md plugin/loader/shared-library/shared-library.go17 plugin/loader/filesystem
All directives use reference counting for automatic lifecycle management:
bus.AddDirective(di, refHandler) returns directive.Reference directive/directive.godirective.ReferenceHandler directive/directive.goreference.Release() decrements count directive/directive.goUnrefDisposeDur, the directive instance is disposed directive/directive.goValues produced by resolvers are managed through the directive.ResolverHandler interface directive/resolver.go which provides AddValue(), RemoveValue(), and ClearValues() methods.
Refresh this wiki
This wiki was recently refreshed. Please wait 4 days to refresh again.