// Copyright 2023 Greptime Team // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. use std::sync::Arc; use common_meta::key::TableMetadataManager; use common_meta::key::topic_name::TopicNameKey; use common_meta::region_registry::LeaderRegionRegistry; use common_meta::wal_provider::build_kafka_client; use common_procedure::{ProcedureWithId, watcher}; use common_wal::config::kafka::common::KafkaConnectionConfig; use common_wal::maybe_skip_kafka_integration_test; use common_wal::test_util::get_kafka_endpoints; use meta_srv::procedure::wal_prune::{Context as WalPruneContext, WalPruneProcedure}; use rskafka::client::partition::{Compression, UnknownTopicHandling}; use rskafka::record::Record; use tests_integration::standalone::GreptimeDbStandaloneBuilder; use crate::event_recorder_test_util::assert_single_event; #[tokio::test(flavor = "multi_thread")] async fn test_standalone_wal_prune_event() { maybe_skip_kafka_integration_test!(); common_telemetry::init_default_ut_logging(); let standalone = GreptimeDbStandaloneBuilder::new("test_standalone_wal_prune_event") .build() .await; let topic_name = format!("test_standalone_wal_prune_event-{}", uuid::Uuid::new_v4()); let connection = KafkaConnectionConfig { broker_endpoints: get_kafka_endpoints(), ..Default::default() }; let client = Arc::new(build_kafka_client(&connection).await.unwrap()); let controller_client = client.controller_client().unwrap(); controller_client .create_topic(&topic_name, 1, 1, 5_000) .await .unwrap(); let partition_client = client .partition_client(&topic_name, 0, UnknownTopicHandling::Retry) .await .unwrap(); let records = (0..3) .map(|i| Record { key: Some(format!("key_{i}").into()), value: Some(format!("value_{i}").into()), timestamp: chrono::Utc::now(), headers: Default::default(), }) .collect(); let offsets = partition_client .produce(records, Compression::NoCompression) .await .unwrap() .offsets; let pruned_entry_id = offsets[2] as u64; let table_metadata_manager = Arc::new(TableMetadataManager::new(standalone.kv_backend.clone())); table_metadata_manager .topic_name_manager() .batch_put(vec![TopicNameKey::new(&topic_name)]) .await .unwrap(); let procedure = WalPruneProcedure::new( WalPruneContext { client: client.clone(), table_metadata_manager, leader_region_registry: Arc::new(LeaderRegionRegistry::default()), }, None, topic_name.clone(), pruned_entry_id, false, ); let procedure_with_id = ProcedureWithId::with_random_id(Box::new(procedure)); let procedure_id = procedure_with_id.id; let mut watcher = standalone .procedure_manager .submit(procedure_with_id) .await .unwrap(); watcher::wait(&mut watcher).await.unwrap(); let query = format!( r#"SELECT count(*) AS event_count FROM greptime_private.events WHERE type = 'wal_prune' AND procedure_id = '{procedure_id}' AND procedure_state = 'Done' AND json_path_match(procedure_trigger, '$.type == "Succeeded"') AND topic_name = '{topic_name}' AND prunable_entry_id = {pruned_entry_id} AND latest_offset = 3 AND json_path_match(payload, '$.version == 1') AND json_path_match(payload, '$.logical_delete == false')"# ); assert_single_event(standalone.fe_instance(), &query).await; controller_client .delete_topic(&topic_name, 5_000) .await .unwrap(); }