1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
//! Admin executor for `VelesQL` v3.6.
//!
//! Handles FLUSH statements by delegating to existing [`Database`]
//! and collection flush APIs.
use crate::velesql::{AdminStatement, FlushStatement};
use crate::{Error, Result, SearchResult};
use super::Database;
/// Dispatches to `flush()` (fast) or `flush_full()` based on the `full` flag.
///
/// Avoids repeating `if full { flush_full() } else { flush() }` at each call
/// site while staying closure-free (no `redundant_closure_for_method_calls`).
macro_rules! flush_dispatch {
($coll:expr, $full:expr) => {
if $full {
$coll.flush_full()
} else {
$coll.flush()
}
};
}
impl Database {
/// Dispatches an admin statement to the appropriate executor.
///
/// # Errors
///
/// Returns an error if the target collection does not exist (named FLUSH)
/// or if the flush operation itself fails.
pub(super) fn execute_admin(&self, stmt: &AdminStatement) -> Result<Vec<SearchResult>> {
match stmt {
AdminStatement::Flush(flush) => self.execute_flush(flush),
}
}
/// Executes a `FLUSH [FULL] [collection]` statement.
///
/// - No collection: flushes all collections in every registry.
/// - Named collection: resolves and flushes that single collection.
/// - `full = true`: includes index serialization (`flush_full`).
/// - `full = false`: WAL-only fast flush.
///
/// # Errors
///
/// Returns an error if a named collection does not exist or if any
/// individual flush operation fails.
fn execute_flush(&self, stmt: &FlushStatement) -> Result<Vec<SearchResult>> {
if let Some(ref name) = stmt.collection {
self.flush_single_collection(name, stmt.full)?;
} else {
self.flush_all_collections(stmt.full)?;
}
let payload = serde_json::json!({
"status": "flushed",
"full": stmt.full,
});
let result = SearchResult::new(crate::Point::metadata_only(0, payload), 0.0);
Ok(vec![result])
}
/// Flushes a single collection by name, choosing fast or full mode.
///
/// Checks vector, graph, and metadata registries in order.
///
/// # Errors
///
/// Returns `CollectionNotFound` if the name does not match any registry.
fn flush_single_collection(&self, name: &str, full: bool) -> Result<()> {
if let Some(vc) = self.get_vector_collection(name) {
return flush_dispatch!(vc, full);
}
if let Some(gc) = self.get_graph_collection(name) {
return flush_dispatch!(gc, full);
}
if let Some(mc) = self.get_metadata_collection(name) {
return flush_dispatch!(mc, full);
}
Err(Error::CollectionNotFound(name.to_string()))
}
/// Flushes all collections across all registries.
///
/// Iterates vector, graph, and metadata registries. Uses fast or full
/// mode based on the `full` flag. Fails on the first error encountered.
///
/// # Errors
///
/// Returns the first flush error encountered.
fn flush_all_collections(&self, full: bool) -> Result<()> {
for (_, vc) in self.vector_colls.read().iter() {
flush_dispatch!(vc, full)?;
}
for (_, gc) in self.graph_colls.read().iter() {
flush_dispatch!(gc, full)?;
}
for (_, mc) in self.metadata_colls.read().iter() {
flush_dispatch!(mc, full)?;
}
Ok(())
}
}