no rwlocks
Some checks failed
ci/woodpecker/push/test Pipeline failed

This commit is contained in:
JMARyA 2025-05-04 23:52:55 +02:00
parent 6c54873ca2
commit dd4cb7fcc6
Signed by: jmarya
GPG key ID: 901B2ADDF27C2263
11 changed files with 36 additions and 26 deletions

7
Cargo.lock generated
View file

@ -106,6 +106,12 @@ dependencies = [
"num-traits", "num-traits",
] ]
[[package]]
name = "arc-swap"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
[[package]] [[package]]
name = "argh" name = "argh"
version = "0.1.13" version = "0.1.13"
@ -1230,6 +1236,7 @@ dependencies = [
name = "owl" name = "owl"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"arc-swap",
"argh", "argh",
"chrono", "chrono",
"crossbeam", "crossbeam",

View file

@ -25,3 +25,4 @@ env_logger = "0.11.8"
parking_lot = { version = "0.12.3", features = ["send_guard"] } parking_lot = { version = "0.12.3", features = ["send_guard"] }
crossbeam = { version = "0.8.4", features = ["crossbeam-channel"] } crossbeam = { version = "0.8.4", features = ["crossbeam-channel"] }
once_cell = "1.21.3" once_cell = "1.21.3"
arc-swap = "1.7.1"

View file

@ -61,10 +61,10 @@ pub fn relation(args: TokenStream, input: TokenStream) -> TokenStream {
let relation_name = struct_name.to_string().to_case(Case::Snake); let relation_name = struct_name.to_string().to_case(Case::Snake);
let expanded = quote! { let expanded = quote! {
#[derive(owl::Serialize, owl::Deserialize, Default)] #[derive(owl::Serialize, owl::Deserialize, Default, Clone)]
#input_struct #input_struct
#[derive(owl::Deserialize, owl::Serialize, Debug)] #[derive(owl::Deserialize, owl::Serialize, Debug, Clone)]
pub struct #struct_ref_name { pub struct #struct_ref_name {
pub id: Id, pub id: Id,
pub inner: owl::db::relation::RelationReference pub inner: owl::db::relation::RelationReference
@ -166,7 +166,7 @@ pub fn model(_: TokenStream, input: TokenStream) -> TokenStream {
let relation_name = struct_name.to_string().to_case(Case::Snake); let relation_name = struct_name.to_string().to_case(Case::Snake);
let expanded = quote! { let expanded = quote! {
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize, Clone)]
#input_struct #input_struct
impl owl::db::store::Saveable for #struct_name {} impl owl::db::store::Saveable for #struct_name {}

View file

@ -4,7 +4,7 @@ use chrono::Utc;
use serde::{Deserialize, Deserializer, Serialize}; use serde::{Deserialize, Deserializer, Serialize};
// historic field // historic field
#[derive(Deserialize, Serialize, Default, Debug, PartialEq)] #[derive(Deserialize, Serialize, Default, Debug, PartialEq, Clone)]
pub struct Historic<T> { pub struct Historic<T> {
pub values: Vec<(chrono::DateTime<Utc>, T)>, pub values: Vec<(chrono::DateTime<Utc>, T)>,
} }

View file

@ -1,3 +1,4 @@
use arc_swap::ArcSwap;
use parking_lot::{RwLock, RwLockReadGuard}; use parking_lot::{RwLock, RwLockReadGuard};
use std::{ use std::{
ops::{Deref, DerefMut}, ops::{Deref, DerefMut},
@ -170,7 +171,7 @@ impl Database {
} }
/// Update every model in `entries` according to `u(_)` /// Update every model in `entries` according to `u(_)`
pub fn update<T: 'static + Serialize + Identifiable + Send + Sync, F: Fn(&mut T)>( pub fn update<T: 'static + Serialize + Identifiable + Send + Sync + Clone, F: Fn(&mut T)>(
&self, &self,
entries: &mut [Model<T>], entries: &mut [Model<T>],
u: F, u: F,
@ -259,7 +260,7 @@ impl Database {
)? )?
}; };
let model = Model { let model = Model {
inner: Arc::new(RwLock::new(m)), inner: Arc::new(ArcSwap::new(Arc::new(m))),
}; };
if self.cached { if self.cached {
@ -284,9 +285,10 @@ impl Database {
} }
let data = data.read(); let data = data.read();
let data = (*data).deref();
unsafe { unsafe {
Store::save(&T::model_id(), data.deref(), self.named, &*self.storage); Store::save(&T::model_id(), data, self.named, &*self.storage);
} }
} }
@ -296,7 +298,7 @@ impl Database {
data: T, data: T,
) -> Model<T> { ) -> Model<T> {
let model = Model { let model = Model {
inner: Arc::new(RwLock::new(data)), inner: Arc::new(ArcSwap::new(Arc::new(data))),
}; };
self.save_model(&model); self.save_model(&model);
let id = model.full_id().to_string(); let id = model.full_id().to_string();
@ -313,7 +315,7 @@ impl Database {
// TODO : cache eviction based on ref counts // TODO : cache eviction based on ref counts
pub struct Model<T> { pub struct Model<T> {
inner: Arc<RwLock<T>>, inner: Arc<ArcSwap<T>>,
} }
impl Model<File> { impl Model<File> {
@ -325,7 +327,7 @@ impl Model<File> {
impl<T: Identifiable> Model<T> { impl<T: Identifiable> Model<T> {
pub fn from_raw(raw: T) -> Model<T> { pub fn from_raw(raw: T) -> Model<T> {
Model { Model {
inner: Arc::new(RwLock::new(raw)), inner: Arc::new(ArcSwap::new(Arc::new(raw))),
} }
} }
@ -337,23 +339,23 @@ impl<T: Identifiable> Model<T> {
self.read().reference() self.read().reference()
} }
pub fn read(&self) -> RwLockReadGuard<T> { pub fn read(&self) -> arc_swap::Guard<Arc<T>> {
self.inner.read() self.inner.load()
} }
} }
impl<T: 'static + Serialize + Identifiable + Send + Sync> Model<T> { impl<T: 'static + Serialize + Identifiable + Send + Sync + Clone> Model<T> {
pub fn write<F: Fn(&mut T)>(&mut self, db: &Database, u: F) { pub fn write<F: Fn(&mut T)>(&mut self, db: &Database, u: F) {
let mut me = self.inner.write(); let mut me = (**self.inner.load()).clone();
u(me.deref_mut()); u(&mut me);
drop(me); self.inner.swap(Arc::new(me));
db.save_model(self); db.save_model(self);
} }
/// Update the model inline without writing to `Database` /// Update the model inline without writing to `Database`
pub fn write_raw_inline<F: Fn(&mut T)>(&mut self, u: F) { pub fn write_raw_inline<F: Fn(&mut T)>(&mut self, u: F) {
let mut me = self.inner.write(); let mut me = (**self.inner.load()).clone();
u(me.deref_mut()); u(&mut me);
drop(me); drop(me);
} }
} }
@ -367,7 +369,7 @@ impl<T: 'static + Serialize + Identifiable + Send + Sync> ModelObj for Model<T>
impl<T> Clone for Model<T> { impl<T> Clone for Model<T> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
inner: Arc::clone(&self.inner), inner: self.inner.clone(),
} }
} }
} }

View file

@ -17,7 +17,7 @@ fn sha256(input: &[u8]) -> String {
} }
/// A generic file /// A generic file
#[derive(Debug, Clone)] #[derive(Debug)]
#[model] #[model]
pub struct File { pub struct File {
id: Id, id: Id,

View file

@ -6,7 +6,7 @@ pub use crate as owl;
use crate::db::id::Id; use crate::db::id::Id;
/// Represents a geographical location with an ID, coordinates, and optional address /// Represents a geographical location with an ID, coordinates, and optional address
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, PartialEq)]
#[model] #[model]
pub struct Location { pub struct Location {
pub id: Id, pub id: Id,

View file

@ -5,7 +5,7 @@ pub use crate as owl;
use crate::db::id::Id; use crate::db::id::Id;
/// Represents a mail address with an ID and the address itself /// Represents a mail address with an ID and the address itself
#[derive(Debug, Clone)] #[derive(Debug)]
#[model] #[model]
pub struct MailAddress { pub struct MailAddress {
/// Unique identifier for the mail address /// Unique identifier for the mail address

View file

@ -32,7 +32,7 @@ pub struct Person {
pub locations: Historic<Vec<IdRef<Location>>>, pub locations: Historic<Vec<IdRef<Location>>>,
} }
#[derive(Deserialize, Serialize, Debug, PartialEq)] #[derive(Deserialize, Serialize, Debug, PartialEq, Clone)]
pub enum Gender { pub enum Gender {
Male, Male,
Female, Female,

View file

@ -5,7 +5,7 @@ pub use crate as owl;
use crate::db::id::Id; use crate::db::id::Id;
/// Represents a phone number with an ID, the phone number itself, and the country code. /// Represents a phone number with an ID, the phone number itself, and the country code.
#[derive(Debug, Clone)] #[derive(Debug)]
#[model] #[model]
pub struct PhoneNumber { pub struct PhoneNumber {
id: Id, id: Id,

View file

@ -437,7 +437,7 @@ impl<
} }
pub trait RelationRef: pub trait RelationRef:
Identifiable + for<'a> Deserialize<'a> + Serialize + Send + Sync + 'static Identifiable + for<'a> Deserialize<'a> + Serialize + Send + Sync + 'static + Clone
{ {
fn top(&self) -> IdRef<serde_json::Value>; fn top(&self) -> IdRef<serde_json::Value>;
fn sub(&self) -> IdRef<serde_json::Value>; fn sub(&self) -> IdRef<serde_json::Value>;
@ -445,7 +445,7 @@ pub trait RelationRef:
fn update_meta(&mut self, weight: Option<f64>, meta: Option<serde_json::Value>); fn update_meta(&mut self, weight: Option<f64>, meta: Option<serde_json::Value>);
} }
#[derive(Deserialize, Serialize, Debug)] #[derive(Deserialize, Serialize, Debug, Clone)]
pub struct RelationReference { pub struct RelationReference {
pub top: IdRef<serde_json::Value>, pub top: IdRef<serde_json::Value>,
pub sub: IdRef<serde_json::Value>, pub sub: IdRef<serde_json::Value>,