use std::{collections::BTreeMap, sync::Arc};
use monsta_proto::*;
use tokio::sync::Mutex;
use crate::{collection::Collection, Error, Result};
#[derive(Clone)]
pub struct Database {
inner: Arc<Mutex<Inner>>,
}
struct Inner {
desc: DatabaseDesc,
collections: BTreeMap<u64, Collection>,
collection_ids: BTreeMap<String, u64>,
next_collection_id: u64,
}
impl Database {
pub fn new(id: u64, spec: DatabaseSpec) -> Self {
let desc = DatabaseDesc {
id,
name: spec.name,
};
let inner = Inner {
desc,
collections: BTreeMap::new(),
collection_ids: BTreeMap::new(),
next_collection_id: 1,
};
Self {
inner: Arc::new(Mutex::new(inner)),
}
}
pub async fn desc(&self) -> DatabaseDesc {
let inner = self.inner.lock().await;
inner.desc.clone()
}
pub async fn collection(&self, id: u64) -> Option<Collection> {
let inner = self.inner.lock().await;
inner.collections.get(&id).cloned()
}
pub async fn create_collection(&self, spec: CollectionSpec) -> Result<Collection> {
let mut inner = self.inner.lock().await;
if inner.collection_ids.contains_key(&spec.name) {
return Err(Error::AlreadyExists(format!(
"collection name {}",
spec.name
)));
}
let id = inner.next_collection_id;
inner.next_collection_id += 1;
let name = spec.name.clone();
let co = Collection::new(inner.desc.id, id, spec);
inner.collections.insert(id, co.clone());
inner.collection_ids.insert(name, id);
Ok(co)
}
pub async fn lookup_collection(&self, name: &str) -> Option<Collection> {
let inner = self.inner.lock().await;
inner
.collection_ids
.get(name)
.and_then(|id| inner.collections.get(id).cloned())
}
pub async fn execute_transaction(&self, _: DatabaseTxnRequest) -> Result<DatabaseTxnResponse> {
todo!()
}
}