DCBDB is an event store designed for dynamic consistency boundaries with a gRPC interface. It provides a robust foundation for event-driven architectures where consistency boundaries may shift based on business requirements.
DCBDB stores data in a single paged file with fixed-size pages and an MVCC, copy-on-write update strategy. A small header node records the transaction sequence number (TSN), the next free PageID, and the roots for three B+ trees: the events tree (ordered by monotonically increasing Position), the tags tree (for tag-based indexing), and the free-lists tree (for reusable page IDs). Writers never mutate pages in place: they allocate new pages, write modified nodes, and on commit atomically publish a new header that points to the new roots; readers hold a TSN and can continue traversing the old roots safely. Large event payloads are split across overflow pages and referenced from leaf records, while small payloads are stored inline. This design yields crash-safe commits, concurrent readers without blocking, and efficient space reuse via the free-lists tree.
-
Build the project:
cargo build --release
-
Start the gRPC server:
./target/release/grpc_server --path /path/to/event-store
-
In another terminal, run the example client:
./target/release/example_client
This will start a server, connect to it with the example client, append an event, and then read all events in the database.
To build the project, you need to have Rust and Cargo installed. If you don't have them installed, you can get them from rustup.rs.
Once you have Rust and Cargo installed, you can build the project with:
cargo build --release
This will create the executable in target/release/
.
The gRPC server can be started using the grpc_server
binary. You can run it directly after building:
./target/release/grpc_server --path /path/to/event-store --address 127.0.0.1:50051
Or you can use cargo run
(dev build, slower):
cargo run --bin grpc_server -- --path /path/to/event-store --address 127.0.0.1:50051
The gRPC server accepts the following command-line options:
-p, --path <PATH>
: Path to the event store directory (required)-a, --address <ADDR>
: Address to listen on (default: "127.0.0.1:50051")-h, --help
: Print help information-V, --version
: Print version information
You can interact with the gRPC server using any gRPC client. The server implements the following methods:
Read
: Read events from the event storeAppend
: Append events to the event store
DCBDB includes an example client that you can use to interact with the gRPC server. You can run it with:
cargo run --bin example_client -- --address http://127.0.0.1:50051
The example client:
- Connects to the gRPC server
- Appends an event to the event store
- Reads events from the event store using a query
- Displays the events that were read
DCBDB provides a Rust client that you can use to interact with the gRPC server in your own code. Here's an example of how to use it:
use dcbdb::api::{DCBEvent, DCBEventStoreAPI, DCBQuery, DCBQueryItem};
use dcbdb::grpc::GrpcEventStoreClient;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Connect to the gRPC server
let client = GrpcEventStoreClient::connect("http://127.0.0.1:50051").await?;
// Append an event
let event = DCBEvent {
event_type: "example".to_string(),
tags: vec!["tag1".to_string(), "tag2".to_string()],
data: b"Hello, world!".to_vec(),
};
let position = client.append(vec![event], None)?;
println!("Appended event at position: {}", position);
// Read events
let query = DCBQuery {
items: vec![DCBQueryItem {
types: vec!["example".to_string()],
tags: vec!["tag1".to_string()],
}],
};
let response = client.read(Some(query), None, None)?;
// Iterate through the events
for event in response {
println!("Event at position {}: {:?}", event.position, event.event);
}
Ok(())
}
You can also use other gRPC clients to interact with the server. The protocol definition is in the proto/event_store.proto
file.
- The event store is stored in the directory specified by the
--path
option. - The server listens on the address specified by the
--address
option. - The server uses the gRPC protocol for communication.
- The server is implemented in Rust and uses the Tokio runtime for asynchronous I/O.
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.