fix numeric IDs not working with persistence, use u32 instead of u64, switch to numeric by default

master
Ondřej Hruška 3 years ago
parent 2b510dfda4
commit fbd2a1ed75
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 11
      Cargo.lock
  2. 2
      yopa-web/Cargo.toml
  3. 4
      yopa-web/resources/src/utils.js
  4. 2
      yopa-web/resources/static/bundle.js
  5. 2
      yopa-web/resources/static/bundle.js.map
  6. 3
      yopa/Cargo.toml
  7. 42
      yopa/src/id.rs
  8. 40
      yopa/src/lib.rs
  9. 20
      yopa/src/serde_atomic_id.rs

11
Cargo.lock generated

@ -395,6 +395,15 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "atomic"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3410529e8288c463bedb5930f82833bc0c90e5d2fe639a56582a4d09220b281"
dependencies = [
"autocfg",
]
[[package]] [[package]]
name = "atty" name = "atty"
version = "0.2.14" version = "0.2.14"
@ -2631,9 +2640,9 @@ name = "yopa"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"atomic",
"bincode", "bincode",
"itertools", "itertools",
"lazy_static",
"log", "log",
"parking_lot", "parking_lot",
"serde", "serde",

@ -8,7 +8,7 @@ build = "build.rs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
yopa = { path = "../yopa", features = ["uuid-ids"] } yopa = { path = "../yopa" }
serde = "1" serde = "1"
serde_json = "1" serde_json = "1"
heck = "0.3.2" heck = "0.3.2"

@ -23,8 +23,8 @@ export function objCopy(object) {
} }
export function castId(id) { export function castId(id) {
return id.toString(); //return id.toString();
//return +id; return +id;
} }
// like _.isEmpty, but less stupid // like _.isEmpty, but less stupid

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -19,8 +19,9 @@ parking_lot = "0.11.1"
anyhow = "1.0.38" anyhow = "1.0.38"
thiserror = "1.0.23" thiserror = "1.0.23"
itertools = "0.10.0" itertools = "0.10.0"
lazy_static = "1.4.0" #lazy_static = "1.4.0"
bincode = "1.3.1" bincode = "1.3.1"
atomic = "0.5.0"
[features] [features]
default = [] default = []

