mirror of
https://github.com/Start9Labs/patch-db.git
synced 2026-03-30 12:01:57 +00:00
fix locking behaviour to use single db exclusively
This commit is contained in:
@@ -200,19 +200,22 @@ pub struct Store {
|
|||||||
}
|
}
|
||||||
impl Store {
|
impl Store {
|
||||||
pub async fn open<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
|
pub async fn open<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
|
||||||
if !path.as_ref().exists() {
|
let (_lock, path) = {
|
||||||
tokio::fs::File::create(path.as_ref()).await?;
|
if !path.as_ref().exists() {
|
||||||
}
|
tokio::fs::File::create(path.as_ref()).await?;
|
||||||
let path = tokio::fs::canonicalize(path).await?;
|
|
||||||
let _lock = {
|
|
||||||
let mut lock = OPEN_STORES.lock().await;
|
|
||||||
if let Some(open) = lock.get(&path) {
|
|
||||||
open.clone().lock().await.unwrap()
|
|
||||||
} else {
|
|
||||||
let tex = Qutex::new(());
|
|
||||||
lock.insert(path.clone(), tex.clone());
|
|
||||||
tex.lock().await.unwrap()
|
|
||||||
}
|
}
|
||||||
|
let path = tokio::fs::canonicalize(path).await?;
|
||||||
|
let mut lock = OPEN_STORES.lock().await;
|
||||||
|
(
|
||||||
|
if let Some(open) = lock.get(&path) {
|
||||||
|
open.clone().lock().await.unwrap()
|
||||||
|
} else {
|
||||||
|
let tex = Qutex::new(());
|
||||||
|
lock.insert(path.clone(), tex.clone());
|
||||||
|
tex.lock().await.unwrap()
|
||||||
|
},
|
||||||
|
path,
|
||||||
|
)
|
||||||
};
|
};
|
||||||
Ok(tokio::task::spawn_blocking(move || {
|
Ok(tokio::task::spawn_blocking(move || {
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate as patch_db;
|
use crate as patch_db;
|
||||||
|
use patch_db_macro::HasModel;
|
||||||
use proptest::prelude::*;
|
use proptest::prelude::*;
|
||||||
use tokio::{fs, runtime::Builder};
|
use tokio::{fs, runtime::Builder};
|
||||||
use patch_db_macro::HasModel;
|
|
||||||
|
|
||||||
async fn init_db(db_name: String) -> PatchDb {
|
async fn init_db(db_name: String) -> PatchDb {
|
||||||
cleanup_db(&db_name).await;
|
cleanup_db(&db_name).await;
|
||||||
@@ -17,7 +17,8 @@ async fn init_db(db_name: String) -> PatchDb {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await.unwrap();
|
.await
|
||||||
|
.unwrap();
|
||||||
db
|
db
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,36 +28,33 @@ async fn cleanup_db(db_name: &String) {
|
|||||||
|
|
||||||
async fn put_string_into_root(db: PatchDb, s: String) -> Arc<Revision> {
|
async fn put_string_into_root(db: PatchDb, s: String) -> Arc<Revision> {
|
||||||
println!("trying string: {}", s);
|
println!("trying string: {}", s);
|
||||||
db.put(
|
db.put(&JsonPointer::<&'static str>::default(), &s)
|
||||||
&JsonPointer::<&'static str>::default(),
|
.await
|
||||||
&s
|
.unwrap()
|
||||||
)
|
|
||||||
.await.unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn basic() {
|
async fn basic() {
|
||||||
let db = init_db("basic.test.db".to_string()).await;
|
let db = init_db("test.db".to_string()).await;
|
||||||
let ptr: JsonPointer = "/b/b".parse().unwrap();
|
let ptr: JsonPointer = "/b/b".parse().unwrap();
|
||||||
let mut get_res: Value = db.get(&ptr).await.unwrap();
|
let mut get_res: Value = db.get(&ptr).await.unwrap();
|
||||||
assert_eq!(get_res, 1);
|
assert_eq!(get_res, 1);
|
||||||
db.put(&ptr, &"hello").await.unwrap();
|
db.put(&ptr, &"hello").await.unwrap();
|
||||||
get_res = db.get(&ptr).await.unwrap();
|
get_res = db.get(&ptr).await.unwrap();
|
||||||
assert_eq!(get_res, "hello");
|
assert_eq!(get_res, "hello");
|
||||||
cleanup_db(&"basic.test.db".to_string()).await;
|
cleanup_db(&"test.db".to_string()).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn transaction() {
|
async fn transaction() {
|
||||||
let db = init_db("transaction.test.db".to_string()).await;
|
let db = init_db("test.db".to_string()).await;
|
||||||
let mut tx = db.begin();
|
let mut tx = db.begin();
|
||||||
let ptr: JsonPointer = "/b/b".parse().unwrap();
|
let ptr: JsonPointer = "/b/b".parse().unwrap();
|
||||||
tx.put(&ptr, &(2 as usize)).await.unwrap();
|
tx.put(&ptr, &(2 as usize)).await.unwrap();
|
||||||
tx.put(&ptr, &(1 as usize)).await.unwrap();
|
tx.put(&ptr, &(1 as usize)).await.unwrap();
|
||||||
let _res = tx.commit().await.unwrap();
|
let _res = tx.commit().await.unwrap();
|
||||||
println!("res = {:?}", _res);
|
println!("res = {:?}", _res);
|
||||||
cleanup_db(&"transaction.test.db".to_string()).await;
|
cleanup_db(&"test.db".to_string()).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
proptest! {
|
proptest! {
|
||||||
@@ -69,10 +67,10 @@ proptest! {
|
|||||||
.thread_stack_size(3 * 1024 * 1024)
|
.thread_stack_size(3 * 1024 * 1024)
|
||||||
.build()
|
.build()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let db = runtime.block_on(init_db("doesnt_crash.test.db".to_string()));
|
let db = runtime.block_on(init_db("test.db".to_string()));
|
||||||
let put_future = put_string_into_root(db, s);
|
let put_future = put_string_into_root(db, s);
|
||||||
runtime.block_on(put_future);
|
runtime.block_on(put_future);
|
||||||
runtime.block_on(cleanup_db(&"doesnt_crash.test.db".to_string()));
|
runtime.block_on(cleanup_db(&"test.db".to_string()));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user