1use std::collections::{BTreeMap, HashMap, HashSet};
16use std::fmt::{Debug, Display};
17use std::sync::Arc;
18use std::sync::atomic::AtomicBool;
19use std::sync::atomic::Ordering::Relaxed;
20use std::thread;
21use std::time::{Duration, SystemTime};
22
23use anyhow::{Context, anyhow};
24use async_trait::async_trait;
25use cluster_limit_service_client::ClusterLimitServiceClient;
26use either::Either;
27use futures::stream::BoxStream;
28use list_rate_limits_response::RateLimitInfo;
29use lru::LruCache;
30use replace_job_plan::ReplaceJob;
31use risingwave_common::catalog::{
32 AlterDatabaseParam, FunctionId, IndexId, ObjectId, SecretId, TableId,
33};
34use risingwave_common::config::{MAX_CONNECTION_WINDOW_SIZE, MetaConfig};
35use risingwave_common::hash::WorkerSlotMapping;
36use risingwave_common::id::{
37 ConnectionId, DatabaseId, JobId, SchemaId, SinkId, SubscriptionId, UserId, ViewId, WorkerId,
38};
39use risingwave_common::monitor::EndpointExt;
40use risingwave_common::system_param::AdaptiveParallelismStrategy;
41use risingwave_common::system_param::reader::SystemParamsReader;
42use risingwave_common::telemetry::report::TelemetryInfoFetcher;
43use risingwave_common::util::addr::HostAddr;
44use risingwave_common::util::meta_addr::MetaAddressStrategy;
45use risingwave_common::util::resource_util::cpu::total_cpu_available;
46use risingwave_common::util::resource_util::hostname;
47use risingwave_common::util::resource_util::memory::system_memory_available_bytes;
48use risingwave_common::util::retry::exponential_backoff;
49use risingwave_common::util::version::current_rw_version;
50use risingwave_error::bail;
51use risingwave_error::tonic::ErrorIsFromTonicServerImpl;
52use risingwave_hummock_sdk::change_log::{TableChangeLog, TableChangeLogs};
53use risingwave_hummock_sdk::version::{HummockVersion, HummockVersionDelta};
54use risingwave_hummock_sdk::{
55 CompactionGroupId, HummockEpoch, HummockVersionId, ObjectIdRange, SyncResult,
56};
57use risingwave_pb::backup_service::backup_service_client::BackupServiceClient;
58use risingwave_pb::backup_service::*;
59use risingwave_pb::catalog::{
60 Connection, PbComment, PbDatabase, PbFunction, PbIndex, PbSchema, PbSink, PbSource,
61 PbSubscription, PbTable, PbView, Table,
62};
63use risingwave_pb::cloud_service::cloud_service_client::CloudServiceClient;
64use risingwave_pb::cloud_service::*;
65use risingwave_pb::common::worker_node::Property;
66use risingwave_pb::common::{HostAddress, OptionalUint32, OptionalUint64, WorkerNode, WorkerType};
67use risingwave_pb::configured_monitor_service_client;
68use risingwave_pb::connector_service::sink_coordination_service_client::SinkCoordinationServiceClient;
69use risingwave_pb::ddl_service::alter_owner_request::Object;
70use risingwave_pb::ddl_service::create_iceberg_table_request::{PbSinkJobInfo, PbTableJobInfo};
71use risingwave_pb::ddl_service::ddl_service_client::DdlServiceClient;
72use risingwave_pb::ddl_service::*;
73use risingwave_pb::hummock::compact_task::TaskStatus;
74use risingwave_pb::hummock::get_compaction_score_response::PickerInfo;
75use risingwave_pb::hummock::get_table_change_logs_request::PbTableFilter;
76use risingwave_pb::hummock::hummock_manager_service_client::HummockManagerServiceClient;
77use risingwave_pb::hummock::rise_ctl_update_compaction_config_request::mutable_config::MutableConfig;
78use risingwave_pb::hummock::subscribe_compaction_event_request::Register;
79use risingwave_pb::hummock::write_limits::WriteLimit;
80use risingwave_pb::hummock::*;
81use risingwave_pb::iceberg_compaction::subscribe_iceberg_compaction_event_request::Register as IcebergRegister;
82use risingwave_pb::iceberg_compaction::{
83 SubscribeIcebergCompactionEventRequest, SubscribeIcebergCompactionEventResponse,
84 subscribe_iceberg_compaction_event_request,
85};
86use risingwave_pb::id::{ActorId, FragmentId, HummockSstableId, IcebergCompactionTaskId, SourceId};
87use risingwave_pb::meta::alter_connector_props_request::{
88 AlterConnectorPropsObject, AlterIcebergTableIds, ExtraOptions,
89};
90use risingwave_pb::meta::cancel_creating_jobs_request::PbJobs;
91use risingwave_pb::meta::cluster_service_client::ClusterServiceClient;
92use risingwave_pb::meta::event_log_service_client::EventLogServiceClient;
93use risingwave_pb::meta::heartbeat_service_client::HeartbeatServiceClient;
94use risingwave_pb::meta::hosted_iceberg_catalog_service_client::HostedIcebergCatalogServiceClient;
95use risingwave_pb::meta::list_actor_splits_response::ActorSplit;
96use risingwave_pb::meta::list_actor_states_response::ActorState;
97use risingwave_pb::meta::list_cdc_progress_response::PbCdcProgress;
98use risingwave_pb::meta::list_iceberg_tables_response::IcebergTable;
99use risingwave_pb::meta::list_refresh_table_states_response::RefreshTableState;
100use risingwave_pb::meta::list_streaming_job_states_response::StreamingJobState;
101use risingwave_pb::meta::list_table_fragments_response::TableFragmentInfo;
102use risingwave_pb::meta::meta_member_service_client::MetaMemberServiceClient;
103use risingwave_pb::meta::notification_service_client::NotificationServiceClient;
104use risingwave_pb::meta::scale_service_client::ScaleServiceClient;
105use risingwave_pb::meta::serving_service_client::ServingServiceClient;
106use risingwave_pb::meta::session_param_service_client::SessionParamServiceClient;
107use risingwave_pb::meta::stream_manager_service_client::StreamManagerServiceClient;
108use risingwave_pb::meta::system_params_service_client::SystemParamsServiceClient;
109use risingwave_pb::meta::telemetry_info_service_client::TelemetryInfoServiceClient;
110use risingwave_pb::meta::{FragmentDistribution, *};
111use risingwave_pb::monitor_service::monitor_service_client::MonitorServiceClient;
112use risingwave_pb::monitor_service::stack_trace_request::ActorTracesFormat;
113use risingwave_pb::monitor_service::{StackTraceRequest, StackTraceResponse};
114use risingwave_pb::secret::PbSecretRef;
115use risingwave_pb::stream_plan::StreamFragmentGraph;
116use risingwave_pb::user::alter_default_privilege_request::Operation as AlterDefaultPrivilegeOperation;
117use risingwave_pb::user::update_user_request::UpdateField;
118use risingwave_pb::user::user_service_client::UserServiceClient;
119use risingwave_pb::user::*;
120use thiserror_ext::AsReport;
121use tokio::sync::mpsc::{Receiver, UnboundedSender, unbounded_channel};
122use tokio::sync::oneshot::Sender;
123use tokio::sync::{RwLock, mpsc, oneshot};
124use tokio::task::JoinHandle;
125use tokio::time::{self};
126use tokio_retry::strategy::jitter;
127use tokio_stream::wrappers::UnboundedReceiverStream;
128use tonic::transport::Endpoint;
129use tonic::{Code, Request, Streaming};
130
131use crate::channel::{Channel, WrappedChannelExt};
132use crate::error::{Result, RpcError};
133use crate::hummock_meta_client::{
134 CompactionEventItem, HummockMetaClient, HummockMetaClientChangeLogInfo,
135 IcebergCompactionEventItem,
136};
137use crate::meta_rpc_client_method_impl;
138
139#[derive(Clone, Debug)]
141pub struct MetaClient {
142 worker_id: WorkerId,
143 worker_type: WorkerType,
144 host_addr: HostAddr,
145 inner: GrpcMetaClient,
146 meta_config: Arc<MetaConfig>,
147 cluster_id: String,
148 shutting_down: Arc<AtomicBool>,
149}
150
151impl MetaClient {
152 pub fn worker_id(&self) -> WorkerId {
153 self.worker_id
154 }
155
156 pub fn host_addr(&self) -> &HostAddr {
157 &self.host_addr
158 }
159
160 pub fn worker_type(&self) -> WorkerType {
161 self.worker_type
162 }
163
164 pub fn cluster_id(&self) -> &str {
165 &self.cluster_id
166 }
167
168 pub async fn subscribe(
170 &self,
171 subscribe_type: SubscribeType,
172 ) -> Result<Streaming<SubscribeResponse>> {
173 let request = SubscribeRequest {
174 subscribe_type: subscribe_type as i32,
175 host: Some(self.host_addr.to_protobuf()),
176 worker_id: self.worker_id(),
177 };
178
179 let retry_strategy = GrpcMetaClient::retry_strategy_to_bound(
180 Duration::from_secs(self.meta_config.max_heartbeat_interval_secs as u64),
181 true,
182 );
183
184 tokio_retry::Retry::spawn(retry_strategy, || async {
185 let request = request.clone();
186 self.inner.subscribe(request).await
187 })
188 .await
189 }
190
191 pub async fn create_connection(
192 &self,
193 connection_name: String,
194 database_id: DatabaseId,
195 schema_id: SchemaId,
196 owner_id: UserId,
197 req: create_connection_request::Payload,
198 ) -> Result<WaitVersion> {
199 let request = CreateConnectionRequest {
200 name: connection_name,
201 database_id,
202 schema_id,
203 owner_id,
204 payload: Some(req),
205 };
206 let resp = self.inner.create_connection(request).await?;
207 Ok(resp
208 .version
209 .ok_or_else(|| anyhow!("wait version not set"))?)
210 }
211
212 pub async fn create_secret(
213 &self,
214 secret_name: String,
215 database_id: DatabaseId,
216 schema_id: SchemaId,
217 owner_id: UserId,
218 value: Vec<u8>,
219 ) -> Result<WaitVersion> {
220 let request = CreateSecretRequest {
221 name: secret_name,
222 database_id,
223 schema_id,
224 owner_id,
225 value,
226 };
227 let resp = self.inner.create_secret(request).await?;
228 Ok(resp
229 .version
230 .ok_or_else(|| anyhow!("wait version not set"))?)
231 }
232
233 pub async fn list_connections(&self, _name: Option<&str>) -> Result<Vec<Connection>> {
234 let request = ListConnectionsRequest {};
235 let resp = self.inner.list_connections(request).await?;
236 Ok(resp.connections)
237 }
238
239 pub async fn drop_connection(
240 &self,
241 connection_id: ConnectionId,
242 cascade: bool,
243 ) -> Result<WaitVersion> {
244 let request = DropConnectionRequest {
245 connection_id,
246 cascade,
247 };
248 let resp = self.inner.drop_connection(request).await?;
249 Ok(resp
250 .version
251 .ok_or_else(|| anyhow!("wait version not set"))?)
252 }
253
254 pub async fn drop_secret(&self, secret_id: SecretId, cascade: bool) -> Result<WaitVersion> {
255 let request = DropSecretRequest { secret_id, cascade };
256 let resp = self.inner.drop_secret(request).await?;
257 Ok(resp
258 .version
259 .ok_or_else(|| anyhow!("wait version not set"))?)
260 }
261
262 pub async fn register_new(
266 addr_strategy: MetaAddressStrategy,
267 worker_type: WorkerType,
268 addr: &HostAddr,
269 property: Property,
270 meta_config: Arc<MetaConfig>,
271 ) -> (Self, SystemParamsReader) {
272 let ret =
273 Self::register_new_inner(addr_strategy, worker_type, addr, property, meta_config).await;
274
275 match ret {
276 Ok(ret) => ret,
277 Err(err) => {
278 tracing::error!(error = %err.as_report(), "failed to register worker, exiting...");
279 std::process::exit(1);
280 }
281 }
282 }
283
284 async fn register_new_inner(
285 addr_strategy: MetaAddressStrategy,
286 worker_type: WorkerType,
287 addr: &HostAddr,
288 property: Property,
289 meta_config: Arc<MetaConfig>,
290 ) -> Result<(Self, SystemParamsReader)> {
291 tracing::info!("register meta client using strategy: {}", addr_strategy);
292
293 let retry_strategy = GrpcMetaClient::retry_strategy_to_bound(
295 Duration::from_secs(meta_config.max_heartbeat_interval_secs as u64),
296 true,
297 );
298
299 let init_result: Result<_> = tokio_retry::RetryIf::spawn(
300 retry_strategy,
301 || async {
302 let grpc_meta_client =
303 GrpcMetaClient::new(&addr_strategy, meta_config.clone()).await?;
304
305 let add_worker_resp = grpc_meta_client
306 .add_worker_node(AddWorkerNodeRequest {
307 worker_type: worker_type as i32,
308 host: Some(addr.to_protobuf()),
309 property: Some(property.clone()),
310 resource: Some(risingwave_pb::common::worker_node::Resource {
311 rw_version: current_rw_version(),
312 total_memory_bytes: system_memory_available_bytes() as _,
313 total_cpu_cores: total_cpu_available() as _,
314 hostname: hostname(),
315 }),
316 })
317 .await
318 .context("failed to add worker node")?;
319
320 let system_params_resp = grpc_meta_client
321 .get_system_params(GetSystemParamsRequest {})
322 .await
323 .context("failed to get initial system params")?;
324
325 Ok((add_worker_resp, system_params_resp, grpc_meta_client))
326 },
327 |e: &RpcError| !e.is_from_tonic_server_impl(),
330 )
331 .await;
332
333 let (add_worker_resp, system_params_resp, grpc_meta_client) = init_result?;
334 let worker_id = add_worker_resp
335 .node_id
336 .expect("AddWorkerNodeResponse::node_id is empty");
337
338 let meta_client = Self {
339 worker_id,
340 worker_type,
341 host_addr: addr.clone(),
342 inner: grpc_meta_client,
343 meta_config: meta_config.clone(),
344 cluster_id: add_worker_resp.cluster_id,
345 shutting_down: Arc::new(false.into()),
346 };
347
348 static REPORT_PANIC: std::sync::Once = std::sync::Once::new();
349 REPORT_PANIC.call_once(|| {
350 let meta_client_clone = meta_client.clone();
351 std::panic::update_hook(move |default_hook, info| {
352 meta_client_clone.try_add_panic_event_blocking(info, None);
354 default_hook(info);
355 });
356 });
357
358 Ok((meta_client, system_params_resp.params.unwrap().into()))
359 }
360
361 pub async fn activate(&self, addr: &HostAddr) -> Result<()> {
363 let request = ActivateWorkerNodeRequest {
364 host: Some(addr.to_protobuf()),
365 node_id: self.worker_id,
366 };
367 let retry_strategy = GrpcMetaClient::retry_strategy_to_bound(
368 Duration::from_secs(self.meta_config.max_heartbeat_interval_secs as u64),
369 true,
370 );
371 tokio_retry::Retry::spawn(retry_strategy, || async {
372 let request = request.clone();
373 self.inner.activate_worker_node(request).await
374 })
375 .await?;
376
377 Ok(())
378 }
379
380 pub async fn send_heartbeat(&self) -> Result<()> {
382 let request = HeartbeatRequest {
383 node_id: self.worker_id,
384 };
385 let resp = self.inner.heartbeat(request).await?;
386 if let Some(status) = resp.status
387 && status.code() == risingwave_pb::common::status::Code::UnknownWorker
388 {
389 if !self.shutting_down.load(Relaxed) {
392 tracing::error!(message = status.message, "worker expired");
393 std::process::exit(1);
394 }
395 }
396 Ok(())
397 }
398
399 pub async fn create_database(&self, db: PbDatabase) -> Result<WaitVersion> {
400 let request = CreateDatabaseRequest { db: Some(db) };
401 let resp = self.inner.create_database(request).await?;
402 Ok(resp
404 .version
405 .ok_or_else(|| anyhow!("wait version not set"))?)
406 }
407
408 pub async fn create_schema(&self, schema: PbSchema) -> Result<WaitVersion> {
409 let request = CreateSchemaRequest {
410 schema: Some(schema),
411 };
412 let resp = self.inner.create_schema(request).await?;
413 Ok(resp
415 .version
416 .ok_or_else(|| anyhow!("wait version not set"))?)
417 }
418
419 pub async fn create_materialized_view(
420 &self,
421 table: PbTable,
422 graph: StreamFragmentGraph,
423 dependencies: HashSet<ObjectId>,
424 resource_type: streaming_job_resource_type::ResourceType,
425 if_not_exists: bool,
426 refresh_interval_sec: Option<u64>,
427 ) -> Result<WaitVersion> {
428 let request = CreateMaterializedViewRequest {
429 materialized_view: Some(table),
430 fragment_graph: Some(graph),
431 resource_type: Some(PbStreamingJobResourceType {
432 resource_type: Some(resource_type),
433 }),
434 dependencies: dependencies.into_iter().collect(),
435 if_not_exists,
436 refresh_interval_sec,
437 };
438 let resp = self.inner.create_materialized_view(request).await?;
439 Ok(resp
441 .version
442 .ok_or_else(|| anyhow!("wait version not set"))?)
443 }
444
445 pub async fn drop_materialized_view(
446 &self,
447 table_id: TableId,
448 cascade: bool,
449 ) -> Result<WaitVersion> {
450 let request = DropMaterializedViewRequest { table_id, cascade };
451
452 let resp = self.inner.drop_materialized_view(request).await?;
453 Ok(resp
454 .version
455 .ok_or_else(|| anyhow!("wait version not set"))?)
456 }
457
458 pub async fn create_source(
459 &self,
460 source: PbSource,
461 graph: Option<StreamFragmentGraph>,
462 if_not_exists: bool,
463 ) -> Result<WaitVersion> {
464 let request = CreateSourceRequest {
465 source: Some(source),
466 fragment_graph: graph,
467 if_not_exists,
468 };
469
470 let resp = self.inner.create_source(request).await?;
471 Ok(resp
472 .version
473 .ok_or_else(|| anyhow!("wait version not set"))?)
474 }
475
476 pub async fn create_sink(
477 &self,
478 sink: PbSink,
479 graph: StreamFragmentGraph,
480 dependencies: HashSet<ObjectId>,
481 resource_type: streaming_job_resource_type::ResourceType,
482 if_not_exists: bool,
483 since_timestamp_epoch: Option<u64>,
484 ) -> Result<WaitVersion> {
485 let request = CreateSinkRequest {
486 sink: Some(sink),
487 fragment_graph: Some(graph),
488 dependencies: dependencies.into_iter().collect(),
489 if_not_exists,
490 resource_type: Some(PbStreamingJobResourceType {
491 resource_type: Some(resource_type),
492 }),
493 since_timestamp_epoch,
494 };
495
496 let resp = self.inner.create_sink(request).await?;
497 Ok(resp
498 .version
499 .ok_or_else(|| anyhow!("wait version not set"))?)
500 }
501
502 pub async fn create_subscription(&self, subscription: PbSubscription) -> Result<WaitVersion> {
503 let request = CreateSubscriptionRequest {
504 subscription: Some(subscription),
505 };
506
507 let resp = self.inner.create_subscription(request).await?;
508 Ok(resp
509 .version
510 .ok_or_else(|| anyhow!("wait version not set"))?)
511 }
512
513 pub async fn create_function(&self, function: PbFunction) -> Result<WaitVersion> {
514 let request = CreateFunctionRequest {
515 function: Some(function),
516 };
517 let resp = self.inner.create_function(request).await?;
518 Ok(resp
519 .version
520 .ok_or_else(|| anyhow!("wait version not set"))?)
521 }
522
523 pub async fn create_table(
524 &self,
525 source: Option<PbSource>,
526 table: PbTable,
527 graph: StreamFragmentGraph,
528 job_type: PbTableJobType,
529 if_not_exists: bool,
530 dependencies: HashSet<ObjectId>,
531 ) -> Result<WaitVersion> {
532 let request = CreateTableRequest {
533 materialized_view: Some(table),
534 fragment_graph: Some(graph),
535 source,
536 job_type: job_type as _,
537 if_not_exists,
538 dependencies: dependencies.into_iter().collect(),
539 };
540 let resp = self.inner.create_table(request).await?;
541 Ok(resp
543 .version
544 .ok_or_else(|| anyhow!("wait version not set"))?)
545 }
546
547 pub async fn comment_on(&self, comment: PbComment) -> Result<WaitVersion> {
548 let request = CommentOnRequest {
549 comment: Some(comment),
550 };
551 let resp = self.inner.comment_on(request).await?;
552 Ok(resp
553 .version
554 .ok_or_else(|| anyhow!("wait version not set"))?)
555 }
556
557 pub async fn alter_name(
558 &self,
559 object: alter_name_request::Object,
560 name: &str,
561 ) -> Result<WaitVersion> {
562 let request = AlterNameRequest {
563 object: Some(object),
564 new_name: name.to_owned(),
565 };
566 let resp = self.inner.alter_name(request).await?;
567 Ok(resp
568 .version
569 .ok_or_else(|| anyhow!("wait version not set"))?)
570 }
571
572 pub async fn alter_owner(&self, object: Object, owner_id: UserId) -> Result<WaitVersion> {
573 let request = AlterOwnerRequest {
574 object: Some(object),
575 owner_id,
576 };
577 let resp = self.inner.alter_owner(request).await?;
578 Ok(resp
579 .version
580 .ok_or_else(|| anyhow!("wait version not set"))?)
581 }
582
583 pub async fn alter_subscription_retention(
584 &self,
585 subscription_id: SubscriptionId,
586 retention_seconds: u64,
587 definition: String,
588 ) -> Result<WaitVersion> {
589 let request = AlterSubscriptionRetentionRequest {
590 subscription_id,
591 retention_seconds,
592 definition,
593 };
594 let resp = self.inner.alter_subscription_retention(request).await?;
595 Ok(resp
596 .version
597 .ok_or_else(|| anyhow!("wait version not set"))?)
598 }
599
600 pub async fn alter_database_param(
601 &self,
602 database_id: DatabaseId,
603 param: AlterDatabaseParam,
604 ) -> Result<WaitVersion> {
605 let request = match param {
606 AlterDatabaseParam::BarrierIntervalMs(barrier_interval_ms) => {
607 let barrier_interval_ms = OptionalUint32 {
608 value: barrier_interval_ms,
609 };
610 AlterDatabaseParamRequest {
611 database_id,
612 param: Some(alter_database_param_request::Param::BarrierIntervalMs(
613 barrier_interval_ms,
614 )),
615 }
616 }
617 AlterDatabaseParam::CheckpointFrequency(checkpoint_frequency) => {
618 let checkpoint_frequency = OptionalUint64 {
619 value: checkpoint_frequency,
620 };
621 AlterDatabaseParamRequest {
622 database_id,
623 param: Some(alter_database_param_request::Param::CheckpointFrequency(
624 checkpoint_frequency,
625 )),
626 }
627 }
628 };
629 let resp = self.inner.alter_database_param(request).await?;
630 Ok(resp
631 .version
632 .ok_or_else(|| anyhow!("wait version not set"))?)
633 }
634
635 pub async fn alter_set_schema(
636 &self,
637 object: alter_set_schema_request::Object,
638 new_schema_id: SchemaId,
639 ) -> Result<WaitVersion> {
640 let request = AlterSetSchemaRequest {
641 new_schema_id,
642 object: Some(object),
643 };
644 let resp = self.inner.alter_set_schema(request).await?;
645 Ok(resp
646 .version
647 .ok_or_else(|| anyhow!("wait version not set"))?)
648 }
649
650 pub async fn alter_source(&self, source: PbSource) -> Result<WaitVersion> {
651 let request = AlterSourceRequest {
652 source: Some(source),
653 };
654 let resp = self.inner.alter_source(request).await?;
655 Ok(resp
656 .version
657 .ok_or_else(|| anyhow!("wait version not set"))?)
658 }
659
660 pub async fn alter_parallelism(
661 &self,
662 job_id: JobId,
663 parallelism: PbTableParallelism,
664 adaptive_parallelism_strategy: Option<AdaptiveParallelismStrategy>,
665 deferred: bool,
666 ) -> Result<()> {
667 let request = AlterParallelismRequest {
668 table_id: job_id,
669 parallelism: Some(parallelism),
670 deferred,
671 adaptive_parallelism_strategy: adaptive_parallelism_strategy
672 .map(|strategy| strategy.to_string()),
673 };
674
675 self.inner.alter_parallelism(request).await?;
676 Ok(())
677 }
678
679 pub async fn alter_backfill_parallelism(
680 &self,
681 job_id: JobId,
682 parallelism: Option<PbTableParallelism>,
683 adaptive_parallelism_strategy: Option<AdaptiveParallelismStrategy>,
684 deferred: bool,
685 ) -> Result<()> {
686 let request = AlterBackfillParallelismRequest {
687 table_id: job_id,
688 parallelism,
689 deferred,
690 adaptive_parallelism_strategy: adaptive_parallelism_strategy
691 .map(|strategy| strategy.to_string()),
692 };
693
694 self.inner.alter_backfill_parallelism(request).await?;
695 Ok(())
696 }
697
698 pub async fn alter_streaming_job_config(
699 &self,
700 job_id: JobId,
701 entries_to_add: HashMap<String, String>,
702 keys_to_remove: Vec<String>,
703 ) -> Result<()> {
704 let request = AlterStreamingJobConfigRequest {
705 job_id,
706 entries_to_add,
707 keys_to_remove,
708 };
709
710 self.inner.alter_streaming_job_config(request).await?;
711 Ok(())
712 }
713
714 pub async fn alter_fragment_parallelism(
715 &self,
716 fragment_ids: Vec<FragmentId>,
717 parallelism: Option<PbTableParallelism>,
718 ) -> Result<()> {
719 let request = AlterFragmentParallelismRequest {
720 fragment_ids,
721 parallelism,
722 };
723
724 self.inner.alter_fragment_parallelism(request).await?;
725 Ok(())
726 }
727
728 pub async fn alter_cdc_table_backfill_parallelism(
729 &self,
730 table_id: JobId,
731 parallelism: PbTableParallelism,
732 ) -> Result<()> {
733 let request = AlterCdcTableBackfillParallelismRequest {
734 table_id,
735 parallelism: Some(parallelism),
736 };
737 self.inner
738 .alter_cdc_table_backfill_parallelism(request)
739 .await?;
740 Ok(())
741 }
742
743 pub async fn alter_resource_group(
744 &self,
745 job_id: JobId,
746 resource_group: Option<String>,
747 deferred: bool,
748 ) -> Result<()> {
749 let request = AlterResourceGroupRequest {
750 job_id,
751 resource_group,
752 deferred,
753 };
754
755 self.inner.alter_resource_group(request).await?;
756 Ok(())
757 }
758
759 pub async fn alter_database_resource_group(
760 &self,
761 database_id: DatabaseId,
762 resource_group: Option<String>,
763 deferred: bool,
764 ) -> Result<WaitVersion> {
765 let request = AlterDatabaseResourceGroupRequest {
766 database_id,
767 resource_group,
768 deferred,
769 };
770
771 let resp = self.inner.alter_database_resource_group(request).await?;
772 Ok(resp
773 .version
774 .ok_or_else(|| anyhow!("wait version not set"))?)
775 }
776
777 pub async fn alter_swap_rename(
778 &self,
779 object: alter_swap_rename_request::Object,
780 ) -> Result<WaitVersion> {
781 let request = AlterSwapRenameRequest {
782 object: Some(object),
783 };
784 let resp = self.inner.alter_swap_rename(request).await?;
785 Ok(resp
786 .version
787 .ok_or_else(|| anyhow!("wait version not set"))?)
788 }
789
790 pub async fn alter_secret(
791 &self,
792 secret_id: SecretId,
793 secret_name: String,
794 database_id: DatabaseId,
795 schema_id: SchemaId,
796 owner_id: UserId,
797 value: Vec<u8>,
798 ) -> Result<WaitVersion> {
799 let request = AlterSecretRequest {
800 secret_id,
801 name: secret_name,
802 database_id,
803 schema_id,
804 owner_id,
805 value,
806 };
807 let resp = self.inner.alter_secret(request).await?;
808 Ok(resp
809 .version
810 .ok_or_else(|| anyhow!("wait version not set"))?)
811 }
812
813 pub async fn replace_job(
814 &self,
815 graph: StreamFragmentGraph,
816 replace_job: ReplaceJob,
817 ) -> Result<WaitVersion> {
818 let request = ReplaceJobPlanRequest {
819 plan: Some(ReplaceJobPlan {
820 fragment_graph: Some(graph),
821 replace_job: Some(replace_job),
822 }),
823 };
824 let resp = self.inner.replace_job_plan(request).await?;
825 Ok(resp
827 .version
828 .ok_or_else(|| anyhow!("wait version not set"))?)
829 }
830
831 pub async fn auto_schema_change(&self, schema_change: SchemaChangeEnvelope) -> Result<()> {
832 let request = AutoSchemaChangeRequest {
833 schema_change: Some(schema_change),
834 };
835 let _ = self.inner.auto_schema_change(request).await?;
836 Ok(())
837 }
838
839 pub async fn wait_iceberg_pk_index_sink_epoch(
842 &self,
843 sink_id: SinkId,
844 epoch: u64,
845 ) -> Result<Option<i64>> {
846 let request = WaitIcebergPkIndexSinkEpochRequest { sink_id, epoch };
847 let resp = self.inner.wait_iceberg_pk_index_sink_epoch(request).await?;
848 Ok(resp.snapshot_id)
849 }
850
851 pub async fn create_view(
852 &self,
853 view: PbView,
854 dependencies: HashSet<ObjectId>,
855 ) -> Result<WaitVersion> {
856 let request = CreateViewRequest {
857 view: Some(view),
858 dependencies: dependencies.into_iter().collect(),
859 };
860 let resp = self.inner.create_view(request).await?;
861 Ok(resp
863 .version
864 .ok_or_else(|| anyhow!("wait version not set"))?)
865 }
866
867 pub async fn create_index(
868 &self,
869 index: PbIndex,
870 table: PbTable,
871 graph: StreamFragmentGraph,
872 resource_type: streaming_job_resource_type::ResourceType,
873 if_not_exists: bool,
874 ) -> Result<WaitVersion> {
875 let request = CreateIndexRequest {
876 index: Some(index),
877 index_table: Some(table),
878 fragment_graph: Some(graph),
879 if_not_exists,
880 resource_type: Some(PbStreamingJobResourceType {
881 resource_type: Some(resource_type),
882 }),
883 };
884 let resp = self.inner.create_index(request).await?;
885 Ok(resp
887 .version
888 .ok_or_else(|| anyhow!("wait version not set"))?)
889 }
890
891 pub async fn drop_table(
892 &self,
893 source_id: Option<SourceId>,
894 table_id: TableId,
895 cascade: bool,
896 ) -> Result<WaitVersion> {
897 let request = DropTableRequest {
898 source_id: source_id.map(risingwave_pb::ddl_service::drop_table_request::SourceId::Id),
899 table_id,
900 cascade,
901 };
902
903 let resp = self.inner.drop_table(request).await?;
904 Ok(resp
905 .version
906 .ok_or_else(|| anyhow!("wait version not set"))?)
907 }
908
909 pub async fn compact_iceberg_table(&self, sink_id: SinkId) -> Result<IcebergCompactionTaskId> {
910 let request = CompactIcebergTableRequest { sink_id };
911 let resp = self.inner.compact_iceberg_table(request).await?;
912 Ok(resp.task_id)
913 }
914
915 pub async fn rewrite_iceberg_table_manifests(&self, sink_id: SinkId) -> Result<()> {
916 let request = RewriteIcebergTableManifestsRequest { sink_id };
917 let _resp = self.inner.rewrite_iceberg_table_manifests(request).await?;
918 Ok(())
919 }
920
921 pub async fn expire_iceberg_table_snapshots(&self, sink_id: SinkId) -> Result<()> {
922 let request = ExpireIcebergTableSnapshotsRequest { sink_id };
923 let _resp = self.inner.expire_iceberg_table_snapshots(request).await?;
924 Ok(())
925 }
926
927 pub async fn remove_iceberg_table_orphan_files(
928 &self,
929 sink_id: SinkId,
930 ) -> Result<RemoveIcebergTableOrphanFilesResponse> {
931 let request = RemoveIcebergTableOrphanFilesRequest { sink_id };
932 self.inner.remove_iceberg_table_orphan_files(request).await
933 }
934
935 pub async fn drop_view(&self, view_id: ViewId, cascade: bool) -> Result<WaitVersion> {
936 let request = DropViewRequest { view_id, cascade };
937 let resp = self.inner.drop_view(request).await?;
938 Ok(resp
939 .version
940 .ok_or_else(|| anyhow!("wait version not set"))?)
941 }
942
943 pub async fn drop_source(&self, source_id: SourceId, cascade: bool) -> Result<WaitVersion> {
944 let request = DropSourceRequest { source_id, cascade };
945 let resp = self.inner.drop_source(request).await?;
946 Ok(resp
947 .version
948 .ok_or_else(|| anyhow!("wait version not set"))?)
949 }
950
951 pub async fn reset_source(&self, source_id: SourceId) -> Result<WaitVersion> {
952 let request = ResetSourceRequest { source_id };
953 let resp = self.inner.reset_source(request).await?;
954 Ok(resp
955 .version
956 .ok_or_else(|| anyhow!("wait version not set"))?)
957 }
958
959 pub async fn drop_sink(&self, sink_id: SinkId, cascade: bool) -> Result<WaitVersion> {
960 let request = DropSinkRequest { sink_id, cascade };
961 let resp = self.inner.drop_sink(request).await?;
962 Ok(resp
963 .version
964 .ok_or_else(|| anyhow!("wait version not set"))?)
965 }
966
967 pub async fn drop_subscription(
968 &self,
969 subscription_id: SubscriptionId,
970 cascade: bool,
971 ) -> Result<WaitVersion> {
972 let request = DropSubscriptionRequest {
973 subscription_id,
974 cascade,
975 };
976 let resp = self.inner.drop_subscription(request).await?;
977 Ok(resp
978 .version
979 .ok_or_else(|| anyhow!("wait version not set"))?)
980 }
981
982 pub async fn drop_index(&self, index_id: IndexId, cascade: bool) -> Result<WaitVersion> {
983 let request = DropIndexRequest { index_id, cascade };
984 let resp = self.inner.drop_index(request).await?;
985 Ok(resp
986 .version
987 .ok_or_else(|| anyhow!("wait version not set"))?)
988 }
989
990 pub async fn drop_function(
991 &self,
992 function_id: FunctionId,
993 cascade: bool,
994 ) -> Result<WaitVersion> {
995 let request = DropFunctionRequest {
996 function_id,
997 cascade,
998 };
999 let resp = self.inner.drop_function(request).await?;
1000 Ok(resp
1001 .version
1002 .ok_or_else(|| anyhow!("wait version not set"))?)
1003 }
1004
1005 pub async fn drop_database(&self, database_id: DatabaseId) -> Result<WaitVersion> {
1006 let request = DropDatabaseRequest { database_id };
1007 let resp = self.inner.drop_database(request).await?;
1008 Ok(resp
1009 .version
1010 .ok_or_else(|| anyhow!("wait version not set"))?)
1011 }
1012
1013 pub async fn drop_schema(&self, schema_id: SchemaId, cascade: bool) -> Result<WaitVersion> {
1014 let request = DropSchemaRequest { schema_id, cascade };
1015 let resp = self.inner.drop_schema(request).await?;
1016 Ok(resp
1017 .version
1018 .ok_or_else(|| anyhow!("wait version not set"))?)
1019 }
1020
1021 pub async fn create_user(&self, user: UserInfo) -> Result<u64> {
1023 let request = CreateUserRequest { user: Some(user) };
1024 let resp = self.inner.create_user(request).await?;
1025 Ok(resp.version)
1026 }
1027
1028 pub async fn drop_user(&self, user_id: UserId) -> Result<u64> {
1029 let request = DropUserRequest { user_id };
1030 let resp = self.inner.drop_user(request).await?;
1031 Ok(resp.version)
1032 }
1033
1034 pub async fn update_user(
1035 &self,
1036 user: UserInfo,
1037 update_fields: Vec<UpdateField>,
1038 ) -> Result<u64> {
1039 let request = UpdateUserRequest {
1040 user: Some(user),
1041 update_fields: update_fields
1042 .into_iter()
1043 .map(|field| field as i32)
1044 .collect::<Vec<_>>(),
1045 };
1046 let resp = self.inner.update_user(request).await?;
1047 Ok(resp.version)
1048 }
1049
1050 pub async fn grant_privilege(
1051 &self,
1052 user_ids: Vec<UserId>,
1053 privileges: Vec<GrantPrivilege>,
1054 with_grant_option: bool,
1055 granted_by: UserId,
1056 ) -> Result<u64> {
1057 let request = GrantPrivilegeRequest {
1058 user_ids,
1059 privileges,
1060 with_grant_option,
1061 granted_by,
1062 };
1063 let resp = self.inner.grant_privilege(request).await?;
1064 Ok(resp.version)
1065 }
1066
1067 pub async fn revoke_privilege(
1068 &self,
1069 user_ids: Vec<UserId>,
1070 privileges: Vec<GrantPrivilege>,
1071 granted_by: UserId,
1072 revoke_by: UserId,
1073 revoke_grant_option: bool,
1074 cascade: bool,
1075 ) -> Result<u64> {
1076 let request = RevokePrivilegeRequest {
1077 user_ids,
1078 privileges,
1079 granted_by,
1080 revoke_by,
1081 revoke_grant_option,
1082 cascade,
1083 };
1084 let resp = self.inner.revoke_privilege(request).await?;
1085 Ok(resp.version)
1086 }
1087
1088 pub async fn alter_default_privilege(
1089 &self,
1090 user_ids: Vec<UserId>,
1091 database_id: DatabaseId,
1092 schema_ids: Vec<SchemaId>,
1093 operation: AlterDefaultPrivilegeOperation,
1094 granted_by: UserId,
1095 ) -> Result<()> {
1096 let request = AlterDefaultPrivilegeRequest {
1097 user_ids,
1098 database_id,
1099 schema_ids,
1100 operation: Some(operation),
1101 granted_by,
1102 };
1103 self.inner.alter_default_privilege(request).await?;
1104 Ok(())
1105 }
1106
1107 pub async fn unregister(&self) -> Result<()> {
1109 let request = DeleteWorkerNodeRequest {
1110 host: Some(self.host_addr.to_protobuf()),
1111 };
1112 self.inner.delete_worker_node(request).await?;
1113 self.shutting_down.store(true, Relaxed);
1114 Ok(())
1115 }
1116
1117 pub async fn try_unregister(&self) {
1119 match self.unregister().await {
1120 Ok(_) => {
1121 tracing::info!(
1122 worker_id = %self.worker_id(),
1123 "successfully unregistered from meta service",
1124 )
1125 }
1126 Err(e) => {
1127 tracing::warn!(
1128 error = %e.as_report(),
1129 worker_id = %self.worker_id(),
1130 "failed to unregister from meta service",
1131 );
1132 }
1133 }
1134 }
1135
1136 pub async fn list_worker_nodes(
1137 &self,
1138 worker_type: Option<WorkerType>,
1139 ) -> Result<Vec<WorkerNode>> {
1140 let request = ListAllNodesRequest {
1141 worker_type: worker_type.map(Into::into),
1142 include_starting_nodes: true,
1143 };
1144 let resp = self.inner.list_all_nodes(request).await?;
1145 Ok(resp.nodes)
1146 }
1147
1148 pub fn start_heartbeat_loop(
1150 meta_client: MetaClient,
1151 min_interval: Duration,
1152 ) -> (JoinHandle<()>, Sender<()>) {
1153 let (shutdown_tx, mut shutdown_rx) = tokio::sync::oneshot::channel();
1154 let join_handle = tokio::spawn(async move {
1155 let mut min_interval_ticker = tokio::time::interval(min_interval);
1156 loop {
1157 tokio::select! {
1158 biased;
1159 _ = &mut shutdown_rx => {
1161 tracing::info!("Heartbeat loop is stopped");
1162 return;
1163 }
1164 _ = min_interval_ticker.tick() => {},
1166 }
1167 tracing::debug!(target: "events::meta::client_heartbeat", "heartbeat");
1168 match tokio::time::timeout(
1169 min_interval * 3,
1171 meta_client.send_heartbeat(),
1172 )
1173 .await
1174 {
1175 Ok(Ok(_)) => {}
1176 Ok(Err(err)) => {
1177 tracing::warn!(error = %err.as_report(), "Failed to send_heartbeat");
1178 }
1179 Err(_) => {
1180 tracing::warn!("Failed to send_heartbeat: timeout");
1181 }
1182 }
1183 }
1184 });
1185 (join_handle, shutdown_tx)
1186 }
1187
1188 pub async fn risectl_list_state_tables(&self) -> Result<Vec<PbTable>> {
1189 let request = RisectlListStateTablesRequest {};
1190 let resp = self.inner.risectl_list_state_tables(request).await?;
1191 Ok(resp.tables)
1192 }
1193
1194 pub async fn risectl_resume_backfill(
1195 &self,
1196 request: RisectlResumeBackfillRequest,
1197 ) -> Result<()> {
1198 self.inner.risectl_resume_backfill(request).await?;
1199 Ok(())
1200 }
1201
1202 pub async fn flush(&self, database_id: DatabaseId) -> Result<HummockVersionId> {
1203 let request = FlushRequest { database_id };
1204 let resp = self.inner.flush(request).await?;
1205 Ok(resp.hummock_version_id)
1206 }
1207
1208 pub async fn wait(&self, job_id: Option<JobId>) -> Result<WaitVersion> {
1209 let request = WaitRequest { job_id };
1210 let resp = self.inner.wait(request).await?;
1211 Ok(resp
1212 .version
1213 .ok_or_else(|| anyhow!("wait version not set"))?)
1214 }
1215
1216 pub async fn recover(&self) -> Result<()> {
1217 let request = RecoverRequest {};
1218 self.inner.recover(request).await?;
1219 Ok(())
1220 }
1221
1222 pub async fn cancel_creating_jobs(&self, jobs: PbJobs) -> Result<Vec<u32>> {
1223 let request = CancelCreatingJobsRequest { jobs: Some(jobs) };
1224 let resp = self.inner.cancel_creating_jobs(request).await?;
1225 Ok(resp.canceled_jobs)
1226 }
1227
1228 pub async fn list_table_fragments(
1229 &self,
1230 job_ids: &[JobId],
1231 ) -> Result<HashMap<JobId, TableFragmentInfo>> {
1232 let request = ListTableFragmentsRequest {
1233 table_ids: job_ids.to_vec(),
1234 };
1235 let resp = self.inner.list_table_fragments(request).await?;
1236 Ok(resp.table_fragments)
1237 }
1238
1239 pub async fn list_streaming_job_states(&self) -> Result<Vec<StreamingJobState>> {
1240 let resp = self
1241 .inner
1242 .list_streaming_job_states(ListStreamingJobStatesRequest {})
1243 .await?;
1244 Ok(resp.states)
1245 }
1246
1247 pub async fn list_fragment_distributions(
1248 &self,
1249 include_node: bool,
1250 ) -> Result<Vec<FragmentDistribution>> {
1251 let resp = self
1252 .inner
1253 .list_fragment_distribution(ListFragmentDistributionRequest {
1254 include_node: Some(include_node),
1255 })
1256 .await?;
1257 Ok(resp.distributions)
1258 }
1259
1260 pub async fn list_creating_fragment_distribution(&self) -> Result<Vec<FragmentDistribution>> {
1261 let resp = self
1262 .inner
1263 .list_creating_fragment_distribution(ListCreatingFragmentDistributionRequest {
1264 include_node: Some(true),
1265 })
1266 .await?;
1267 Ok(resp.distributions)
1268 }
1269
1270 pub async fn get_fragment_by_id(
1271 &self,
1272 fragment_id: FragmentId,
1273 ) -> Result<Option<FragmentDistribution>> {
1274 let resp = self
1275 .inner
1276 .get_fragment_by_id(GetFragmentByIdRequest { fragment_id })
1277 .await?;
1278 Ok(resp.distribution)
1279 }
1280
1281 pub async fn get_fragment_vnodes(
1282 &self,
1283 fragment_id: FragmentId,
1284 ) -> Result<Vec<(ActorId, Vec<u32>)>> {
1285 let resp = self
1286 .inner
1287 .get_fragment_vnodes(GetFragmentVnodesRequest { fragment_id })
1288 .await?;
1289 Ok(resp
1290 .actor_vnodes
1291 .into_iter()
1292 .map(|actor| (actor.actor_id, actor.vnode_indices))
1293 .collect())
1294 }
1295
1296 pub async fn get_actor_vnodes(&self, actor_id: ActorId) -> Result<Vec<u32>> {
1297 let resp = self
1298 .inner
1299 .get_actor_vnodes(GetActorVnodesRequest { actor_id })
1300 .await?;
1301 Ok(resp.vnode_indices)
1302 }
1303
1304 pub async fn list_actor_states(&self) -> Result<Vec<ActorState>> {
1305 let resp = self
1306 .inner
1307 .list_actor_states(ListActorStatesRequest {})
1308 .await?;
1309 Ok(resp.states)
1310 }
1311
1312 pub async fn list_actor_splits(&self) -> Result<Vec<ActorSplit>> {
1313 let resp = self
1314 .inner
1315 .list_actor_splits(ListActorSplitsRequest {})
1316 .await?;
1317
1318 Ok(resp.actor_splits)
1319 }
1320
1321 pub async fn pause(&self) -> Result<PauseResponse> {
1322 let request = PauseRequest {};
1323 let resp = self.inner.pause(request).await?;
1324 Ok(resp)
1325 }
1326
1327 pub async fn resume(&self) -> Result<ResumeResponse> {
1328 let request = ResumeRequest {};
1329 let resp = self.inner.resume(request).await?;
1330 Ok(resp)
1331 }
1332
1333 pub async fn apply_throttle(
1334 &self,
1335 throttle_target: PbThrottleTarget,
1336 throttle_type: risingwave_pb::common::PbThrottleType,
1337 id: u32,
1338 rate: Option<u32>,
1339 ) -> Result<ApplyThrottleResponse> {
1340 let request = ApplyThrottleRequest {
1341 throttle_target: throttle_target as i32,
1342 throttle_type: throttle_type as i32,
1343 id,
1344 rate,
1345 };
1346 let resp = self.inner.apply_throttle(request).await?;
1347 Ok(resp)
1348 }
1349
1350 pub async fn get_cluster_recovery_status(&self) -> Result<RecoveryStatus> {
1351 let resp = self
1352 .inner
1353 .get_cluster_recovery_status(GetClusterRecoveryStatusRequest {})
1354 .await?;
1355 Ok(resp.get_status().unwrap())
1356 }
1357
1358 pub async fn get_cluster_info(&self) -> Result<GetClusterInfoResponse> {
1359 let request = GetClusterInfoRequest {};
1360 let resp = self.inner.get_cluster_info(request).await?;
1361 Ok(resp)
1362 }
1363
1364 pub async fn reschedule(
1365 &self,
1366 worker_reschedules: HashMap<u32, PbWorkerReschedule>,
1367 revision: u64,
1368 resolve_no_shuffle_upstream: bool,
1369 ) -> Result<(bool, u64)> {
1370 let request = RescheduleRequest {
1371 revision,
1372 resolve_no_shuffle_upstream,
1373 worker_reschedules,
1374 };
1375 let resp = self.inner.reschedule(request).await?;
1376 Ok((resp.success, resp.revision))
1377 }
1378
1379 pub async fn risectl_get_pinned_versions_summary(
1380 &self,
1381 ) -> Result<RiseCtlGetPinnedVersionsSummaryResponse> {
1382 let request = RiseCtlGetPinnedVersionsSummaryRequest {};
1383 self.inner
1384 .rise_ctl_get_pinned_versions_summary(request)
1385 .await
1386 }
1387
1388 pub async fn risectl_get_checkpoint_hummock_version(
1389 &self,
1390 ) -> Result<RiseCtlGetCheckpointVersionResponse> {
1391 let request = RiseCtlGetCheckpointVersionRequest {};
1392 self.inner.rise_ctl_get_checkpoint_version(request).await
1393 }
1394
1395 pub async fn risectl_pause_hummock_version_checkpoint(
1396 &self,
1397 ) -> Result<RiseCtlPauseVersionCheckpointResponse> {
1398 let request = RiseCtlPauseVersionCheckpointRequest {};
1399 self.inner.rise_ctl_pause_version_checkpoint(request).await
1400 }
1401
1402 pub async fn risectl_resume_hummock_version_checkpoint(
1403 &self,
1404 ) -> Result<RiseCtlResumeVersionCheckpointResponse> {
1405 let request = RiseCtlResumeVersionCheckpointRequest {};
1406 self.inner.rise_ctl_resume_version_checkpoint(request).await
1407 }
1408
1409 pub async fn init_metadata_for_replay(
1410 &self,
1411 tables: Vec<PbTable>,
1412 compaction_groups: Vec<CompactionGroupInfo>,
1413 ) -> Result<()> {
1414 let req = InitMetadataForReplayRequest {
1415 tables,
1416 compaction_groups,
1417 };
1418 let _resp = self.inner.init_metadata_for_replay(req).await?;
1419 Ok(())
1420 }
1421
1422 pub async fn replay_version_delta(
1423 &self,
1424 version_delta: HummockVersionDelta,
1425 ) -> Result<(HummockVersion, Vec<CompactionGroupId>)> {
1426 let req = ReplayVersionDeltaRequest {
1427 version_delta: Some(version_delta.into()),
1428 };
1429 let resp = self.inner.replay_version_delta(req).await?;
1430 Ok((
1431 HummockVersion::from_rpc_protobuf(&resp.version.unwrap()),
1432 resp.modified_compaction_groups,
1433 ))
1434 }
1435
1436 pub async fn list_version_deltas(
1437 &self,
1438 start_id: HummockVersionId,
1439 num_limit: u32,
1440 committed_epoch_limit: HummockEpoch,
1441 ) -> Result<Vec<HummockVersionDelta>> {
1442 let req = ListVersionDeltasRequest {
1443 start_id,
1444 num_limit,
1445 committed_epoch_limit,
1446 };
1447 Ok(self
1448 .inner
1449 .list_version_deltas(req)
1450 .await?
1451 .version_deltas
1452 .unwrap()
1453 .version_deltas
1454 .iter()
1455 .map(HummockVersionDelta::from_rpc_protobuf)
1456 .collect())
1457 }
1458
1459 pub async fn trigger_compaction_deterministic(
1460 &self,
1461 version_id: HummockVersionId,
1462 compaction_groups: Vec<CompactionGroupId>,
1463 ) -> Result<()> {
1464 let req = TriggerCompactionDeterministicRequest {
1465 version_id,
1466 compaction_groups,
1467 };
1468 self.inner.trigger_compaction_deterministic(req).await?;
1469 Ok(())
1470 }
1471
1472 pub async fn disable_commit_epoch(&self) -> Result<HummockVersion> {
1473 let req = DisableCommitEpochRequest {};
1474 Ok(HummockVersion::from_rpc_protobuf(
1475 &self
1476 .inner
1477 .disable_commit_epoch(req)
1478 .await?
1479 .current_version
1480 .unwrap(),
1481 ))
1482 }
1483
1484 pub async fn get_assigned_compact_task_num(&self) -> Result<usize> {
1485 let req = GetAssignedCompactTaskNumRequest {};
1486 let resp = self.inner.get_assigned_compact_task_num(req).await?;
1487 Ok(resp.num_tasks as usize)
1488 }
1489
1490 pub async fn risectl_list_compaction_group(&self) -> Result<Vec<CompactionGroupInfo>> {
1491 let req = RiseCtlListCompactionGroupRequest {};
1492 let resp = self.inner.rise_ctl_list_compaction_group(req).await?;
1493 Ok(resp.compaction_groups)
1494 }
1495
1496 pub async fn risectl_update_compaction_config(
1497 &self,
1498 compaction_groups: &[CompactionGroupId],
1499 configs: &[MutableConfig],
1500 ) -> Result<()> {
1501 let req = RiseCtlUpdateCompactionConfigRequest {
1502 compaction_group_ids: compaction_groups.to_vec(),
1503 configs: configs
1504 .iter()
1505 .map(
1506 |c| rise_ctl_update_compaction_config_request::MutableConfig {
1507 mutable_config: Some(c.clone()),
1508 },
1509 )
1510 .collect(),
1511 };
1512 let _resp = self.inner.rise_ctl_update_compaction_config(req).await?;
1513 Ok(())
1514 }
1515
1516 pub async fn backup_meta(&self, remarks: Option<String>) -> Result<u64> {
1517 let req = BackupMetaRequest { remarks };
1518 let resp = self.inner.backup_meta(req).await?;
1519 Ok(resp.job_id)
1520 }
1521
1522 pub async fn get_backup_job_status(&self, job_id: u64) -> Result<(BackupJobStatus, String)> {
1523 let req = GetBackupJobStatusRequest { job_id };
1524 let resp = self.inner.get_backup_job_status(req).await?;
1525 Ok((resp.job_status(), resp.message))
1526 }
1527
1528 pub async fn delete_meta_snapshot(&self, snapshot_ids: &[u64]) -> Result<()> {
1529 let req = DeleteMetaSnapshotRequest {
1530 snapshot_ids: snapshot_ids.to_vec(),
1531 };
1532 let _resp = self.inner.delete_meta_snapshot(req).await?;
1533 Ok(())
1534 }
1535
1536 pub async fn get_meta_snapshot_manifest(&self) -> Result<MetaSnapshotManifest> {
1537 let req = GetMetaSnapshotManifestRequest {};
1538 let resp = self.inner.get_meta_snapshot_manifest(req).await?;
1539 Ok(resp.manifest.expect("should exist"))
1540 }
1541
1542 pub async fn get_telemetry_info(&self) -> Result<TelemetryInfoResponse> {
1543 let req = GetTelemetryInfoRequest {};
1544 let resp = self.inner.get_telemetry_info(req).await?;
1545 Ok(resp)
1546 }
1547
1548 pub async fn get_meta_store_endpoint(&self) -> Result<String> {
1549 let req = GetMetaStoreInfoRequest {};
1550 let resp = self.inner.get_meta_store_info(req).await?;
1551 Ok(resp.meta_store_endpoint)
1552 }
1553
1554 pub async fn alter_sink_props(
1555 &self,
1556 sink_id: SinkId,
1557 changed_props: BTreeMap<String, String>,
1558 changed_secret_refs: BTreeMap<String, PbSecretRef>,
1559 connector_conn_ref: Option<ConnectionId>,
1560 ) -> Result<()> {
1561 let req = AlterConnectorPropsRequest {
1562 object_id: sink_id.as_raw_id(),
1563 changed_props: changed_props.into_iter().collect(),
1564 changed_secret_refs: changed_secret_refs.into_iter().collect(),
1565 connector_conn_ref,
1566 object_type: AlterConnectorPropsObject::Sink as i32,
1567 extra_options: None,
1568 };
1569 let _resp = self.inner.alter_connector_props(req).await?;
1570 Ok(())
1571 }
1572
1573 pub async fn alter_iceberg_table_props(
1574 &self,
1575 table_id: TableId,
1576 sink_id: SinkId,
1577 source_id: SourceId,
1578 changed_props: BTreeMap<String, String>,
1579 changed_secret_refs: BTreeMap<String, PbSecretRef>,
1580 connector_conn_ref: Option<ConnectionId>,
1581 ) -> Result<()> {
1582 let req = AlterConnectorPropsRequest {
1583 object_id: table_id.as_raw_id(),
1584 changed_props: changed_props.into_iter().collect(),
1585 changed_secret_refs: changed_secret_refs.into_iter().collect(),
1586 connector_conn_ref,
1587 object_type: AlterConnectorPropsObject::IcebergTable as i32,
1588 extra_options: Some(ExtraOptions::AlterIcebergTableIds(AlterIcebergTableIds {
1589 sink_id,
1590 source_id,
1591 })),
1592 };
1593 let _resp = self.inner.alter_connector_props(req).await?;
1594 Ok(())
1595 }
1596
1597 pub async fn alter_source_connector_props(
1598 &self,
1599 source_id: SourceId,
1600 changed_props: BTreeMap<String, String>,
1601 changed_secret_refs: BTreeMap<String, PbSecretRef>,
1602 connector_conn_ref: Option<ConnectionId>,
1603 ) -> Result<()> {
1604 let req = AlterConnectorPropsRequest {
1605 object_id: source_id.as_raw_id(),
1606 changed_props: changed_props.into_iter().collect(),
1607 changed_secret_refs: changed_secret_refs.into_iter().collect(),
1608 connector_conn_ref,
1609 object_type: AlterConnectorPropsObject::Source as i32,
1610 extra_options: None,
1611 };
1612 let _resp = self.inner.alter_connector_props(req).await?;
1613 Ok(())
1614 }
1615
1616 pub async fn alter_connection_connector_props(
1617 &self,
1618 connection_id: u32,
1619 changed_props: BTreeMap<String, String>,
1620 changed_secret_refs: BTreeMap<String, PbSecretRef>,
1621 ) -> Result<()> {
1622 let req = AlterConnectorPropsRequest {
1623 object_id: connection_id,
1624 changed_props: changed_props.into_iter().collect(),
1625 changed_secret_refs: changed_secret_refs.into_iter().collect(),
1626 connector_conn_ref: None, object_type: AlterConnectorPropsObject::Connection as i32,
1628 extra_options: None,
1629 };
1630 let _resp = self.inner.alter_connector_props(req).await?;
1631 Ok(())
1632 }
1633
1634 pub async fn alter_source_properties_safe(
1637 &self,
1638 source_id: SourceId,
1639 changed_props: BTreeMap<String, String>,
1640 changed_secret_refs: BTreeMap<String, PbSecretRef>,
1641 reset_splits: bool,
1642 ) -> Result<()> {
1643 let req = AlterSourcePropertiesSafeRequest {
1644 source_id: source_id.as_raw_id(),
1645 changed_props: changed_props.into_iter().collect(),
1646 changed_secret_refs: changed_secret_refs.into_iter().collect(),
1647 options: Some(PropertyUpdateOptions { reset_splits }),
1648 };
1649 let _resp = self.inner.alter_source_properties_safe(req).await?;
1650 Ok(())
1651 }
1652
1653 pub async fn reset_source_splits(&self, source_id: SourceId) -> Result<()> {
1656 let req = ResetSourceSplitsRequest {
1657 source_id: source_id.as_raw_id(),
1658 };
1659 let _resp = self.inner.reset_source_splits(req).await?;
1660 Ok(())
1661 }
1662
1663 pub async fn inject_source_offsets(
1666 &self,
1667 source_id: SourceId,
1668 split_offsets: HashMap<String, String>,
1669 ) -> Result<Vec<String>> {
1670 let req = InjectSourceOffsetsRequest {
1671 source_id: source_id.as_raw_id(),
1672 split_offsets,
1673 };
1674 let resp = self.inner.inject_source_offsets(req).await?;
1675 Ok(resp.applied_split_ids)
1676 }
1677
1678 pub async fn set_system_param(
1679 &self,
1680 param: String,
1681 value: Option<String>,
1682 ) -> Result<Option<SystemParamsReader>> {
1683 let req = SetSystemParamRequest { param, value };
1684 let resp = self.inner.set_system_param(req).await?;
1685 Ok(resp.params.map(SystemParamsReader::from))
1686 }
1687
1688 pub async fn clear_file_cache(
1689 &self,
1690 clear_meta_cache: bool,
1691 clear_data_cache: bool,
1692 ) -> Result<()> {
1693 self.inner
1694 .clear_file_cache(ClearFileCacheRequest {
1695 clear_meta_cache,
1696 clear_data_cache,
1697 })
1698 .await?;
1699 Ok(())
1700 }
1701
1702 pub async fn get_session_params(&self) -> Result<String> {
1703 let req = GetSessionParamsRequest {};
1704 let resp = self.inner.get_session_params(req).await?;
1705 Ok(resp.params)
1706 }
1707
1708 pub async fn set_session_param(&self, param: String, value: Option<String>) -> Result<String> {
1709 let req = SetSessionParamRequest { param, value };
1710 let resp = self.inner.set_session_param(req).await?;
1711 Ok(resp.param)
1712 }
1713
1714 pub async fn get_ddl_progress(&self) -> Result<Vec<DdlProgress>> {
1715 let req = GetDdlProgressRequest {};
1716 let resp = self.inner.get_ddl_progress(req).await?;
1717 Ok(resp.ddl_progress)
1718 }
1719
1720 pub async fn split_compaction_group(
1721 &self,
1722 group_id: CompactionGroupId,
1723 table_ids_to_new_group: &[TableId],
1724 partition_vnode_count: u32,
1725 ) -> Result<CompactionGroupId> {
1726 let req = SplitCompactionGroupRequest {
1727 group_id,
1728 table_ids: table_ids_to_new_group.to_vec(),
1729 partition_vnode_count,
1730 };
1731 let resp = self.inner.split_compaction_group(req).await?;
1732 Ok(resp.new_group_id)
1733 }
1734
1735 pub async fn get_tables(
1736 &self,
1737 table_ids: Vec<TableId>,
1738 include_dropped_tables: bool,
1739 ) -> Result<HashMap<TableId, Table>> {
1740 let req = GetTablesRequest {
1741 table_ids,
1742 include_dropped_tables,
1743 };
1744 let resp = self.inner.get_tables(req).await?;
1745 Ok(resp.tables)
1746 }
1747
1748 pub async fn list_serving_vnode_mappings(
1749 &self,
1750 ) -> Result<HashMap<FragmentId, (JobId, WorkerSlotMapping)>> {
1751 let req = GetServingVnodeMappingsRequest {};
1752 let resp = self.inner.get_serving_vnode_mappings(req).await?;
1753 let mappings = resp
1754 .worker_slot_mappings
1755 .into_iter()
1756 .map(|p| {
1757 (
1758 p.fragment_id,
1759 (
1760 resp.fragment_to_table
1761 .get(&p.fragment_id)
1762 .cloned()
1763 .unwrap_or_default(),
1764 WorkerSlotMapping::from_protobuf(p.mapping.as_ref().unwrap()),
1765 ),
1766 )
1767 })
1768 .collect();
1769 Ok(mappings)
1770 }
1771
1772 pub async fn warm_up_table_cache(
1773 &self,
1774 table_id: TableId,
1775 concurrency: u32,
1776 ) -> Result<(u64, u32)> {
1777 let response = self
1778 .inner
1779 .warm_up_table_cache(WarmUpTableCacheRequest {
1780 table_id,
1781 concurrency,
1782 })
1783 .await?;
1784 Ok((response.key_count, response.worker_count))
1785 }
1786
1787 pub async fn risectl_list_compaction_status(
1788 &self,
1789 ) -> Result<(
1790 Vec<CompactStatus>,
1791 Vec<CompactTaskAssignment>,
1792 Vec<CompactTaskProgress>,
1793 )> {
1794 let req = RiseCtlListCompactionStatusRequest {};
1795 let resp = self.inner.rise_ctl_list_compaction_status(req).await?;
1796 Ok((
1797 resp.compaction_statuses,
1798 resp.task_assignment,
1799 resp.task_progress,
1800 ))
1801 }
1802
1803 pub async fn get_compaction_score(
1804 &self,
1805 compaction_group_id: CompactionGroupId,
1806 ) -> Result<Vec<PickerInfo>> {
1807 let req = GetCompactionScoreRequest {
1808 compaction_group_id,
1809 };
1810 let resp = self.inner.get_compaction_score(req).await?;
1811 Ok(resp.scores)
1812 }
1813
1814 pub async fn risectl_rebuild_table_stats(&self) -> Result<()> {
1815 let req = RiseCtlRebuildTableStatsRequest {};
1816 let _resp = self.inner.rise_ctl_rebuild_table_stats(req).await?;
1817 Ok(())
1818 }
1819
1820 pub async fn list_branched_object(&self) -> Result<Vec<BranchedObject>> {
1821 let req = ListBranchedObjectRequest {};
1822 let resp = self.inner.list_branched_object(req).await?;
1823 Ok(resp.branched_objects)
1824 }
1825
1826 pub async fn list_active_write_limit(&self) -> Result<HashMap<CompactionGroupId, WriteLimit>> {
1827 let req = ListActiveWriteLimitRequest {};
1828 let resp = self.inner.list_active_write_limit(req).await?;
1829 Ok(resp.write_limits)
1830 }
1831
1832 pub async fn list_hummock_meta_config(&self) -> Result<HashMap<String, String>> {
1833 let req = ListHummockMetaConfigRequest {};
1834 let resp = self.inner.list_hummock_meta_config(req).await?;
1835 Ok(resp.configs)
1836 }
1837
1838 pub async fn get_table_change_logs(
1839 &self,
1840 epoch_only: bool,
1841 start_epoch_inclusive: Option<u64>,
1842 end_epoch_inclusive: Option<u64>,
1843 table_ids: Option<HashSet<TableId>>,
1844 exclude_empty: bool,
1845 limit: Option<u32>,
1846 ) -> Result<TableChangeLogs> {
1847 let req = GetTableChangeLogsRequest {
1848 epoch_only,
1849 start_epoch_inclusive,
1850 end_epoch_inclusive,
1851 table_ids: table_ids.map(|iter| PbTableFilter {
1852 table_ids: iter.into_iter().collect::<Vec<_>>(),
1853 }),
1854 exclude_empty,
1855 limit,
1856 };
1857 let resp = self.inner.get_table_change_logs(req).await?;
1858 Ok(resp
1859 .table_change_logs
1860 .into_iter()
1861 .map(|(id, change_log)| (TableId::new(id), TableChangeLog::from_protobuf(&change_log)))
1862 .collect())
1863 }
1864
1865 pub async fn delete_worker_node(&self, worker: HostAddress) -> Result<()> {
1866 let _resp = self
1867 .inner
1868 .delete_worker_node(DeleteWorkerNodeRequest { host: Some(worker) })
1869 .await?;
1870
1871 Ok(())
1872 }
1873
1874 pub async fn rw_cloud_validate_source(
1875 &self,
1876 source_type: SourceType,
1877 source_config: HashMap<String, String>,
1878 ) -> Result<RwCloudValidateSourceResponse> {
1879 let req = RwCloudValidateSourceRequest {
1880 source_type: source_type.into(),
1881 source_config,
1882 };
1883 let resp = self.inner.rw_cloud_validate_source(req).await?;
1884 Ok(resp)
1885 }
1886
1887 pub async fn sink_coordinate_client(&self) -> SinkCoordinationRpcClient {
1888 self.inner.core.read().await.sink_coordinate_client.clone()
1889 }
1890
1891 pub async fn list_compact_task_assignment(&self) -> Result<Vec<CompactTaskAssignment>> {
1892 let req = ListCompactTaskAssignmentRequest {};
1893 let resp = self.inner.list_compact_task_assignment(req).await?;
1894 Ok(resp.task_assignment)
1895 }
1896
1897 pub async fn list_event_log(&self) -> Result<Vec<EventLog>> {
1898 let req = ListEventLogRequest::default();
1899 let resp = self.inner.list_event_log(req).await?;
1900 Ok(resp.event_logs)
1901 }
1902
1903 pub async fn list_compact_task_progress(&self) -> Result<Vec<CompactTaskProgress>> {
1904 let req = ListCompactTaskProgressRequest {};
1905 let resp = self.inner.list_compact_task_progress(req).await?;
1906 Ok(resp.task_progress)
1907 }
1908
1909 #[cfg(madsim)]
1910 pub fn try_add_panic_event_blocking(
1911 &self,
1912 panic_info: impl Display,
1913 timeout_millis: Option<u64>,
1914 ) {
1915 }
1916
1917 #[cfg(not(madsim))]
1919 pub fn try_add_panic_event_blocking(
1920 &self,
1921 panic_info: impl Display,
1922 timeout_millis: Option<u64>,
1923 ) {
1924 let event = event_log::EventWorkerNodePanic {
1925 worker_id: self.worker_id,
1926 worker_type: self.worker_type.into(),
1927 host_addr: Some(self.host_addr.to_protobuf()),
1928 panic_info: format!("{panic_info}"),
1929 };
1930 let grpc_meta_client = self.inner.clone();
1931 let _ = thread::spawn(move || {
1932 let rt = tokio::runtime::Builder::new_current_thread()
1933 .enable_all()
1934 .build()
1935 .unwrap();
1936 let req = AddEventLogRequest {
1937 event: Some(add_event_log_request::Event::WorkerNodePanic(event)),
1938 };
1939 rt.block_on(async {
1940 let _ = tokio::time::timeout(
1941 Duration::from_millis(timeout_millis.unwrap_or(1000)),
1942 grpc_meta_client.add_event_log(req),
1943 )
1944 .await;
1945 });
1946 })
1947 .join();
1948 }
1949
1950 pub async fn add_sink_fail_evet(
1951 &self,
1952 sink_id: SinkId,
1953 sink_name: String,
1954 connector: String,
1955 error: String,
1956 ) -> Result<()> {
1957 let event = event_log::EventSinkFail {
1958 sink_id,
1959 sink_name,
1960 connector,
1961 error,
1962 };
1963 let req = AddEventLogRequest {
1964 event: Some(add_event_log_request::Event::SinkFail(event)),
1965 };
1966 self.inner.add_event_log(req).await?;
1967 Ok(())
1968 }
1969
1970 pub async fn add_cdc_auto_schema_change_fail_event(
1971 &self,
1972 source_id: SourceId,
1973 table_name: String,
1974 cdc_table_id: String,
1975 upstream_ddl: String,
1976 fail_info: String,
1977 ) -> Result<()> {
1978 let event = event_log::EventAutoSchemaChangeFail {
1979 table_id: source_id.as_cdc_table_id(),
1980 table_name,
1981 cdc_table_id,
1982 upstream_ddl,
1983 fail_info,
1984 };
1985 let req = AddEventLogRequest {
1986 event: Some(add_event_log_request::Event::AutoSchemaChangeFail(event)),
1987 };
1988 self.inner.add_event_log(req).await?;
1989 Ok(())
1990 }
1991
1992 pub async fn cancel_compact_task(&self, task_id: u64, task_status: TaskStatus) -> Result<bool> {
1993 let req = CancelCompactTaskRequest {
1994 task_id,
1995 task_status: task_status as _,
1996 };
1997 let resp = self.inner.cancel_compact_task(req).await?;
1998 Ok(resp.ret)
1999 }
2000
2001 pub async fn get_version_by_epoch(
2002 &self,
2003 epoch: HummockEpoch,
2004 table_id: TableId,
2005 ) -> Result<PbHummockVersion> {
2006 let req = GetVersionByEpochRequest { epoch, table_id };
2007 let resp = self.inner.get_version_by_epoch(req).await?;
2008 Ok(resp.version.unwrap())
2009 }
2010
2011 pub async fn get_cluster_limits(
2012 &self,
2013 ) -> Result<Vec<risingwave_common::util::cluster_limit::ClusterLimit>> {
2014 let req = GetClusterLimitsRequest {};
2015 let resp = self.inner.get_cluster_limits(req).await?;
2016 Ok(resp.active_limits.into_iter().map(|l| l.into()).collect())
2017 }
2018
2019 pub async fn merge_compaction_group(
2020 &self,
2021 left_group_id: CompactionGroupId,
2022 right_group_id: CompactionGroupId,
2023 ) -> Result<()> {
2024 let req = MergeCompactionGroupRequest {
2025 left_group_id,
2026 right_group_id,
2027 };
2028 self.inner.merge_compaction_group(req).await?;
2029 Ok(())
2030 }
2031
2032 pub async fn list_rate_limits(&self) -> Result<Vec<RateLimitInfo>> {
2034 let request = ListRateLimitsRequest {};
2035 let resp = self.inner.list_rate_limits(request).await?;
2036 Ok(resp.rate_limits)
2037 }
2038
2039 pub async fn list_cdc_progress(&self) -> Result<HashMap<JobId, PbCdcProgress>> {
2040 let request = ListCdcProgressRequest {};
2041 let resp = self.inner.list_cdc_progress(request).await?;
2042 Ok(resp.cdc_progress)
2043 }
2044
2045 pub async fn list_refresh_table_states(&self) -> Result<Vec<RefreshTableState>> {
2046 let request = ListRefreshTableStatesRequest {};
2047 let resp = self.inner.list_refresh_table_states(request).await?;
2048 Ok(resp.states)
2049 }
2050
2051 pub async fn list_iceberg_compaction_status(
2052 &self,
2053 ) -> Result<Vec<list_iceberg_compaction_status_response::IcebergCompactionStatus>> {
2054 let request = ListIcebergCompactionStatusRequest {};
2055 let resp = self.inner.list_iceberg_compaction_status(request).await?;
2056 Ok(resp.statuses)
2057 }
2058
2059 pub async fn list_sink_log_store_tables(
2060 &self,
2061 ) -> Result<Vec<list_sink_log_store_tables_response::SinkLogStoreTable>> {
2062 let request = ListSinkLogStoreTablesRequest {};
2063 let resp = self.inner.list_sink_log_store_tables(request).await?;
2064 Ok(resp.tables)
2065 }
2066
2067 pub async fn create_iceberg_table(
2068 &self,
2069 table_job_info: PbTableJobInfo,
2070 sink_job_info: PbSinkJobInfo,
2071 iceberg_source: PbSource,
2072 if_not_exists: bool,
2073 ) -> Result<WaitVersion> {
2074 let request = CreateIcebergTableRequest {
2075 table_info: Some(table_job_info),
2076 sink_info: Some(sink_job_info),
2077 iceberg_source: Some(iceberg_source),
2078 if_not_exists,
2079 };
2080
2081 let resp = Box::pin(self.inner.create_iceberg_table(request)).await?;
2082 Ok(resp
2083 .version
2084 .ok_or_else(|| anyhow!("wait version not set"))?)
2085 }
2086
2087 pub async fn list_hosted_iceberg_tables(&self) -> Result<Vec<IcebergTable>> {
2088 let request = ListIcebergTablesRequest {};
2089 let resp = self.inner.list_iceberg_tables(request).await?;
2090 Ok(resp.iceberg_tables)
2091 }
2092
2093 pub async fn get_cluster_stack_trace(
2095 &self,
2096 actor_traces_format: ActorTracesFormat,
2097 ) -> Result<StackTraceResponse> {
2098 let request = StackTraceRequest {
2099 actor_traces_format: actor_traces_format as i32,
2100 };
2101 let resp = self.inner.stack_trace(request).await?;
2102 Ok(resp)
2103 }
2104
2105 pub async fn set_sync_log_store_aligned(&self, job_id: JobId, aligned: bool) -> Result<()> {
2106 let request = SetSyncLogStoreAlignedRequest { job_id, aligned };
2107 self.inner.set_sync_log_store_aligned(request).await?;
2108 Ok(())
2109 }
2110
2111 pub async fn refresh(&self, request: RefreshRequest) -> Result<RefreshResponse> {
2112 self.inner.refresh(request).await
2113 }
2114
2115 pub async fn list_unmigrated_tables(&self) -> Result<HashMap<TableId, String>> {
2116 let request = ListUnmigratedTablesRequest {};
2117 let resp = self.inner.list_unmigrated_tables(request).await?;
2118 Ok(resp
2119 .tables
2120 .into_iter()
2121 .map(|table| (table.table_id, table.table_name))
2122 .collect())
2123 }
2124}
2125
2126#[async_trait]
2127impl HummockMetaClient for MetaClient {
2128 async fn unpin_version_before(&self, unpin_version_before: HummockVersionId) -> Result<()> {
2129 let req = UnpinVersionBeforeRequest {
2130 context_id: self.worker_id(),
2131 unpin_version_before,
2132 };
2133 self.inner.unpin_version_before(req).await?;
2134 Ok(())
2135 }
2136
2137 async fn get_current_version(&self) -> Result<HummockVersion> {
2138 let req = GetCurrentVersionRequest::default();
2139 Ok(HummockVersion::from_rpc_protobuf(
2140 &self
2141 .inner
2142 .get_current_version(req)
2143 .await?
2144 .current_version
2145 .unwrap(),
2146 ))
2147 }
2148
2149 async fn get_new_object_ids(&self, number: u32) -> Result<ObjectIdRange> {
2150 let resp = self
2151 .inner
2152 .get_new_object_ids(GetNewObjectIdsRequest { number })
2153 .await?;
2154 Ok(ObjectIdRange::new(resp.start_id, resp.end_id))
2155 }
2156
2157 async fn commit_epoch_with_change_log(
2158 &self,
2159 _epoch: HummockEpoch,
2160 _sync_result: SyncResult,
2161 _change_log_info: Option<HummockMetaClientChangeLogInfo>,
2162 ) -> Result<()> {
2163 panic!("Only meta service can commit_epoch in production.")
2164 }
2165
2166 async fn trigger_manual_compaction(
2167 &self,
2168 compaction_group_id: CompactionGroupId,
2169 table_id: JobId,
2170 level: u32,
2171 target_level: Option<u32>,
2172 sst_ids: Vec<HummockSstableId>,
2173 exclusive: bool,
2174 ) -> Result<bool> {
2175 let req = TriggerManualCompactionRequest {
2177 compaction_group_id,
2178 table_id,
2179 level,
2182 target_level,
2183 sst_ids,
2184 exclusive: Some(exclusive),
2185 ..Default::default()
2186 };
2187
2188 let resp = self.inner.trigger_manual_compaction(req).await?;
2189 Ok(resp.should_retry.unwrap_or(false))
2190 }
2191
2192 async fn trigger_full_gc(
2193 &self,
2194 sst_retention_time_sec: u64,
2195 prefix: Option<String>,
2196 ) -> Result<()> {
2197 self.inner
2198 .trigger_full_gc(TriggerFullGcRequest {
2199 sst_retention_time_sec,
2200 prefix,
2201 })
2202 .await?;
2203 Ok(())
2204 }
2205
2206 async fn subscribe_compaction_event(
2207 &self,
2208 ) -> Result<(
2209 UnboundedSender<SubscribeCompactionEventRequest>,
2210 BoxStream<'static, CompactionEventItem>,
2211 )> {
2212 let (request_sender, request_receiver) =
2213 unbounded_channel::<SubscribeCompactionEventRequest>();
2214 request_sender
2215 .send(SubscribeCompactionEventRequest {
2216 event: Some(subscribe_compaction_event_request::Event::Register(
2217 Register {
2218 context_id: self.worker_id(),
2219 },
2220 )),
2221 create_at: SystemTime::now()
2222 .duration_since(SystemTime::UNIX_EPOCH)
2223 .expect("Clock may have gone backwards")
2224 .as_millis() as u64,
2225 })
2226 .context("Failed to subscribe compaction event")?;
2227
2228 let stream = self
2229 .inner
2230 .subscribe_compaction_event(Request::new(UnboundedReceiverStream::new(
2231 request_receiver,
2232 )))
2233 .await?;
2234
2235 Ok((request_sender, Box::pin(stream)))
2236 }
2237
2238 async fn get_version_by_epoch(
2239 &self,
2240 epoch: HummockEpoch,
2241 table_id: TableId,
2242 ) -> Result<PbHummockVersion> {
2243 self.get_version_by_epoch(epoch, table_id).await
2244 }
2245
2246 async fn subscribe_iceberg_compaction_event(
2247 &self,
2248 ) -> Result<(
2249 UnboundedSender<SubscribeIcebergCompactionEventRequest>,
2250 BoxStream<'static, IcebergCompactionEventItem>,
2251 )> {
2252 let (request_sender, request_receiver) =
2253 unbounded_channel::<SubscribeIcebergCompactionEventRequest>();
2254 request_sender
2255 .send(SubscribeIcebergCompactionEventRequest {
2256 event: Some(subscribe_iceberg_compaction_event_request::Event::Register(
2257 IcebergRegister {
2258 context_id: self.worker_id(),
2259 },
2260 )),
2261 create_at: SystemTime::now()
2262 .duration_since(SystemTime::UNIX_EPOCH)
2263 .expect("Clock may have gone backwards")
2264 .as_millis() as u64,
2265 })
2266 .context("Failed to subscribe compaction event")?;
2267
2268 let stream = self
2269 .inner
2270 .subscribe_iceberg_compaction_event(Request::new(UnboundedReceiverStream::new(
2271 request_receiver,
2272 )))
2273 .await?;
2274
2275 Ok((request_sender, Box::pin(stream)))
2276 }
2277
2278 async fn get_table_change_logs(
2279 &self,
2280 epoch_only: bool,
2281 start_epoch_inclusive: Option<u64>,
2282 end_epoch_inclusive: Option<u64>,
2283 table_ids: Option<HashSet<TableId>>,
2284 exclude_empty: bool,
2285 limit: Option<u32>,
2286 ) -> Result<TableChangeLogs> {
2287 self.get_table_change_logs(
2288 epoch_only,
2289 start_epoch_inclusive,
2290 end_epoch_inclusive,
2291 table_ids,
2292 exclude_empty,
2293 limit,
2294 )
2295 .await
2296 }
2297}
2298
2299#[async_trait]
2300impl TelemetryInfoFetcher for MetaClient {
2301 async fn fetch_telemetry_info(&self) -> std::result::Result<Option<String>, String> {
2302 let resp = self
2303 .get_telemetry_info()
2304 .await
2305 .map_err(|e| e.to_report_string())?;
2306 let tracking_id = resp.get_tracking_id().ok();
2307 Ok(tracking_id.map(|id| id.to_owned()))
2308 }
2309}
2310
2311pub type SinkCoordinationRpcClient = SinkCoordinationServiceClient<Channel>;
2312
2313#[derive(Debug, Clone)]
2314struct GrpcMetaClientCore {
2315 cluster_client: ClusterServiceClient<Channel>,
2316 meta_member_client: MetaMemberServiceClient<Channel>,
2317 heartbeat_client: HeartbeatServiceClient<Channel>,
2318 ddl_client: DdlServiceClient<Channel>,
2319 hummock_client: HummockManagerServiceClient<Channel>,
2320 notification_client: NotificationServiceClient<Channel>,
2321 stream_client: StreamManagerServiceClient<Channel>,
2322 user_client: UserServiceClient<Channel>,
2323 scale_client: ScaleServiceClient<Channel>,
2324 backup_client: BackupServiceClient<Channel>,
2325 telemetry_client: TelemetryInfoServiceClient<Channel>,
2326 system_params_client: SystemParamsServiceClient<Channel>,
2327 session_params_client: SessionParamServiceClient<Channel>,
2328 serving_client: ServingServiceClient<Channel>,
2329 cloud_client: CloudServiceClient<Channel>,
2330 sink_coordinate_client: SinkCoordinationRpcClient,
2331 event_log_client: EventLogServiceClient<Channel>,
2332 cluster_limit_client: ClusterLimitServiceClient<Channel>,
2333 hosted_iceberg_catalog_service_client: HostedIcebergCatalogServiceClient<Channel>,
2334 monitor_client: MonitorServiceClient<Channel>,
2335}
2336
2337impl GrpcMetaClientCore {
2338 pub(crate) fn new(channel: Channel) -> Self {
2339 let cluster_client = ClusterServiceClient::new(channel.clone());
2340 let meta_member_client = MetaMemberClient::new(channel.clone());
2341 let heartbeat_client = HeartbeatServiceClient::new(channel.clone());
2342 let ddl_client =
2343 DdlServiceClient::new(channel.clone()).max_decoding_message_size(usize::MAX);
2344 let hummock_client =
2345 HummockManagerServiceClient::new(channel.clone()).max_decoding_message_size(usize::MAX);
2346 let notification_client = NotificationServiceClient::new(channel.clone())
2350 .accept_compressed(tonic::codec::CompressionEncoding::Zstd)
2351 .max_decoding_message_size(usize::MAX);
2352 let stream_client =
2353 StreamManagerServiceClient::new(channel.clone()).max_decoding_message_size(usize::MAX);
2354 let user_client = UserServiceClient::new(channel.clone());
2355 let scale_client =
2356 ScaleServiceClient::new(channel.clone()).max_decoding_message_size(usize::MAX);
2357 let backup_client = BackupServiceClient::new(channel.clone());
2358 let telemetry_client =
2359 TelemetryInfoServiceClient::new(channel.clone()).max_decoding_message_size(usize::MAX);
2360 let system_params_client = SystemParamsServiceClient::new(channel.clone());
2361 let session_params_client = SessionParamServiceClient::new(channel.clone());
2362 let serving_client = ServingServiceClient::new(channel.clone());
2363 let cloud_client = CloudServiceClient::new(channel.clone());
2364 let sink_coordinate_client = SinkCoordinationServiceClient::new(channel.clone())
2365 .max_decoding_message_size(usize::MAX);
2366 let event_log_client = EventLogServiceClient::new(channel.clone());
2367 let cluster_limit_client = ClusterLimitServiceClient::new(channel.clone());
2368 let hosted_iceberg_catalog_service_client =
2369 HostedIcebergCatalogServiceClient::new(channel.clone());
2370 let monitor_client = configured_monitor_service_client(MonitorServiceClient::new(channel));
2371
2372 GrpcMetaClientCore {
2373 cluster_client,
2374 meta_member_client,
2375 heartbeat_client,
2376 ddl_client,
2377 hummock_client,
2378 notification_client,
2379 stream_client,
2380 user_client,
2381 scale_client,
2382 backup_client,
2383 telemetry_client,
2384 system_params_client,
2385 session_params_client,
2386 serving_client,
2387 cloud_client,
2388 sink_coordinate_client,
2389 event_log_client,
2390 cluster_limit_client,
2391 hosted_iceberg_catalog_service_client,
2392 monitor_client,
2393 }
2394 }
2395}
2396
2397#[derive(Debug, Clone)]
2401struct GrpcMetaClient {
2402 member_monitor_event_sender: mpsc::Sender<Sender<Result<()>>>,
2403 core: Arc<RwLock<GrpcMetaClientCore>>,
2404}
2405
2406type MetaMemberClient = MetaMemberServiceClient<Channel>;
2407
2408struct MetaMemberGroup {
2409 members: LruCache<http::Uri, Option<MetaMemberClient>>,
2410}
2411
2412struct MetaMemberManagement {
2413 core_ref: Arc<RwLock<GrpcMetaClientCore>>,
2414 members: Either<MetaMemberClient, MetaMemberGroup>,
2415 current_leader: http::Uri,
2416 meta_config: Arc<MetaConfig>,
2417}
2418
2419impl MetaMemberManagement {
2420 const META_MEMBER_REFRESH_PERIOD: Duration = Duration::from_secs(5);
2421
2422 fn host_address_to_uri(addr: HostAddress) -> http::Uri {
2423 format!("http://{}:{}", addr.host, addr.port)
2424 .parse()
2425 .unwrap()
2426 }
2427
2428 async fn recreate_core(&self, channel: Channel) {
2429 let mut core = self.core_ref.write().await;
2430 *core = GrpcMetaClientCore::new(channel);
2431 }
2432
2433 async fn refresh_members(&mut self) -> Result<()> {
2434 let leader_addr = match self.members.as_mut() {
2435 Either::Left(client) => {
2436 let resp = client
2437 .to_owned()
2438 .members(MembersRequest {})
2439 .await
2440 .map_err(RpcError::from_meta_status)?;
2441 let resp = resp.into_inner();
2442 resp.members.into_iter().find(|member| member.is_leader)
2443 }
2444 Either::Right(member_group) => {
2445 let mut fetched_members = None;
2446
2447 for (addr, client) in &mut member_group.members {
2448 let members: Result<_> = try {
2449 let mut client = match client {
2450 Some(cached_client) => cached_client.to_owned(),
2451 None => {
2452 let endpoint = GrpcMetaClient::addr_to_endpoint(addr.clone());
2453 let channel = GrpcMetaClient::connect_to_endpoint(endpoint)
2454 .await
2455 .context("failed to create client")
2456 .map_err(RpcError::from)?;
2457 let new_client: MetaMemberClient =
2458 MetaMemberServiceClient::new(channel);
2459 *client = Some(new_client.clone());
2460
2461 new_client
2462 }
2463 };
2464
2465 let resp = client
2466 .members(MembersRequest {})
2467 .await
2468 .context("failed to fetch members")
2469 .map_err(RpcError::from)?;
2470
2471 resp.into_inner().members
2472 };
2473
2474 let fetched = members.is_ok();
2475 fetched_members = Some(members);
2476 if fetched {
2477 break;
2478 }
2479 }
2480
2481 let members = fetched_members
2482 .context("no member available in the list")?
2483 .context("could not refresh members")?;
2484
2485 let mut leader = None;
2487 for member in members {
2488 if member.is_leader {
2489 leader = Some(member.clone());
2490 }
2491
2492 let addr = Self::host_address_to_uri(member.address.unwrap());
2493 if !member_group.members.contains(&addr) {
2495 tracing::info!("new meta member joined: {}", addr);
2496 member_group.members.put(addr, None);
2497 }
2498 }
2499
2500 leader
2501 }
2502 };
2503
2504 if let Some(leader) = leader_addr {
2505 let discovered_leader = Self::host_address_to_uri(leader.address.unwrap());
2506
2507 if discovered_leader != self.current_leader {
2508 tracing::info!("new meta leader {} discovered", discovered_leader);
2509
2510 let retry_strategy = GrpcMetaClient::retry_strategy_to_bound(
2511 Duration::from_secs(self.meta_config.meta_leader_lease_secs),
2512 false,
2513 );
2514
2515 let channel = tokio_retry::Retry::spawn(retry_strategy, || async {
2516 let endpoint = GrpcMetaClient::addr_to_endpoint(discovered_leader.clone());
2517 GrpcMetaClient::connect_to_endpoint(endpoint).await
2518 })
2519 .await?;
2520
2521 self.recreate_core(channel).await;
2522 self.current_leader = discovered_leader;
2523 }
2524 }
2525
2526 Ok(())
2527 }
2528}
2529
2530impl GrpcMetaClient {
2531 const ENDPOINT_KEEP_ALIVE_INTERVAL_SEC: u64 = 60;
2533 const ENDPOINT_KEEP_ALIVE_TIMEOUT_SEC: u64 = 60;
2535 const INIT_RETRY_BASE_INTERVAL_MS: u64 = 10;
2537 const INIT_RETRY_MAX_INTERVAL_MS: u64 = 2000;
2539
2540 fn start_meta_member_monitor(
2541 &self,
2542 init_leader_addr: http::Uri,
2543 members: Either<MetaMemberClient, MetaMemberGroup>,
2544 force_refresh_receiver: Receiver<Sender<Result<()>>>,
2545 meta_config: Arc<MetaConfig>,
2546 ) -> Result<()> {
2547 let core_ref: Arc<RwLock<GrpcMetaClientCore>> = self.core.clone();
2548 let current_leader = init_leader_addr;
2549
2550 let enable_period_tick = matches!(members, Either::Right(_));
2551
2552 let member_management = MetaMemberManagement {
2553 core_ref,
2554 members,
2555 current_leader,
2556 meta_config,
2557 };
2558
2559 let mut force_refresh_receiver = force_refresh_receiver;
2560
2561 tokio::spawn(async move {
2562 let mut member_management = member_management;
2563 let mut ticker = time::interval(MetaMemberManagement::META_MEMBER_REFRESH_PERIOD);
2564
2565 loop {
2566 let event: Option<Sender<Result<()>>> = if enable_period_tick {
2567 tokio::select! {
2568 _ = ticker.tick() => None,
2569 result_sender = force_refresh_receiver.recv() => {
2570 if result_sender.is_none() {
2571 break;
2572 }
2573
2574 result_sender
2575 },
2576 }
2577 } else {
2578 let result_sender = force_refresh_receiver.recv().await;
2579
2580 if result_sender.is_none() {
2581 break;
2582 }
2583
2584 result_sender
2585 };
2586
2587 let tick_result = member_management.refresh_members().await;
2588 if let Err(e) = tick_result.as_ref() {
2589 tracing::warn!(error = %e.as_report(), "refresh meta member client failed");
2590 }
2591
2592 if let Some(sender) = event {
2593 let _resp = sender.send(tick_result);
2595 }
2596 }
2597 });
2598
2599 Ok(())
2600 }
2601
2602 async fn force_refresh_leader(&self) -> Result<()> {
2603 let (sender, receiver) = oneshot::channel();
2604
2605 self.member_monitor_event_sender
2606 .send(sender)
2607 .await
2608 .map_err(|e| anyhow!(e))?;
2609
2610 receiver.await.map_err(|e| anyhow!(e))?
2611 }
2612
2613 pub async fn new(strategy: &MetaAddressStrategy, config: Arc<MetaConfig>) -> Result<Self> {
2615 let (channel, addr) = match strategy {
2616 MetaAddressStrategy::LoadBalance(addr) => {
2617 Self::try_build_rpc_channel(vec![addr.clone()]).await
2618 }
2619 MetaAddressStrategy::List(addrs) => Self::try_build_rpc_channel(addrs.clone()).await,
2620 }?;
2621 let (force_refresh_sender, force_refresh_receiver) = mpsc::channel(1);
2622 let client = GrpcMetaClient {
2623 member_monitor_event_sender: force_refresh_sender,
2624 core: Arc::new(RwLock::new(GrpcMetaClientCore::new(channel))),
2625 };
2626
2627 let meta_member_client = client.core.read().await.meta_member_client.clone();
2628 let members = match strategy {
2629 MetaAddressStrategy::LoadBalance(_) => Either::Left(meta_member_client),
2630 MetaAddressStrategy::List(addrs) => {
2631 let mut members = LruCache::new(20.try_into().unwrap());
2632 for addr in addrs {
2633 members.put(addr.clone(), None);
2634 }
2635 members.put(addr.clone(), Some(meta_member_client));
2636
2637 Either::Right(MetaMemberGroup { members })
2638 }
2639 };
2640
2641 client.start_meta_member_monitor(addr, members, force_refresh_receiver, config.clone())?;
2642
2643 client.force_refresh_leader().await?;
2644
2645 Ok(client)
2646 }
2647
2648 fn addr_to_endpoint(addr: http::Uri) -> Endpoint {
2649 Endpoint::from(addr).initial_connection_window_size(MAX_CONNECTION_WINDOW_SIZE)
2650 }
2651
2652 pub(crate) async fn try_build_rpc_channel(
2653 addrs: impl IntoIterator<Item = http::Uri>,
2654 ) -> Result<(Channel, http::Uri)> {
2655 let endpoints: Vec<_> = addrs
2656 .into_iter()
2657 .map(|addr| (Self::addr_to_endpoint(addr.clone()), addr))
2658 .collect();
2659
2660 let mut last_error = None;
2661
2662 for (endpoint, addr) in endpoints {
2663 match Self::connect_to_endpoint(endpoint).await {
2664 Ok(channel) => {
2665 tracing::info!("Connect to meta server {} successfully", addr);
2666 return Ok((channel, addr));
2667 }
2668 Err(e) => {
2669 tracing::warn!(
2670 error = %e.as_report(),
2671 "Failed to connect to meta server {}, trying again",
2672 addr,
2673 );
2674 last_error = Some(e);
2675 }
2676 }
2677 }
2678
2679 if let Some(last_error) = last_error {
2680 Err(anyhow::anyhow!(last_error)
2681 .context("failed to connect to all meta servers")
2682 .into())
2683 } else {
2684 bail!("no meta server address provided")
2685 }
2686 }
2687
2688 async fn connect_to_endpoint(endpoint: Endpoint) -> Result<Channel> {
2689 let channel = endpoint
2690 .http2_keep_alive_interval(Duration::from_secs(Self::ENDPOINT_KEEP_ALIVE_INTERVAL_SEC))
2691 .keep_alive_timeout(Duration::from_secs(Self::ENDPOINT_KEEP_ALIVE_TIMEOUT_SEC))
2692 .connect_timeout(Duration::from_secs(5))
2693 .monitored_connect("grpc-meta-client", Default::default())
2694 .await?
2695 .wrapped();
2696
2697 Ok(channel)
2698 }
2699
2700 pub(crate) fn retry_strategy_to_bound(
2701 high_bound: Duration,
2702 exceed: bool,
2703 ) -> impl Iterator<Item = Duration> {
2704 let iter = exponential_backoff(
2705 Duration::from_millis(Self::INIT_RETRY_BASE_INTERVAL_MS),
2706 Self::INIT_RETRY_BASE_INTERVAL_MS,
2707 Duration::from_millis(Self::INIT_RETRY_MAX_INTERVAL_MS),
2708 )
2709 .map(jitter);
2710
2711 let mut sum = Duration::default();
2712
2713 iter.take_while(move |duration| {
2714 sum += *duration;
2715
2716 if exceed {
2717 sum < high_bound + *duration
2718 } else {
2719 sum < high_bound
2720 }
2721 })
2722 }
2723}
2724
2725macro_rules! for_all_meta_rpc {
2726 ($macro:ident) => {
2727 $macro! {
2728 { cluster_client, add_worker_node, AddWorkerNodeRequest, AddWorkerNodeResponse }
2729 ,{ cluster_client, activate_worker_node, ActivateWorkerNodeRequest, ActivateWorkerNodeResponse }
2730 ,{ cluster_client, delete_worker_node, DeleteWorkerNodeRequest, DeleteWorkerNodeResponse }
2731 ,{ cluster_client, list_all_nodes, ListAllNodesRequest, ListAllNodesResponse }
2732 ,{ cluster_client, get_cluster_recovery_status, GetClusterRecoveryStatusRequest, GetClusterRecoveryStatusResponse }
2733 ,{ cluster_client, get_meta_store_info, GetMetaStoreInfoRequest, GetMetaStoreInfoResponse }
2734 ,{ heartbeat_client, heartbeat, HeartbeatRequest, HeartbeatResponse }
2735 ,{ stream_client, flush, FlushRequest, FlushResponse }
2736 ,{ stream_client, pause, PauseRequest, PauseResponse }
2737 ,{ stream_client, resume, ResumeRequest, ResumeResponse }
2738 ,{ stream_client, apply_throttle, ApplyThrottleRequest, ApplyThrottleResponse }
2739 ,{ stream_client, cancel_creating_jobs, CancelCreatingJobsRequest, CancelCreatingJobsResponse }
2740 ,{ stream_client, list_table_fragments, ListTableFragmentsRequest, ListTableFragmentsResponse }
2741 ,{ stream_client, list_streaming_job_states, ListStreamingJobStatesRequest, ListStreamingJobStatesResponse }
2742 ,{ stream_client, list_fragment_distribution, ListFragmentDistributionRequest, ListFragmentDistributionResponse }
2743 ,{ stream_client, list_creating_fragment_distribution, ListCreatingFragmentDistributionRequest, ListCreatingFragmentDistributionResponse }
2744 ,{ stream_client, list_sink_log_store_tables, ListSinkLogStoreTablesRequest, ListSinkLogStoreTablesResponse }
2745 ,{ stream_client, list_actor_states, ListActorStatesRequest, ListActorStatesResponse }
2746 ,{ stream_client, list_actor_splits, ListActorSplitsRequest, ListActorSplitsResponse }
2747 ,{ stream_client, recover, RecoverRequest, RecoverResponse }
2748 ,{ stream_client, list_rate_limits, ListRateLimitsRequest, ListRateLimitsResponse }
2749 ,{ stream_client, list_cdc_progress, ListCdcProgressRequest, ListCdcProgressResponse }
2750 ,{ stream_client, list_refresh_table_states, ListRefreshTableStatesRequest, ListRefreshTableStatesResponse }
2751 ,{ stream_client, list_iceberg_compaction_status, ListIcebergCompactionStatusRequest, ListIcebergCompactionStatusResponse }
2752 ,{ stream_client, alter_connector_props, AlterConnectorPropsRequest, AlterConnectorPropsResponse }
2753 ,{ stream_client, alter_source_properties_safe, AlterSourcePropertiesSafeRequest, AlterSourcePropertiesSafeResponse }
2754 ,{ stream_client, reset_source_splits, ResetSourceSplitsRequest, ResetSourceSplitsResponse }
2755 ,{ stream_client, inject_source_offsets, InjectSourceOffsetsRequest, InjectSourceOffsetsResponse }
2756 ,{ stream_client, get_fragment_by_id, GetFragmentByIdRequest, GetFragmentByIdResponse }
2757 ,{ stream_client, get_fragment_vnodes, GetFragmentVnodesRequest, GetFragmentVnodesResponse }
2758 ,{ stream_client, get_actor_vnodes, GetActorVnodesRequest, GetActorVnodesResponse }
2759 ,{ stream_client, set_sync_log_store_aligned, SetSyncLogStoreAlignedRequest, SetSyncLogStoreAlignedResponse }
2760 ,{ stream_client, refresh, RefreshRequest, RefreshResponse }
2761 ,{ stream_client, list_unmigrated_tables, ListUnmigratedTablesRequest, ListUnmigratedTablesResponse }
2762 ,{ ddl_client, create_table, CreateTableRequest, CreateTableResponse }
2763 ,{ ddl_client, alter_name, AlterNameRequest, AlterNameResponse }
2764 ,{ ddl_client, alter_owner, AlterOwnerRequest, AlterOwnerResponse }
2765 ,{ ddl_client, alter_subscription_retention, AlterSubscriptionRetentionRequest, AlterSubscriptionRetentionResponse }
2766 ,{ ddl_client, alter_set_schema, AlterSetSchemaRequest, AlterSetSchemaResponse }
2767 ,{ ddl_client, alter_parallelism, AlterParallelismRequest, AlterParallelismResponse }
2768 ,{ ddl_client, alter_backfill_parallelism, AlterBackfillParallelismRequest, AlterBackfillParallelismResponse }
2769 ,{ ddl_client, alter_streaming_job_config, AlterStreamingJobConfigRequest, AlterStreamingJobConfigResponse }
2770 ,{ ddl_client, alter_fragment_parallelism, AlterFragmentParallelismRequest, AlterFragmentParallelismResponse }
2771 ,{ ddl_client, alter_cdc_table_backfill_parallelism, AlterCdcTableBackfillParallelismRequest, AlterCdcTableBackfillParallelismResponse }
2772 ,{ ddl_client, alter_resource_group, AlterResourceGroupRequest, AlterResourceGroupResponse }
2773 ,{ ddl_client, alter_database_resource_group, AlterDatabaseResourceGroupRequest, AlterDatabaseResourceGroupResponse }
2774 ,{ ddl_client, alter_database_param, AlterDatabaseParamRequest, AlterDatabaseParamResponse }
2775 ,{ ddl_client, create_materialized_view, CreateMaterializedViewRequest, CreateMaterializedViewResponse }
2776 ,{ ddl_client, create_view, CreateViewRequest, CreateViewResponse }
2777 ,{ ddl_client, create_source, CreateSourceRequest, CreateSourceResponse }
2778 ,{ ddl_client, create_sink, CreateSinkRequest, CreateSinkResponse }
2779 ,{ ddl_client, create_subscription, CreateSubscriptionRequest, CreateSubscriptionResponse }
2780 ,{ ddl_client, create_schema, CreateSchemaRequest, CreateSchemaResponse }
2781 ,{ ddl_client, create_database, CreateDatabaseRequest, CreateDatabaseResponse }
2782 ,{ ddl_client, create_secret, CreateSecretRequest, CreateSecretResponse }
2783 ,{ ddl_client, create_index, CreateIndexRequest, CreateIndexResponse }
2784 ,{ ddl_client, create_function, CreateFunctionRequest, CreateFunctionResponse }
2785 ,{ ddl_client, drop_table, DropTableRequest, DropTableResponse }
2786 ,{ ddl_client, drop_materialized_view, DropMaterializedViewRequest, DropMaterializedViewResponse }
2787 ,{ ddl_client, drop_view, DropViewRequest, DropViewResponse }
2788 ,{ ddl_client, drop_source, DropSourceRequest, DropSourceResponse }
2789 ,{ ddl_client, reset_source, ResetSourceRequest, ResetSourceResponse }
2790 ,{ ddl_client, drop_secret, DropSecretRequest, DropSecretResponse}
2791 ,{ ddl_client, drop_sink, DropSinkRequest, DropSinkResponse }
2792 ,{ ddl_client, drop_subscription, DropSubscriptionRequest, DropSubscriptionResponse }
2793 ,{ ddl_client, drop_database, DropDatabaseRequest, DropDatabaseResponse }
2794 ,{ ddl_client, drop_schema, DropSchemaRequest, DropSchemaResponse }
2795 ,{ ddl_client, drop_index, DropIndexRequest, DropIndexResponse }
2796 ,{ ddl_client, drop_function, DropFunctionRequest, DropFunctionResponse }
2797 ,{ ddl_client, replace_job_plan, ReplaceJobPlanRequest, ReplaceJobPlanResponse }
2798 ,{ ddl_client, alter_source, AlterSourceRequest, AlterSourceResponse }
2799 ,{ ddl_client, risectl_list_state_tables, RisectlListStateTablesRequest, RisectlListStateTablesResponse }
2800 ,{ ddl_client, risectl_resume_backfill, RisectlResumeBackfillRequest, RisectlResumeBackfillResponse }
2801 ,{ ddl_client, get_ddl_progress, GetDdlProgressRequest, GetDdlProgressResponse }
2802 ,{ ddl_client, create_connection, CreateConnectionRequest, CreateConnectionResponse }
2803 ,{ ddl_client, list_connections, ListConnectionsRequest, ListConnectionsResponse }
2804 ,{ ddl_client, drop_connection, DropConnectionRequest, DropConnectionResponse }
2805 ,{ ddl_client, comment_on, CommentOnRequest, CommentOnResponse }
2806 ,{ ddl_client, get_tables, GetTablesRequest, GetTablesResponse }
2807 ,{ ddl_client, wait, WaitRequest, WaitResponse }
2808 ,{ ddl_client, auto_schema_change, AutoSchemaChangeRequest, AutoSchemaChangeResponse }
2809 ,{ ddl_client, alter_swap_rename, AlterSwapRenameRequest, AlterSwapRenameResponse }
2810 ,{ ddl_client, alter_secret, AlterSecretRequest, AlterSecretResponse }
2811 ,{ ddl_client, compact_iceberg_table, CompactIcebergTableRequest, CompactIcebergTableResponse }
2812 ,{ ddl_client, rewrite_iceberg_table_manifests, RewriteIcebergTableManifestsRequest, RewriteIcebergTableManifestsResponse }
2813 ,{ ddl_client, expire_iceberg_table_snapshots, ExpireIcebergTableSnapshotsRequest, ExpireIcebergTableSnapshotsResponse }
2814 ,{ ddl_client, remove_iceberg_table_orphan_files, RemoveIcebergTableOrphanFilesRequest, RemoveIcebergTableOrphanFilesResponse }
2815 ,{ ddl_client, create_iceberg_table, CreateIcebergTableRequest, CreateIcebergTableResponse }
2816 ,{ ddl_client, wait_iceberg_pk_index_sink_epoch, WaitIcebergPkIndexSinkEpochRequest, WaitIcebergPkIndexSinkEpochResponse }
2817 ,{ hummock_client, unpin_version_before, UnpinVersionBeforeRequest, UnpinVersionBeforeResponse }
2818 ,{ hummock_client, get_current_version, GetCurrentVersionRequest, GetCurrentVersionResponse }
2819 ,{ hummock_client, replay_version_delta, ReplayVersionDeltaRequest, ReplayVersionDeltaResponse }
2820 ,{ hummock_client, list_version_deltas, ListVersionDeltasRequest, ListVersionDeltasResponse }
2821 ,{ hummock_client, get_assigned_compact_task_num, GetAssignedCompactTaskNumRequest, GetAssignedCompactTaskNumResponse }
2822 ,{ hummock_client, trigger_compaction_deterministic, TriggerCompactionDeterministicRequest, TriggerCompactionDeterministicResponse }
2823 ,{ hummock_client, disable_commit_epoch, DisableCommitEpochRequest, DisableCommitEpochResponse }
2824 ,{ hummock_client, get_new_object_ids, GetNewObjectIdsRequest, GetNewObjectIdsResponse }
2825 ,{ hummock_client, trigger_manual_compaction, TriggerManualCompactionRequest, TriggerManualCompactionResponse }
2826 ,{ hummock_client, trigger_full_gc, TriggerFullGcRequest, TriggerFullGcResponse }
2827 ,{ hummock_client, rise_ctl_get_pinned_versions_summary, RiseCtlGetPinnedVersionsSummaryRequest, RiseCtlGetPinnedVersionsSummaryResponse }
2828 ,{ hummock_client, rise_ctl_list_compaction_group, RiseCtlListCompactionGroupRequest, RiseCtlListCompactionGroupResponse }
2829 ,{ hummock_client, rise_ctl_update_compaction_config, RiseCtlUpdateCompactionConfigRequest, RiseCtlUpdateCompactionConfigResponse }
2830 ,{ hummock_client, rise_ctl_get_checkpoint_version, RiseCtlGetCheckpointVersionRequest, RiseCtlGetCheckpointVersionResponse }
2831 ,{ hummock_client, rise_ctl_pause_version_checkpoint, RiseCtlPauseVersionCheckpointRequest, RiseCtlPauseVersionCheckpointResponse }
2832 ,{ hummock_client, rise_ctl_resume_version_checkpoint, RiseCtlResumeVersionCheckpointRequest, RiseCtlResumeVersionCheckpointResponse }
2833 ,{ hummock_client, init_metadata_for_replay, InitMetadataForReplayRequest, InitMetadataForReplayResponse }
2834 ,{ hummock_client, split_compaction_group, SplitCompactionGroupRequest, SplitCompactionGroupResponse }
2835 ,{ hummock_client, rise_ctl_list_compaction_status, RiseCtlListCompactionStatusRequest, RiseCtlListCompactionStatusResponse }
2836 ,{ hummock_client, get_compaction_score, GetCompactionScoreRequest, GetCompactionScoreResponse }
2837 ,{ hummock_client, rise_ctl_rebuild_table_stats, RiseCtlRebuildTableStatsRequest, RiseCtlRebuildTableStatsResponse }
2838 ,{ hummock_client, subscribe_compaction_event, impl tonic::IntoStreamingRequest<Message = SubscribeCompactionEventRequest>, Streaming<SubscribeCompactionEventResponse> }
2839 ,{ hummock_client, subscribe_iceberg_compaction_event, impl tonic::IntoStreamingRequest<Message = SubscribeIcebergCompactionEventRequest>, Streaming<SubscribeIcebergCompactionEventResponse> }
2840 ,{ hummock_client, list_branched_object, ListBranchedObjectRequest, ListBranchedObjectResponse }
2841 ,{ hummock_client, list_active_write_limit, ListActiveWriteLimitRequest, ListActiveWriteLimitResponse }
2842 ,{ hummock_client, list_hummock_meta_config, ListHummockMetaConfigRequest, ListHummockMetaConfigResponse }
2843 ,{ hummock_client, list_compact_task_assignment, ListCompactTaskAssignmentRequest, ListCompactTaskAssignmentResponse }
2844 ,{ hummock_client, list_compact_task_progress, ListCompactTaskProgressRequest, ListCompactTaskProgressResponse }
2845 ,{ hummock_client, cancel_compact_task, CancelCompactTaskRequest, CancelCompactTaskResponse}
2846 ,{ hummock_client, get_version_by_epoch, GetVersionByEpochRequest, GetVersionByEpochResponse }
2847 ,{ hummock_client, merge_compaction_group, MergeCompactionGroupRequest, MergeCompactionGroupResponse }
2848 ,{ hummock_client, get_table_change_logs, GetTableChangeLogsRequest, GetTableChangeLogsResponse }
2849 ,{ user_client, create_user, CreateUserRequest, CreateUserResponse }
2850 ,{ user_client, update_user, UpdateUserRequest, UpdateUserResponse }
2851 ,{ user_client, drop_user, DropUserRequest, DropUserResponse }
2852 ,{ user_client, grant_privilege, GrantPrivilegeRequest, GrantPrivilegeResponse }
2853 ,{ user_client, revoke_privilege, RevokePrivilegeRequest, RevokePrivilegeResponse }
2854 ,{ user_client, alter_default_privilege, AlterDefaultPrivilegeRequest, AlterDefaultPrivilegeResponse }
2855 ,{ scale_client, get_cluster_info, GetClusterInfoRequest, GetClusterInfoResponse }
2856 ,{ scale_client, reschedule, RescheduleRequest, RescheduleResponse }
2857 ,{ notification_client, subscribe, SubscribeRequest, Streaming<SubscribeResponse> }
2858 ,{ backup_client, backup_meta, BackupMetaRequest, BackupMetaResponse }
2859 ,{ backup_client, get_backup_job_status, GetBackupJobStatusRequest, GetBackupJobStatusResponse }
2860 ,{ backup_client, delete_meta_snapshot, DeleteMetaSnapshotRequest, DeleteMetaSnapshotResponse}
2861 ,{ backup_client, get_meta_snapshot_manifest, GetMetaSnapshotManifestRequest, GetMetaSnapshotManifestResponse}
2862 ,{ telemetry_client, get_telemetry_info, GetTelemetryInfoRequest, TelemetryInfoResponse}
2863 ,{ system_params_client, get_system_params, GetSystemParamsRequest, GetSystemParamsResponse }
2864 ,{ system_params_client, set_system_param, SetSystemParamRequest, SetSystemParamResponse }
2865 ,{ system_params_client, clear_file_cache, ClearFileCacheRequest, ClearFileCacheResponse }
2866 ,{ session_params_client, get_session_params, GetSessionParamsRequest, GetSessionParamsResponse }
2867 ,{ session_params_client, set_session_param, SetSessionParamRequest, SetSessionParamResponse }
2868 ,{ serving_client, get_serving_vnode_mappings, GetServingVnodeMappingsRequest, GetServingVnodeMappingsResponse }
2869 ,{ serving_client, warm_up_table_cache, WarmUpTableCacheRequest, WarmUpTableCacheResponse }
2870 ,{ cloud_client, rw_cloud_validate_source, RwCloudValidateSourceRequest, RwCloudValidateSourceResponse }
2871 ,{ event_log_client, list_event_log, ListEventLogRequest, ListEventLogResponse }
2872 ,{ event_log_client, add_event_log, AddEventLogRequest, AddEventLogResponse }
2873 ,{ cluster_limit_client, get_cluster_limits, GetClusterLimitsRequest, GetClusterLimitsResponse }
2874 ,{ hosted_iceberg_catalog_service_client, list_iceberg_tables, ListIcebergTablesRequest, ListIcebergTablesResponse }
2875 ,{ monitor_client, stack_trace, StackTraceRequest, StackTraceResponse }
2876 }
2877 };
2878}
2879
2880impl GrpcMetaClient {
2881 async fn refresh_client_if_needed(&self, code: Code) {
2882 if matches!(
2883 code,
2884 Code::Unknown | Code::Unimplemented | Code::Unavailable
2885 ) {
2886 tracing::debug!("matching tonic code {}", code);
2887 let (result_sender, result_receiver) = oneshot::channel();
2888 if self
2889 .member_monitor_event_sender
2890 .try_send(result_sender)
2891 .is_ok()
2892 {
2893 if let Ok(Err(e)) = result_receiver.await {
2894 tracing::warn!(error = %e.as_report(), "force refresh meta client failed");
2895 }
2896 } else {
2897 tracing::debug!("skipping the current refresh, somewhere else is already doing it")
2898 }
2899 }
2900 }
2901}
2902
2903impl GrpcMetaClient {
2904 for_all_meta_rpc! { meta_rpc_client_method_impl }
2905}