Skip to content

Commit 25c7f20

Browse files
committed
refactor(nodedb,client,test-support): split oversized modules into submodules
Break up main.rs, control/state/init_prod, control/surrogate/assign/core, and control/backup/restore/orchestrate in nodedb; protocol/text_fields/types in nodedb-types; traits/core/trait_def (default-method bodies extracted into default_impls.rs) in nodedb-client; and cluster_harness/cluster and cluster_harness/node/lifecycle in nodedb-test-support into directories of cohesive submodules.
1 parent 92191b4 commit 25c7f20

36 files changed

Lines changed: 3279 additions & 2339 deletions

File tree

Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
//! Default-provided method bodies for [`crate::traits::core::NodeDb`].
4+
//!
5+
//! Factored out of the trait declaration in `trait_def.rs` so that file
6+
//! stays signatures + docs; each function here backs exactly one
7+
//! default-provided `NodeDb` method, and the trait method delegates to it
8+
//! in one line. Pure relocation — no behavior change.
9+
10+
use std::collections::{HashMap, HashSet};
11+
12+
use nodedb_types::document::Document;
13+
use nodedb_types::dropped_collection::DroppedCollection;
14+
use nodedb_types::error::{NodeDbError, NodeDbResult};
15+
use nodedb_types::filter::{EdgeFilter, MetadataFilter};
16+
use nodedb_types::id::NodeId;
17+
use nodedb_types::result::SearchResult;
18+
use nodedb_types::text_search::TextSearchParams;
19+
20+
use super::quote::quote_ident;
21+
use super::trait_def::NodeDb;
22+
23+
pub(super) fn graph_pagerank_default(
24+
collection: &str,
25+
personalization: Option<HashMap<String, f64>>,
26+
damping: Option<f64>,
27+
max_iterations: Option<u32>,
28+
) -> NodeDbResult<Vec<(String, f64)>> {
29+
let _ = (collection, personalization, damping, max_iterations);
30+
Err(NodeDbError::storage(
31+
"graph_pagerank is not implemented for this NodeDb backend",
32+
))
33+
}
34+
35+
pub(super) async fn document_put_with_vector_default<T: NodeDb + ?Sized>(
36+
this: &T,
37+
doc_collection: &str,
38+
doc: Document,
39+
vector_collection: &str,
40+
id: &str,
41+
embedding: &[f32],
42+
) -> NodeDbResult<()> {
43+
this.document_put(doc_collection, doc).await?;
44+
if !embedding.is_empty() {
45+
this.vector_insert(vector_collection, id, embedding, None)
46+
.await?;
47+
}
48+
Ok(())
49+
}
50+
51+
pub(super) fn document_get_as_of_default(
52+
collection: &str,
53+
id: &str,
54+
as_of_ms: Option<i64>,
55+
valid_time_ms: Option<i64>,
56+
) -> NodeDbResult<Option<Document>> {
57+
let _ = (collection, id, as_of_ms, valid_time_ms);
58+
Err(NodeDbError::storage(
59+
"document_get_as_of is not implemented on this client",
60+
))
61+
}
62+
63+
pub(super) fn document_put_with_valid_time_default(
64+
collection: &str,
65+
doc: Document,
66+
valid_from_ms: Option<i64>,
67+
valid_until_ms: Option<i64>,
68+
) -> NodeDbResult<()> {
69+
let _ = (collection, doc, valid_from_ms, valid_until_ms);
70+
Err(NodeDbError::storage(
71+
"document_put_with_valid_time is not implemented on this client",
72+
))
73+
}
74+
75+
pub(super) fn vector_insert_field_default(
76+
collection: &str,
77+
field_name: &str,
78+
id: &str,
79+
embedding: &[f32],
80+
metadata: Option<Document>,
81+
) -> NodeDbResult<()> {
82+
let _ = (collection, id, embedding, metadata);
83+
Err(NodeDbError::storage(format!(
84+
"vector_insert_field is not implemented on this client; \
85+
field_name={field_name} would have been silently dropped"
86+
)))
87+
}
88+
89+
pub(super) fn vector_search_field_default(
90+
collection: &str,
91+
field_name: &str,
92+
query: &[f32],
93+
k: usize,
94+
filter: Option<&MetadataFilter>,
95+
) -> NodeDbResult<Vec<SearchResult>> {
96+
let _ = (collection, query, k, filter);
97+
Err(NodeDbError::storage(format!(
98+
"vector_search_field is not implemented on this client; \
99+
field_name={field_name} would have been silently dropped"
100+
)))
101+
}
102+
103+
/// Default forward-BFS shortest-path search built on `graph_traverse`.
104+
///
105+
/// See [`crate::traits::core::NodeDb::graph_shortest_path`] for the
106+
/// full contract.
107+
pub(super) async fn graph_shortest_path_default<T: NodeDb + ?Sized>(
108+
this: &T,
109+
collection: &str,
110+
from: &NodeId,
111+
to: &NodeId,
112+
max_depth: u8,
113+
edge_filter: Option<&EdgeFilter>,
114+
) -> NodeDbResult<Option<Vec<NodeId>>> {
115+
if from == to {
116+
return Ok(Some(vec![from.clone()]));
117+
}
118+
if max_depth == 0 {
119+
return Ok(None);
120+
}
121+
122+
// Map of `node -> parent` used to reconstruct the path once the
123+
// target is reached. The source has no parent entry.
124+
let mut parent: HashMap<NodeId, NodeId> = HashMap::new();
125+
let mut frontier: Vec<NodeId> = vec![from.clone()];
126+
127+
for _ in 0..max_depth {
128+
let mut next_frontier: Vec<NodeId> = Vec::new();
129+
for node in &frontier {
130+
let sg = this
131+
.graph_traverse(collection, node, 1, edge_filter)
132+
.await?;
133+
for edge in &sg.edges {
134+
// Only follow edges originating from the current
135+
// node — `graph_traverse` may include adjacent
136+
// edges that don't extend the BFS frontier.
137+
if &edge.from != node {
138+
continue;
139+
}
140+
let dst = &edge.to;
141+
if dst == from || parent.contains_key(dst) {
142+
continue;
143+
}
144+
parent.insert(dst.clone(), node.clone());
145+
if dst == to {
146+
let mut path = vec![to.clone()];
147+
let mut cur = to.clone();
148+
while &cur != from {
149+
let p = parent
150+
.get(&cur)
151+
.expect("BFS reached `to` so all ancestors are tracked")
152+
.clone();
153+
path.push(p.clone());
154+
cur = p;
155+
}
156+
path.reverse();
157+
return Ok(Some(path));
158+
}
159+
next_frontier.push(dst.clone());
160+
}
161+
}
162+
if next_frontier.is_empty() {
163+
return Ok(None);
164+
}
165+
frontier = next_frontier;
166+
}
167+
Ok(None)
168+
}
169+
170+
pub(super) fn text_search_default(
171+
collection: &str,
172+
field: &str,
173+
query: &str,
174+
top_k: usize,
175+
params: TextSearchParams,
176+
allowed_ids: Option<&HashSet<String>>,
177+
) -> NodeDbResult<Vec<SearchResult>> {
178+
let _ = (collection, field, query, top_k, params, allowed_ids);
179+
Err(NodeDbError::storage(
180+
"text_search is not implemented on this client",
181+
))
182+
}
183+
184+
pub(super) async fn batch_vector_insert_default<T: NodeDb + ?Sized>(
185+
this: &T,
186+
collection: &str,
187+
vectors: &[(&str, &[f32])],
188+
) -> NodeDbResult<()> {
189+
for &(id, embedding) in vectors {
190+
this.vector_insert(collection, id, embedding, None).await?;
191+
}
192+
Ok(())
193+
}
194+
195+
pub(super) async fn batch_graph_insert_edges_default<T: NodeDb + ?Sized>(
196+
this: &T,
197+
collection: &str,
198+
edges: &[(&str, &str, &str)],
199+
) -> NodeDbResult<()> {
200+
for &(from, to, label) in edges {
201+
let src = NodeId::try_new(from)
202+
.map_err(|e| NodeDbError::storage(format!("invalid node id: {e}")))?;
203+
let dst = NodeId::try_new(to)
204+
.map_err(|e| NodeDbError::storage(format!("invalid node id: {e}")))?;
205+
this.graph_insert_edge(collection, &src, &dst, label, None)
206+
.await?;
207+
}
208+
Ok(())
209+
}
210+
211+
pub(super) async fn undrop_collection_default<T: NodeDb + ?Sized>(
212+
this: &T,
213+
name: &str,
214+
) -> NodeDbResult<()> {
215+
let sql = format!("UNDROP COLLECTION {}", quote_ident(name));
216+
this.execute_sql(&sql, &[]).await?;
217+
Ok(())
218+
}
219+
220+
pub(super) async fn drop_collection_purge_default<T: NodeDb + ?Sized>(
221+
this: &T,
222+
name: &str,
223+
) -> NodeDbResult<()> {
224+
let sql = format!("DROP COLLECTION {} PURGE", quote_ident(name));
225+
this.execute_sql(&sql, &[]).await?;
226+
Ok(())
227+
}
228+
229+
pub(super) async fn list_dropped_collections_default<T: NodeDb + ?Sized>(
230+
this: &T,
231+
) -> NodeDbResult<Vec<DroppedCollection>> {
232+
let sql = "SELECT tenant_id, name, owner, engine_type, \
233+
deactivated_at_ns, retention_expires_at_ns \
234+
FROM _system.dropped_collections";
235+
let result = this.execute_sql(sql, &[]).await?;
236+
crate::row_decode::parse_dropped_collection_rows(&result.rows)
237+
}
238+
239+
pub(super) fn on_collection_purged_default() -> NodeDbResult<()> {
240+
Err(NodeDbError::storage(
241+
"on_collection_purged is not supported on this client — \
242+
requires a push-capable sync connection (NodeDbLite or a \
243+
sync-enabled remote client)",
244+
))
245+
}

nodedb-client/src/traits/core/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// SPDX-License-Identifier: Apache-2.0
22

3+
mod default_impls;
34
pub mod marker;
45
pub mod quote;
56
pub mod trait_def;

0 commit comments

Comments
 (0)