risingwave_meta/manager/iceberg_compaction/
manual.rs1use anyhow::anyhow;
16use risingwave_connector::sink::catalog::SinkId;
17use risingwave_pb::iceberg_compaction::subscribe_iceberg_compaction_event_request::ReportTask as IcebergReportTask;
18use risingwave_pb::iceberg_compaction::subscribe_iceberg_compaction_event_request::report_task::Status as IcebergReportTaskStatus;
19use risingwave_pb::id::IcebergCompactionTaskId;
20
21use super::*;
22
23impl IcebergCompactionManager {
24 pub(super) fn complete_manual_task_waiter(
25 waiter: ManualCompactionWaiter,
26 report: &IcebergReportTask,
27 ) {
28 let status = IcebergReportTaskStatus::try_from(report.status)
29 .unwrap_or(IcebergReportTaskStatus::Unspecified);
30 let result = match status {
31 IcebergReportTaskStatus::Success => Ok(report.task_id),
32 IcebergReportTaskStatus::Drained
33 | IcebergReportTaskStatus::Busy
34 | IcebergReportTaskStatus::BlockedCapacity
35 | IcebergReportTaskStatus::BlockedStatistics
36 | IcebergReportTaskStatus::Failed
37 | IcebergReportTaskStatus::Unspecified => {
38 let message = report
39 .error_message
40 .clone()
41 .unwrap_or_else(|| "manual iceberg compaction failed".to_owned());
42 Err(anyhow!(
43 "Manual iceberg compaction task {} for sink {} failed: {}",
44 report.task_id,
45 report.sink_id,
46 message
47 )
48 .into())
49 }
50 };
51
52 let _ = waiter.send(result);
53 }
54
55 pub async fn trigger_manual_compaction(
56 &self,
57 sink_id: SinkId,
58 ) -> MetaResult<IcebergCompactionTaskId> {
59 if self.iceberg_compactor_manager.compactor_num() == 0 {
62 return Err(anyhow!("No iceberg compactor available").into());
63 }
64
65 let waiter = self.start_manual_compaction(sink_id).await?;
66 let mut cleanup_guard = scopeguard::guard(Some(waiter), |waiter| {
69 drop(waiter);
70 self.cancel_closed_manual_compaction_waiter(sink_id);
71 });
72
73 tracing::info!(
74 "Manual compaction requested for sink {}, waiting for completion...",
75 sink_id
76 );
77
78 match cleanup_guard.as_mut().unwrap().await {
79 Ok(result) => {
80 let _ = scopeguard::ScopeGuard::into_inner(cleanup_guard);
81 result
82 }
83 Err(_) => {
84 let _ = scopeguard::ScopeGuard::into_inner(cleanup_guard);
85 Err(anyhow!(
86 "Manual iceberg compaction waiter dropped unexpectedly for sink {}",
87 sink_id,
88 )
89 .into())
90 }
91 }
92 }
93
94 pub(super) fn cancel_closed_manual_compaction_waiter(&self, sink_id: SinkId) {
95 let mut guard = self.inner.write();
96 if guard
97 .manual_compaction_waiters
98 .get(&sink_id)
99 .is_some_and(|sender| sender.is_closed())
100 {
101 guard.manual_compaction_waiters.remove(&sink_id);
102 }
103 }
104}