#key-value-store #etcd #consul #zookeeper #distributed #interface #different

rsoffkv

A uniform interface for 3 different distributed key-value storages: Zookeeper, Consul, ETCD

8 releases

0.1.8 Apr 14, 2020
0.1.7 Apr 13, 2020
0.1.3 Feb 28, 2020
0.1.1 Jan 24, 2020

#7 in #consul

Apache-2.0 OR MIT

60KB
1K SLoC

C++ 639 SLoC // 0.0% comments Rust 504 SLoC // 0.0% comments Shell 37 SLoC // 0.1% comments

rsoffkv

License Travis CI Travis CI codecov API Crate

This library is designed to provide a uniform interface for 3 different distributed KV-storages: etcd, Zookeeper, Consul.

Rsoffkv is a wrapper around our C++ library liboffkv. Design details can be found in the liboffkv repository.

Build

  • install vcpkg and set VCPKG_ROOT
  • install dependencies (you can build build rsoffkv only for some of the supported KV-storages; in such a case feel free to change the value of ENABLE_ in the build script)
vcpkg install ppconsul offscale-libetcd-cpp zkpp
  • build with cargo
cargo build
  • (optional) run documentation tests
cargo test

Example

use rsoffkv::client::Client;
use rsoffkv::result::OffkvError;

use rsoffkv::txn::{Transaction, TxnCheck, TxnOp, TxnOpResult};

use std::{thread,time};

fn main() {
    // firstly specify service {zk | consul | etcd} and its address
    // you can also specify a prefix all keys will start with
    let client = Client::new("consul://localhost:8500", "/prefix").unwrap();

    // Each method returns std::Result
    match client.create("/key", "value", false) {
        Ok(initial_version) =>
            println!("Key \"/prefix/key\" successfully created. Initial version: {}",
                     initial_version),
        Err(OffkvError::EntryExists) =>
            println!("Error: key \"/prefix/key\" already exists!"),
    };

    // WATCH EXAMPLE
    let (result, watch_handle) = client.exists("/key", true).unwrap();

    thread::spawn(|| {
        let another_client = Client::new("consul://localhost:8500", "/prefix", false).unwrap();
        thread::sleep(time::Duration::from_secs(5));
        another_client.erase("/key", 0).unwrap();
    });

    // now the key exists
    assert!(result);

    // wait for changes
    watch_handle.wait();

    // if the waiting was completed, the existence state must be different
    let (result, _) = client.exists("/key", false).unwrap();
    assert!(!result);

    // TRANSACTION EXAMPLE
    match client.commit(
        // firstly list your checks
        checks: vec![
            TxnCheck{key: "/key", version: initial_version},
        ],
        // then operations
        ops: vec![
            TxnOp::Create{key: "/key/child", value: "value", leased: false},
            TxnOp::Set{key: "/key", value: "new value"},
        ],
    ) {
        // on success a vector with changed version is returned
        Ok(_) => println!("Success!"),
        // on failure an index of the first failed operation is returned
        Err(OffkvError::TxnFailed(failed_op)) => println!("Failed at {}", failed_op),
    };
}

Dependencies

~0.4–370KB