1mod buckets;
16pub mod compactor;
17pub mod memory_manager;
18pub mod picker;
19mod reader;
20pub mod run;
21mod scheduler;
22mod task;
23#[cfg(test)]
24mod test_util;
25mod twcs;
26mod window;
27
28use std::collections::HashMap;
29
30use common_meta::key::SchemaMetadataManagerRef;
31use common_telemetry::{debug, error};
32use common_time::TimeToLive;
33use common_time::range::TimestampRange;
34pub use scheduler::CompactionRequest;
35pub(crate) use scheduler::{
36 CompactionExecution, CompactionPickFinished, CompactionScheduler, CompactionTransition,
37};
38use serde::{Deserialize, Serialize};
39use snafu::ResultExt;
40use store_api::storage::RegionId;
41
42use crate::error::{GetSchemaMetadataSnafu, Result, TimeoutSnafu};
43use crate::sst::file::{FileHandle, FileMeta, Level};
44
45async fn find_dynamic_options(
47 region_id: RegionId,
48 region_options: &crate::region::options::RegionOptions,
49 schema_metadata_manager: &SchemaMetadataManagerRef,
50) -> Result<(crate::region::options::CompactionOptions, TimeToLive)> {
51 let table_id = region_id.table_id();
52 if let (true, Some(ttl)) = (region_options.compaction_override, region_options.ttl) {
53 debug!(
54 "Use region options directly for table {}: compaction={:?}, ttl={:?}",
55 table_id, region_options.compaction, region_options.ttl
56 );
57 return Ok((region_options.compaction.clone(), ttl));
58 }
59
60 let db_options = tokio::time::timeout(
61 crate::config::FETCH_OPTION_TIMEOUT,
62 schema_metadata_manager.get_schema_options_by_table_id(table_id),
63 )
64 .await
65 .context(TimeoutSnafu)?
66 .context(GetSchemaMetadataSnafu)?;
67
68 let ttl = if let Some(ttl) = region_options.ttl {
69 debug!(
70 "Use region TTL directly for table {}: ttl={:?}",
71 table_id, region_options.ttl
72 );
73 ttl
74 } else {
75 db_options
76 .as_ref()
77 .and_then(|options| options.ttl)
78 .unwrap_or_default()
79 .into()
80 };
81
82 let compaction = if !region_options.compaction_override {
83 if let Some(schema_opts) = db_options {
84 let map: HashMap<String, String> = schema_opts
85 .extra_options
86 .iter()
87 .filter_map(|(k, v)| {
88 if k.starts_with("compaction.") {
89 Some((k.clone(), v.clone()))
90 } else {
91 None
92 }
93 })
94 .collect();
95 if map.is_empty() {
96 region_options.compaction.clone()
97 } else {
98 crate::region::options::RegionOptions::try_from_options(region_id, &map)
99 .map(|o| o.compaction)
100 .unwrap_or_else(|e| {
101 error!(e; "Failed to create RegionOptions from map");
102 region_options.compaction.clone()
103 })
104 }
105 } else {
106 debug!(
107 "DB options is None for table {}, use region compaction: compaction={:?}",
108 table_id, region_options.compaction
109 );
110 region_options.compaction.clone()
111 }
112 } else {
113 debug!(
114 "No schema options for table {}, use region compaction: compaction={:?}",
115 table_id, region_options.compaction
116 );
117 region_options.compaction.clone()
118 };
119
120 debug!(
121 "Resolved dynamic options for table {}: compaction={:?}, ttl={:?}",
122 table_id, compaction, ttl
123 );
124 Ok((compaction, ttl))
125}
126
127#[derive(Debug, Clone)]
128pub struct CompactionOutput {
129 pub output_level: Level,
131 pub inputs: Vec<FileHandle>,
133 pub filter_deleted: bool,
135 pub output_time_range: Option<TimestampRange>,
137}
138
139#[derive(Debug, Clone, Serialize, Deserialize)]
141pub struct SerializedCompactionOutput {
142 output_level: Level,
143 inputs: Vec<FileMeta>,
144 filter_deleted: bool,
145 output_time_range: Option<TimestampRange>,
146}