Filesystem Bridges
Relevant source files
The following files were used as context for generating this wiki page:
Filesystem Bridges provide a mechanism for inter-process communication (IPC) and event persistence by leveraging the local filesystem. These bridges allow different instances of an EventBus to communicate across process boundaries by reading from and writing to shared files or local databases.
The primary implementations include JSONLEventBridge, which uses newline-delimited JSON files, and SQLiteEventBridge, which utilizes a local SQLite database. These bridges are designed for environments where a full-scale message broker is unavailable or unnecessary, providing a lightweight, file-backed alternative for event distribution.
Sources: bubus-ts/src/bridge_jsonl.ts:18-21, bubus-ts/src/bridge_sqlite.ts:36-39, bubus-ts/src/bridges.ts:304-308
JSONL Event Bridge
The JSONLEventBridge implements a filesystem-based event transport using JSON Lines (JSONL). Each event is serialized as a single-line JSON object and appended to a target file. Other processes monitor this file for new lines to ingest events into their local buses.
Architecture and Data Flow
The bridge operates by maintaining a byte offset into the target file. When starting, it records the current file size and only processes data appended after that point. A polling loop periodically checks for new content.
The diagram shows the bidirectional flow: events are appended to the file for outbound communication and polled from the file for inbound communication.
Sources: bubus-ts/src/bridge_jsonl.ts:55-60, bubus-ts/src/bridge_jsonl.ts:89-100
Implementation Details
The bridge uses a polling mechanism defined by poll_interval. It handles transient filesystem errors and ignores malformed lines during the parsing phase.
| Component | Description |
|---|---|
dispatch(event) | Appends a JSON-stringified representation of the event followed by a newline to the file. |
listenLoop() | The background task that repeatedly calls pollNewLines based on the poll_interval. |
readAppended() | Efficiently reads only the new data from the file using the stored byte_offset. |
dispatchInboundPayload() | Reconstructs a BaseEvent from the JSON payload and dispatches it to the internal bus. |
Sources: bubus-ts/src/bridge_jsonl.ts:74-87, bubus-ts/src/bridge_jsonl.ts:130-155
SQLite Event Bridge
The SQLiteEventBridge provides a more robust filesystem bridge by using a SQLite database. This bridge supports structured storage, indexing, and WAL (Write-Ahead Logging) mode for improved concurrency between multiple processes.
Database Schema
The bridge automatically ensures the existence of a table (defaulting to bubus_events) with a specific schema designed to hold event metadata and the full event payload.
| Column | Type | Description |
|---|---|---|
event_id | TEXT | Primary Key; the unique identifier for the event. |
event_created_at | TEXT | Timestamp of event creation, used for cursor-based polling. |
event_type | TEXT | The class name/type of the event. |
event_payload | JSON | The full serialized event data. |
Additional columns starting with event_ are dynamically added to the table schema if they exist in the dispatched event's fields.
Sources: bubus-ts/src/bridge_sqlite.ts:109-114, bubus-ts/src/bridge_sqlite.ts:228-243
Synchronization Logic
The SQLiteEventBridge uses a cursor-based polling approach. It tracks the last_seen_event_created_at and last_seen_event_id to ensure that it only processes new events in chronological order.
This sequence illustrates how the bridge maintains its position in the event stream to avoid duplicate processing.
Sources: bubus-ts/src/bridge_sqlite.ts:153-170, bubus-ts/src/bridge_sqlite.ts:260-269
Socket Event Bridge
The SocketEventBridge utilizes Unix Domain Sockets (UDS) for local IPC. While technically interacting with the filesystem via a socket file, it provides stream-oriented communication rather than persistent file storage.
Connection Lifecycle
- Initialization: Validates the socket path length (limited to 90 characters for compatibility).
- Starting: If acting as a listener, it unlinks any existing file at the path and creates a new server.
- Communication: Events are sent as JSON strings followed by a newline character (
\n) over the socket connection.
Sources: bubus-ts/src/bridges.ts:46-51, bubus-ts/src/bridges.ts:241-255
Configuration and Compatibility
Filesystem bridges are primarily supported in Node.js runtimes due to their reliance on node:fs, node:net, and node:sqlite.
Optional Dependencies
Bridges check for environment compatibility and required modules before starting.
| Bridge | Dependency | Runtime Requirement |
|---|---|---|
JSONLEventBridge | node:fs | Node.js |
SQLiteEventBridge | node:sqlite | Node.js 22+ |
SocketEventBridge | node:net, node:fs | Node.js |
Sources: bubus-ts/src/bridge_sqlite.ts:102-108, bubus-ts/src/optional_deps.ts:1-12, bubus-ts/src/bridges.ts:23-26
Common Options
| Parameter | Type | Default | Description |
|---|---|---|---|
path | string | (Required) | The filesystem path to the file, database, or socket. |
poll_interval | number | 0.25 | Frequency (in seconds) to check for updates. |
name | string | Auto-generated | Internal name for the bridge's inbound EventBus. |
Sources: bubus-ts/src/bridge_jsonl.ts:23-25, bubus-ts/src/bridge_sqlite.ts:36-41
Conclusion
Filesystem Bridges within the bubus project enable robust, local IPC by utilizing common filesystem primitives. By offering both simple append-only logs via JSONLEventBridge and structured, indexed storage via SQLiteEventBridge, the system provides flexible options for cross-process event synchronization and persistence without requiring external network services.