tuwunel_database/map/compact.rs
1//! Manual compaction controls for database maps.
2//!
3//! The module exposes range, level, completion, and exclusivity settings.
4//! `Map::compact_blocking` applies them synchronously.
5
6use rocksdb::{BottommostLevelCompaction, CompactOptions};
7use tuwunel_core::{Err, Result, implement};
8
9use crate::keyval::KeyBuf;
10
11/// Configures a manual compaction for a map.
12///
13/// A range can limit selected keys, while level selection controls compaction
14/// placement. Completion and exclusivity flags determine how aggressively
15/// RocksDB runs the operation.
16#[derive(Clone, Debug, Default)]
17pub struct Options {
18 /// Bounds the key range selected for compaction.
19 ///
20 /// A missing lower or upper bound leaves that side of the range unbounded.
21 pub range: (Option<KeyBuf>, Option<KeyBuf>),
22
23 /// Describes the supported manual-compaction level modes.
24 ///
25 /// `(None, None)` lets RocksDB choose placement, and `(None, Some(target))`
26 /// compacts all levels into `target`. `(Some(level), None)` validates
27 /// `level` but leaves normal placement unchanged; two explicit levels are
28 /// unsupported.
29 pub level: (Option<usize>, Option<usize>),
30
31 /// Controls whether bottommost data is compacted fully.
32 ///
33 /// When disabled, RocksDB avoids recompacting bottommost files created by
34 /// this compaction. Enabling this option forces bottommost compaction.
35 pub exhaustive: bool,
36
37 /// Controls whether manual compaction runs exclusively.
38 ///
39 /// When enabled, RocksDB waits for ongoing compactions and pauses automatic
40 /// compaction until this operation finishes.
41 pub exclusive: bool,
42}
43
44/// Compacts this map synchronously with the supplied options.
45///
46/// The key range and supported target placement are forwarded to RocksDB
47/// manual compaction. Unsupported level combinations and invalid target levels
48/// are returned to the caller.
49#[implement(super::Map)]
50#[tracing::instrument(
51 name = "compact",
52 level = "info"
53 skip(self),
54 fields(%self),
55)]
56pub fn compact_blocking(&self, opts: Options) -> Result {
57 let mut co = CompactOptions::default();
58 co.set_exclusive_manual_compaction(opts.exclusive);
59 co.set_bottommost_level_compaction(match opts.exhaustive {
60 | true => BottommostLevelCompaction::Force,
61 | false => BottommostLevelCompaction::ForceOptimized,
62 });
63
64 match opts.level {
65 | (None, None) => {
66 co.set_change_level(true);
67 co.set_target_level(-1);
68 },
69 | (None, Some(level)) => {
70 co.set_change_level(true);
71 co.set_target_level(level.try_into()?);
72 },
73 | (Some(level), None) => {
74 co.set_change_level(false);
75 co.set_target_level(level.try_into()?);
76 },
77 | (Some(_), Some(_)) => return Err!("compacting between specific levels not supported"),
78 }
79
80 self.engine
81 .db
82 .compact_range_cf_opt(&self.cf(), opts.range.0, opts.range.1, &co);
83
84 Ok(())
85}