common_meta/reconciliation/reconcile_table/
reconciliation_start.rs1use common_procedure::{Context as ProcedureContext, Status};
16use common_telemetry::info;
17use serde::{Deserialize, Serialize};
18use snafu::ensure;
19
20use crate::ddl::utils::region_metadata_lister::RegionMetadataLister;
21use crate::error::{self, Result};
22use crate::metrics::{self};
23use crate::reconciliation::reconcile_table::resolve_column_metadata::ResolveColumnMetadata;
24use crate::reconciliation::reconcile_table::{
25 ReconcileTableContext, ReconcileTableProcedure, State,
26};
27
28#[derive(Debug, Serialize, Deserialize)]
36pub struct ReconciliationStart;
37
38#[async_trait::async_trait]
39#[typetag::serde]
40impl State for ReconciliationStart {
41 async fn next(
42 &mut self,
43 ctx: &mut ReconcileTableContext,
44 procedure_ctx: &ProcedureContext,
45 ) -> Result<(Box<dyn State>, Status)> {
46 let table_id = ctx.table_id();
47
48 let (physical_table_id, physical_table_route) = ctx
49 .table_metadata_manager
50 .table_route_manager()
51 .get_physical_table_route(table_id)
52 .await?;
53 ensure!(
54 physical_table_id == table_id,
55 error::UnexpectedSnafu {
56 err_msg: format!(
57 "Reconcile table only works for physical table, but got logical table: {}, table_id: {}",
58 ctx.table_name(),
59 table_id
60 ),
61 }
62 );
63
64 info!(
65 "Reconciling table: {}, table_id: {}, procedure_id: {}",
66 ctx.table_name(),
67 table_id,
68 procedure_ctx.procedure_id
69 );
70 let region_metadata_lister = RegionMetadataLister::new(ctx.node_manager.clone());
72
73 let region_metadatas = {
74 let _timer = metrics::METRIC_META_RECONCILIATION_LIST_REGION_METADATA_DURATION
75 .with_label_values(&[metrics::TABLE_TYPE_PHYSICAL])
76 .start_timer();
77 region_metadata_lister
79 .list(physical_table_id, &physical_table_route.region_routes)
80 .await?
81 };
82 ctx.volatile_ctx
83 .result_summary
84 .record_scanned_regions(region_metadatas.len());
85
86 ensure!(!region_metadatas.is_empty(), {
87 metrics::METRIC_META_RECONCILIATION_STATS
88 .with_label_values(&[
89 ReconcileTableProcedure::TYPE_NAME,
90 metrics::TABLE_TYPE_PHYSICAL,
91 metrics::STATS_TYPE_NO_REGION_METADATA,
92 ])
93 .inc();
94
95 error::UnexpectedSnafu {
96 err_msg: format!(
97 "No region metadata found for table: {}, table_id: {}",
98 ctx.table_name(),
99 table_id
100 ),
101 }
102 });
103
104 ensure!(region_metadatas.iter().all(|r| r.is_some()), {
105 metrics::METRIC_META_RECONCILIATION_STATS
106 .with_label_values(&[
107 ReconcileTableProcedure::TYPE_NAME,
108 metrics::TABLE_TYPE_PHYSICAL,
109 metrics::STATS_TYPE_REGION_NOT_OPEN,
110 ])
111 .inc();
112
113 error::UnexpectedSnafu {
114 err_msg: format!(
115 "Some regions are not opened, table: {}, table_id: {}",
116 ctx.table_name(),
117 table_id
118 ),
119 }
120 });
121
122 ctx.volatile_ctx.result_summary.mark_start_completed();
123
124 ctx.persistent_ctx.physical_table_route = Some(physical_table_route);
127 let region_metadatas = region_metadatas.into_iter().map(|r| r.unwrap()).collect();
128 Ok((
129 Box::new(ResolveColumnMetadata::new(
130 ctx.persistent_ctx.resolve_strategy,
131 region_metadatas,
132 )),
133 Status::executing(false),
135 ))
136 }
137}