diff --git a/CHANGELOG.md b/CHANGELOG.md index a28ac58..cffaef3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +# [v1.0.0](https://github.com/carvilsi/gruphst/releases/tag/v1.0.0) (2024-08-28) + +- added custom path to persists file + # [v0.13.0](https://github.com/carvilsi/gruphst/releases/tag/v0.13.0) (2024-08-19) - supports Vec for Vertex attribute content: *set_attr_vec_u8* and *get_attr_vec_u8* diff --git a/Cargo.lock b/Cargo.lock index 2408bda..299abfa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -225,7 +225,7 @@ dependencies = [ [[package]] name = "gruphst" -version = "0.13.0" +version = "1.0.0" dependencies = [ "bincode", "criterion", diff --git a/Cargo.toml b/Cargo.toml index 421051b..bf51f7a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "gruphst" -version = "0.13.0" +version = "1.0.0" edition = "2021" description = "An in-memory graph database" license = "MIT" @@ -11,8 +11,6 @@ homepage = "https://github.com/carvilsi/gruphst" keywords = ["graph-database", "in-memory-database", "persistence"] categories = ["database"] -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] bincode = "1.0" serde = { version = "1.0", features = ["derive", "rc"] } diff --git a/README.md b/README.md index 4c97840..b3d4b8d 100644 --- a/README.md +++ b/README.md @@ -131,7 +131,7 @@ fn main() -> Result<(), Box> { // a file called "middle-earth.grphst" will be created, // later we can load it with: // let loaded_graphs = Graphs::load("middle-earth.grphst")?; - graphs.persists()?; + graphs.persists(None)?; Ok(()) } diff --git a/examples/middle-earth/Cargo.lock b/examples/middle-earth/Cargo.lock index 9e08860..f20cc97 100644 --- a/examples/middle-earth/Cargo.lock +++ b/examples/middle-earth/Cargo.lock @@ -61,7 +61,7 @@ dependencies = [ [[package]] name = "gruphst" -version = "0.12.0" +version = "1.0.0" dependencies = [ "bincode", "dotenv", diff --git a/examples/middle-earth/src/main.rs b/examples/middle-earth/src/main.rs index 419a172..afbf4c9 100644 --- a/examples/middle-earth/src/main.rs +++ b/examples/middle-earth/src/main.rs @@ -105,7 +105,7 @@ fn main() -> Result<(), Box> { // a file called "middle-earth.grphst" will be created, // later we can load it with: // let loaded_graphs = Graphs::load("middle-earth.grphst")?; - graphs.persists()?; + graphs.persists(None)?; Ok(()) } diff --git a/examples/rock-paper-scissors-lizard-spock/Cargo.lock b/examples/rock-paper-scissors-lizard-spock/Cargo.lock index 364e957..79c0370 100644 --- a/examples/rock-paper-scissors-lizard-spock/Cargo.lock +++ b/examples/rock-paper-scissors-lizard-spock/Cargo.lock @@ -61,7 +61,7 @@ dependencies = [ [[package]] name = "gruphst" -version = "0.11.1" +version = "1.0.0" dependencies = [ "bincode", "dotenv", diff --git a/examples/rock-paper-scissors-lizard-spock/src/main.rs b/examples/rock-paper-scissors-lizard-spock/src/main.rs index 0d06238..332f040 100644 --- a/examples/rock-paper-scissors-lizard-spock/src/main.rs +++ b/examples/rock-paper-scissors-lizard-spock/src/main.rs @@ -86,7 +86,7 @@ fn main() { // maybe now you want to persists the game rules // to use it other day ;) - let _ = rules.persists(); + let _ = rules.persists(None); // get the characters let characters = rules.get_uniq_vertices(None).unwrap(); diff --git a/src/edge/query.rs b/src/edge/query.rs index 547b8a6..ae0744f 100644 --- a/src/edge/query.rs +++ b/src/edge/query.rs @@ -63,9 +63,9 @@ impl Edge { // finds a Vertex by Id on an Edge pub fn find_vertex_by_id(&self, id: &str) -> Result { - if self.get_from_vertex().get_id() == id.to_string() { + if self.get_from_vertex().get_id() == *id { Ok(self.get_from_vertex()) - } else if self.get_to_vertex().get_id() == id.to_string() { + } else if self.get_to_vertex().get_id() == *id { Ok(self.get_to_vertex()) } else { Err("Vertex not found") diff --git a/src/graphs/persistence.rs b/src/graphs/persistence.rs index 5307a21..991a996 100644 --- a/src/graphs/persistence.rs +++ b/src/graphs/persistence.rs @@ -23,10 +23,13 @@ impl Graphs { /// /// // will write a file called 'Middle-earth.grphst' with /// // the content of the graphs - /// graphs.persists(); + /// graphs.persists(None); /// ``` - pub fn persists(&self) -> Result<(), Box> { - let file_name = format!("{}.grphst", self.get_label().replace(' ', "_")); + pub fn persists(&self, file_path: Option<&str>) -> Result<(), Box> { + let file_name = match file_path { + Some(fp) => format!("{}{}.grphst", fp, self.get_label().replace(' ', "_")), + None => format!("{}.grphst", self.get_label().replace(' ', "_")), + }; let mut file = OpenOptions::new() .create(true) .write(true) @@ -48,7 +51,7 @@ impl Graphs { /// "created", /// &Vertex::new("One Ring")); /// let mut graphs = Graphs::init_with("Middle-earth", &edge); - /// graphs.persists(); + /// graphs.persists(None); /// /// let loaded_graphs = Graphs::load("Middle-earth.grphst").unwrap(); /// ``` diff --git a/src/util/mod.rs b/src/util/mod.rs index 557b711..e0af95b 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -21,7 +21,7 @@ pub(crate) fn graphs_memory_watcher(graphs: &Graphs) { mem_prss if mem_prss >= 99_f32 => { error!("memory usage critical: {:.2}", mem_prss); error!("auto persisting current graphs: {}, then panicking", graphs.get_label()); - let _ = graphs.persists(); + let _ = graphs.persists(None); panic!("memory usage critical, auto-persisted current graphs"); } _ => debug!("memory ok: {:.2}", mem_prss), diff --git a/src/vertex/mod.rs b/src/vertex/mod.rs index 32e2387..03bc7cb 100644 --- a/src/vertex/mod.rs +++ b/src/vertex/mod.rs @@ -121,8 +121,8 @@ impl Vertex { self.vrtx.borrow_mut().attr.insert(attr_k.to_string(), attr_v.to_string()); } - pub fn set_attr_vec_u8(&mut self, attr_k: &str, attr_v: &Vec) { - self.vrtx.borrow_mut().attr_vec_u8.insert(attr_k.to_string(), attr_v.clone()); + pub fn set_attr_vec_u8(&mut self, attr_k: &str, attr_v: &[u8]) { + self.vrtx.borrow_mut().attr_vec_u8.insert(attr_k.to_string(), attr_v.to_owned()); } /// Get attribute for a vertex diff --git a/tests/data/.gitignore b/tests/data/.gitignore new file mode 100644 index 0000000..04fbd7a --- /dev/null +++ b/tests/data/.gitignore @@ -0,0 +1,2 @@ +!*.grphst +graphs-a.grphst diff --git a/tests/data/big-big-big.grphst b/tests/data/big-big-big.grphst new file mode 100644 index 0000000..665c881 Binary files /dev/null and b/tests/data/big-big-big.grphst differ diff --git a/tests/data/wrong-persisted-file.grphst b/tests/data/wrong-persisted-file.grphst new file mode 100644 index 0000000..5457519 --- /dev/null +++ b/tests/data/wrong-persisted-file.grphst @@ -0,0 +1,300 @@ +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 diff --git a/tests/persistence_test.rs b/tests/persistence_test.rs index 8241796..d7e3b6d 100644 --- a/tests/persistence_test.rs +++ b/tests/persistence_test.rs @@ -2,39 +2,69 @@ use gruphst::edge::Edge; use gruphst::graphs::Graphs; use gruphst::vertex::Vertex; -#[test] -fn persistence() { +fn prepare_persistence_test() -> (Graphs, Edge, Edge) { let mut gru = Graphs::init("graphs-a"); let mut edge1 = Vertex::new("a edge"); edge1.set_attr("foo", "bar"); let edge2 = Vertex::new("b edge"); - let graph1 = Edge::create(&edge1, "relation a-b", &edge2); - gru.add_edge(&graph1, None); + let edge1 = Edge::create(&edge1, "relation a-b", &edge2); + gru.add_edge(&edge1, None); let edge3 = Vertex::new("c edge"); let edge4 = Vertex::new("d edge"); - let graph2 = Edge::create(&edge3, "relation c-d", &edge4); - gru.add_edge(&graph2, None); + let edge2 = Edge::create(&edge3, "relation c-d", &edge4); + gru.add_edge(&edge2, None); + + (gru, edge1, edge2) +} + +fn assertion_persisted_graphs(grphs: Graphs, name: String, edge1: Edge, edge2: Edge) { + let graphs = grphs.get_edges(Some(name.as_str())).unwrap(); + assert_eq!(grphs.get_label(), name); + assert_eq!(graphs[0].get_relation(), edge1.get_relation()); + assert_eq!(graphs[0].get_from_vertex().get_label(), "a edge"); + assert_eq!(graphs[0].get_from_vertex().attr_len(), 1); + assert_eq!(graphs[0].get_from_vertex().get_attr("foo").unwrap(), "bar"); + assert_eq!(graphs[1], edge2); +} + +#[test] +fn should_persists_on_default_path() { + let (gru, edge1, edge2) = prepare_persistence_test(); - let _ = gru.persists(); + let _ = gru.persists(None); let name = gru.get_label(); let file_name = format!("{}.grphst", name); let grphs = Graphs::load(&file_name); match grphs { Ok(grphs) => { - let graphs = grphs.get_edges(Some(name.as_str())).unwrap(); - assert_eq!(grphs.get_label(), name); - assert_eq!(graphs[0].get_relation(), graph1.get_relation()); - assert_eq!(graphs[0].get_from_vertex().get_label(), "a edge"); - assert_eq!(graphs[0].get_from_vertex().attr_len(), 1); - assert_eq!(graphs[0].get_from_vertex().get_attr("foo").unwrap(), "bar"); - assert_eq!(graphs[1], graph2); + assertion_persisted_graphs(grphs, name, edge1, edge2); } Err(_) => panic!(), } } +#[test] +fn should_persists_on_custom_path() { + let (gru, edge1, edge2) = prepare_persistence_test(); + + let path = "./tests/data/"; + let _ = gru.persists(Some(path)); + let name = gru.get_label(); + let file_name = format!("{}{}.grphst", path, name); + let grphs = Graphs::load(file_name.as_str()); + match grphs { + Ok(grphs) => { + assertion_persisted_graphs(grphs, name, edge1, edge2); + } + Err(err) => { + println!("{err}"); + panic!() + }, + } +} + #[test] fn load_persisted_should_fail_fail_does_not_exists() { assert!(Graphs::load("tests/does-not-exists.grphst").is_err());