Skip to content

Commit 09e1f90

Browse files
committed
Merge branch 'devel-0.0.1'
2 parents 281a913 + 64e3cdd commit 09e1f90

22 files changed

Lines changed: 1223 additions & 773 deletions

File tree

lib/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ rand = "0.8.5" # Consistent
1313
actix-web = "4.11.0" # Crucial: Updated to match security crate's version
1414
actix-rt = "2.10.0" # Updated to match server crate's version
1515
dotenv = "0.15.0" # Aligned with server
16-
tokio = { version = "1.44.2", features = ["macros", "rt-multi-thread"] } # Updated to latest stable
16+
tokio = { version = "1.44.2", features = ["full"] } # Updated to latest stable
1717
tracing = "0.1.37" # Updated to latest stable
1818
tracing-subscriber = "0.3.18" # Updated to latest stable
1919
env_logger = "0.11.8" # Aligned with storage_daemon_server

lib/src/database.rs

Lines changed: 121 additions & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -1,187 +1,146 @@
11
// lib/src/database.rs
2+
// Corrected: 2025-07-02 - Final version ensuring correct trait usage and error handling.
3+
// Fixed models import path and conditional RocksDBStorage import.
4+
5+
use std::sync::Arc;
6+
// Conditionally import RocksDBStorage
7+
#[cfg(feature = "with-rocksdb")]
8+
use crate::storage_engine::RocksDBStorage;
9+
use crate::storage_engine::{GraphStorageEngine, SledGraphStorage, StorageConfig, StorageEngineType, open_sled_db};
10+
use models::{Vertex, Edge, Identifier}; // Corrected: Removed `crate::` prefix
11+
use models::errors::{GraphError, GraphResult}; // Use GraphResult directly
12+
use uuid::Uuid;
13+
use serde_json::Value; // For query results
214

