Skip to content

Commit

Permalink
refactor: lock the whole transaction in memory store
Browse files Browse the repository at this point in the history
  • Loading branch information
yxonic committed Jun 5, 2022
1 parent db4114f commit 24e466f
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 21 deletions.
98 changes: 96 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions rcommunity_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ edition = "2021"

[dependencies]
async-trait = "0.1.56"
parking_lot = "0.12.1"
thiserror = "1.0.31"
tracing = "0.1.34"

[dev-dependencies]
tokio = { version = "1.19.0", features = ["macros", "rt-multi-thread"] }
3 changes: 1 addition & 2 deletions rcommunity_core/src/backend.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use async_trait::async_trait;

use crate::{
error::Error, query::reaction, Enumerable, ItemType, Multiple, Numerical, Once, ReactionType,
UserType, WithData,
error::Error, Enumerable, ItemType, Multiple, Numerical, Once, ReactionType, UserType, WithData,
};

#[async_trait]
Expand Down
7 changes: 5 additions & 2 deletions rcommunity_core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// clippy settings
#![warn(clippy::pedantic)]
#![allow(clippy::module_name_repetitions)]
// toggle unstable features
#![allow(incomplete_features)]
#![feature(specialization)]
#![feature(associated_type_defaults)]
#![feature(negative_impls)]

pub mod error;
pub mod traits;
Expand Down
7 changes: 4 additions & 3 deletions rcommunity_core/src/markers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ impl<T: ReactionType> store::Storable for T {
}
default async fn store_unique_index(
&self,
txn: &mut impl Transaction,
user: &impl UserType,
item: &impl ItemType,
_txn: &mut impl Transaction,
_user: &impl UserType,
_item: &impl ItemType,
) -> Result<()> {
// by default do nothing
Ok(())
}
}
Expand Down
42 changes: 35 additions & 7 deletions rcommunity_core/src/store/memory.rs
Original file line number Diff line number Diff line change
@@ -1,39 +1,61 @@
use async_trait::async_trait;
use std::sync::RwLock;
use parking_lot::Mutex;
use std::{collections::BTreeMap, sync::Arc};

use crate::error::Result;

use super::{Store, Transaction};

type StringMap = Arc<RwLock<BTreeMap<String, String>>>;
type StringMap = BTreeMap<String, String>;

#[derive(Debug, Default)]
pub struct MemoryStore {
pub store: StringMap,
pub store: Arc<Mutex<StringMap>>,
}

impl Default for MemoryStore {
fn default() -> Self {
MemoryStore {
store: Arc::new(Mutex::new(StringMap::new())),
}
}
}

#[async_trait]
impl Store for MemoryStore {
type Trans = MemoryTransaction;
async fn txn_begin(&self) -> Result<MemoryTransaction> {
// remain locked for this whole transaction
let guard = self.store.lock();
std::mem::forget(guard);
Ok(MemoryTransaction {
store: self.store.clone(),
})
}
}

pub struct MemoryTransaction {
store: StringMap,
store: Arc<Mutex<StringMap>>,
}

impl MemoryTransaction {
fn get_map(&self) -> &StringMap {
unsafe { self.store.data_ptr().as_ref().unwrap() }
}
fn get_map_mut(&mut self) -> &mut StringMap {
unsafe { self.store.data_ptr().as_mut().unwrap() }
}
}

#[async_trait]
impl Transaction for MemoryTransaction {
async fn get(&self, key: String) -> Result<Option<String>> {
Ok(self.store.read().unwrap().get(&key).map(String::from))
Ok(self.get_map().get(&key).map(String::from))
}
async fn get_for_update(&mut self, key: String) -> Result<Option<String>> {
self.get(key).await
}
async fn put(&mut self, key: String, value: String) -> Result<()> {
self.store.write().unwrap().insert(key, value);
self.get_map_mut().insert(key, value);
Ok(())
}
async fn commit(&mut self) -> Result<()> {
Expand All @@ -43,3 +65,9 @@ impl Transaction for MemoryTransaction {
unimplemented!();
}
}

impl Drop for MemoryTransaction {
fn drop(&mut self) {
unsafe { self.store.force_unlock() };
}
}
1 change: 1 addition & 0 deletions rcommunity_core/src/store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub trait Store {
#[async_trait]
pub trait Transaction: Send {
async fn get(&self, key: String) -> Result<Option<String>>;
async fn get_for_update(&mut self, key: String) -> Result<Option<String>>;
async fn put(&mut self, key: String, value: String) -> Result<()>;
async fn commit(&mut self) -> Result<()>;
async fn rollback(&mut self) -> Result<()>;
Expand Down
5 changes: 0 additions & 5 deletions rcommunity_core/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ pub trait UserType: Clone + Sync + Unique {}
pub trait ItemType: Clone + Sync + Unique {}
pub trait ReactionType: Clone + Sync {}

// user type can't be reaction type
impl<T> !UserType for T where T: ReactionType {}

pub trait WithData: Unique + ReactionType {
type Item;
}
Expand All @@ -23,5 +20,3 @@ pub trait Once: ReactionType {
const IS_ONCE: bool = true;
}
pub trait Multiple: ReactionType {}
// reaction is either once or multiple
impl<T> !Once for T where T: Multiple {}

0 comments on commit 24e466f

Please sign in to comment.