Skip to main content

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}