3-
use uuid::Uuid; // Uuid is used in the Transaction trait
4-
5-
// Core graph model types
6-
use models::{Edge, Identifier, Json, Vertex};
7-
8-
// More specific model types, assuming their locations within the 'models' crate
9-
// Please adjust these paths if your 'models' crate has a different internal structure.
10-
use models::bulk_insert::BulkInsertItem;
11-
// FIX: Changed from models::edges::EdgeDirection to models::queries::EdgeDirection
12-
use models::queries::EdgeDirection; // CORRECTED PATH
13-
use models::properties::{EdgeProperties, NamedProperty, PropertyValue, VertexProperties};
14-
use models::queries::{Query, QueryOutputValue};
15-
16-
// Application-specific models, if they are used within database.rs or re-exported from here
17-
use models::medical::{Login, User}; // Assuming these are in models::medical
18-
19-
// Import your custom error type
20-
use crate::errors::Result;
21-
22-
// Define a type alias for a dynamic iterator, commonly used for trait objects
23-
// and allowing different iterator implementations to be returned.
24-
pub type DynIter<'a, T> = Box<dyn Iterator<Item = Result<T>> + 'a>;
25-
26-
27-
/// Defines the core functionality required for a datastore.
15+
/// A graph database wrapper that provides a simplified interface for
16+
/// interacting with an underlying `GraphStorageEngine`.
2817
///
29-
/// Any type implementing this trait can serve as the backend for the `Database`.
30-
pub trait Datastore {
31-
/// The associated transaction type for this datastore.
32-
///
33-
/// This associated type allows the `Datastore` trait to define methods
34-
/// that return a specific transaction type, which in turn implements
35-
/// the `Transaction` trait. The `'a` lifetime parameter indicates that
36-
/// the transaction's lifetime is tied to the lifetime of the `Datastore`
37-
/// instance from which it was created.
38-
type Transaction<'a>
39-
where
40-
Self: 'a; // Self must outlive 'a, or 'a is tied to Self's lifetime
41-
42-
/// Begins a new transaction for this datastore.
43-
///
44-
/// The returned transaction can be used for both read and write operations.
45-
fn transaction(&'_ self) -> Self::Transaction<'_>;
18+
/// This struct manages the storage engine instance and provides convenient methods
19+
/// for graph operations.
20+
#[derive(Debug)]
21+
pub struct Database {
22+
storage_engine: Arc<dyn GraphStorageEngine>,
4623
}
4724

25+
impl Database {
26+
/// Creates a new database instance based on the provided storage configuration.
27+
///
28+
/// This function initializes and starts the chosen storage engine (Sled or RocksDB).
29+
///
30+
/// # Arguments
31+
/// * `config`: The configuration for the storage engine.
32+
///
33+
/// # Returns
34+
/// A `GraphResult` indicating success or a `GraphError` if initialization fails.
35+
pub async fn new(config: StorageConfig) -> GraphResult<Self> {
36+
let storage_engine: Arc<dyn GraphStorageEngine> = match config.engine_type {
37+
StorageEngineType::Sled => {
38+
// Open Sled DB and create SledGraphStorage
39+
let db = open_sled_db(&config.data_path)?;
40+
Arc::new(SledGraphStorage::new(db)?)
41+
},
42+
StorageEngineType::RocksDB => {
43+
// Conditionally compile RocksDB initialization if the feature is enabled
44+
#[cfg(feature = "with-rocksdb")]
45+
{
46+
Arc::new(RocksDBStorage::new(&config)?)
47+
}
48+
#[cfg(not(feature = "with-rocksdb"))]
49+
{
50+
return Err(GraphError::ConfigError(
51+
"RocksDB backend requested but 'with-rocksdb' feature is not enabled. \
52+
Please enable it in lib/Cargo.toml".to_string()
53+
));
54+
}
55+
},
56+
// Add other storage types here as they are implemented (e.g., PostgreSQL, Redis)
57+
_ => return Err(GraphError::ConfigError(
58+
format!("Unsupported storage engine type: {:?}", config.engine_type)
59+
)),
60+
};
61+
62+
// Start the chosen storage engine
63+
storage_engine.start().await?;
64+
65+
Ok(Database { storage_engine })
66+
}
4867

49-
/// Defines the operations that can be performed within a database transaction.
50-
///
51-
/// This trait outlines the read and write methods for interacting with the graph data.
52-
pub trait Transaction<'a>: Sized {
53-
// Graph Read Operations
54-
55-
/// Returns the total number of vertices in the database.
56-
fn vertex_count(&self) -> u64;
57-
58-
/// Returns an iterator over all vertices in the database.
59-
fn all_vertices(&'a self) -> Result<DynIter<'a, Vertex>>;
60-
61-
/// Returns an iterator over vertices starting from a given offset UUID.
62-
/// Useful for pagination or resuming iteration.
63-
fn range_vertices(&'a self, offset: Uuid) -> Result<DynIter<'a, Vertex>>;
64-
65-
/// Returns an iterator over specific vertices identified by their UUIDs.
66-
fn specific_vertices(&'a self, ids: Vec<Uuid>) -> Result<DynIter<'a, Vertex>>;
67-
68-
/// Returns an optional iterator of vertex UUIDs that have a property with the given name.
69-
/// Returns `None` if the property is not indexed.
70-
fn vertex_ids_with_property(&'a self, name: Identifier) -> Result<Option<DynIter<'a, Uuid>>>;
71-
72-
/// Returns an optional iterator of vertex UUIDs that have a property with the given name
73-
/// and a specific JSON value. Returns `None` if the property is not indexed.
74-
fn vertex_ids_with_property_value(&'a self, name: Identifier, value: &Json) -> Result<Option<DynIter<'a, Uuid>>>;
75-
76-
/// Returns the total number of edges in the database.
77-
fn edge_count(&self) -> u64;
78-
79-
/// Returns an iterator over all edges in the database.
80-
fn all_edges(&'a self) -> Result<DynIter<'a, Edge>>;
81-
82-
/// Returns an iterator over edges starting from a given offset Edge.
83-
/// Useful for pagination or resuming iteration.
84-
fn range_edges(&'a self, offset: Edge) -> Result<DynIter<'a, Edge>>;
85-
86-
/// Returns an iterator over reversed edges (inbound to outbound) starting from a given offset Edge.
87-
fn range_reversed_edges(&'a self, offset: Edge) -> Result<DynIter<'a, Edge>>;
88-
89-
/// Returns an iterator over specific edges.
90-
fn specific_edges(&'a self, edges: Vec<Edge>) -> Result<DynIter<'a, Edge>>;
91-
92-
/// Returns an optional iterator of edges that have a property with the given name.
93-
/// Returns `None` if the property is not indexed.
94-
fn edges_with_property(&'a self, name: Identifier) -> Result<Option<DynIter<'a, Edge>>>;
95-
96-
/// Returns an optional iterator of edges that have a property with the given name
97-
/// and a specific JSON value. Returns `None` if the property is not indexed.
98-
fn edges_with_property_value(&'a self, name: Identifier, value: &Json) -> Result<Option<DynIter<'a, Edge>>>;
99-
100-
/// Retrieves the value of a specific property for a given vertex.
101-
fn vertex_property(&self, vertex: &Vertex, name: Identifier) -> Result<Option<Json>>;
102-
103-
/// Returns an iterator over all properties (name and value) for a given vertex.
104-
fn all_vertex_properties_for_vertex(&'a self, vertex: &Vertex) -> Result<DynIter<'a, (Identifier, Json)>>;
105-
106-
/// Retrieves the value of a specific property for a given edge.
107-
fn edge_property(&self, edge: &Edge, name: Identifier) -> Result<Option<Json>>;
108-
109-
/// Returns an iterator over all properties (name and value) for a given edge.
110-
fn all_edge_properties_for_edge(&'a self, edge: &Edge) -> Result<DynIter<'a, (Identifier, Json)>>;
111-
112-
// Graph Write Operations
113-
114-
/// Deletes a collection of vertices and all their associated edges and properties.
115-
fn delete_vertices(&mut self, vertices: Vec<Vertex>) -> Result<()>;
68+
/// Returns a reference to the underlying graph storage engine.
69+
pub fn storage(&self) -> &Arc<dyn GraphStorageEngine> {
70+
&self.storage_engine
71+
}
11672

117-
/// Deletes a collection of edges and their associated properties.
118-
fn delete_edges(&mut self, edges: Vec<Edge>) -> Result<()>;
73+
// --- Proxy methods to GraphStorageEngine for convenience ---
11974

120-
/// Deletes specific properties from vertices.
121-
fn delete_vertex_properties(&mut self, props: Vec<(Uuid, Identifier)>) -> Result<()>;
75+
/// Creates a new vertex in the database.
76+
pub async fn create_vertex(&self, vertex: Vertex) -> GraphResult<()> {
77+
self.storage_engine.as_ref().create_vertex(vertex).await
78+
}
12279

123-
/// Deletes specific properties from edges.
124-
fn delete_edge_properties(&mut self, props: Vec<(Edge, Identifier)>) -> Result<()>;
80+
/// Retrieves a vertex by its ID.
81+
pub async fn get_vertex(&self, id: &Uuid) -> GraphResult<Option<Vertex>> {
82+
self.storage_engine.as_ref().get_vertex(id).await
83+
}
12584

126-
/// Synchronizes the datastore's internal state with its persistent storage.
127-
/// This might involve flushing buffers or performing compaction.
128-
fn sync(&self) -> Result<()>;
85+
/// Updates an existing vertex in the database.
86+
pub async fn update_vertex(&self, vertex: Vertex) -> GraphResult<()> {
87+
self.storage_engine.as_ref().update_vertex(vertex).await
88+
}
12989

130-
/// Creates a new vertex in the database. Returns `true` if created, `false` if it already existed.
131-
fn create_vertex(&mut self, vertex: &Vertex) -> Result<bool>;
90+
/// Deletes a vertex by its ID.
91+
pub async fn delete_vertex(&self, id: &Uuid) -> GraphResult<()> {
92+
self.storage_engine.as_ref().delete_vertex(id).await
93+
}
13294

133-
/// Creates a new edge in the database. Returns `true` if created, `false` if it already existed
134-
/// or if the incident vertices do not exist.
135-
fn create_edge(&mut self, edge: &Edge) -> Result<bool>;
95+
/// Retrieves all vertices from the database.
96+
pub async fn get_all_vertices(&self) -> GraphResult<Vec<Vertex>> {
97+
self.storage_engine.as_ref().get_all_vertices().await
98+
}
13699

137-
/// Performs a bulk insert of various graph items (vertices, edges, properties).
138-
/// This method is typically optimized for performance by batching operations.
139-
fn bulk_insert(&mut self, items: Vec<BulkInsertItem>) -> Result<()>;
100+
/// Creates a new edge in the database.
101+
pub async fn create_edge(&self, edge: Edge) -> GraphResult<()> {
102+
self.storage_engine.as_ref().create_edge(edge).await
103+
}
140104

141-
/// Indexes a property by its name. After indexing, queries on this property
142-
/// will be more efficient. This operation may take time for existing data.
143-
fn index_property(&mut self, name: Identifier) -> Result<()>;
105+
/// Retrieves an edge by its composite key (outbound ID, type, inbound ID).
106+
pub async fn get_edge(&self, outbound_id: &Uuid, edge_type: &Identifier, inbound_id: &Uuid) -> GraphResult<Option<Edge>> {
107+
self.storage_engine.as_ref().get_edge(outbound_id, edge_type, inbound_id).await
108+
}
144109

145-
/// Sets (creates or updates) a specific property for a collection of vertices.
146-
fn set_vertex_properties(&mut self, vertices: Vec<Uuid>, name: Identifier, value: &Json) -> Result<()>;
110+
/// Updates an existing edge in the database.
111+
pub async fn update_edge(&self, edge: Edge) -> GraphResult<()> {
112+
self.storage_engine.as_ref().update_edge(edge).await
113+
}
147114

148-
/// Sets (creates or updates) a specific property for a collection of edges.
149-
fn set_edge_properties(&mut self, edges: Vec<Edge>, name: Identifier, value: &Json) -> Result<()>;
150-
}
115+
/// Deletes an edge by its composite key.
116+
pub async fn delete_edge(&self, outbound_id: &Uuid, edge_type: &Identifier, inbound_id: &Uuid) -> GraphResult<()> {
117+
self.storage_engine.as_ref().delete_edge(outbound_id, edge_type, inbound_id).await
118+
}
151119

120+
/// Retrieves all edges from the database.
121+
pub async fn get_all_edges(&self) -> GraphResult<Vec<Edge>> {
122+
self.storage_engine.as_ref().get_all_edges().await
123+
}
152124

153-
/// A graph database wrapper that provides a simplified interface for
154-
/// interacting with an underlying `Datastore`.
155-
///
156-
/// This struct manages the datastore instance and provides convenient methods
157-
/// to obtain read and write transactions.
158-
#[derive(Debug)]
159-
pub struct Database<D: Datastore> {
160-
datastore: D,
161-
}
125+
/// Executes a generic query string against the graph storage engine.
126+
/// The interpretation of the query string depends on the underlying engine.
127+
pub async fn query(&self, query_string: &str) -> GraphResult<Value> {
128+
self.storage_engine.as_ref().query(query_string).await
129+
}
162130

163-
impl<D: Datastore> Database<D> {
164-
/// Creates a new database instance.
165-
///
166-
/// # Arguments
167-
/// * `datastore`: The underlying datastore implementation that will store the data.
168-
pub fn new(datastore: D) -> Self {
169-
Self { datastore }
131+
/// Returns the type of the underlying storage engine.
132+
pub fn get_type(&self) -> &'static str {
133+
self.storage_engine.as_ref().get_type()
170134
}
171135

172-
/// Gets a read transaction for performing read operations on the database.
173-
///
174-
/// The transaction's lifetime is tied to the `Database` instance.
175-
pub fn read_txn(&self) -> D::Transaction<'_> {
176-
self.datastore.transaction()
136+
/// Checks if the underlying storage engine is running.
137+
pub fn is_running(&self) -> bool {
138+
self.storage_engine.as_ref().is_running()
177139
}
178140

179-
/// Gets a write transaction for performing write operations on the database.
180-
///
181-
/// The transaction is typically committed automatically when it goes out of scope (dropped),
182-
/// or it might provide explicit commit/rollback methods depending on the `Transaction`
183-
/// trait implementation.
184-
pub fn write_txn(&mut self) -> D::Transaction<'_> {
185-
self.datastore.transaction()
141+
/// Stops the underlying storage engine gracefully.
142+
pub async fn stop(&self) -> GraphResult<()> {
143+
self.storage_engine.as_ref().stop().await
186144
}
187145
}
146+

lib/src/engine/medical.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use models::Identifier;
66
use models::ToVertex;
77
use models::vertices::Vertex as ModelVertex; // Alias to avoid conflict with EngineVertex
88
use uuid::Uuid;
9+
use models::identifiers::SerializableUuid;
910
// This import is correct for models::properties::PropertyValue
1011
use models::properties::PropertyValue;
1112

@@ -14,10 +15,9 @@ fn convert_model_vertex_to_engine_vertex(v: &ModelVertex) -> crate::engine::vert
1415
use std::collections::BTreeMap;
1516

1617
let mut eng_vertex = crate::engine::vertex::Vertex::new(v.label.to_string());
17-
eng_vertex.id = v.id;
18+
eng_vertex.id = Uuid::from(v.id); // Convert SerializableUuid to Uuid
1819
eng_vertex.properties = v.properties.iter()
19-
.map(|(k, prop_val)| { // prop_val is &models::properties::PropertyValue
20-
// This match correctly extracts String from models::properties::PropertyValue::String
20+
.map(|(k, prop_val)| {
2121
let string_value = match prop_val {
2222
PropertyValue::String(s) => s.clone(),
2323
// Add conversion logic for other PropertyValue variants if needed
@@ -26,11 +26,8 @@ fn convert_model_vertex_to_engine_vertex(v: &ModelVertex) -> crate::engine::vert
2626
"UNSUPPORTED_PROPERTY_TYPE".to_string()
2727
},
2828
};
29-
// This line *produces* models::properties::PropertyValue::String
3029
(k.clone(), PropertyValue::String(string_value))
3130
})
32-
// This collect now produces a BTreeMap with models::properties::PropertyValue,
33-
// which will match eng_vertex.properties after the fix in lib/src/engine/vertex.rs
3431
.collect::<BTreeMap<String, PropertyValue>>();
3532
eng_vertex
3633
}

lib/src/lib.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// lib/src/lib.rs
2-
// Updated: 2025-06-30 - Refactored to use the new 'models' crate for shared types.
2+
// Updated: 2025-07-02 - Refactored to use the new 'models' crate for shared types.
3+
// Corrected unresolved imports for SledUserStorage and UserStorageEngine.
34

45
#![cfg_attr(feature = "bench-suite", feature(test))]
56

@@ -49,7 +50,10 @@ pub use crate::memory::*;
4950
// REMOVED: pub use models::PropertyValue; // <-- REMOVED THIS DUPLICATE LINE
5051

5152
// Re-export from storage_engine/mod.rs
52-
pub use crate::storage_engine::{SledUserStorage, UserStorageEngine, open_sled_db, StorageEngine, GraphStorageEngine};
53+
// Removed SledUserStorage and UserStorageEngine as their definitions/re-exports are not available.
54+
// If these are needed, ensure they are correctly defined and re-exported in storage_engine/mod.rs
55+
// and storage_engine/user_storage.rs
56+
pub use crate::storage_engine::{open_sled_db, StorageEngine, GraphStorageEngine};
5357

5458

5559
// Do NOT glob-import engine and models together to avoid ambiguity
@@ -88,3 +92,4 @@ pub use crate::sled::managers::SledManager as SledDatastore;
8892

8993
#[cfg(feature = "sled-datastore")]
9094
pub type CurrentDatastore = SledDatastore;
95+

0 commit comments

Comments
 (0)