This repository has been archived on 2022-03-12. You can view files and clone it, but cannot push or open issues or pull requests.
xuproxy/src/database.rs

91 lines
2.7 KiB
Rust

use log::{error, info};
use rusqlite::{params, OptionalExtension};
use tokio::sync::{
mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
oneshot,
};
#[derive(Debug)]
enum Task {
GetFile(oneshot::Sender<Option<String>>, String),
AddFile(oneshot::Sender<bool>, String, String),
}
pub struct DbExecutor {
rx: UnboundedReceiver<Task>,
db: rusqlite::Connection,
}
impl DbExecutor {
pub fn create(dbpath: &str) -> rusqlite::Result<(Self, ExecutorConnection)> {
let (tx, rx) = unbounded_channel();
let db = rusqlite::Connection::open(dbpath)?;
db.execute(
"create table if not exists files(\
id integer primary key, path text not null, url text not null, \
timestamp integer default (strftime('%s','now')))",
[],
)?;
info!("Database executor '{}' created!", dbpath);
Ok((Self { rx, db }, ExecutorConnection { tx }))
}
pub fn run(&mut self) {
while let Some(task) = self.rx.blocking_recv() {
match task {
Task::GetFile(tx, p) => {
let paste = self
.db
.query_row(
"select url from files where path=? limit 1",
params![p],
|r| r.get(0),
)
.optional()
.unwrap_or_else(|v| {
error!("A database error has occurred: {}", v);
None
});
tx.send(paste).unwrap();
}
Task::AddFile(tx, p, u) => {
if let Err(e) = self
.db
.execute("insert into files(path,url) values(?,?)", params![p, u])
{
error!("A database error has occurred: {}", e);
tx.send(false).unwrap();
} else {
tx.send(true).unwrap();
}
}
}
}
}
}
pub struct ExecutorConnection {
tx: UnboundedSender<Task>,
}
impl Clone for ExecutorConnection {
fn clone(&self) -> Self {
Self {
tx: self.tx.clone(),
}
}
}
impl ExecutorConnection {
pub async fn add_file(&self, path: String, url: String) -> bool {
let (otx, orx) = oneshot::channel();
self.tx.send(Task::AddFile(otx, path, url)).unwrap();
orx.await.unwrap()
}
pub async fn get_file(&self, path: String) -> Option<String> {
let (otx, orx) = oneshot::channel();
self.tx.send(Task::GetFile(otx, path)).unwrap();
orx.await.unwrap()
}
}