tsoracle-server 0.1.1

Embeddable gRPC server for the timestamp oracle.
Documentation

Crates.io DeepWiki guide CI Coverage Status License

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-openraft ships 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-client handles leader discovery, request coalescing, and reconnection for you.
  • ๐Ÿ“ˆ Operational metrics โ€” enable the metrics feature on tsoracle-server to emit allocator, leader, and request metrics through the metrics facade.
  • ๐Ÿงช 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:

cargo install tsoracle
tsoracle serve

The server listens on 127.0.0.1:50551 and persists state under ./tsoracle-data/.

Then call it from Rust:

use tsoracle_client::Client;

let client = Client::connect(vec!["http://127.0.0.1:50551".into()]).await?;

let ts = client.get_ts().await?;             // a strictly increasing Timestamp
let batch = client.get_ts_batch(64).await?;  // amortize RPC cost across many IDs

Use as a library

Embed the server in your own binary instead of running the CLI:

use tsoracle_server::Server;
use tsoracle_driver_file::FileDriver;

let driver = FileDriver::open_or_init("./tsoracle-data")?;
let server = Server::builder()
    .consensus_driver(driver)
    .build()?;

server
    .serve_with_shutdown("127.0.0.1:50551".parse()?, async {
        let _ = tokio::signal::ctrl_c().await;
    })
    .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 ConsensusDriver contract, and operational topics (fsync cost, leader handoff, deployment topologies).
  • docs.rs/tsoracle-server โ€” generated API reference.

Examples

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.