fedimint_cursed_redb/
native.rs1use std::path::Path;
2
3use anyhow::{Context as _, Result};
4use fedimint_db_locked::{Locked, LockedBuilder};
5use redb::Database;
6
7use crate::MemAndRedb;
8
9impl MemAndRedb {
10 pub async fn new(db_path: impl AsRef<Path>) -> Result<Locked<MemAndRedb>> {
11 let db_path = db_path.as_ref();
12 fedimint_core::task::block_in_place(|| Self::open_blocking(db_path))
13 }
14
15 fn open_blocking(db_path: &Path) -> Result<Locked<MemAndRedb>> {
16 std::fs::create_dir_all(
17 db_path
18 .parent()
19 .ok_or_else(|| anyhow::anyhow!("db path must have a base dir"))?,
20 )?;
21 LockedBuilder::new(db_path)?.with_db(|| {
22 let db = match Database::create(db_path) {
23 Ok(db) => db,
24 Err(redb::DatabaseError::UpgradeRequired(_)) => {
25 Self::migrate_v2_to_v3(db_path)?;
26 Database::create(db_path)
27 .context("Failed to open redb database after v2->v3 migration")?
28 }
29 Err(e) => {
30 return Err(anyhow::Error::from(e))
31 .context("Failed to create/open redb database");
32 }
33 };
34 Self::new_from_redb(db).map_err(|e| anyhow::Error::msg(e.to_string()))
35 })
36 }
37
38 fn migrate_v2_to_v3(db_path: &Path) -> Result<()> {
39 tracing::info!("Migrating redb database from v2 to v3 file format");
40 let mut old_db = redb2::Database::open(db_path)
41 .context("Failed to open redb v2 database for migration")?;
42 old_db
43 .upgrade()
44 .context("Failed to upgrade redb database to v3 format")?;
45 tracing::info!("Successfully migrated redb database to v3 format");
46 Ok(())
47 }
48}