mirror of
https://github.com/aljazceru/cdk.git
synced 2025-12-19 13:44:55 +01:00
Drop the in-memory database (#613)
* Drop the in-memory database Fixes #607 This PR drops the implementation of in-memory database traits. They are useful for testing purposes since the tests should test our codebase and assume the database works as expected (although a follow-up PR should write a sanity test suite for all database trait implementors). As complexity is worth with database requirements to simplify complexity and add more robustness, for instance, with the following plans to add support for transactions or buffered writes, it would become more complex and time-consuming to support a correct database trait. This PR drops the implementation and replaces it with a SQLite memory instance * Remove OnceCell<Mint> Without this change, a single Mint is shared for all tests, and the first tests to run and shutdown makes the other databases (not-reachable, as dropping the tokio engine would also drop the database instance). There is no real reason, other than perhaps performance. The mint should perhaps run in their own tokio engine and share channels as API interfaces, or a new instance should be created in each tests * Fixed bug with foreign keys [1] https://gist.github.com/crodas/bad00997c63bd5ac58db3c5bd90747ed * Show more debug on failure * Remove old code * Remove old references to WalletMemoryDatabase
This commit is contained in:
29
crates/cdk-sqlite/src/common.rs
Normal file
29
crates/cdk-sqlite/src/common.rs
Normal file
@@ -0,0 +1,29 @@
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
||||
use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions};
|
||||
use sqlx::{Error, Pool, Sqlite};
|
||||
|
||||
#[inline(always)]
|
||||
pub async fn create_sqlite_pool(path: &str) -> Result<Pool<Sqlite>, Error> {
|
||||
let db_options = SqliteConnectOptions::from_str(path)?
|
||||
.busy_timeout(Duration::from_secs(10))
|
||||
.read_only(false)
|
||||
.pragma("busy_timeout", "5000")
|
||||
.pragma("journal_mode", "wal")
|
||||
.pragma("synchronous", "normal")
|
||||
.pragma("temp_store", "memory")
|
||||
.pragma("mmap_size", "30000000000")
|
||||
.shared_cache(true)
|
||||
.create_if_missing(true);
|
||||
|
||||
let pool = SqlitePoolOptions::new()
|
||||
.min_connections(1)
|
||||
.max_connections(1)
|
||||
.idle_timeout(None)
|
||||
.max_lifetime(None)
|
||||
.connect_with(db_options)
|
||||
.await?;
|
||||
|
||||
Ok(pool)
|
||||
}
|
||||
@@ -3,6 +3,8 @@
|
||||
#![warn(missing_docs)]
|
||||
#![warn(rustdoc::bare_urls)]
|
||||
|
||||
mod common;
|
||||
|
||||
#[cfg(feature = "mint")]
|
||||
pub mod mint;
|
||||
#[cfg(feature = "wallet")]
|
||||
|
||||
61
crates/cdk-sqlite/src/mint/memory.rs
Normal file
61
crates/cdk-sqlite/src/mint/memory.rs
Normal file
@@ -0,0 +1,61 @@
|
||||
//! In-memory database that is provided by the `cdk-sqlite` crate, mainly for testing purposes.
|
||||
use std::collections::HashMap;
|
||||
|
||||
use cdk_common::common::LnKey;
|
||||
use cdk_common::database::{self, MintDatabase};
|
||||
use cdk_common::mint::{self, MintKeySetInfo, MintQuote};
|
||||
use cdk_common::nuts::{CurrencyUnit, Id, MeltBolt11Request, Proofs};
|
||||
use cdk_common::MintInfo;
|
||||
use uuid::Uuid;
|
||||
|
||||
use super::MintSqliteDatabase;
|
||||
|
||||
/// Creates a new in-memory [`MintSqliteDatabase`] instance
|
||||
pub async fn empty() -> Result<MintSqliteDatabase, database::Error> {
|
||||
let db = MintSqliteDatabase::new(":memory:").await?;
|
||||
db.migrate().await;
|
||||
Ok(db)
|
||||
}
|
||||
|
||||
/// Creates a new in-memory [`MintSqliteDatabase`] instance with the given state
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn new_with_state(
|
||||
active_keysets: HashMap<CurrencyUnit, Id>,
|
||||
keysets: Vec<MintKeySetInfo>,
|
||||
mint_quotes: Vec<MintQuote>,
|
||||
melt_quotes: Vec<mint::MeltQuote>,
|
||||
pending_proofs: Proofs,
|
||||
spent_proofs: Proofs,
|
||||
melt_request: Vec<(MeltBolt11Request<Uuid>, LnKey)>,
|
||||
mint_info: MintInfo,
|
||||
) -> Result<MintSqliteDatabase, database::Error> {
|
||||
let db = empty().await?;
|
||||
|
||||
for active_keyset in active_keysets {
|
||||
db.set_active_keyset(active_keyset.0, active_keyset.1)
|
||||
.await?;
|
||||
}
|
||||
|
||||
for keyset in keysets {
|
||||
db.add_keyset_info(keyset).await?;
|
||||
}
|
||||
|
||||
for quote in mint_quotes {
|
||||
db.add_mint_quote(quote).await?;
|
||||
}
|
||||
|
||||
for quote in melt_quotes {
|
||||
db.add_melt_quote(quote).await?;
|
||||
}
|
||||
|
||||
db.add_proofs(pending_proofs, None).await?;
|
||||
db.add_proofs(spent_proofs, None).await?;
|
||||
|
||||
for (melt_request, ln_key) in melt_request {
|
||||
db.add_melt_request(melt_request, ln_key).await?;
|
||||
}
|
||||
|
||||
db.set_mint_info(mint_info).await?;
|
||||
|
||||
Ok(db)
|
||||
}
|
||||
@@ -3,7 +3,6 @@
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use bitcoin::bip32::DerivationPath;
|
||||
@@ -20,35 +19,28 @@ use cdk_common::{
|
||||
};
|
||||
use error::Error;
|
||||
use lightning_invoice::Bolt11Invoice;
|
||||
use sqlx::sqlite::{SqliteConnectOptions, SqlitePool, SqlitePoolOptions, SqliteRow};
|
||||
use sqlx::Row;
|
||||
use sqlx::sqlite::SqliteRow;
|
||||
use sqlx::{Pool, Row, Sqlite};
|
||||
use uuid::fmt::Hyphenated;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::common::create_sqlite_pool;
|
||||
|
||||
pub mod error;
|
||||
pub mod memory;
|
||||
|
||||
/// Mint SQLite Database
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MintSqliteDatabase {
|
||||
pool: SqlitePool,
|
||||
pool: Pool<Sqlite>,
|
||||
}
|
||||
|
||||
impl MintSqliteDatabase {
|
||||
/// Create new [`MintSqliteDatabase`]
|
||||
pub async fn new(path: &Path) -> Result<Self, Error> {
|
||||
let path = path.to_str().ok_or(Error::InvalidDbPath)?;
|
||||
let db_options = SqliteConnectOptions::from_str(path)?
|
||||
.busy_timeout(Duration::from_secs(5))
|
||||
.read_only(false)
|
||||
.create_if_missing(true)
|
||||
.auto_vacuum(sqlx::sqlite::SqliteAutoVacuum::Full);
|
||||
|
||||
let pool = SqlitePoolOptions::new()
|
||||
.max_connections(1)
|
||||
.connect_with(db_options)
|
||||
.await?;
|
||||
|
||||
Ok(Self { pool })
|
||||
pub async fn new<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
|
||||
Ok(Self {
|
||||
pool: create_sqlite_pool(path.as_ref().to_str().ok_or(Error::InvalidDbPath)?).await?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Migrate [`MintSqliteDatabase`]
|
||||
|
||||
12
crates/cdk-sqlite/src/wallet/memory.rs
Normal file
12
crates/cdk-sqlite/src/wallet/memory.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
//! Wallet in memory database
|
||||
|
||||
use cdk_common::database::Error;
|
||||
|
||||
use super::WalletSqliteDatabase;
|
||||
|
||||
/// Creates a new in-memory [`WalletSqliteDatabase`] instance
|
||||
pub async fn empty() -> Result<WalletSqliteDatabase, Error> {
|
||||
let db = WalletSqliteDatabase::new(":memory:").await?;
|
||||
db.migrate().await;
|
||||
Ok(db)
|
||||
}
|
||||
@@ -16,33 +16,27 @@ use cdk_common::{
|
||||
SpendingConditions, State,
|
||||
};
|
||||
use error::Error;
|
||||
use sqlx::sqlite::{SqliteConnectOptions, SqlitePool, SqliteRow};
|
||||
use sqlx::{ConnectOptions, Row};
|
||||
use sqlx::sqlite::SqliteRow;
|
||||
use sqlx::{Pool, Row, Sqlite};
|
||||
use tracing::instrument;
|
||||
|
||||
use crate::common::create_sqlite_pool;
|
||||
|
||||
pub mod error;
|
||||
pub mod memory;
|
||||
|
||||
/// Wallet SQLite Database
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct WalletSqliteDatabase {
|
||||
pool: SqlitePool,
|
||||
pool: Pool<Sqlite>,
|
||||
}
|
||||
|
||||
impl WalletSqliteDatabase {
|
||||
/// Create new [`WalletSqliteDatabase`]
|
||||
pub async fn new(path: &Path) -> Result<Self, Error> {
|
||||
let path = path.to_str().ok_or(Error::InvalidDbPath)?;
|
||||
let _conn = SqliteConnectOptions::from_str(path)?
|
||||
.journal_mode(sqlx::sqlite::SqliteJournalMode::Wal)
|
||||
.read_only(false)
|
||||
.create_if_missing(true)
|
||||
.auto_vacuum(sqlx::sqlite::SqliteAutoVacuum::Full)
|
||||
.connect()
|
||||
.await?;
|
||||
|
||||
let pool = SqlitePool::connect(path).await?;
|
||||
|
||||
Ok(Self { pool })
|
||||
pub async fn new<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
|
||||
Ok(Self {
|
||||
pool: create_sqlite_pool(path.as_ref().to_str().ok_or(Error::InvalidDbPath)?).await?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Migrate [`WalletSqliteDatabase`]
|
||||
|
||||
Reference in New Issue
Block a user