FDB blob storage support
This commit is contained in:
@@ -50,7 +50,7 @@ async fn test_1(db: Store) {
|
||||
for id in 0..100 {
|
||||
handles.push({
|
||||
let db = db.clone();
|
||||
tokio::spawn(async move { db.assign_document_id(0, 0).await })
|
||||
tokio::spawn(async move { db.assign_document_id(0, u8::MAX).await })
|
||||
});
|
||||
expected_ids.insert(id);
|
||||
}
|
||||
@@ -80,9 +80,9 @@ async fn test_2(db: Store) {
|
||||
// Create document ids and try reassigning
|
||||
let mut expected_ids = AHashSet::new();
|
||||
let mut batch = BatchBuilder::new();
|
||||
batch.with_account_id(0).with_collection(0);
|
||||
batch.with_account_id(0).with_collection(u8::MAX);
|
||||
for pos in 0..100 {
|
||||
let id = db.assign_document_id(0, 0).await.unwrap();
|
||||
let id = db.assign_document_id(0, u8::MAX).await.unwrap();
|
||||
if pos % 2 == 0 {
|
||||
batch.create_document(id);
|
||||
} else {
|
||||
@@ -95,14 +95,14 @@ async fn test_2(db: Store) {
|
||||
tokio::time::sleep(Duration::from_secs(3)).await;
|
||||
|
||||
for _ in 0..expected_ids.len() {
|
||||
let id = db.assign_document_id(0, 0).await.unwrap();
|
||||
let id = db.assign_document_id(0, u8::MAX).await.unwrap();
|
||||
assert!(
|
||||
expected_ids.remove(&id),
|
||||
"already assigned or invalid: {id}"
|
||||
);
|
||||
}
|
||||
assert_eq!(db.assign_document_id(0, 0).await.unwrap(), 100);
|
||||
assert_eq!(db.assign_document_id(0, 0).await.unwrap(), 101);
|
||||
assert_eq!(db.assign_document_id(0, u8::MAX).await.unwrap(), 100);
|
||||
assert_eq!(db.assign_document_id(0, u8::MAX).await.unwrap(), 101);
|
||||
|
||||
db.destroy().await;
|
||||
}
|
||||
@@ -111,7 +111,7 @@ async fn test_3(db: Store) {
|
||||
// Try reassigning deleted ids
|
||||
let mut expected_ids = AHashSet::new();
|
||||
let mut batch = BatchBuilder::new();
|
||||
batch.with_account_id(0).with_collection(0);
|
||||
batch.with_account_id(0).with_collection(u8::MAX);
|
||||
for id in 0..100 {
|
||||
if id % 2 == 0 {
|
||||
batch.create_document(id);
|
||||
@@ -121,14 +121,14 @@ async fn test_3(db: Store) {
|
||||
}
|
||||
db.write(batch.build()).await.unwrap();
|
||||
for _ in 0..expected_ids.len() {
|
||||
let id = db.assign_document_id(0, 0).await.unwrap();
|
||||
let id = db.assign_document_id(0, u8::MAX).await.unwrap();
|
||||
assert!(
|
||||
expected_ids.remove(&id),
|
||||
"already assigned or invalid: {id}"
|
||||
);
|
||||
}
|
||||
assert_eq!(db.assign_document_id(0, 0).await.unwrap(), 100);
|
||||
assert_eq!(db.assign_document_id(0, 0).await.unwrap(), 101);
|
||||
assert_eq!(db.assign_document_id(0, u8::MAX).await.unwrap(), 100);
|
||||
assert_eq!(db.assign_document_id(0, u8::MAX).await.unwrap(), 101);
|
||||
|
||||
db.destroy().await;
|
||||
}
|
||||
|
||||
@@ -52,7 +52,6 @@ path = "{TMP}/db.db?mode=rwc"
|
||||
#[tokio::test]
|
||||
pub async fn blob_tests() {
|
||||
let temp_dir = TempDir::new("blob_tests", true);
|
||||
let mut blob_store = None;
|
||||
|
||||
for (store_id, store_cfg) in [("s3", CONFIG_S3), ("fs", CONFIG_LOCAL)] {
|
||||
let config =
|
||||
@@ -65,20 +64,24 @@ pub async fn blob_tests() {
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
println!("Testing store {}...", store_id);
|
||||
println!("Testing blob store {}...", store_id);
|
||||
test_store(blob_store_.clone()).await;
|
||||
blob_store = Some(blob_store_);
|
||||
}
|
||||
let blob_store = blob_store.unwrap();
|
||||
|
||||
// Start SQLite store
|
||||
// Init store
|
||||
let store: Store = SqliteStore::open(
|
||||
//let store: Store = FdbStore::open(
|
||||
&Config::new(&CONFIG_DB.replace("{TMP}", temp_dir.path.as_path().to_str().unwrap()))
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.into();
|
||||
store.destroy().await;
|
||||
|
||||
// Test internal blob store
|
||||
let blob_store: BlobStore = store.clone().into();
|
||||
test_store(blob_store.clone()).await;
|
||||
|
||||
// Blob hash exists
|
||||
let hash = BlobHash::from(b"abc".as_slice());
|
||||
@@ -387,17 +390,76 @@ pub async fn blob_tests() {
|
||||
}
|
||||
|
||||
async fn test_store(store: BlobStore) {
|
||||
// Test small blob
|
||||
const DATA: &[u8] = b"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce erat nisl, dignissim a porttitor id, varius nec arcu. Sed mauris.";
|
||||
let hash = BlobHash::from(DATA);
|
||||
|
||||
store.put_blob(b"abc", DATA).await.unwrap();
|
||||
store.put_blob(hash.as_slice(), DATA).await.unwrap();
|
||||
assert_eq!(
|
||||
String::from_utf8(store.get_blob(b"abc", 0..u32::MAX).await.unwrap().unwrap()).unwrap(),
|
||||
String::from_utf8(
|
||||
store
|
||||
.get_blob(hash.as_slice(), 0..u32::MAX)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
)
|
||||
.unwrap(),
|
||||
std::str::from_utf8(DATA).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
String::from_utf8(store.get_blob(b"abc", 11..57).await.unwrap().unwrap()).unwrap(),
|
||||
String::from_utf8(
|
||||
store
|
||||
.get_blob(hash.as_slice(), 11..57)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
)
|
||||
.unwrap(),
|
||||
std::str::from_utf8(&DATA[11..57]).unwrap()
|
||||
);
|
||||
assert!(store.delete_blob(b"abc").await.unwrap());
|
||||
assert!(store.get_blob(b"abc", 0..u32::MAX).await.unwrap().is_none());
|
||||
assert!(store.delete_blob(hash.as_slice()).await.unwrap());
|
||||
assert!(store
|
||||
.get_blob(hash.as_slice(), 0..u32::MAX)
|
||||
.await
|
||||
.unwrap()
|
||||
.is_none());
|
||||
|
||||
// Test large blob
|
||||
let mut data = Vec::with_capacity(50 * 1024 * 1024);
|
||||
while data.len() < 50 * 1024 * 1024 {
|
||||
data.extend_from_slice(DATA);
|
||||
let marker = format!(" [{}] ", data.len());
|
||||
data.extend_from_slice(marker.as_bytes());
|
||||
}
|
||||
let hash = BlobHash::from(&data);
|
||||
store.put_blob(hash.as_slice(), &data).await.unwrap();
|
||||
assert_eq!(
|
||||
String::from_utf8(
|
||||
store
|
||||
.get_blob(hash.as_slice(), 0..u32::MAX)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
)
|
||||
.unwrap(),
|
||||
std::str::from_utf8(&data).unwrap()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
String::from_utf8(
|
||||
store
|
||||
.get_blob(hash.as_slice(), 3000111..4000999)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
)
|
||||
.unwrap(),
|
||||
std::str::from_utf8(&data[3000111..4000999]).unwrap()
|
||||
);
|
||||
assert!(store.delete_blob(hash.as_slice()).await.unwrap());
|
||||
assert!(store
|
||||
.get_blob(hash.as_slice(), 0..u32::MAX)
|
||||
.await
|
||||
.unwrap()
|
||||
.is_none());
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ use std::io::Read;
|
||||
|
||||
use ::store::Store;
|
||||
|
||||
use store::backend::sqlite::SqliteStore;
|
||||
use store::backend::{foundationdb::FdbStore, sqlite::SqliteStore};
|
||||
use utils::config::Config;
|
||||
|
||||
pub struct TempDir {
|
||||
@@ -49,7 +49,8 @@ pub async fn store_tests() {
|
||||
temp_dir.path.display(),
|
||||
temp_dir.path.display()
|
||||
);
|
||||
let db: Store = SqliteStore::open(&Config::new(&config_file).unwrap())
|
||||
//let db: Store = SqliteStore::open(&Config::new(&config_file).unwrap())
|
||||
let db: Store = FdbStore::open(&Config::new(&config_file).unwrap())
|
||||
.await
|
||||
.unwrap()
|
||||
.into();
|
||||
|
||||
Reference in New Issue
Block a user