Skip to content

Commit

Permalink
feat: switch to redb for cache performance
Browse files Browse the repository at this point in the history
  • Loading branch information
oknozor committed Feb 16, 2024
1 parent 63da9a9 commit 33655e3
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 82 deletions.
46 changes: 10 additions & 36 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ iced_core = "0.10.0"
iced_runtime = "0.1.1"
iced_style = "0.9.0"
tokio = { version = "1.29.1", features = ["process", "macros", "io-util"] }
sled = "0.34.7"
redb = "1.5.0"

onagre-launcher-toolkit = "0.1.2"
clap = { version = "^4", features = ["derive"] }
Expand Down
6 changes: 3 additions & 3 deletions src/db/desktop_entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ pub struct DesktopEntryEntity<'a> {
pub weight: u8,
}

impl Entity for DesktopEntryEntity<'_> {
fn get_key(&self) -> Vec<u8> {
self.name.as_bytes().to_vec()
impl<'a> Entity<'a> for DesktopEntryEntity<'a> {
fn get_key(&self) -> Cow<'a, str> {
self.name.clone()
}
fn get_weight(&self) -> u8 {
self.weight
Expand Down
88 changes: 52 additions & 36 deletions src/db/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use once_cell::sync::Lazy;
use std::borrow::Cow;
use std::cmp::Reverse;
use std::fmt::Debug;
use std::sync::Arc;
use tracing::{debug, trace};

use redb::{ReadableTable, TableDefinition};
use serde::de::DeserializeOwned;
use serde::Serialize;

Expand All @@ -14,69 +17,82 @@ pub static DB: Lazy<Database> = Lazy::new(Database::default);

#[derive(Clone, Debug)]
pub struct Database {
inner: sled::Db,
inner: Arc<redb::Database>,
}

impl Default for Database {
fn default() -> Self {
let path = dirs::data_dir().expect("Cannot open data dir");

let path = path.join("onagre");
let path = path.join("onagre-db");
let path = path.as_path();

debug!("Opening database {:?}", path);

let database = match redb::Database::open(path) {
Ok(db) => db,
Err(_err) => redb::Database::create(path).expect("failed to create database"),
};

Database {
inner: sled::open(path).unwrap(),
inner: Arc::new(database),
}
}
}

impl Database {
pub fn insert<T>(&self, collection: &str, entity: &T) -> sled::Result<()>
pub fn insert<'a, T>(&self, collection: &str, entity: &T) -> Result<(), redb::Error>
where
T: Sized + Entity + Serialize,
T: Sized + Entity<'a> + Serialize,
{
let json = serde_json::to_string(entity).expect("Serialization error");

let result = self
.inner
.open_tree(collection)?
.insert(entity.get_key(), json.as_bytes())
.map(|_res| ());

self.inner.flush().expect("Failed to flush database");
result
let db = self.inner.clone();
let write_tnx = db.begin_write()?;
{
let definition = TableDefinition::<&str, &str>::new(collection);
let mut table = write_tnx.open_table(definition)?;
table.insert(entity.get_key().as_ref(), json.as_str())?;
}
write_tnx.commit()?;
Ok(())
}

pub fn get_by_key<T>(&self, collection: &str, key: &str) -> Option<T>
pub fn get_by_key<'a, T>(&self, collection: &str, key: &str) -> Option<T>
where
T: Entity + DeserializeOwned,
T: Entity<'a> + DeserializeOwned,
{
self.inner
.open_tree(collection)
.unwrap()
.get(key.as_bytes())
let definition = TableDefinition::<&str, &str>::new(collection);
let db = self.inner.clone();
let Ok(read_txn) = db.begin_write() else {
return None;
};

let table = read_txn
.open_table(definition)
.expect("failed to open database");
table
.get(key)
.ok()
.flatten()
.map(|data| data.to_vec())
.map(String::from_utf8)
.map(Result::unwrap)
.map(|raw_data| serde_json::from_str(&raw_data))
.map(Result::unwrap)
.map(|data| serde_json::from_str(data.value()))
.and_then(Result::ok)
}

pub fn get_all<T>(&self, collection: &str) -> Vec<T>
pub fn get_all<'a, T>(&self, collection: &str) -> Vec<T>
where
T: Entity + DeserializeOwned + Debug,
T: Entity<'a> + DeserializeOwned + Debug,
{
let mut results: Vec<T> = self
.inner
.open_tree(collection)
.unwrap()
let definition = TableDefinition::<&str, &str>::new(collection);
let db = self.inner.clone();
let Ok(read_txn) = db.begin_write() else {
return vec![];
};
let table = read_txn.open_table(definition).unwrap();
let mut results: Vec<T> = table
.iter()
.map(|res| res.expect("Database error"))
.map(|(_k, v)| String::from_utf8(v.to_vec()).unwrap())
.map(|entity_string| serde_json::from_str(entity_string.as_str()))
.unwrap()
.filter_map(Result::ok)
.map(|(_key, value)| serde_json::from_str(value.value()))
.flat_map(Result::ok)
.collect();

Expand All @@ -90,7 +106,7 @@ impl Database {
}
}

pub trait Entity {
fn get_key(&self) -> Vec<u8>;
pub trait Entity<'a> {
fn get_key(&self) -> Cow<'a, str>;
fn get_weight(&self) -> u8;
}
6 changes: 3 additions & 3 deletions src/db/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ impl PluginCommandEntity<'_> {
}
}

impl Entity for PluginCommandEntity<'_> {
fn get_key(&self) -> Vec<u8> {
self.query.as_bytes().to_vec()
impl<'a> Entity<'a> for PluginCommandEntity<'a> {
fn get_key(&self) -> Cow<'a, str> {
self.query.clone()
}

fn get_weight(&self) -> u8 {
Expand Down
6 changes: 3 additions & 3 deletions src/db/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ impl WebEntity<'_> {
}
}

impl Entity for WebEntity<'_> {
fn get_key(&self) -> Vec<u8> {
self.query().as_bytes().to_vec()
impl<'a> Entity<'a> for WebEntity<'a> {
fn get_key(&self) -> Cow<'a, str> {
self.query.clone()
}

fn get_weight(&self) -> u8 {
Expand Down

0 comments on commit 33655e3

Please sign in to comment.