From 3613db8b1ce2d3f2afcfa9eb32ed005bf9f77654 Mon Sep 17 00:00:00 2001 From: yggverse Date: Thu, 30 Jan 2025 13:07:07 +0200 Subject: [PATCH] implement search providers memory cache --- src/profile/search.rs | 75 ++++++++++++++++++++++++++++++++++ src/profile/search/database.rs | 1 + src/profile/search/error.rs | 16 ++++++++ src/profile/search/memory.rs | 39 ++++++++++++++++++ 4 files changed, 131 insertions(+) create mode 100644 src/profile/search.rs create mode 100644 src/profile/search/error.rs create mode 100644 src/profile/search/memory.rs diff --git a/src/profile/search.rs b/src/profile/search.rs new file mode 100644 index 00000000..777ccb18 --- /dev/null +++ b/src/profile/search.rs @@ -0,0 +1,75 @@ +mod database; +mod error; +mod memory; + +use database::Database; +use error::Error; +use memory::Memory; +use sqlite::{Connection, Transaction}; +use std::{rc::Rc, sync::RwLock}; + +pub struct Search { + database: Database, // permanent storage + memory: Memory, // fast search index +} + +impl Search { + // Constructors + + /// Create new `Self` + pub fn build(connection: &Rc>, profile_id: &Rc) -> Self { + // Init children components + let database = Database::init(connection, profile_id); + let memory = Memory::init(); + + // Build initial index + index(&database, &memory); + + // Return new `Self` + Self { database, memory } + } + + // Actions + + /// Get records from the memory index + pub fn records(&self) -> Vec { + self.memory.records() + } + + /// Delete record from `database` and `memory` index + pub fn delete(&self, id: i64) -> Result<(), Error> { + match self.database.delete(id) { + Ok(_) => Ok(index(&self.database, &self.memory)?), + Err(e) => Err(Error::Database(e)), + } + } +} + +// Tools + +pub fn migrate(tx: &Transaction) -> Result<(), String> { + // Migrate self components + if let Err(e) = database::init(tx) { + return Err(e.to_string()); + } + + // Delegate migration to childs + // nothing yet.. + + // Success + Ok(()) +} + +/// Sync memory index with database +fn index(database: &Database, memory: &Memory) -> Result<(), Error> { + memory.clear(); + match database.records() { + Ok(records) => { + for record in records { + memory.push(record.id, record.query, record.is_default) + } + } + Err(e) => return Err(Error::Database(e)), + } + Ok(()) +} diff --git a/src/profile/search/database.rs b/src/profile/search/database.rs index 7b00b3b7..c7f12588 100644 --- a/src/profile/search/database.rs +++ b/src/profile/search/database.rs @@ -1,6 +1,7 @@ use sqlite::{Connection, Error, Transaction}; use std::{rc::Rc, sync::RwLock}; +#[derive(Clone)] pub struct Row { pub id: i64, //pub profile_id: i64, diff --git a/src/profile/search/error.rs b/src/profile/search/error.rs new file mode 100644 index 00000000..a9ab3744 --- /dev/null +++ b/src/profile/search/error.rs @@ -0,0 +1,16 @@ +use std::fmt::{Display, Formatter, Result}; + +#[derive(Debug)] +pub enum Error { + Database(sqlite::Error), +} + +impl Display for Error { + fn fmt(&self, f: &mut Formatter) -> Result { + match self { + Self::Database(e) => { + write!(f, "Database error: {e}") + } + } + } +} diff --git a/src/profile/search/memory.rs b/src/profile/search/memory.rs new file mode 100644 index 00000000..401c3278 --- /dev/null +++ b/src/profile/search/memory.rs @@ -0,0 +1,39 @@ +use super::database::Row; +use std::cell::RefCell; + +/// Reduce disk usage by cache Bookmarks index in memory +pub struct Memory { + index: RefCell>, +} + +impl Memory { + // Constructors + + /// Create new `Self` + pub fn init() -> Self { + Self { + index: RefCell::new(Vec::new()), + } + } + + // Actions + + /// Add new record + pub fn push(&self, id: i64, query: String, is_default: bool) { + self.index.borrow_mut().push(Row { + id, + query, + is_default, + }) + } + + /// Clear all records + pub fn clear(&self) { + self.index.borrow_mut().clear() + } + + /// Get record by `ID` + pub fn records(&self) -> Vec { + self.index.borrow().clone() + } +}