mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-10-26 13:46:23 +00:00
feat: clean up soft-dropped regions offline (#8458)
* fix(meta): skip reopening dropped tables during purge Purge soft-dropped tables by dropping stored routes directly instead of reopening tombstoned regions first. Treat legacy \`PurgeDroppedTableState::OpenRegions\` snapshots as a compatibility-only transition to \`DropRegions\`. Files: - \`src/common/meta/src/ddl/purge_dropped_table.rs\` - \`src/common/meta/src/ddl/undrop_table.rs\` - \`src/common/meta/src/ddl/tests/drop_table.rs\` Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * fix(meta): guard undrop restore race Serialize `UNDROP TABLE` with same-name creates by seeding the original table name before procedure submission, and clean up reopened regions when metadata restore fails. Files: - `src/common/meta/src/ddl/undrop_table.rs` - `src/common/meta/src/ddl_manager.rs` - `src/common/meta/src/ddl/tests/drop_table.rs` Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * feat: clean up soft-dropped regions offline Use an explicit RegionCleanUp request for purge-table cleanup so tombstoned regions can be removed without reopening them. Route cleanup through datanode, Mito, and metric-engine offline paths, including WAL obsoletion and region directory removal. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * fix(datanode): reject cleanup for registered regions Return `RegionBusy` when `RegionCleanUp` targets a region already tracked by the datanode, so offline cleanup only runs for regions without a local mapping. Add coverage for `OfflineCleanup` engine selection and registered-region rejection. Files: - `src/datanode/src/region_server.rs` Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * fix(meta): require tombstone before undrop Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * fix(meta): reject file-engine soft drop Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * fix: harden soft-drop cleanup paths Reject `RegionCleanUp` for already-open Mito regions instead of turning cleanup into a drop. Make `UndropTableProcedure` tolerate missing persisted table names and always deregister failure detectors after restore-failure cleanup. Files: - `src/common/meta/src/ddl/undrop_table.rs` - `src/mito2/src/engine/open_test.rs` - `src/mito2/src/worker/handle_open.rs` Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * chore: bump cleanup proto dependency Bump \`greptime-proto\` to the reviewed cleanup RPC revision and align cleanup request parsing and dispatch with the renamed \`CleanUpRequest\` payload. Files: - \`Cargo.toml\` - \`Cargo.lock\` - \`src/store-api/src/region_request.rs\` - \`src/common/meta/src/ddl/drop_table/executor.rs\` Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * refactor: share region cleanup helpers Share common region cleanup helpers between normal drop and offline cleanup while keeping their preconditions separate. - Extract shared dropped-region runtime cleanup for `handle_drop_request` and `handle_offline_cleanup_request`. - Share runtime artifact and manifest cache cleanup after full deletion paths. - Make full-drop directory removal policy explicit: full drop and purge cleanup force physical deletion, while partial drop may defer to global GC. Files: - `src/mito2/src/worker/handle_drop.rs` - `src/mito2/src/worker/handle_open.rs` Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * chore: preserve soft-drop cleanup split state Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * refactor: remove obsolete CleanUp match arm from RegionRequest The `CleanUp` variant in the `region_request::Body` match is now handled exclusively by `RegionServer` via a separate path. This arm would have returned an unexpected error, so removing it eliminates dead code. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * fix(meta): clean every soft-dropped region replica Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * fix(meta): order soft-drop replica cleanup Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * Revert "fix(meta): order soft-drop replica cleanup" This reverts commit e77162d3e5ebcf2817e2845a6a5177c328fb2c60. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> * Revert "fix(meta): clean every soft-dropped region replica" This reverts commit 2378e00cc258ca1b6a85a1aafbd68c79c666f43c. Signed-off-by: Lei, HUANG <ratuthomm@gmail.com> --------- Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>
This commit is contained in:
@@ -23,10 +23,10 @@ use api::v1::column_def::{
|
||||
};
|
||||
use api::v1::region::bulk_insert_request::Body;
|
||||
use api::v1::region::{
|
||||
AlterRequest, AlterRequests, BuildIndexRequest, BulkInsertRequest, CloseRequest,
|
||||
CompactRequest, CreateRequest, CreateRequests, DeleteRequests, DropRequest, DropRequests,
|
||||
FlushRequest, InsertRequests, OpenRequest, TruncateRequest, alter_request, compact_request,
|
||||
region_request, truncate_request,
|
||||
AlterRequest, AlterRequests, BuildIndexRequest, BulkInsertRequest,
|
||||
CleanUpRequest as PbCleanUpRequest, CloseRequest, CompactRequest, CreateRequest,
|
||||
CreateRequests, DeleteRequests, DropRequest, DropRequests, FlushRequest, InsertRequests,
|
||||
OpenRequest, TruncateRequest, alter_request, compact_request, region_request, truncate_request,
|
||||
};
|
||||
use api::v1::{
|
||||
self, Analyzer, ArrowIpc, FulltextBackend as PbFulltextBackend, Option as PbOption, Rows,
|
||||
@@ -145,6 +145,7 @@ pub enum RegionRequest {
|
||||
Create(RegionCreateRequest),
|
||||
Drop(RegionDropRequest),
|
||||
Open(RegionOpenRequest),
|
||||
CleanUp(RegionCleanUpRequest),
|
||||
Close(RegionCloseRequest),
|
||||
Alter(RegionAlterRequest),
|
||||
Flush(RegionFlushRequest),
|
||||
@@ -167,6 +168,7 @@ impl RegionRequest {
|
||||
region_request::Body::Create(create) => make_region_create(create),
|
||||
region_request::Body::Drop(drop) => make_region_drop(drop),
|
||||
region_request::Body::Open(open) => make_region_open(open),
|
||||
region_request::Body::CleanUp(clean_up) => make_region_clean_up(clean_up),
|
||||
region_request::Body::Close(close) => make_region_close(close),
|
||||
region_request::Body::Alter(alter) => make_region_alter(alter),
|
||||
region_request::Body::Flush(flush) => make_region_flush(flush),
|
||||
@@ -189,10 +191,6 @@ impl RegionRequest {
|
||||
reason: "RemoteDynFilter request should be handled separately by RegionServer",
|
||||
}
|
||||
.fail(),
|
||||
region_request::Body::CleanUp(_) => UnexpectedSnafu {
|
||||
reason: "CleanUp request should be handled separately by RegionServer",
|
||||
}
|
||||
.fail(),
|
||||
region_request::Body::ApplyStagingManifest(apply) => {
|
||||
make_region_apply_staging_manifest(apply)
|
||||
}
|
||||
@@ -329,6 +327,20 @@ fn make_region_open(open: OpenRequest) -> Result<Vec<(RegionId, RegionRequest)>>
|
||||
)])
|
||||
}
|
||||
|
||||
fn make_region_clean_up(clean_up: PbCleanUpRequest) -> Result<Vec<(RegionId, RegionRequest)>> {
|
||||
let region_id = RegionId::from(clean_up.region_id);
|
||||
let table_dir = table_dir(&clean_up.path, region_id.table_id());
|
||||
Ok(vec![(
|
||||
region_id,
|
||||
RegionRequest::CleanUp(RegionCleanUpRequest {
|
||||
engine: clean_up.engine,
|
||||
table_dir,
|
||||
path_type: PathType::Bare,
|
||||
options: clean_up.options,
|
||||
}),
|
||||
)])
|
||||
}
|
||||
|
||||
fn make_region_close(close: CloseRequest) -> Result<Vec<(RegionId, RegionRequest)>> {
|
||||
let region_id = close.region_id.into();
|
||||
Ok(vec![(
|
||||
@@ -652,6 +664,26 @@ impl RegionOpenRequest {
|
||||
}
|
||||
}
|
||||
|
||||
/// Offline region cleanup request.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RegionCleanUpRequest {
|
||||
/// Region engine name
|
||||
pub engine: String,
|
||||
/// Directory for table's data home. Usually is composed by catalog and table id
|
||||
pub table_dir: String,
|
||||
/// Path type for generating paths
|
||||
pub path_type: PathType,
|
||||
/// Options of the cleaned region.
|
||||
pub options: HashMap<String, String>,
|
||||
}
|
||||
|
||||
impl RegionCleanUpRequest {
|
||||
/// Returns true when the region belongs to the metric engine's physical table.
|
||||
pub fn is_physical_table(&self) -> bool {
|
||||
self.options.contains_key(PHYSICAL_TABLE_METADATA_KEY)
|
||||
}
|
||||
}
|
||||
|
||||
/// Close region request.
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
|
||||
pub struct RegionCloseRequest {
|
||||
@@ -1642,6 +1674,7 @@ impl fmt::Display for RegionRequest {
|
||||
RegionRequest::Create(_) => write!(f, "Create"),
|
||||
RegionRequest::Drop(_) => write!(f, "Drop"),
|
||||
RegionRequest::Open(_) => write!(f, "Open"),
|
||||
RegionRequest::CleanUp(_) => write!(f, "CleanUp"),
|
||||
RegionRequest::Close(_) => write!(f, "Close"),
|
||||
RegionRequest::Alter(_) => write!(f, "Alter"),
|
||||
RegionRequest::Flush(_) => write!(f, "Flush"),
|
||||
@@ -2203,6 +2236,28 @@ mod tests {
|
||||
assert_eq!(request.requirements, RegionRequirements::object_storage());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_region_cleanup_from_proto() {
|
||||
let clean_up = api::v1::region::CleanUpRequest {
|
||||
region_id: RegionId::new(42, 3).as_u64(),
|
||||
engine: "mito".to_string(),
|
||||
path: "test".to_string(),
|
||||
options: HashMap::from([("k".to_string(), "v".to_string())]),
|
||||
};
|
||||
|
||||
let requests =
|
||||
RegionRequest::try_from_request_body(region_request::Body::CleanUp(clean_up)).unwrap();
|
||||
let RegionRequest::CleanUp(request) = &requests[0].1 else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
assert_eq!(requests[0].0, RegionId::new(42, 3));
|
||||
assert_eq!(request.engine, "mito");
|
||||
assert_eq!(request.table_dir, "data/test/42/");
|
||||
assert_eq!(request.path_type, PathType::Bare);
|
||||
assert_eq!(request.options.get("k"), Some(&"v".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_validate_modify_column_fulltext_options() {
|
||||
let kind = AlterKind::SetIndexes {
|
||||
|
||||
Reference in New Issue
Block a user