Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade native_db to 0.7 #192

Merged
merged 1 commit into from
Jul 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 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 crates/resolute/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ futures-util = "0.3"
path-clean = "1.0"
sha2 = "0.10"
steamlocate = "2.0.0-beta.2"
native_db = { version = "0.6", optional = true }
native_db = { version = "0.7", optional = true }
native_model = { version = "0.4", optional = true }
redb = { version = "2.0", optional = true }

Expand Down
54 changes: 32 additions & 22 deletions crates/resolute/src/db.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,34 @@
use std::{io::ErrorKind, path::Path};

use log::{info, warn};
use native_db::{db_type::Error as NativeDbError, Database, DatabaseBuilder};
use native_db::{db_type::Error as NativeDbError, Builder, Database, Models};
use once_cell::sync::Lazy;
use redb::{DatabaseError, StorageError};

use crate::{mods::ResoluteMod, Error, Result};
use crate::{mods::ResoluteMod, Error, Result as ResoluteResult};

/// Wrapper for interacting with a Resolute database
#[allow(missing_debug_implementations)]
pub struct ResoluteDatabase<'a> {
db: Database<'a>,
}

impl<'a> ResoluteDatabase<'a> {
impl ResoluteDatabase<'_> {
/// Opens a database using a provided builder.
/// If the database doesn't already exist at the given path, it will be created.
pub fn open(builder: &'a DatabaseBuilder, db_path: impl AsRef<Path>) -> Result<Self> {
pub fn open(db_path: impl AsRef<Path>) -> ResoluteResult<Self> {
info!("Opening database at {}", db_path.as_ref().display());

// Try to open an already-existing database
let db = match builder.open(&db_path) {
let builder = Builder::new();
let db = match builder.open(&MODELS, &db_path) {
// If it fails because it doesn't exist, then go ahead and create one instead
Err(
NativeDbError::Io(err)
| NativeDbError::RedbDatabaseError(DatabaseError::Storage(StorageError::Io(err))),
) if err.kind() == ErrorKind::NotFound => {
warn!("Database doesn't exist; creating");
builder.create(&db_path)?
builder.create(&MODELS, &db_path)?
}

Ok(db) => db,
Expand All @@ -37,40 +39,36 @@ impl<'a> ResoluteDatabase<'a> {
Ok(Self { db })
}

/// Defines the database models on a builder
pub fn define_models(builder: &mut DatabaseBuilder) -> Result<()> {
builder.define::<ResoluteMod>()?;
Ok(())
}

/// Retrieves all mods stored in the database
pub fn get_mods(&self) -> Result<Vec<ResoluteMod>> {
pub fn get_mods(&self) -> ResoluteResult<Vec<ResoluteMod>> {
let read = self.db.r_transaction()?;
let mods = read.scan().primary()?.all().collect();
let mods = read.scan().primary()?.all().collect::<Result<_, _>>()?;
Ok(mods)
}

/// Retrieves all mods from the database that have an installed version
pub fn get_installed_mods(&self) -> Result<Vec<ResoluteMod>> {
pub fn get_installed_mods(&self) -> ResoluteResult<Vec<ResoluteMod>> {
let read = self.db.r_transaction()?;
let mods = read
.scan()
.primary()?
.all()
.collect::<Result<Vec<_>, _>>()?
.into_iter()
.filter(|rmod: &ResoluteMod| rmod.installed_version.is_some())
.collect();
Ok(mods)
}

/// Retrieves a single mod from the database by its ID
pub fn get_mod(&self, id: impl AsRef<str>) -> Result<Option<ResoluteMod>> {
pub fn get_mod(&self, id: impl AsRef<str>) -> ResoluteResult<Option<ResoluteMod>> {
let read = self.db.r_transaction()?;
let rmod = read.get().primary(id.as_ref().to_owned())?;
let rmod = read.get().primary(id.as_ref())?;
Ok(rmod)
}

/// Stores a mod in the database (overwrites any existing entry for the same mod)
pub fn store_mod(&self, rmod: ResoluteMod) -> Result<()> {
pub fn store_mod(&self, rmod: ResoluteMod) -> ResoluteResult<()> {
let mod_name = rmod.to_string();

let rw = self.db.rw_transaction()?;
Expand All @@ -82,7 +80,7 @@ impl<'a> ResoluteDatabase<'a> {
}

/// Removes a mod from the database
pub fn remove_mod(&self, rmod: ResoluteMod) -> Result<()> {
pub fn remove_mod(&self, rmod: ResoluteMod) -> ResoluteResult<()> {
let mod_name = rmod.to_string();

// Remove the mod
Expand All @@ -95,13 +93,25 @@ impl<'a> ResoluteDatabase<'a> {
}

/// Removes a mod from the database by its ID
pub fn remove_mod_by_id(&self, id: impl AsRef<str>) -> Result<()> {
pub fn remove_mod_by_id(&self, id: impl AsRef<str>) -> ResoluteResult<()> {
// Find the item in the database
let id = id.as_ref().to_owned();
let id = id.as_ref();
let read = self.db.r_transaction()?;
let rmod: ResoluteMod = read.get().primary(id.clone())?.ok_or_else(|| Error::ItemNotFound(id))?;
let rmod: ResoluteMod = read
.get()
.primary(id)?
.ok_or_else(|| Error::ItemNotFound(id.to_owned()))?;

// Remove it
self.remove_mod(rmod)
}
}

/// Models that a [`ResoluteDatabase`] interacts with
pub static MODELS: Lazy<Models> = Lazy::new(|| {
let mut models = Models::new();
models
.define::<ResoluteMod>()
.expect("Unable to define ResoluteMod model");
models
});
2 changes: 1 addition & 1 deletion crates/resolute/src/mods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use serde::{Deserialize, Serialize};
use url::Url;

#[cfg(feature = "db")]
use native_db::{native_db, InnerKeyValue};
use native_db::{native_db, ToKey};
#[cfg(feature = "db")]
use native_model::{native_model, Model};

Expand Down
2 changes: 0 additions & 2 deletions crates/tauri-app/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ clap = { version = "4.5", features = ["derive"] }
url = "2.5"
log = "0.4"
sha2 = "0.10"
native_db = "0.6"
once_cell = "1.19"
itertools = "0.13"
path-clean = "1.0"
opener = "0.7"
Expand Down
11 changes: 1 addition & 10 deletions crates/tauri-app/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,6 @@ use std::{env, error::Error, io, thread, time::Duration};
use anyhow::{bail, Context};
use clap::Parser;
use log::{debug, error, info, warn, LevelFilter};
use native_db::DatabaseBuilder;
use once_cell::sync::Lazy;
use resolute::{db::ResoluteDatabase, discover, manager::ModManager, manifest};
use tauri::{async_runtime, App, AppHandle, Manager, WebviewUrl, WebviewWindow, WebviewWindowBuilder, WindowEvent};
use tauri_plugin_deep_link::DeepLinkExt;
Expand All @@ -90,13 +88,6 @@ use url::Url;
mod commands;
mod settings;

/// Lazily-initialized database builder for the Resolute DB
static DB_BUILDER: Lazy<DatabaseBuilder> = Lazy::new(|| {
let mut builder = DatabaseBuilder::new();
ResoluteDatabase::define_models(&mut builder).expect("unable to define models on database builder");
builder
});

#[derive(Debug, Parser)]
#[command(version)]
struct Cli {
Expand Down Expand Up @@ -268,7 +259,7 @@ async fn init(app: &AppHandle) -> Result<(), anyhow::Error> {
.app_data_dir()
.context("Unable to get data dir")?
.join("resolute.db");
let db = ResoluteDatabase::open(&DB_BUILDER, db_path).context("Unable to open database")?;
let db = ResoluteDatabase::open(db_path).context("Unable to open database")?;

// Get the Resonite path setting
info!("Retrieving Resonite path from settings store");
Expand Down