Skip to main content

kevy_embedded/
store_tick.rs

1//! `Store::tick` — the Manual-mode maintenance cadence, the same
2//! per-shard body the background reaper drives. A `#[path]` child of
3//! `store.rs`, split under the 500-LOC rule.
4
5use kevy_store::ExpireStats;
6
7use crate::store::{Store, lock_write};
8
9impl Store {
10    /// Run one TTL-reaper tick across every shard. Required call cadence in
11    /// `Manual` mode (~10×/s to match Redis `hz=10`). Returns the summed stats.
12    pub fn tick(&self) -> ExpireStats {
13        let mut total = ExpireStats::default();
14        for (shard_i, shard) in self.shards.iter().enumerate() {
15            #[cfg(not(all(feature = "index", feature = "persist", not(target_arch = "wasm32"))))]
16            let _ = shard_i;
17            let stats = {
18                let mut g = lock_write(shard);
19                // Tiering upkeep: budget re-resolution + the index/view
20                // floor feed, then the tick continuation of the
21                // budgeted spill.
22                #[cfg(all(feature = "tier", not(target_arch = "wasm32")))]
23                crate::shard::tier_tick_upkeep(&mut g, self.config.tier_budget, self.shards.len());
24                let _ = g.store.demote_step();
25                let _ = g.store.tier_compact_tick();
26                // The window tick rides the manual cadence exactly as it
27                // rides the background reaper's — a Manual-mode store
28                // with a windowed table must slide too, not silently
29                // stay all-hot.
30                #[cfg(all(feature = "index", feature = "persist", not(target_arch = "wasm32")))]
31                if let Some(dir) = &self.config.data_dir {
32                    let inner = &mut *g;
33                    crate::ops_index_window::window_tick(
34                        &mut inner.idx_segs,
35                        &mut inner.store,
36                        &mut inner.aof,
37                        &self.tables,
38                        &kevy_persist::layout::segs_dir(dir, shard_i),
39                    );
40                }
41                g.store.tick_expire(self.config.reaper_samples, self.config.reaper_max_rounds)
42            };
43            total.sampled += stats.sampled;
44            total.expired += stats.expired;
45            // Auto-rewrite rides the caller-driven tick in Manual mode; the
46            // non-blocking path releases the lock for the disk spill.
47            #[cfg(feature = "persist")]
48            crate::reaper::concurrent_auto_rewrite(
49                shard,
50                kevy_persist::RewritePolicy {
51                    pct: self.config.auto_aof_rewrite_pct,
52                    min_size: self.config.auto_aof_rewrite_min_size,
53                    bytes: self.config.auto_aof_rewrite_bytes,
54                    interval_secs: self.config.auto_aof_rewrite_interval_secs,
55                },
56                self.config.metric_sink.as_ref(),
57            );
58        }
59        total
60    }
61}