9 releases
Uses new Rust 2024
new 0.1.8 | Mar 16, 2025 |
---|---|
0.1.7 | Mar 16, 2025 |
#836 in Database interfaces
179 downloads per month
33KB
561 lines
Overview
This crate implements distributed locking using Cloud Spanner. It relies on Spanner's TrueTime and transactions support to achieve its locking mechanism. It's a port of the original spindle, which is written in Go.
Use cases
One use case for this library is leader election. If you want one host/node/pod to be the leader within a cluster/group, you can achieve that with this crate. When the leader fails, it will fail over to another host/node/pod within a specific timeout.
Usage
At the moment, the table needs to be created beforehand using the following DDL (locktable
is just an example):
CREATE TABLE locktable (
name STRING(MAX) NOT NULL,
heartbeat TIMESTAMP OPTIONS (allow_commit_timestamp=true),
token TIMESTAMP OPTIONS (allow_commit_timestamp=true),
writer STRING(MAX),
) PRIMARY KEY (name)
After creating the lock object, you will call the run()
function which will attempt to acquire a named lock at a regular interval (lease duration). A has_lock()
function is provided which returns true (along with the lock token) if the lock is successfully acquired. Something like:
use spindle_rs::*;
...
fn main() -> Result<(), Box<dyn Error>> {
let (tx, rx) = channel();
ctrlc::set_handler(move || tx.send(()).unwrap()).unwrap();
let mut lock = LockBuilder::new()
.db("projects/p/instances/i/databases/db".to_string())
.table("locktable".to_string()) // see CREATE TABLE
.name("spindle-rs".to_string())
// .id(":8080".to_string())
.duration_ms(5000)
.build();
lock.run();
// Wait for a bit before calling has_lock().
thread::sleep(Duration::from_secs(10));
let (locked, node, token) = lock.has_lock();
println!("has_lock: {locked}, {node}, {token}");
// Wait for Ctrl-C.
rx.recv().unwrap();
lock.close();
Ok(())
}
Example
A sample code is provided to demonstrate the mechanism through logs. You can try running multiple processes in multiple terminals.
$ git clone https://github.com/flowerinthenight/spindle-rs
$ cd spindle-rs/
$ cargo build
# Update args with your actual values:
$ RUST_LOG=info ./target/debug/example \
projects/p/instances/i/databases/db \
locktable
The leader process should output something like leader active (me)
. You can then try to stop (Ctrl+C) that process and observe another one taking over as leader.
License
This library is licensed under the Apache 2.0 License.
Dependencies
~22–33MB
~485K SLoC