91 lines
2.7 KiB
Rust
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()
|
|
}
|
|
}
|