Skip to main content

nodedb_fts/index/writer/
state.rs

1// SPDX-License-Identifier: Apache-2.0
2
3//! Index state, construction, and backend access.
4
5use crate::{
6    backend::FtsBackend,
7    lsm::memtable::{Memtable, MemtableConfig},
8    posting::Bm25Params,
9};
10use nodedb_mem::MemoryGovernor;
11use std::sync::{Arc, atomic::AtomicU64};
12
13/// Full-text search index generic over storage backend.
14///
15/// Indexing, search, and highlighting use the [`FtsBackend`] storage contract.
16///
17/// Writes accumulate in an in-memory `Memtable`, one state per index.
18/// Threshold-triggered flushing writes each index's postings to an
19/// immutable segment of that index through the backend.
20/// Queries merge the active memtable with stored segments.
21/// The backend determines segment durability.
22///
23/// [`MemoryGovernor`] enforces per-engine memory budgets on large
24/// allocations (compaction, segment merge, query term collection).
25pub struct FtsIndex<B: FtsBackend> {
26    pub(crate) backend: B,
27    pub(crate) bm25_params: Bm25Params,
28    pub(crate) memtable: Memtable,
29    /// Monotonic segment ID counter.
30    pub(super) next_segment_id: AtomicU64,
31    /// Memory governor for budget enforcement.
32    pub(crate) governor: Arc<MemoryGovernor>,
33}
34
35impl<B: FtsBackend> FtsIndex<B> {
36    /// Create a new FTS index with the given backend, default BM25 params, and a memory governor.
37    pub fn new(backend: B, governor: Arc<MemoryGovernor>) -> Self {
38        Self {
39            backend,
40            bm25_params: Bm25Params::default(),
41            memtable: Memtable::new(MemtableConfig::default()),
42            next_segment_id: AtomicU64::new(1),
43            governor,
44        }
45    }
46
47    /// Create a new FTS index with custom BM25 parameters and a memory governor.
48    pub fn with_params(backend: B, params: Bm25Params, governor: Arc<MemoryGovernor>) -> Self {
49        Self {
50            bm25_params: params,
51            ..Self::new(backend, governor)
52        }
53    }
54
55    /// Create a new FTS index whose memtable spills at `memtable` thresholds.
56    /// Unreachable thresholds keep every posting in the memtable.
57    pub fn with_memtable_config(
58        backend: B,
59        memtable: MemtableConfig,
60        governor: Arc<MemoryGovernor>,
61    ) -> Self {
62        Self {
63            memtable: Memtable::new(memtable),
64            ..Self::new(backend, governor)
65        }
66    }
67
68    /// Create a new FTS index with custom BM25 parameters whose memtable
69    /// spills at `memtable` thresholds.
70    pub fn with_config(
71        backend: B,
72        params: Bm25Params,
73        memtable: MemtableConfig,
74        governor: Arc<MemoryGovernor>,
75    ) -> Self {
76        Self {
77            bm25_params: params,
78            memtable: Memtable::new(memtable),
79            ..Self::new(backend, governor)
80        }
81    }
82
83    /// Access the underlying backend.
84    pub fn backend(&self) -> &B {
85        &self.backend
86    }
87
88    /// Mutable access to the underlying backend.
89    pub fn backend_mut(&mut self) -> &mut B {
90        &mut self.backend
91    }
92
93    /// Access the active memtable (for LSM query merging).
94    pub fn memtable(&self) -> &Memtable {
95        &self.memtable
96    }
97}