@ -6,46 +6,12 @@
//! It is better to treat both ID implementations as opaque. //! It is better to treat both ID implementations as opaque.
#[cfg(feature = "uuid-ids")] #[cfg(feature = "uuid-ids")]
mod impl_uuid { #[allow(non_camel_case_types)]
/// Common identifier type pub type ID = uuid::Uuid;
#[allow(non_camel_case_types)]
pub type ID = uuid::Uuid;
pub fn next_id() -> ID {
uuid::Uuid::new_v4()
}
pub fn zero_id() -> ID {
uuid::Uuid::nil()
}
}
#[cfg(not(feature = "uuid-ids"))]
mod impl_u64 {
/// Common identifier type
#[allow(non_camel_case_types)]
pub type ID = u64;
lazy_static::lazy_static! {
static ref COUNTER: parking_lot::Mutex<u64> = parking_lot::Mutex::new(0);
}
pub fn next_id() -> ID {
let mut m = COUNTER.lock();
let v = *m;
*m += 1;
v
}
pub fn zero_id() -> ID {
0
}
}
#[cfg(not(feature = "uuid-ids"))] #[cfg(not(feature = "uuid-ids"))]
pub use impl_u64::{next_id, zero_id, ID}; #[allow(non_camel_case_types)]
#[cfg(feature = "uuid-ids")] pub type ID = u32;
pub use impl_uuid::{next_id, zero_id, ID};
/// Something that has ID /// Something that has ID
pub trait HaveId { pub trait HaveId {

@ -1,7 +1,7 @@
#[macro_use] #[macro_use]
extern crate log; extern crate log;
#[macro_use] // #[macro_use]
extern crate serde_json; // extern crate serde_json;
use std::borrow::Cow; use std::borrow::Cow;
use std::collections::HashMap; use std::collections::HashMap;
@ -15,7 +15,6 @@ use thiserror::Error;
use cool::{map_drain_filter, KVVecToKeysOrValues}; use cool::{map_drain_filter, KVVecToKeysOrValues};
pub use data::TypedValue; pub use data::TypedValue;
use id::next_id;
pub use id::ID; pub use id::ID;
use insert::InsertObj; use insert::InsertObj;
use insert::InsertValue; use insert::InsertValue;
@ -32,6 +31,7 @@ pub mod insert;
pub mod model; pub mod model;
pub mod update; pub mod update;
mod serde_atomic_id;
mod serde_map_as_list; mod serde_map_as_list;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
@ -39,7 +39,7 @@ mod tests;
pub const VERSION: &'static str = env!("CARGO_PKG_VERSION"); pub const VERSION: &'static str = env!("CARGO_PKG_VERSION");
/// Stupid storage with naive inefficient file persistence /// Stupid storage with naive inefficient file persistence
#[derive(Debug, Default, Serialize, Deserialize, Clone)] #[derive(Debug, Default, Serialize, Deserialize)]
pub struct Storage { pub struct Storage {
#[serde(with = "serde_map_as_list")] #[serde(with = "serde_map_as_list")]
obj_models: HashMap<ID, model::ObjectModel>, obj_models: HashMap<ID, model::ObjectModel>,
@ -55,6 +55,10 @@ pub struct Storage {
#[serde(with = "serde_map_as_list")] #[serde(with = "serde_map_as_list")]
values: HashMap<ID, data::Value>, values: HashMap<ID, data::Value>,
#[cfg(not(feature = "uuid-ids"))]
#[serde(with = "serde_atomic_id")]
next_id : atomic::Atomic<ID>,
#[serde(skip)] #[serde(skip)]
opts: StoreOpts, opts: StoreOpts,
} }
@ -123,6 +127,16 @@ impl Storage {
Ok(s) Ok(s)
} }
#[cfg(not(feature = "uuid-ids"))]
fn next_id(&self) -> ID {
self.next_id.fetch_add(1, atomic::Ordering::Relaxed)
}
#[cfg(feature = "uuid-ids")]
fn next_id(&self) -> ID {
uuid::Uuid::new_v4()
}
/// Set backing file and its encoding /// Set backing file and its encoding
pub fn set_file(&mut self, file: impl AsRef<Path>, format: FileEncoding) { pub fn set_file(&mut self, file: impl AsRef<Path>, format: FileEncoding) {
self.opts.file_format = format; self.opts.file_format = format;
@ -399,7 +413,7 @@ impl Storage {
} }
debug!("Define object model \"{}\"", tpl.name); debug!("Define object model \"{}\"", tpl.name);
let id = next_id(); let id = self.next_id();
tpl.id = id; tpl.id = id;
self.obj_models.insert(id, tpl); self.obj_models.insert(id, tpl);
Ok(id) Ok(id)
@ -448,7 +462,7 @@ impl Storage {
rel.reciprocal_name rel.reciprocal_name
); );
let id = next_id(); let id = self.next_id();
rel.id = id; rel.id = id;
self.rel_models.insert(id, rel); self.rel_models.insert(id, rel);
Ok(id) Ok(id)
@ -502,7 +516,7 @@ impl Storage {
prop.name, prop.name,
self.describe_model(prop.object) self.describe_model(prop.object)
); );
let id = next_id(); let id = self.next_id();
prop.id = id; prop.id = id;
self.prop_models.insert(id, prop); self.prop_models.insert(id, prop);
Ok(id) Ok(id)
@ -748,7 +762,7 @@ impl Storage {
)); ));
} }
let object_id = next_id(); let object_id = self.next_id();
let object = data::Object { let object = data::Object {
id: object_id, id: object_id,
model: obj_model_id, model: obj_model_id,
@ -780,7 +794,7 @@ impl Storage {
} }
for val_instance in values { for val_instance in values {
values_to_insert.push(data::Value { values_to_insert.push(data::Value {
id: next_id(), id: self.next_id(),
object: parent_id, object: parent_id,
model: prop.id, model: prop.id,
value: val_instance.value.cast_to(prop.data_type).map_err(|v| { value: val_instance.value.cast_to(prop.data_type).map_err(|v| {
@ -793,7 +807,7 @@ impl Storage {
} else { } else {
if !prop.optional { if !prop.optional {
values_to_insert.push(data::Value { values_to_insert.push(data::Value {
id: next_id(), id: self.next_id(),
object: parent_id, object: parent_id,
model: prop.id, model: prop.id,
value: prop.default.clone(), value: prop.default.clone(),
@ -843,7 +857,7 @@ impl Storage {
} }
} }
let relation_id = next_id(); let relation_id = self.next_id();
// Relations can have properties // Relations can have properties
values_to_insert.extend(find_values_to_insert( values_to_insert.extend(find_values_to_insert(
@ -981,7 +995,7 @@ impl Storage {
for val_instance in values { for val_instance in values {
values_to_insert.push(data::Value { values_to_insert.push(data::Value {
id: val_instance.id.unwrap_or_else(|| next_id()), id: val_instance.id.unwrap_or_else(|| self.next_id()),
object: parent_id, object: parent_id,
model: prop.id, model: prop.id,
value: val_instance.value, value: val_instance.value,
@ -1050,7 +1064,7 @@ impl Storage {
} }
} }
let relation_id = rel_instance.id.unwrap_or_else(|| next_id()); let relation_id = rel_instance.id.unwrap_or_else(|| self.next_id());
// Relations can have properties // Relations can have properties
let (ins, del) = find_values_to_change( let (ins, del) = find_values_to_change(

@ -0,0 +1,20 @@
//! Serialize atomic ID by fetching its value
use crate::id::ID;
use serde::{Serialize, Deserializer, Deserialize};
pub fn serialize<S>(x: &atomic::Atomic<ID>, s: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
x.load(atomic::Ordering::Relaxed)
.serialize(s)
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<atomic::Atomic<ID>, D::Error>
where
D: Deserializer<'de>
{
let id : ID = ID::deserialize(deserializer)?;
Ok(atomic::Atomic::new(id))
}
Loading…
Cancel
Save