mod collection;
pub mod data;
mod memory;
pub mod query;
#[cfg(feature = "store-nats")]
mod nats;
#[cfg(feature = "store-postgres")]
mod postgres;
#[cfg(feature = "store-redis")]
mod redis;
#[cfg(feature = "store-sled")]
mod sled;
#[cfg(feature = "store-sqlite")]
mod sqlite;
#[allow(clippy::module_inception)]
mod store;
#[cfg(test)]
mod tests;
use data::*;
use serde::{Deserialize, Serialize, de::DeserializeOwned};
use serde_json::Value as JsonValue;
#[allow(unused_imports)]
pub use store::Store;
use crate::{ActError, Result};
use query::*;
use std::error::Error;
use strum::{AsRefStr, EnumIter};
#[allow(unused_imports)]
pub use memory::MemoryStore;
#[cfg(feature = "store-nats")]
#[allow(unused_imports)]
pub use nats::NatsStore;
#[cfg(feature = "store-postgres")]
#[allow(unused_imports)]
pub use postgres::PostgresStore;
#[cfg(feature = "store-redis")]
#[allow(unused_imports)]
pub use redis::RedisStore;
#[cfg(feature = "store-sled")]
#[allow(unused_imports)]
pub use sled::SledStore;
#[cfg(feature = "store-sqlite")]
#[allow(unused_imports)]
pub use sqlite::SqliteStore;
fn map_db_err(err: impl Error) -> ActError {
ActError::Store(err.to_string())
}
#[derive(Debug, Clone, AsRefStr, PartialEq, Hash, Eq, EnumIter)]
pub enum StoreIden {
#[strum(serialize = "packages")]
Packages,
#[strum(serialize = "models")]
Models,
#[strum(serialize = "procs")]
Procs,
#[strum(serialize = "tasks")]
Tasks,
#[strum(serialize = "vars")]
Vars,
#[strum(serialize = "messages")]
Messages,
#[strum(serialize = "deliveries")]
Deliveries,
#[strum(serialize = "events")]
Events,
#[strum(serialize = "ops")]
Ops,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct PageData<T> {
pub count: usize,
pub page_num: usize,
pub page_count: usize,
pub page_size: usize,
pub rows: Vec<T>,
}
pub trait DbCollectionIden {
fn iden() -> StoreIden;
fn indexed_fields() -> &'static [&'static str] {
&[]
}
fn version() -> i32 {
0
}
fn upcast_current(mut value: JsonValue) -> Result<Self>
where
Self: DeserializeOwned,
{
if let JsonValue::Object(ref mut map) = value {
map.entry("v".to_string())
.or_insert_with(|| JsonValue::Number(serde_json::Number::from(0)));
}
serde_json::from_value(value).map_err(map_db_err)
}
fn upcast(value: JsonValue) -> Result<Self>
where
Self: DeserializeOwned,
{
Self::upcast_current(value)
}
}
pub struct ScanOptions {
pub is_rev: bool,
pub op: ScanOperation,
pub prefix: String,
}
impl ScanOptions {
pub fn new(op: ScanOperation, prefix: String, is_rev: bool) -> Self {
Self { is_rev, op, prefix }
}
}
pub enum ScanOperation {
Ne,
Eq,
In { values: Vec<String> },
Range {
lower: Option<String>,
upper: Option<String>,
},
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum StoreBatchOp {
Put { key: String, value: Vec<u8> },
Delete { key: String },
}
#[async_trait::async_trait]
pub trait KvStore: Send + Sync {
async fn get(&self, key: &str) -> Result<Option<Vec<u8>>>;
async fn put(&self, key: &str, value: Vec<u8>) -> Result<()>;
async fn delete(&self, key: &str) -> Result<()>;
async fn batch(&self, ops: &[StoreBatchOp]) -> Result<()> {
for op in ops {
match op {
StoreBatchOp::Put { key, value } => self.put(key, value.clone()).await?,
StoreBatchOp::Delete { key } => self.delete(key).await?,
}
}
Ok(())
}
async fn scan_prefix(&self, key: &str, options: ScanOptions) -> Result<Vec<(String, Vec<u8>)>>;
}
#[async_trait::async_trait]
pub trait DbCollection: Send + Sync {
type Item;
async fn exists(&self, id: &str) -> Result<bool>;
async fn find(&self, id: &str) -> Result<Self::Item>;
async fn query(&self, query: &Query) -> Result<PageData<Self::Item>>;
async fn create(&self, data: &Self::Item) -> Result<bool>;
async fn update(&self, data: &Self::Item) -> Result<bool>;
async fn delete(&self, id: &str) -> Result<bool>;
}