Kernel & Plugin Orchestration
Understand how ZCore orchestrates application modularity, topological startup ordering, and deterministic lifespans.
As monolithic applications or microservices grow, managing disparate @app.on_event("startup") hooks across multiple domains leads to non-deterministic startup bugs. ZCore introduces the Kernel and a runtime-checkable Plugin protocol to enforce a deterministic Directed Acyclic Graph (DAG) lifecycle.
1. The Plugin Protocol
A ZCore plugin is a modular domain unit conforming to the Plugin protocol. Each plugin declares its metadata, upstream dependencies, and lifecycle hooks:
# plugins.py
from fastapi import FastAPI
from zcore import Plugin
class TasksPlugin(Plugin):
name: str = "tasks"
version: str = "1.0.0"
dependencies: list[str] = ["auth"] # Requires AuthPlugin to start first
def setup(self, app: FastAPI) -> None:
# Attach routers and middleware during application initialization
from .routers import router_instance
app.include_router(router_instance.router)
async def before_startup(self) -> None:
# Pre-initialization routines
pass
async def on_startup(self) -> None:
# Core domain startup (e.g., cache warming)
pass
async def after_startup(self) -> None:
# Post-initialization tasks
pass
async def on_shutdown(self) -> None:
# Teardown logic (e.g., closing domain-specific connection pools)
pass2. Topological Sorting (DAG Resolution)
When kernel.setup(app) is executed, the Kernel inspects all registered plugins and builds a dependency graph. Using Python's native graphlib.TopologicalSorter, it flattens the graph into a strictly ordered execution sequence:
Strict Dependency Integrity:
- Missing Dependencies: If
TasksPlugindeclaresdependencies = ["auth"], but no plugin withname = "auth"was added to the Kernel, startup aborts immediately with a descriptiveRuntimeError. - Cyclic Dependencies: If Plugin A depends on Plugin B, and Plugin B depends on Plugin A, the Kernel detects the cycle and raises a
RuntimeErrorbefore running any application code.
3. Deterministic Lifespan Orchestration
The Kernel integrates natively with FastAPI's lifespan context manager (FastAPI(lifespan=kernel.lifespan)).
Startup Sequence (Topological Order)
- Runs
before_startup()for all plugins in dependency order. - Runs
on_startup()for all plugins in dependency order. - Runs
after_startup()for all plugins in dependency order.
Shutdown Sequence (Strictly Reversed Order)
Upon application termination, the Kernel executes on_shutdown() in reverse topological order.
If AuthPlugin started before TasksPlugin, then TasksPlugin will shut down before AuthPlugin. This prevents orphaned state transitions or database errors if TasksPlugin attempts to write audit logs during shutdown.
Once all plugins have safely completed their shutdown hooks, the Kernel automatically releases framework resources by closing active cache connections (close_cache()) and disposing the database engine pool (db_manager.close()).
4. Centralized Event Dispatching
During kernel.setup(app), the Kernel automatically registers its active EventDispatcher instance as a global Singleton in the IoCContainer:
# Kernel registers the singleton internally:
container.register_singleton(EventDispatcher, self.dispatcher)This decouples your application layers: any service or repository can inject EventDispatcher and publish domain events without holding direct references to listening modules.
Dependency Injection (IoC Container)
Explore ZCore's custom Inversion of Control container, constructor auto-wiring, signature caching, and lifecycle management.
Dynamic Search Engine & Security
How ZCore compiles nested JSON filters into safe SQL, protects against DoS attacks, and enforces column-level security.