use std::ops::{Deref, DerefMut};
use std::path::PathBuf;
use fs_extra::dir;
use r2d2::PooledConnection;
use r2d2_sqlite::SqliteConnectionManager;
use crate::{
config::LoadConfig,
error::Result,
events::{CrawlerCheckpoint, Profile, SerializedEvent},
Database,
};
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DatabaseStats {
pub size: u64,
pub event_count: u64,
pub room_count: u64,
}
pub struct Connection {
pub(crate) inner: PooledConnection<SqliteConnectionManager>,
pub(crate) path: PathBuf,
}
impl Connection {
pub fn load_checkpoints(&self) -> Result<Vec<CrawlerCheckpoint>> {
let mut stmt = self.prepare(
"SELECT room_id, token, full_crawl, direction
FROM crawlercheckpoints",
)?;
let rows = stmt.query_map([], |row| {
Ok(CrawlerCheckpoint {
room_id: row.get(0)?,
token: row.get(1)?,
full_crawl: row.get(2)?,
direction: row.get(3)?,
})
})?;
let mut checkpoints = Vec::new();
for row in rows {
let checkpoint: CrawlerCheckpoint = row?;
checkpoints.push(checkpoint);
}
Ok(checkpoints)
}
pub fn is_empty(&self) -> Result<bool> {
let event_count: i64 = Database::get_event_count(&self.inner)?;
let checkpoint_count: i64 =
self.query_row("SELECT COUNT(*) FROM crawlercheckpoints", [], |row| {
row.get(0)
})?;
Ok(event_count == 0 && checkpoint_count == 0)
}
pub fn is_room_indexed(&self, room_id: &str) -> Result<bool> {
let event_count: i64 = Database::get_event_count_for_room(&self.inner, room_id)?;
let checkpoint_count: i64 = self.query_row(
"SELECT COUNT(*) FROM crawlercheckpoints WHERE room_id=?1",
[room_id],
|row| row.get(0),
)?;
Ok(event_count != 0 || checkpoint_count != 0)
}
pub fn get_stats(&self) -> Result<DatabaseStats> {
let event_count = Database::get_event_count(&self.inner)? as u64;
let room_count = Database::get_room_count(&self.inner)? as u64;
let size = dir::get_size(&self.path)?;
Ok(DatabaseStats {
size,
event_count,
room_count,
})
}
pub fn load_file_events(
&self,
load_config: &LoadConfig,
) -> Result<Vec<(SerializedEvent, Profile)>> {
Ok(Database::load_file_events(
self,
&load_config.room_id,
load_config.limit,
load_config.from_event.as_deref(),
&load_config.direction,
)?)
}
pub fn get_user_version(&self) -> Result<i64> {
Database::get_user_version(self)
}
pub fn set_user_version(&self, version: i64) -> Result<()> {
Database::set_user_version(self, version)
}
}
impl Deref for Connection {
type Target = PooledConnection<SqliteConnectionManager>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl DerefMut for Connection {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}