1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
//! # RapidDB
//! A reasonably fast configurable embedded key-value sensor database
//!
//! ## Features
//! - Simple and flexible optional embedded REST API
//! - Simple key-value database interface
//! - Lightweight embedded database
//! - Store sensor data inside a sensor database
//! - Memory first with on-disk persistence
//! - Memory Mapped Append-only Vector backing storage
//! - Bring your own database or API implementation
//!
//! ## Documentation
//! Visit the [Documentation](https://docs.rs/rapiddb).
//!
//! ## 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
//! ```no_run
//! #[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
//! ```no_run
//! 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);
//! assert_eq!(db.write().unwrap().get_latest("test-0"), value);
//! ```
//!
//! Extending the functionality of the REST API with custom endpoints
//! using warp Filters and custom aggregates
//! ```no_run
//! use std::{
//! collections::HashMap,
//! sync::{Arc, Mutex, RwLock},
//! };
//!
//! use rapiddb::traits::IDatabase;
//!
//! use warp::{Filter, Rejection, Reply};
//!
//! /// GET /api/custom/:String/latest
//! pub fn get_latest_custom(
//! db: std::sync::Arc<std::sync::RwLock<dyn IDatabase>>,
//! ) -> impl Filter<Extract = impl Reply, Error = Rejection> + 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<Mutex<dyn Fn(&str, &[u8], &Arc<Mutex<Vec<u8>>>) + Send>>,
//! > = Default::default();
//!
//! let test_fn = Arc::new(Mutex::new(
//! |_: &str, value: &[u8], aggregate: &Arc<Mutex<Vec<u8>>>| {
//! let obj = serde_json::from_slice::<serde_json::Value>(value)
//! .unwrap_or_default();
//!
//! 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();
//! },
//! ));
//!
//! aggregates_fn.insert("test-0".to_string(), test_fn.clone());
//! aggregates_fn.insert("test-1".to_string(), test_fn);
//!
//! let db = Arc::new(RwLock::new(
//! rapiddb::db::MMAVDatabase::new_with_all(".db", aggregates_fn),
//! ));
//!
//! let value = b"{\"key\": \"value\"}";
//! db.write().unwrap().post("test-0", value);
//! assert_eq!(db.write().unwrap().get_latest("test-0"), value);
//!
//! warp::serve(
//! rapiddb::api::endpoints(db.clone()).or(get_latest_custom(db)),
//! )
//! .run(([0, 0, 0, 0], 3030))
//! .await;
//! }
//! ```
pub mod api;
pub mod db;
pub mod errors;
pub mod traits;