This commit is contained in:
parent
6c54873ca2
commit
dd4cb7fcc6
11 changed files with 36 additions and 26 deletions
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -106,6 +106,12 @@ dependencies = [
|
|||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arc-swap"
|
||||
version = "1.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
|
||||
|
||||
[[package]]
|
||||
name = "argh"
|
||||
version = "0.1.13"
|
||||
|
@ -1230,6 +1236,7 @@ dependencies = [
|
|||
name = "owl"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"arc-swap",
|
||||
"argh",
|
||||
"chrono",
|
||||
"crossbeam",
|
||||
|
|
|
@ -25,3 +25,4 @@ env_logger = "0.11.8"
|
|||
parking_lot = { version = "0.12.3", features = ["send_guard"] }
|
||||
crossbeam = { version = "0.8.4", features = ["crossbeam-channel"] }
|
||||
once_cell = "1.21.3"
|
||||
arc-swap = "1.7.1"
|
||||
|
|
|
@ -61,10 +61,10 @@ pub fn relation(args: TokenStream, input: TokenStream) -> TokenStream {
|
|||
let relation_name = struct_name.to_string().to_case(Case::Snake);
|
||||
|
||||
let expanded = quote! {
|
||||
#[derive(owl::Serialize, owl::Deserialize, Default)]
|
||||
#[derive(owl::Serialize, owl::Deserialize, Default, Clone)]
|
||||
#input_struct
|
||||
|
||||
#[derive(owl::Deserialize, owl::Serialize, Debug)]
|
||||
#[derive(owl::Deserialize, owl::Serialize, Debug, Clone)]
|
||||
pub struct #struct_ref_name {
|
||||
pub id: Id,
|
||||
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 expanded = quote! {
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
#[derive(serde::Serialize, serde::Deserialize, Clone)]
|
||||
#input_struct
|
||||
impl owl::db::store::Saveable for #struct_name {}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ use chrono::Utc;
|
|||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
|
||||
// historic field
|
||||
#[derive(Deserialize, Serialize, Default, Debug, PartialEq)]
|
||||
#[derive(Deserialize, Serialize, Default, Debug, PartialEq, Clone)]
|
||||
pub struct Historic<T> {
|
||||
pub values: Vec<(chrono::DateTime<Utc>, T)>,
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use arc_swap::ArcSwap;
|
||||
use parking_lot::{RwLock, RwLockReadGuard};
|
||||
use std::{
|
||||
ops::{Deref, DerefMut},
|
||||
|
@ -170,7 +171,7 @@ impl Database {
|
|||
}
|
||||
|
||||
/// 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,
|
||||
entries: &mut [Model<T>],
|
||||
u: F,
|
||||
|
@ -259,7 +260,7 @@ impl Database {
|
|||
)?
|
||||
};
|
||||
let model = Model {
|
||||
inner: Arc::new(RwLock::new(m)),
|
||||
inner: Arc::new(ArcSwap::new(Arc::new(m))),
|
||||
};
|
||||
|
||||
if self.cached {
|
||||
|
@ -284,9 +285,10 @@ impl Database {
|
|||
}
|
||||
|
||||
let data = data.read();
|
||||
let data = (*data).deref();
|
||||
|
||||
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,
|
||||
) -> Model<T> {
|
||||
let model = Model {
|
||||
inner: Arc::new(RwLock::new(data)),
|
||||
inner: Arc::new(ArcSwap::new(Arc::new(data))),
|
||||
};
|
||||
self.save_model(&model);
|
||||
let id = model.full_id().to_string();
|
||||
|
@ -313,7 +315,7 @@ impl Database {
|
|||
// TODO : cache eviction based on ref counts
|
||||
|
||||
pub struct Model<T> {
|
||||
inner: Arc<RwLock<T>>,
|
||||
inner: Arc<ArcSwap<T>>,
|
||||
}
|
||||
|
||||
impl Model<File> {
|
||||
|
@ -325,7 +327,7 @@ impl Model<File> {
|
|||
impl<T: Identifiable> Model<T> {
|
||||
pub fn from_raw(raw: T) -> Model<T> {
|
||||
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()
|
||||
}
|
||||
|
||||
pub fn read(&self) -> RwLockReadGuard<T> {
|
||||
self.inner.read()
|
||||
pub fn read(&self) -> arc_swap::Guard<Arc<T>> {
|
||||
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) {
|
||||
let mut me = self.inner.write();
|
||||
u(me.deref_mut());
|
||||
drop(me);
|
||||
let mut me = (**self.inner.load()).clone();
|
||||
u(&mut me);
|
||||
self.inner.swap(Arc::new(me));
|
||||
db.save_model(self);
|
||||
}
|
||||
|
||||
/// Update the model inline without writing to `Database`
|
||||
pub fn write_raw_inline<F: Fn(&mut T)>(&mut self, u: F) {
|
||||
let mut me = self.inner.write();
|
||||
u(me.deref_mut());
|
||||
let mut me = (**self.inner.load()).clone();
|
||||
u(&mut me);
|
||||
drop(me);
|
||||
}
|
||||
}
|
||||
|
@ -367,7 +369,7 @@ impl<T: 'static + Serialize + Identifiable + Send + Sync> ModelObj for Model<T>
|
|||
impl<T> Clone for Model<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
inner: Arc::clone(&self.inner),
|
||||
inner: self.inner.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ fn sha256(input: &[u8]) -> String {
|
|||
}
|
||||
|
||||
/// A generic file
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug)]
|
||||
#[model]
|
||||
pub struct File {
|
||||
id: Id,
|
||||
|
|
|
@ -6,7 +6,7 @@ pub use crate as owl;
|
|||
use crate::db::id::Id;
|
||||
|
||||
/// Represents a geographical location with an ID, coordinates, and optional address
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[model]
|
||||
pub struct Location {
|
||||
pub id: Id,
|
||||
|
|
|
@ -5,7 +5,7 @@ pub use crate as owl;
|
|||
use crate::db::id::Id;
|
||||
|
||||
/// Represents a mail address with an ID and the address itself
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug)]
|
||||
#[model]
|
||||
pub struct MailAddress {
|
||||
/// Unique identifier for the mail address
|
||||
|
|
|
@ -32,7 +32,7 @@ pub struct Person {
|
|||
pub locations: Historic<Vec<IdRef<Location>>>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, PartialEq)]
|
||||
#[derive(Deserialize, Serialize, Debug, PartialEq, Clone)]
|
||||
pub enum Gender {
|
||||
Male,
|
||||
Female,
|
||||
|
|
|
@ -5,7 +5,7 @@ pub use crate as owl;
|
|||
use crate::db::id::Id;
|
||||
|
||||
/// Represents a phone number with an ID, the phone number itself, and the country code.
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug)]
|
||||
#[model]
|
||||
pub struct PhoneNumber {
|
||||
id: Id,
|
||||
|
|
|
@ -437,7 +437,7 @@ impl<
|
|||
}
|
||||
|
||||
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 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>);
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||
pub struct RelationReference {
|
||||
pub top: IdRef<serde_json::Value>,
|
||||
pub sub: IdRef<serde_json::Value>,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue