Skip to content

Commit 54a9e82

Browse files
committed
add version number support
1 parent 9b5ffdd commit 54a9e82

File tree

6 files changed

+229
-90
lines changed

6 files changed

+229
-90
lines changed

src/common/tracing/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ pub use crate::remote_log::LogMessage;
5353
pub use crate::remote_log::RemoteLog;
5454
pub use crate::remote_log::RemoteLogElement;
5555
pub use crate::remote_log::RemoteLogGuard;
56+
pub use crate::remote_log::PERSISTENT_LOG_SCHEMA_VERSION;
5657
pub use crate::structlog::DummyReporter;
5758
pub use crate::structlog::StructLogReporter;
5859

src/common/tracing/src/remote_log.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ use serde_json::Map;
5353
use crate::Config;
5454
use crate::GlobalLogger;
5555

56+
pub const PERSISTENT_LOG_SCHEMA_VERSION: usize = 1;
57+
5658
/// An appender that sends log records to persistent storage
5759
#[derive(Debug)]
5860
pub struct RemoteLog {
@@ -178,8 +180,9 @@ impl RemoteLog {
178180
op.as_ref()?;
179181

180182
let path = format!(
181-
"stage/internal/{}/{}.parquet",
183+
"stage/internal/{}_v{}/{}.parquet",
182184
stage_name,
185+
PERSISTENT_LOG_SCHEMA_VERSION,
183186
uuid::Uuid::new_v4()
184187
);
185188

src/query/service/src/persistent_log/global_persistent_log.rs

Lines changed: 100 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,19 @@ use databend_common_exception::ErrorCode;
3030
use databend_common_exception::Result;
3131
use databend_common_license::license::Feature;
3232
use databend_common_license::license_manager::LicenseManagerSwitch;
33-
use databend_common_meta_client::ClientHandle;
3433
use databend_common_meta_client::MetaGrpcClient;
3534
use databend_common_meta_kvapi::kvapi::KVApi;
3635
use databend_common_meta_semaphore::acquirer::Permit;
3736
use databend_common_meta_semaphore::Semaphore;
37+
use databend_common_meta_store::MetaStore;
38+
use databend_common_meta_store::MetaStoreProvider;
3839
use databend_common_meta_types::MatchSeq;
3940
use databend_common_meta_types::Operation;
4041
use databend_common_meta_types::UpsertKV;
4142
use databend_common_sql::Planner;
4243
use databend_common_storage::DataOperator;
4344
use databend_common_tracing::GlobalLogger;
45+
use databend_common_tracing::PERSISTENT_LOG_SCHEMA_VERSION;
4446
use log::error;
4547
use log::info;
4648
use rand::random;
@@ -55,14 +57,13 @@ use crate::persistent_log::table_schemas::QueryProfileTable;
5557
use crate::sessions::QueryContext;
5658

5759
pub struct GlobalPersistentLog {
58-
meta_client: Option<Arc<ClientHandle>>,
60+
meta_store: MetaStore,
5961
interval: u64,
6062
tenant_id: String,
6163
node_id: String,
6264
cluster_id: String,
6365
stage_name: String,
6466
initialized: AtomicBool,
65-
stopped: AtomicBool,
6667
tables: Vec<Box<dyn PersistentLogTable>>,
6768
retention: usize,
6869
}
@@ -79,7 +80,7 @@ impl GlobalPersistentLog {
7980
let mut tables: Vec<Box<dyn PersistentLogTable>> = vec![];
8081

8182
if cfg.log.query.on {
82-
let query_details = QueryDetailsTable;
83+
let query_details = QueryDetailsTable::new();
8384
info!(
8485
"Persistent query details table is enabled, persistent_system.{}",
8586
query_details.table_name()
@@ -88,30 +89,35 @@ impl GlobalPersistentLog {
8889
}
8990

9091
if cfg.log.profile.on {
91-
let profile = QueryProfileTable;
92+
let profile = QueryProfileTable::new();
9293
info!(
9394
"Persistent query profile table is enabled, persistent_system.{}",
9495
profile.table_name()
9596
);
9697
tables.push(Box::new(profile));
9798
}
9899

99-
let query_log = QueryLogTable;
100+
let query_log = QueryLogTable::new();
100101
info!(
101102
"Persistent query log table is enabled, persistent_system.{}",
102103
query_log.table_name()
103104
);
104105
tables.push(Box::new(query_log));
105106

107+
let stage_name = format!(
108+
"{}_v{}",
109+
cfg.log.persistentlog.stage_name.clone(),
110+
PERSISTENT_LOG_SCHEMA_VERSION
111+
);
112+
106113
let instance = Arc::new(Self {
107-
meta_client: Some(meta_client),
114+
meta_store: MetaStore::R(meta_client),
108115
interval: cfg.log.persistentlog.interval as u64,
109116
tenant_id: cfg.query.tenant_id.tenant_name().to_string(),
110117
node_id: cfg.query.node_id.clone(),
111118
cluster_id: cfg.query.cluster_id.clone(),
112-
stage_name: cfg.log.persistentlog.stage_name.clone(),
119+
stage_name,
113120
initialized: AtomicBool::new(false),
114-
stopped: AtomicBool::new(false),
115121
tables,
116122
retention: cfg.log.persistentlog.retention,
117123
});
@@ -127,21 +133,24 @@ impl GlobalPersistentLog {
127133
Ok(())
128134
}
129135

136+
/// Create a dummy instance of GlobalPersistentLog for testing purposes.
130137
pub async fn create_dummy(cfg: &InnerConfig) -> Result<Self> {
131138
setup_operator().await?;
139+
let meta_store = MetaStoreProvider::new(cfg.meta.to_meta_grpc_client_conf())
140+
.create_meta_store()
141+
.await?;
132142
Ok(Self {
133-
meta_client: None,
143+
meta_store,
134144
interval: cfg.log.persistentlog.interval as u64,
135145
tenant_id: cfg.query.tenant_id.tenant_name().to_string(),
136146
node_id: cfg.query.node_id.clone(),
137147
cluster_id: cfg.query.cluster_id.clone(),
138148
stage_name: cfg.log.persistentlog.stage_name.clone(),
139149
initialized: AtomicBool::new(false),
140-
stopped: AtomicBool::new(false),
141150
tables: vec![
142-
Box::new(QueryDetailsTable),
143-
Box::new(QueryProfileTable),
144-
Box::new(QueryLogTable),
151+
Box::new(QueryDetailsTable::new()),
152+
Box::new(QueryProfileTable::new()),
153+
Box::new(QueryLogTable::new()),
145154
],
146155
retention: cfg.log.persistentlog.retention,
147156
})
@@ -157,6 +166,7 @@ impl GlobalPersistentLog {
157166

158167
pub async fn work(&self) -> Result<()> {
159168
let mut prepared = false;
169+
let meta_key = format!("{}/persistent_log_work", self.tenant_id);
160170
// Wait all services to be initialized
161171
loop {
162172
if !self.initialized.load(Ordering::SeqCst) {
@@ -171,19 +181,10 @@ impl GlobalPersistentLog {
171181
}
172182
});
173183
loop {
174-
if self.stopped.load(Ordering::SeqCst) {
175-
return Ok(());
176-
}
177184
// create the stage, database and table if not exists
178185
// alter the table if schema is changed
179186
if !prepared {
180-
let prepare_guard = self
181-
.acquire(
182-
&format!("{}/persistent_log_prepare", self.tenant_id),
183-
self.interval,
184-
0,
185-
)
186-
.await?;
187+
let prepare_guard = self.acquire(&meta_key, self.interval, 0).await?;
187188
match self.prepare().await {
188189
Ok(_) => {
189190
info!("Persistent log prepared successfully");
@@ -195,13 +196,21 @@ impl GlobalPersistentLog {
195196
}
196197
drop(prepare_guard);
197198
}
198-
let meta_key = format!("{}/persistent_log_work", self.tenant_id);
199199
let may_permit = self
200200
.acquire(&meta_key, self.interval, self.interval)
201201
.await?;
202202
if let Some(guard) = may_permit {
203203
if let Err(e) = self.do_copy_into().await {
204204
error!("Persistent log copy into failed: {:?}", e);
205+
let latest_version = self.get_version_from_meta().await?;
206+
if let Some(version) = latest_version {
207+
if version > PERSISTENT_LOG_SCHEMA_VERSION as u64 {
208+
info!("Persistent log tables enable version suffix");
209+
for table in &self.tables {
210+
table.enable_version_suffix();
211+
}
212+
}
213+
}
205214
}
206215
self.finish_hook(&meta_key).await?;
207216
drop(guard);
@@ -222,8 +231,12 @@ impl GlobalPersistentLog {
222231
lease: u64,
223232
interval: u64,
224233
) -> Result<Option<Permit>> {
234+
let meta_client = match &self.meta_store {
235+
MetaStore::R(handle) => handle.clone(),
236+
_ => unreachable!("Metastore::L should only used for testing"),
237+
};
225238
let acquired_guard = Semaphore::new_acquired(
226-
self.meta_client.clone().unwrap(),
239+
meta_client,
227240
meta_key,
228241
1,
229242
self.node_id.clone(),
@@ -235,9 +248,7 @@ impl GlobalPersistentLog {
235248
return Ok(Some(acquired_guard));
236249
}
237250
if match self
238-
.meta_client
239-
.clone()
240-
.unwrap()
251+
.meta_store
241252
.get_kv(&format!("{}/last_timestamp", meta_key))
242253
.await?
243254
{
@@ -257,9 +268,7 @@ impl GlobalPersistentLog {
257268
}
258269

259270
pub async fn finish_hook(&self, meta_key: &str) -> Result<()> {
260-
self.meta_client
261-
.clone()
262-
.unwrap()
271+
self.meta_store
263272
.upsert_kv(UpsertKV::new(
264273
format!("{}/last_timestamp", meta_key),
265274
MatchSeq::Any,
@@ -299,31 +308,47 @@ impl GlobalPersistentLog {
299308
let create_db = "CREATE DATABASE IF NOT EXISTS persistent_system";
300309
self.execute_sql(create_db).await?;
301310

302-
for table in &self.tables {
303-
let session = create_session(&self.tenant_id, &self.cluster_id).await?;
304-
let context = session.create_query_context().await?;
305-
let table_name = table.table_name();
306-
let old_table = context
307-
.get_table(CATALOG_DEFAULT, "persistent_system", table_name)
308-
.await;
309-
if old_table.is_ok() {
310-
let old_schema = old_table?.schema();
311-
if !table.schema_equal(old_schema) {
312-
let rename_target =
313-
format!("`{}_old_{}`", table_name, chrono::Local::now().timestamp());
314-
let rename = format!(
315-
"ALTER TABLE persistent_system.{} RENAME TO {}",
316-
table_name, rename_target
311+
let session = create_session(&self.tenant_id, &self.cluster_id).await?;
312+
let context = session.create_query_context().await?;
313+
if let Some(version) = self.get_version_from_meta().await? {
314+
if version > PERSISTENT_LOG_SCHEMA_VERSION as u64 {
315+
// older version node need put the logs into the table has version suffix
316+
for table in &self.tables {
317+
table.enable_version_suffix();
318+
}
319+
return Ok(());
320+
}
321+
let mut need_rename = false;
322+
for table in &self.tables {
323+
let old_table = context
324+
.get_table(CATALOG_DEFAULT, "persistent_system", &table.table_name())
325+
.await;
326+
if old_table.is_ok() {
327+
let old_schema = old_table?.schema();
328+
if !table.schema_equal(old_schema) {
329+
need_rename = true;
330+
}
331+
}
332+
}
333+
if need_rename {
334+
for table in &self.tables {
335+
let old_table_name = format!("`{}_v{}`", table.table_name(), version);
336+
let rename_sql = format!(
337+
"ALTER TABLE IF EXISTS persistent_system.{} RENAME TO {}",
338+
table.table_name(),
339+
old_table_name
317340
);
318-
info!("Persistent log table already exists, but schema is different, renaming to {}", rename_target);
319-
self.execute_sql(&rename).await?;
341+
self.execute_sql(&rename_sql).await?;
320342
}
321-
} else {
322-
info!("Persistent log table {} not exists, creating", table_name);
323343
}
344+
}
345+
self.set_version_to_meta(PERSISTENT_LOG_SCHEMA_VERSION)
346+
.await?;
347+
for table in &self.tables {
324348
let create_table = table.create_table_sql();
325349
self.execute_sql(&create_table).await?;
326350
}
351+
327352
Ok(())
328353
}
329354

@@ -392,8 +417,30 @@ impl GlobalPersistentLog {
392417
Ok(())
393418
}
394419

395-
pub fn stop(&self) {
396-
self.stopped.store(true, Ordering::SeqCst);
420+
pub async fn get_version_from_meta(&self) -> Result<Option<u64>> {
421+
match self
422+
.meta_store
423+
.get_kv(&format!("{}/persistent_log_work/version", self.tenant_id))
424+
.await?
425+
{
426+
Some(v) => {
427+
let version: u64 = serde_json::from_slice(&v.data)?;
428+
Ok(Some(version))
429+
}
430+
None => Ok(None),
431+
}
432+
}
433+
434+
pub async fn set_version_to_meta(&self, version: usize) -> Result<()> {
435+
self.meta_store
436+
.upsert_kv(UpsertKV::new(
437+
&format!("{}/persistent_log_work/version", self.tenant_id),
438+
MatchSeq::Any,
439+
Operation::Update(serde_json::to_vec(&version)?),
440+
None,
441+
))
442+
.await?;
443+
Ok(())
397444
}
398445
}
399446

src/query/service/src/persistent_log/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,7 @@ mod session;
1717
mod table_schemas;
1818

1919
pub use global_persistent_log::GlobalPersistentLog;
20+
pub use table_schemas::PersistentLogTable;
21+
pub use table_schemas::QueryDetailsTable;
22+
pub use table_schemas::QueryLogTable;
23+
pub use table_schemas::QueryProfileTable;

0 commit comments

Comments
 (0)