Lifecycle & Dependency Injection
Understanding how MicroCoreOS boots and wires dependencies is key to mastering the architecture.
🚀 The Boot Sequence
The Kernel manages a strict lifecycle to ensure all resources are ready before the first request arrives.
- Tool Setup:
- Every Tool's
setup()method is called. - This is where tools allocate resources (DB connections, HTTP server instances).
- Every Tool's
- Plugin Initialization (DI phase):
- Plugins are discovered in
domains/*/plugins/. - The Kernel inspects the
__init__signature of each plugin. - It resolves and injects the requested Tools by name.
- Plugins are discovered in
- Plugin Boot:
- Every Plugin's
on_boot()is called. - Plugins register their interest: endpoints with
http, subscriptions withevent_bus.
- Every Plugin's
- Boot Completion:
- Tools receive
on_boot_complete(container). This allows tools to interact with other tools now that everything is wired.
- Tools receive
- System Online:
- The HTTP server starts, and the system begins processing events.
💉 Dependency Injection
DI in MicroCoreOS is declarative and name-based.
python
class MyPlugin(BasePlugin):
def __init__(self, db, auth, logger): # I want these tools
self.db = db
self.auth = auth
self.logger = logger- Transparent: No complex configuration or decorators. Just name the tool in your constructor.
- Kernel-Managed: The container handles the singleton lifecycle of tools and delivers them to your plugins.
🧪 Testing with DI
Because dependencies are passed via the constructor, testing a plugin in isolation is trivial using mocks:
python
from unittest.mock import AsyncMock, MagicMock
async def test_my_plugin():
# 1. Prepare mocks
mock_db = AsyncMock()
# 2. Instantiate plugin with mocks (no kernel needed)
plugin = MyPlugin(db=mock_db, auth=MagicMock(), logger=MagicMock())
# 3. Call and Assert
await plugin.execute({"id": 1})
mock_db.query_one.assert_called_once()