mz_adapter/catalog/
cluster_state.rs1use mz_adapter_types::cluster_state::{
19 AutoScalingPolicy, AvailabilityZones, BurstRecord, ClusterSchedule, ExpectedClusterState,
20 OnHydrationPolicy, OnTimeout, ReconfigurationRecord, ReconfigurationStatus,
21 ReconfigurationTarget,
22};
23use mz_catalog::memory::objects::{
24 BurstState, ClusterVariant, ClusterVariantManaged, ReconfigurationState,
25};
26use mz_controller_types::ClusterId;
27use mz_sql::plan::OnTimeoutAction;
28
29use crate::catalog::CatalogState;
30
31pub(crate) fn project_expected(managed: &ClusterVariantManaged) -> ExpectedClusterState {
34 let ClusterVariantManaged {
37 size,
38 availability_zones,
39 logging,
40 arrangement_compression,
41 replication_factor,
42 optimizer_feature_overrides: _,
43 schedule,
44 auto_scaling_strategy,
45 reconfiguration,
46 burst,
47 } = managed;
48 ExpectedClusterState {
49 size: size.clone(),
50 replication_factor: *replication_factor,
51 availability_zones: AvailabilityZones(availability_zones.clone()),
52 logging: logging.clone(),
53 arrangement_compression: *arrangement_compression,
54 schedule: cluster_schedule(schedule),
55 auto_scaling_policy: auto_scaling_strategy.as_ref().map(auto_scaling_policy),
56 reconfiguration: reconfiguration.as_ref().map(reconfiguration_record),
57 burst: burst.as_ref().map(burst_record),
58 }
59}
60
61pub(crate) fn cluster_matches_expected(
66 state: &CatalogState,
67 cluster_id: ClusterId,
68 expected: &ExpectedClusterState,
69) -> bool {
70 let Some(cluster) = state.try_get_cluster(cluster_id) else {
71 return false;
72 };
73 let ClusterVariant::Managed(managed) = &cluster.config.variant else {
74 return false;
75 };
76 project_expected(managed) == *expected
77}
78
79fn reconfiguration_record(record: &ReconfigurationState) -> ReconfigurationRecord {
80 let ReconfigurationState {
84 target,
85 deadline,
86 on_timeout: on_timeout_action,
87 status,
88 } = record;
89 let mz_catalog::memory::objects::ReconfigurationTarget {
90 size,
91 replication_factor,
92 availability_zones,
93 logging,
94 arrangement_compression,
95 } = target;
96 ReconfigurationRecord {
97 target: ReconfigurationTarget {
98 size: size.clone(),
99 replication_factor: *replication_factor,
100 availability_zones: AvailabilityZones(availability_zones.clone()),
101 logging: logging.clone(),
102 arrangement_compression: *arrangement_compression,
103 },
104 deadline: *deadline,
105 on_timeout: on_timeout(*on_timeout_action),
106 status: reconfiguration_status(*status),
107 }
108}
109
110fn reconfiguration_status(
111 status: mz_catalog::memory::objects::ReconfigurationStatus,
112) -> ReconfigurationStatus {
113 match status {
114 mz_catalog::memory::objects::ReconfigurationStatus::InProgress => {
115 ReconfigurationStatus::InProgress
116 }
117 mz_catalog::memory::objects::ReconfigurationStatus::Finalized => {
118 ReconfigurationStatus::Finalized
119 }
120 mz_catalog::memory::objects::ReconfigurationStatus::TimedOut => {
121 ReconfigurationStatus::TimedOut
122 }
123 mz_catalog::memory::objects::ReconfigurationStatus::Cancelled => {
124 ReconfigurationStatus::Cancelled
125 }
126 mz_catalog::memory::objects::ReconfigurationStatus::ResourceExhausted => {
127 ReconfigurationStatus::ResourceExhausted
128 }
129 }
130}
131
132fn on_timeout(action: OnTimeoutAction) -> OnTimeout {
133 match action {
134 OnTimeoutAction::Commit => OnTimeout::Commit,
135 OnTimeoutAction::Rollback => OnTimeout::Rollback,
136 }
137}
138
139fn cluster_schedule(schedule: &mz_sql::plan::ClusterSchedule) -> ClusterSchedule {
140 match schedule {
141 mz_sql::plan::ClusterSchedule::Manual => ClusterSchedule::Manual,
142 mz_sql::plan::ClusterSchedule::Refresh {
143 hydration_time_estimate,
144 } => ClusterSchedule::Refresh {
145 hydration_time_estimate: *hydration_time_estimate,
146 },
147 }
148}
149
150fn burst_record(record: &BurstState) -> BurstRecord {
151 let BurstState {
155 burst_size,
156 linger_duration,
157 steady_hydrated_at,
158 } = record;
159 BurstRecord {
160 burst_size: burst_size.clone(),
161 linger_duration: *linger_duration,
162 steady_hydrated_at: *steady_hydrated_at,
163 }
164}
165
166fn auto_scaling_policy(strategy: &mz_sql::plan::AutoScalingStrategy) -> AutoScalingPolicy {
167 let mz_sql::plan::AutoScalingStrategy { on_hydration } = strategy;
168 AutoScalingPolicy {
169 on_hydration: on_hydration.as_ref().map(|on_hydration| {
170 let mz_sql::plan::OnHydration {
171 hydration_size,
172 linger_duration,
173 } = on_hydration;
174 OnHydrationPolicy {
175 hydration_size: hydration_size.clone(),
176 linger_duration: *linger_duration,
177 }
178 }),
179 }
180}