Skip to content

snower/ruslock

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ruslock

Rust client for slock.

The crate exposes two independent APIs:

  • ruslock::blocking uses std::net::TcpStream and a reader thread.
  • ruslock::aio uses tokio and async/await.

The blocking API does not wrap a tokio runtime. Both APIs share the same protocol, LockData, error, and primitive logic.

Blocking Quickstart

use ruslock::{LockData, Result};

fn main() -> Result<()> {
    let client = ruslock::blocking::Client::connect("127.0.0.1:5658")?;
    let mut lock = client.lock("order:1001", 5, 10);

    lock.acquire_with_data(LockData::set("aaa"))?;
    lock.release()?;
    client.close();
    Ok(())
}

Async Quickstart

use ruslock::{LockData, Result};

#[tokio::main]
async fn main() -> Result<()> {
    let client = ruslock::aio::Client::connect("127.0.0.1:5658").await?;
    let mut lock = client.lock("order:1001", 5, 10);

    lock.acquire_with_data(LockData::set("aaa")).await?;
    lock.release().await?;
    client.close().await;
    Ok(())
}

Replset

use ruslock::Result;

fn main() -> Result<()> {
    let client = ruslock::blocking::ReplsetClient::connect(
        "127.0.0.1:5658,127.0.0.1:5659",
    )?;
    let mut lock = client.lock("replset-key", 5, 10);
    lock.acquire()?;
    lock.release()?;
    client.close();
    Ok(())
}

Runtime Client Selection

Use ClientHandle when deployment is selected from configuration. A single node creates a normal client backend, while multiple nodes create a replset backend. The business code after construction is identical.

use ruslock::Result;

fn run(nodes: String) -> Result<()> {
    let client = ruslock::blocking::ClientHandle::connect(nodes)?;
    let mut lock = client.lock("order:1001", 5, 10);

    lock.acquire()?;
    lock.release()?;
    client.close();
    Ok(())
}
use ruslock::Result;

async fn run(nodes: String) -> Result<()> {
    let client = ruslock::aio::ClientHandle::connect(nodes).await?;
    let mut lock = client.lock("order:1001", 5, 10);

    lock.acquire().await?;
    lock.release().await?;
    client.close().await;
    Ok(())
}

LockData

use ruslock::LockData;

let data = LockData::pipeline(vec![
    LockData::set("aaa"),
    LockData::append("bbb"),
]);
let encoded = data.encode().unwrap();
assert_eq!(encoded[4], ruslock::protocol::constants::LOCK_DATA_COMMAND_TYPE_PIPELINE);

Feature Flags

  • blocking: synchronous client facade.
  • aio: async tokio client facade.
  • replset: replset facade.
  • default: ["blocking", "aio", "replset"].

Tests

Unit and mock transport tests do not require a server:

cargo test --all-features

Java parity and integration tests use a local slock endpoint. Defaults match the Java client tests:

$env:SLOCK_TEST_HOST = "127.0.0.1"
$env:SLOCK_TEST_PORT = "5658"
cargo test --all-features --test java_parity_blocking --test java_parity_async --test java_parity_replset --test java_parity_lock_data --test java_parity_flow_tree

The benchmark parity test is ignored by default:

cargo test --all-features --test java_parity_benchmark -- --ignored

About

slock rust client

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages