Quick Start Examples
Relevant source files
The following files were used as context for generating this wiki page:
Quick Start Examples serve as the primary entry point for developers to understand the core mechanics of the bubus event bus. These examples demonstrate how to define strongly-typed events, register various types of handlers (wildcard, string-based, and class-based), and manage the lifecycle of dispatched events in both Python and TypeScript environments.
The examples cover fundamental patterns such as result validation, asynchronous handler execution, and the automatic tracking of parent-child relationships between events. By following these patterns, developers can ensure type safety across distributed systems and maintain a clear audit trail of event flows.
Event Definition and Type Safety
Events are defined by extending the BaseEvent class. In Python, this utilizes pydantic for schema validation, while the TypeScript implementation uses zod. A critical feature is the definition of event_result_type, which enforces that handlers return data matching a specific schema.
Core Event Structure
| Feature | Implementation Detail | Source |
|---|---|---|
| Schema Validation | Pydantic (Python) / Zod (TS) | examples/simple.py:12, bubus-ts/examples/simple.ts:8 |
| Result Enforcement | event_result_type attribute | examples/simple.py:18, bubus-ts/examples/simple.ts:12 |
| Unique ID | Automatic UUIDv7 generation | bubus-ts/examples/simple.ts:25 |
Event Definition Flow
The following diagram illustrates how an event is defined and how its result schema is enforced during execution.
The flow of event definition and result validation.
Sources: examples/simple.py:12-25, bubus-ts/examples/simple.ts:7-17
Handler Registration Patterns
Handlers can be registered to an EventBus using three primary methods: Wildcard, String Pattern, or Class Reference.
Handler Types
- Wildcard (
*): Observes every event flowing through the bus, typically used for logging or auditing. - Class Reference: Provides the best type inference for payloads and return values.
- String Pattern: Matches events by their
event_typestring, allowing for dynamic or weaker-typed registrations.
// TypeScript Class Registration
bus.on(RegisterUserEvent, async (event) => {
return { user_id: 'u1', welcome_email_sent: true };
});
// Wildcard Registration
bus.on('*', (event) => console.log(event.event_type));
Sources: bubus-ts/examples/simple.ts:24-38, bubus-ts/tests/handlers.test.ts:25-39
Relationship Tracking
bubus automatically tracks parent-child relationships when events are emitted from within the context of a running handler. This creates a traceable execution tree.
Recursive Event Dispatch
When a handler for ParentEvent uses event.bus.emit(), the new ChildEvent automatically receives the ID of the ParentEvent as its event_parent_id.
Sequence diagram of nested event tracking.
Sources: bubus-ts/examples/parent_child_tracking.ts:32-75
Result Inspection and Monitoring
Once an event is dispatched, developers can inspect the outcomes of all registered handlers through the event_results collection.
Result Lifecycle Table
| Status | Description |
|---|---|
pending | Handler is queued but hasn't started. |
started | Handler is currently executing. |
completed | Handler finished and return value passed validation. |
error | Handler threw an exception or returned an invalid shape. |
Sources: examples/simple.py:59-70, bubus-ts/examples/simple.ts:58-71
UI Dashboard Monitoring
For real-time inspection, the project includes a FastAPI-based UI that reads from a SQLite history mirror.
# Start the monitoring UI
export EVENT_HISTORY_DB=./events.sqlite
uv run uvicorn ui.main:app --reload
Sources: ui/README.md:1-20
Imperative Wrappers (SDK Style)
The events_suck module provides a utility to wrap an EventBus in an imperative SDK-style client, making event emission feel like standard method calls while maintaining the underlying bus architecture.
const SDKClient = events_suck.wrap('SDKClient', {
create: CreateEvent,
update: UpdateEvent,
});
const client = new SDKClient(bus);
const user_id = await client.create({ name: 'bob', age: 45 });
Sources: bubus-ts/tests/events_suck.test.ts:7-33
Summary
These examples demonstrate that bubus is designed for high observability and strict type safety. By utilizing class-based event definitions and the automatic parent-child tracking provided by the EventBus, developers can build complex async workflows that remain debuggable through standard logging and the provided web dashboard.