monsta-server 0.0.1

Monsta server
Documentation
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!()
    }
}