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