use super::{Database, DatabaseClient};
use crate::db;
use crate::errors::*;
use crate::signed::Signed;
use crate::sync;
use async_trait::async_trait;
use sequoia_openpgp::Fingerprint;
use tokio::sync::mpsc;
pub enum Query {
AddRelease(Fingerprint, Signed, mpsc::Sender<String>),
IndexFromScan(sync::TreeQuery, mpsc::Sender<(String, usize)>),
Spill(Vec<u8>, mpsc::Sender<Vec<(db::Key, db::Value)>>),
GetValue(Vec<u8>, mpsc::Sender<db::Value>),
Count(Vec<u8>, mpsc::Sender<u64>),
}
#[derive(Debug)]
pub struct DatabaseServer {
db: Database,
rx: mpsc::Receiver<Query>,
}
impl DatabaseServer {
pub fn new(db: Database) -> (DatabaseServer, DatabaseServerClient) {
let (tx, rx) = mpsc::channel(32);
let server = DatabaseServer { db, rx };
let client = DatabaseServerClient { tx };
(server, client)
}
pub async fn run(&mut self) -> Result<()> {
while let Some(msg) = self.rx.recv().await {
match msg {
Query::AddRelease(fp, signed, tx) => {
let hash = self.db.add_release(&fp, &signed).await?;
tx.send(hash).await.ok();
}
Query::IndexFromScan(query, tx) => {
let ret = self.db.index_from_scan(&query).await?;
tx.send(ret).await.ok();
}
Query::Spill(prefix, tx) => {
let ret = self.db.spill(&prefix).await?;
tx.send(ret).await.ok();
}
Query::GetValue(key, tx) => {
let ret = self.db.get_value(&key).await?;
tx.send(ret).await.ok();
}
Query::Count(key, tx) => {
let ret = self.db.count(&key).await?;
tx.send(ret).await.ok();
}
}
}
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct DatabaseServerClient {
tx: mpsc::Sender<Query>,
}
impl DatabaseServerClient {
async fn request<T>(&self, query: Query, mut rx: mpsc::Receiver<T>) -> Result<T> {
self.tx
.send(query)
.await
.map_err(|_| anyhow!("Database server disconnected"))?;
let ret = rx.recv().await.context("Database server disconnected")?;
Ok(ret)
}
}
#[async_trait]
impl DatabaseClient for DatabaseServerClient {
async fn add_release(&mut self, fp: &Fingerprint, signed: &Signed) -> Result<String> {
let (tx, rx) = mpsc::channel(1);
let query = Query::AddRelease(fp.clone(), signed.clone(), tx);
self.request(query, rx).await
}
async fn index_from_scan(&mut self, query: &sync::TreeQuery) -> Result<(String, usize)> {
let (tx, rx) = mpsc::channel(1);
let query = Query::IndexFromScan(query.clone(), tx);
self.request(query, rx).await
}
async fn spill(&self, prefix: &[u8]) -> Result<Vec<(db::Key, db::Value)>> {
let (tx, rx) = mpsc::channel(1);
let query = Query::Spill(prefix.to_vec(), tx);
self.request(query, rx).await
}
async fn get_value(&self, key: &[u8]) -> Result<db::Value> {
let (tx, rx) = mpsc::channel(1);
let query = Query::GetValue(key.to_vec(), tx);
self.request(query, rx).await
}
async fn count(&mut self, key: &[u8]) -> Result<u64> {
let (tx, rx) = mpsc::channel(1);
let query = Query::Count(key.to_vec(), tx);
self.request(query, rx).await
}
}