RapidDB

A reasonably fast configurable embedded key-value sensor database

Features

Documentation

Visit the Documentation.

Getting Started

Docker

Run database with docker bash docker run -dit --rm -p 3030:3030 --name rapiddb ghcr.io/kruserr/rapiddb/rapiddb

Git and cargo

Clone the repo and build the database from source bash git clone https://github.com/kruserr/rapiddb.git cd rapiddb cargo run --release

Add to your cargo project

Add the following to your dependencies in Cargo.toml toml tokio = { version = "1", features = ["full"] } warp = "0.3" rapiddb = "0.1.7"

Paste the following to your main.rs ```rust

[tokio::main]

async fn main() { let db = std::sync::Arc::new(std::sync::RwLock::new( rapiddb::db::MMAVDatabase::new(), ));

warp::serve(rapiddb::api::endpoints(db)) .run(([0, 0, 0, 0], 3030)) .await; } ```

Run the database with cargo bash cargo run --release

Interact with the database using curl

Write to database with curl bash curl -X POST localhost:3030/api/v0/test-0 -H 'Content-Type: application/json' -d '{"temp":4.00}'

Read from database with curl bash curl localhost:3030/api/v0/test-0/latest

Explore the API with curl bash curl localhost:3030/api/v0 curl localhost:3030/api/v0/sensors curl localhost:3030/api/v0/test-0

Explore and customize the database

The database is highly customizable, if you use the database inside your cargo project. You can interact with the db object, and explore the IDatabase interface. You can also use warp::Filter to extend the API. You can also implement the IDatabase interface yourself, for your own database. Explore the docs to learn more, or look at the examples below, or inside the repo.

Examples

Using the database directly ```rust use rapiddb::traits::IDatabase;

let db = std::sync::Arc::new( std::sync::RwLock::new( rapiddb::db::MMAVDatabase::new() ) );

let value = b"{\"key\": \"value\"}"; db.write().unwrap().post("test-0", value); asserteq!(db.write().unwrap().getlatest("test-0"), value); ```

Extending the functionality of the REST API with custom endpoints using warp Filters and custom aggregates ```rust use std::{ collections::HashMap, sync::{Arc, Mutex, RwLock}, };

use rapiddb::traits::IDatabase;

use warp::{Filter, Rejection, Reply};

/// GET /api/custom/:String/latest pub fn getlatestcustom( db: std::sync::Arc>, ) -> impl Filter + Clone { warp::path!("api" / "custom" / String / "latest") .and(warp::get()) .map(move |id: String| { let mut lock = db.write().unwrap(); let result = lock.get_latest(&id);

  if !result.is_empty() {
    return warp::hyper::Response::builder()
      .status(warp::http::StatusCode::OK)
      .body(result);
  }

  warp::hyper::Response::builder()
    .status(warp::http::StatusCode::NOT_FOUND)
    .body(Default::default())
})

}

[tokio::main]

async fn main() { let mut aggregates_fn: HashMap< String, Arc>>) + Send>>,

= Default::default();

let testfn = Arc::new(Mutex::new( |: &str, value: &[u8], aggregate: &Arc>>| { let obj = serdejson::fromslice::(value) .unwrapordefault();

  if obj["temp"].is_null() {
    return;
  }

  aggregate
    .lock()
    .map(|mut x| {
      let mut aggregate_obj =
        serde_json::from_slice::<serde_json::Value>(&x)
          .unwrap_or_default();

      let mut temp_sum =
        aggregate_obj["temp_sum"].as_f64().unwrap_or_default();
      let mut temp_sum_count = aggregate_obj["temp_sum_count"]
        .as_f64()
        .unwrap_or_default();

      temp_sum += obj["temp"].as_f64().unwrap_or_default();
      temp_sum_count += 1.;
      let temp_avg = temp_sum / temp_sum_count;

      aggregate_obj["temp_sum"] = serde_json::json!(temp_sum);
      aggregate_obj["temp_sum_count"] =
        serde_json::json!(temp_sum_count);
      aggregate_obj["temp_avg"] = serde_json::json!(temp_avg);

      *x = aggregate_obj.to_string().as_bytes().to_vec();
    })
    .err();
},

));

aggregatesfn.insert("test-0".tostring(), testfn.clone()); aggregatesfn.insert("test-1".tostring(), testfn);

let db = Arc::new(RwLock::new( rapiddb::db::MMAVDatabase::newwithall(".db", aggregates_fn), ));

let value = b"{\"key\": \"value\"}"; db.write().unwrap().post("test-0", value); asserteq!(db.write().unwrap().getlatest("test-0"), value);

warp::serve( rapiddb::api::endpoints(db.clone()).or(getlatestcustom(db)), ) .run(([0, 0, 0, 0], 3030)) .await; } ```