2024-03-10 04:52:50 +01:00
|
|
|
use jobdispatcher::{JobDispatcher, JobOrder};
|
2024-03-07 16:18:47 +01:00
|
|
|
use rusqlite::Connection;
|
2024-03-10 04:52:50 +01:00
|
|
|
use std::sync::{mpsc::Receiver, Arc};
|
2024-03-07 16:18:47 +01:00
|
|
|
|
2024-03-10 04:52:50 +01:00
|
|
|
pub struct DatabaseBackend {
|
|
|
|
pub file: String,
|
|
|
|
pub conn: Connection,
|
|
|
|
pub dispatcher: Arc<JobDispatcher<Query, Out>>,
|
|
|
|
pub recv: Receiver<JobOrder<Query, Out>>,
|
2024-03-07 16:18:47 +01:00
|
|
|
}
|
|
|
|
|
2024-03-10 04:52:50 +01:00
|
|
|
impl DatabaseBackend {
|
2024-03-07 16:18:47 +01:00
|
|
|
pub fn new(file: &str) -> Self {
|
2024-03-10 04:52:50 +01:00
|
|
|
let (dispatcher, recv) = jobdispatcher::JobDispatcher::<Query, Out>::new();
|
2024-03-07 16:18:47 +01:00
|
|
|
let conn = Connection::open(file).unwrap();
|
2024-03-10 04:52:50 +01:00
|
|
|
|
2024-03-07 16:18:47 +01:00
|
|
|
conn.execute(
|
|
|
|
"CREATE TABLE IF NOT EXISTS urls (
|
|
|
|
id INTEGER PRIMARY KEY,
|
|
|
|
url TEXT NOT NULL,
|
|
|
|
timestamp TEXT NOT NULL
|
|
|
|
)",
|
|
|
|
[],
|
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
|
2024-03-10 04:52:50 +01:00
|
|
|
let dispatcher = Arc::new(dispatcher);
|
2024-03-07 16:18:47 +01:00
|
|
|
Self {
|
|
|
|
file: file.to_string(),
|
2024-03-10 04:52:50 +01:00
|
|
|
conn,
|
|
|
|
dispatcher,
|
|
|
|
recv,
|
2024-03-07 16:18:47 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-10 04:52:50 +01:00
|
|
|
pub fn take_db(&self) -> Database {
|
|
|
|
Database::new(self.dispatcher.clone())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn run(&self) {
|
|
|
|
while let Ok(job) = self.recv.recv() {
|
|
|
|
match job.param {
|
|
|
|
Query::InsertUrl(ref url) => {
|
|
|
|
let timestamp = chrono::Local::now().to_rfc3339();
|
|
|
|
self.conn
|
|
|
|
.execute(
|
|
|
|
"INSERT INTO urls (url, timestamp) VALUES (?, ?)",
|
|
|
|
[url, ×tamp],
|
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
job.done(Out::Ok);
|
|
|
|
}
|
|
|
|
Query::CheckForUrl(ref url) => {
|
|
|
|
let conn = Connection::open(&self.file).unwrap();
|
|
|
|
let mut stmt = conn
|
|
|
|
.prepare("SELECT COUNT(*) FROM urls WHERE url = ?")
|
|
|
|
.unwrap();
|
|
|
|
let count: i64 = stmt.query_row([url], |row| row.get(0)).unwrap();
|
|
|
|
job.done(Out::Bool(count > 0));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub enum Query {
|
|
|
|
InsertUrl(String),
|
|
|
|
CheckForUrl(String),
|
|
|
|
}
|
|
|
|
|
|
|
|
pub enum Out {
|
|
|
|
Ok,
|
|
|
|
Bool(bool),
|
|
|
|
// Rows(Vec<String>),
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct Database {
|
|
|
|
conn: Arc<JobDispatcher<Query, Out>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Database {
|
|
|
|
pub fn new(conn: Arc<JobDispatcher<Query, Out>>) -> Self {
|
|
|
|
Self { conn }
|
2024-03-07 16:18:47 +01:00
|
|
|
}
|
|
|
|
|
2024-03-10 04:52:50 +01:00
|
|
|
pub fn insert_url(&self, url: &str) {
|
|
|
|
self.conn.send(Query::InsertUrl(url.to_string()));
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn check_for_url(&self, url: &str) -> bool {
|
|
|
|
match self.conn.send(Query::CheckForUrl(url.to_string())) {
|
|
|
|
Out::Ok => false,
|
|
|
|
Out::Bool(b) => b,
|
|
|
|
}
|
2024-03-07 16:18:47 +01:00
|
|
|
}
|
|
|
|
}
|