A standalone timestamp oracle for Rust โ strictly monotonic, gap-free integer timestamps over gRPC, with pluggable consensus.
Features
- ๐ข Monotonic & gap-free โ every issued timestamp is strictly greater than the last; no skipped or repeated values, ever.
- ๐ก๏ธ Crash-safe โ window state is fsync'd before any timestamp in that window is handed out, so a restart never rewinds.
- ๐ Pluggable consensus, openraft included โ
tsoracle-driver-openraftships a production-ready replicated driver; implement one trait (ConsensusDriver) to back tsoracle with raft-rs, etcd, or your own replicated log instead. - ๐ฆ gRPC client included โ
tsoracle-clienthandles leader discovery, request coalescing, and reconnection for you. - ๐ Operational metrics โ enable the
metricsfeature ontsoracle-serverto emit allocator, leader, and request metrics through themetricsfacade. - ๐งช Hardened โ coverage-guided fuzzing on the postcard decoders, failpoint-driven crash tests, and a stress harness covering single-process and multi-process raft topologies.
- ๐งฉ Embeddable โ host the server inside your own binary with a few lines of Rust, or run the standalone CLI.
Quickstart
Install the standalone binary and start the server:
The server listens on 127.0.0.1:50551 and persists state under ./tsoracle-data/.
Then call it from Rust:
use Client;
let client = connect.await?;
let ts = client.get_ts.await?; // a strictly increasing Timestamp
let batch = client.get_ts_batch.await?; // amortize RPC cost across many IDs
Use as a library
Embed the server in your own binary instead of running the CLI:
use Server;
use FileDriver;
let driver = open_or_init?;
let server = builder
.consensus_driver
.build?;
server
.serve_with_shutdown
.await?;
A complete, runnable version lives in examples/embedded-server. Want to mount tsoracle inside an existing tonic server? See Server::into_router.
What's a TSO?
A timestamp oracle is a service that hands out strictly increasing integer IDs which order events across a distributed system. You reach for one when:
- You're building a database with snapshot isolation or MVCC (Spanner, TiDB, CockroachDB, FoundationDB all use a TSO internally).
- You need to merge change-data from many shards into one globally ordered stream.
- You want audit logs with a real "happens-before" relation across machines.
- Per-host clocks aren't monotonic or accurate enough, and database sequences don't scale to your workload.
tsoracle is a small, embeddable Rust implementation. The consensus layer is left as a trait, so you can run it single-node behind one fsync (the default), or wire it into a replicated log of your choice.
Documentation
- DeepWiki โ prose documentation covering the window allocator, the
ConsensusDrivercontract, and operational topics (fsync cost, leader handoff, deployment topologies). - docs.rs/tsoracle-server โ generated API reference.
Examples
- examples/embedded-server โ embed
tsoracle-serverwith the file driver in your own binary, with graceful shutdown. - examples/failover-demo โ pedagogy: watch the failover fence keep timestamps strictly monotonic across simulated leadership changes, in-process, no openraft.
- For HA, use
tsoracle-driver-openraft; seeexamples/openraft-standalone(your own dedicated raft) andexamples/openraft-piggyback(share your service's existing raft).
Each example is its own crate. Build with cargo run -p example-<name>.
Contributing
Issues and pull requests are welcome. See CONTRIBUTING.md for local setup, the checks CI will run on your PR, commit message conventions, and the release process.
Contributors
Made with contrib.rocks.
License
Licensed under Apache-2.0.