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

feat(db-arch): ctx functions and use of global db #2378

Open
wants to merge 6 commits into
base: dev
Choose a base branch
from

Conversation

mariocynicys
Copy link
Collaborator

The first PR in the series of PRs related to database architecture changes. Changes here won't have effect on builds since they are guarded with a new-db-arch feature flag.

This adds some utility methods in the context to get the global & wallet & address databases and data directories.

Also adds some concrete usages of the global db.

pub fn global_dir(&self) -> Result<PathBuf, String> {
let path = path_to_db_root(self.conf["dbdir"].as_str()).join("global");
if !path.exists() {
std::fs::create_dir_all(&path).map_err(|e| format!("Failed to create global directory: {}", e))?;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i opted for this io to be sync to avoid the ripple effect it will cause if it's async (it is A LOT esp in address db usage).

The path will probably always exist (for global and wallet dirs) anyways unless this is the first run.
For address dirs, "first runs" happen more frequently, but still, by no means a lot.

Copy link
Member

@borngraced borngraced left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Welldone!

if !path.exists() {
std::fs::create_dir_all(&path).map_err(|e| format!("Failed to create wallet directory: {}", e))?;
}
Ok(path)
Copy link
Member

@borngraced borngraced Mar 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we probably should add a new field to MmCtx e.tg rmd160_hex and initialize once same place rmd160 is initialized.

This will enable us to avoid constructing hex::encode(self.rmd160().as_slice()) every time we need to call wallet_dir and similar functions

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aha agreed. there is a lot of room for optimizations really (e.g. cache connections and return arcs to them). but i didn't wanna optimize early on to not make the review harder.
we def can add this now. or else wait till the skeleton is ready and target unoptimized code then (it should be abstracted behind funcs like these, so the optimization then wouldn't really bloat the review).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

by caching the connection, we don't re-calculate the hex every call to wallet DB.
01b7085

Comment on lines +75 to +81
// TODO: Can't use `conn` in the return statement because it's a mutex borrow, and also clippy complains when assigning the result into a temporary `result`.
#[allow(clippy::let_and_return)]
let result = conn
.prepare(SELECT_PEERS_NAMES)?
.query_map([], |row| Ok((row.get(0)?, row.get(1)?)))?
.collect::<SqlResult<HashMap<String, String>>>()
.collect::<SqlResult<HashMap<String, String>>>();
result
Copy link
Member

@borngraced borngraced Mar 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

conn is not dropped at the right place!. In this case, we need to explicitly drop conn after we're done with it.

pub fn select_peers_names(ctx: &MmArc) -> SqlResult<HashMap<String, String>, SqlError> {
    #[cfg(not(feature = "new-db-arch"))]
    let conn = ctx.sqlite_connection();
    #[cfg(feature = "new-db-arch")]
    let conn = ctx.global_db().unwrap();
    let peers_names = conn
        .prepare(SELECT_PEERS_NAMES)?
        .query_map([], |row| Ok((row.get(0)?, row.get(1)?)))?
        .collect::<SqlResult<HashMap<String, String>>>();
    drop(conn);

    peers_names
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ummmm... no it should be dropped since peer_names is owned.

Copy link
Member

@borngraced borngraced Mar 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well, compiler doesn't think so.

conn dropped here while still borrowed
   | ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type std::ops::ControlFlow<std::result::Result<std::convert::Infallible, db_common::sqlite::rusqlite::Error>, db_common::sqlite::rusqlite::Statement<'_>>

Comment on lines 373 to 381
#[cfg(all(feature = "new-db-arch", not(target_arch = "wasm32")))]
pub fn global_db(&self) -> Result<Connection, String> {
// TODO: Initialize this DB on startup and cache it in the context to avoid having this function return `Result`.
// Note that you are using `unwrap`s in the calls to `global_db`.
let path = self.global_dir()?.join("global.db");
log_sqlite_file_open_attempt(&path);
let connection = try_s!(Connection::open(path));
Ok(connection)
}
Copy link
Member

@borngraced borngraced Mar 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/ TODO: Initialize this DB on startup and cache it in the context to avoid having this function return Result.
// Note that you are using unwraps in the calls to global_db.

in addition to doing this, it will help us avoid performing these operations every time the function is called. There similar functions too e.g wallet_dir, async_wallet_db

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines 386 to 413
#[cfg(all(feature = "new-db-arch", not(target_arch = "wasm32")))]
pub fn wallet_db(&self) -> Result<Connection, String> {
// TODO: Initialize this DB on startup and cache it in the context to avoid having this function return `Result`.
let path = self.wallet_dir()?.join("MM2-shared.db");
log_sqlite_file_open_attempt(&path);
let connection = try_s!(Connection::open(path));
Ok(connection)
}

/// Returns an AsyncSQL connection to the shared wallet database.
///
/// This replaces `self.wallet_db()` and should be used for new implementations.
#[cfg(all(feature = "new-db-arch", not(target_arch = "wasm32")))]
pub async fn async_wallet_db(&self) -> Result<AsyncConnection, String> {
let path = self.wallet_dir()?.join("KOMODEFI.db");
log_sqlite_file_open_attempt(&path);
let connection = try_s!(AsyncConnection::open(path).await);
Ok(connection)
}

/// Returns a SQL connection to the address database.
#[cfg(all(feature = "new-db-arch", not(target_arch = "wasm32")))]
pub fn address_db(&self, address: &str) -> Result<Connection, String> {
let path = self.address_dir(address)?.join("MM2.db");
log_sqlite_file_open_attempt(&path);
let connection = try_s!(Connection::open(path));
Ok(connection)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably prefer strictly typed errors instead of Strings on these to be able to handle various error situations in the incoming implementations.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onur-ozkan
onur-ozkan previously approved these changes Mar 6, 2025
Copy link
Member

@onur-ozkan onur-ozkan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am confident that our tests would fail if there was a problem with using an incorrect DB path/connection/etc.

LGTM other than my previous notes.

this avoids re-computations that will result in the same output. this also removes the fallible method annotation from global and wallet db getters, since we know for sure they are initialized and have a copy of them.

note that the name MM2-Shared.db for the wallet db was changed to a simple wallet.db. Also for the async wallet db (KOMODEFI.db), it changes to wallet.db as well for simplicity (merging them/their tables together in the same DB file).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants