rushdb_storage/adapter_budgets.rs
1//! Per-adapter resource budgets: the vector adapter's own cache budget
2//! (`vector_cache_bytes`, a child of the managed limit), and a named child of
3//! the shared phase budget per query adapter (SQL, graph), so each adapter's
4//! `peak`/`used` (a real, measured high-water mark — see
5//! [`crate::resources::ByteBudget::snapshot`]) is individually observable.
6//! Each phase child's limit equals its parent's, so those are pure
7//! attribution: they do not narrow the shared capacity the adapters contend
8//! on (see [`crate::resources::ByteBudget::child`]).
9
10use crate::resources::ByteBudget;
11use crate::{StorageError, Store};
12
13/// The vector cache budget and one named attribution child per query
14/// adapter. `None` exactly when its budget (`vector_cache_bytes` /
15/// `phase_resources`) is disabled.
16pub(crate) struct AdapterBudgets {
17 vector_cache: Option<ByteBudget>,
18 sql_phase: Option<ByteBudget>,
19 graph_phase: Option<ByteBudget>,
20}
21
22impl AdapterBudgets {
23 pub(crate) fn new(
24 vector_cache: Option<ByteBudget>,
25 phase: Option<&ByteBudget>,
26 ) -> Result<Self, StorageError> {
27 let child = |parent: Option<&ByteBudget>, name: &'static str| {
28 parent
29 .map(|parent| parent.child(name, parent.snapshot().limit))
30 .transpose()
31 .map_err(|e| StorageError::InvalidConfiguration(e.to_string()))
32 };
33 Ok(Self {
34 vector_cache,
35 sql_phase: child(phase, "sql-phase")?,
36 graph_phase: child(phase, "graph-phase")?,
37 })
38 }
39}
40
41impl Store {
42 /// The vector adapter's cache budget (`vector_cache_bytes`).
43 #[must_use]
44 pub fn vector_cache_budget(&self) -> Option<ByteBudget> {
45 self.adapter_budgets.vector_cache.clone()
46 }
47
48 /// The SQL adapter's named child of [`Store::phase_budget`].
49 #[must_use]
50 pub fn sql_phase_budget(&self) -> Option<ByteBudget> {
51 self.adapter_budgets.sql_phase.clone()
52 }
53
54 /// The native graph/query adapter's named child of [`Store::phase_budget`]
55 #[must_use]
56 pub fn graph_phase_budget(&self) -> Option<ByteBudget> {
57 self.adapter_budgets.graph_phase.clone()
58 }
59}