1use std::time::Duration;
7
8use mssf_com::{
9 FabricClient::{IFabricHealthClient4, IFabricNodeHealthResult},
10 FabricTypes::{
11 FABRIC_APPLICATION_HEALTH_REPORT, FABRIC_CLUSTER_HEALTH_POLICY,
12 FABRIC_CLUSTER_HEALTH_QUERY_DESCRIPTION, FABRIC_CLUSTER_HEALTH_REPORT,
13 FABRIC_DEPLOYED_APPLICATION_HEALTH_REPORT, FABRIC_DEPLOYED_SERVICE_PACKAGE_HEALTH_REPORT,
14 FABRIC_HEALTH_INFORMATION, FABRIC_HEALTH_REPORT, FABRIC_HEALTH_REPORT_KIND_APPLICATION,
15 FABRIC_HEALTH_REPORT_KIND_CLUSTER, FABRIC_HEALTH_REPORT_KIND_DEPLOYED_APPLICATION,
16 FABRIC_HEALTH_REPORT_KIND_DEPLOYED_SERVICE_PACKAGE, FABRIC_HEALTH_REPORT_KIND_INVALID,
17 FABRIC_HEALTH_REPORT_KIND_NODE, FABRIC_HEALTH_REPORT_KIND_PARTITION,
18 FABRIC_HEALTH_REPORT_KIND_SERVICE, FABRIC_HEALTH_REPORT_KIND_STATEFUL_SERVICE_REPLICA,
19 FABRIC_HEALTH_REPORT_KIND_STATELESS_SERVICE_INSTANCE, FABRIC_NODE_HEALTH_QUERY_DESCRIPTION,
20 FABRIC_NODE_HEALTH_REPORT, FABRIC_PARTITION_HEALTH_REPORT, FABRIC_SERVICE_HEALTH_REPORT,
21 FABRIC_STATEFUL_SERVICE_REPLICA_HEALTH_REPORT,
22 FABRIC_STATELESS_SERVICE_INSTANCE_HEALTH_REPORT, FABRIC_URI,
23 },
24};
25
26use crate::{
27 mem::{BoxPool, GetRawWithBoxPool},
28 runtime::executor::BoxedCancelToken,
29 sync::{FabricReceiver, fabric_begin_end_proxy},
30 types::{ClusterHealth, HealthReport, NodeHealthQueryDescription, NodeHealthResult},
31};
32
33#[derive(Debug, Clone)]
38pub struct HealthClient {
39 com: IFabricHealthClient4,
40}
41
42impl From<IFabricHealthClient4> for HealthClient {
43 fn from(value: IFabricHealthClient4) -> Self {
44 Self { com: value }
45 }
46}
47
48impl From<HealthClient> for IFabricHealthClient4 {
49 fn from(value: HealthClient) -> Self {
50 value.com
51 }
52}
53
54impl HealthClient {
56 pub fn report_health(&self, health_report: &HealthReport) -> crate::Result<()> {
63 match health_report {
64 HealthReport::Invalid => {
65 let fabric_health_report = FABRIC_HEALTH_REPORT {
66 Kind: FABRIC_HEALTH_REPORT_KIND_INVALID,
67 Value: std::ptr::null_mut(),
68 };
69 unsafe { self.com.ReportHealth(&fabric_health_report) }
70 }
71 HealthReport::StatefulServiceReplica(health_report) => {
72 let fabric_health_info =
73 FABRIC_HEALTH_INFORMATION::from(&health_report.health_information);
74 let fabric_health_report_value = FABRIC_STATEFUL_SERVICE_REPLICA_HEALTH_REPORT {
75 PartitionId: health_report.partition_id,
76 ReplicaId: health_report.replica_id,
77 HealthInformation: &fabric_health_info,
78 Reserved: std::ptr::null_mut(),
79 };
80 let fabric_health_report = FABRIC_HEALTH_REPORT {
81 Kind: FABRIC_HEALTH_REPORT_KIND_STATEFUL_SERVICE_REPLICA,
82 Value: &fabric_health_report_value as *const _ as *mut _,
83 };
84 unsafe { self.com.ReportHealth(&fabric_health_report) }
85 }
86 HealthReport::StatelessServiceInstance(health_report) => {
87 let fabric_health_info =
88 FABRIC_HEALTH_INFORMATION::from(&health_report.health_information);
89 let fabric_health_report_value = FABRIC_STATELESS_SERVICE_INSTANCE_HEALTH_REPORT {
90 PartitionId: health_report.partition_id,
91 InstanceId: health_report.instance_id,
92 HealthInformation: &fabric_health_info,
93 Reserved: std::ptr::null_mut(),
94 };
95 let fabric_health_report = FABRIC_HEALTH_REPORT {
96 Kind: FABRIC_HEALTH_REPORT_KIND_STATELESS_SERVICE_INSTANCE,
97 Value: &fabric_health_report_value as *const _ as *mut _,
98 };
99 unsafe { self.com.ReportHealth(&fabric_health_report) }
100 }
101 HealthReport::Partition(health_report) => {
102 let fabric_health_info =
103 FABRIC_HEALTH_INFORMATION::from(&health_report.health_information);
104 let fabric_health_report_value = FABRIC_PARTITION_HEALTH_REPORT {
105 PartitionId: health_report.partition_id,
106 HealthInformation: &fabric_health_info,
107 Reserved: std::ptr::null_mut(),
108 };
109 let fabric_health_report = FABRIC_HEALTH_REPORT {
110 Kind: FABRIC_HEALTH_REPORT_KIND_PARTITION,
111 Value: &fabric_health_report_value as *const _ as *mut _,
112 };
113 unsafe { self.com.ReportHealth(&fabric_health_report) }
114 }
115 HealthReport::Node(health_report) => {
116 let fabric_health_info =
117 FABRIC_HEALTH_INFORMATION::from(&health_report.health_information);
118 let fabric_health_report_value = FABRIC_NODE_HEALTH_REPORT {
119 NodeName: health_report.node_name.as_pcwstr(),
120 HealthInformation: &fabric_health_info,
121 Reserved: std::ptr::null_mut(),
122 };
123 let fabric_health_report = FABRIC_HEALTH_REPORT {
124 Kind: FABRIC_HEALTH_REPORT_KIND_NODE,
125 Value: &fabric_health_report_value as *const _ as *mut _,
126 };
127 unsafe { self.com.ReportHealth(&fabric_health_report) }
128 }
129 HealthReport::Service(health_report) => {
130 let fabric_health_info =
131 FABRIC_HEALTH_INFORMATION::from(&health_report.health_information);
132 let fabric_health_report_value = FABRIC_SERVICE_HEALTH_REPORT {
133 ServiceName: FABRIC_URI(health_report.service_name.as_ptr() as *mut u16),
134 HealthInformation: &fabric_health_info,
135 Reserved: std::ptr::null_mut(),
136 };
137 let fabric_health_report = FABRIC_HEALTH_REPORT {
138 Kind: FABRIC_HEALTH_REPORT_KIND_SERVICE,
139 Value: &fabric_health_report_value as *const _ as *mut _,
140 };
141 unsafe { self.com.ReportHealth(&fabric_health_report) }
142 }
143 HealthReport::Application(health_report) => {
144 let fabric_health_info =
145 FABRIC_HEALTH_INFORMATION::from(&health_report.health_information);
146 let fabric_health_report_value = FABRIC_APPLICATION_HEALTH_REPORT {
147 ApplicationName: FABRIC_URI(health_report.application_name.as_ptr() as *mut u16),
148 HealthInformation: &fabric_health_info,
149 Reserved: std::ptr::null_mut(),
150 };
151 let fabric_health_report = FABRIC_HEALTH_REPORT {
152 Kind: FABRIC_HEALTH_REPORT_KIND_APPLICATION,
153 Value: &fabric_health_report_value as *const _ as *mut _,
154 };
155 unsafe { self.com.ReportHealth(&fabric_health_report) }
156 }
157 HealthReport::DeployedApplication(health_report) => {
158 let fabric_health_info =
159 FABRIC_HEALTH_INFORMATION::from(&health_report.health_information);
160 let fabric_health_report_value = FABRIC_DEPLOYED_APPLICATION_HEALTH_REPORT {
161 ApplicationName: FABRIC_URI(health_report.application_name.as_ptr() as *mut u16),
162 NodeName: health_report.node_name.as_pcwstr(),
163 HealthInformation: &fabric_health_info,
164 Reserved: std::ptr::null_mut(),
165 };
166 let fabric_health_report = FABRIC_HEALTH_REPORT {
167 Kind: FABRIC_HEALTH_REPORT_KIND_DEPLOYED_APPLICATION,
168 Value: &fabric_health_report_value as *const _ as *mut _,
169 };
170 unsafe { self.com.ReportHealth(&fabric_health_report) }
171 }
172 HealthReport::DeployedServicePackage(health_report) => {
173 let fabric_health_info =
174 FABRIC_HEALTH_INFORMATION::from(&health_report.health_information);
175 let fabric_health_report_value = FABRIC_DEPLOYED_SERVICE_PACKAGE_HEALTH_REPORT {
176 ApplicationName: FABRIC_URI(health_report.application_name.as_ptr() as *mut u16),
177 ServiceManifestName: health_report.service_manifest_name.as_pcwstr(),
178 NodeName: health_report.node_name.as_pcwstr(),
179 HealthInformation: &fabric_health_info,
180 Reserved: std::ptr::null_mut(),
181 };
182 let fabric_health_report = FABRIC_HEALTH_REPORT {
183 Kind: FABRIC_HEALTH_REPORT_KIND_DEPLOYED_SERVICE_PACKAGE,
184 Value: &fabric_health_report_value as *const _ as *mut _,
185 };
186 unsafe { self.com.ReportHealth(&fabric_health_report) }
187 }
188 HealthReport::Cluster(health_report) => {
189 let fabric_health_info =
190 FABRIC_HEALTH_INFORMATION::from(&health_report.health_information);
191 let fabric_health_report_value = FABRIC_CLUSTER_HEALTH_REPORT {
192 HealthInformation: &fabric_health_info,
193 Reserved: std::ptr::null_mut(),
194 };
195 let fabric_health_report = FABRIC_HEALTH_REPORT {
196 Kind: FABRIC_HEALTH_REPORT_KIND_CLUSTER,
197 Value: &fabric_health_report_value as *const _ as *mut _,
198 };
199 unsafe { self.com.ReportHealth(&fabric_health_report) }
200 }
201 }.map_err(crate::Error::from)
202 }
203}
204
205impl HealthClient {
206 fn get_node_health_internal(
207 &self,
208 desc: &FABRIC_NODE_HEALTH_QUERY_DESCRIPTION,
209 timeout_milliseconds: u32,
210 cancellation_token: Option<BoxedCancelToken>,
211 ) -> FabricReceiver<crate::WinResult<IFabricNodeHealthResult>> {
212 let com1 = &self.com;
213 let com2 = self.com.clone();
214 fabric_begin_end_proxy(
215 move |callback| unsafe {
216 com1.BeginGetNodeHealth2(desc, timeout_milliseconds, callback)
217 },
218 move |ctx| unsafe { com2.EndGetNodeHealth2(ctx) },
219 cancellation_token,
220 )
221 }
222
223 fn get_cluster_health_internal(
224 &self,
225 desc: &FABRIC_CLUSTER_HEALTH_QUERY_DESCRIPTION,
226 timeout_milliseconds: u32,
227 cancellation_token: Option<BoxedCancelToken>,
228 ) -> FabricReceiver<crate::WinResult<mssf_com::FabricClient::IFabricClusterHealthResult>> {
229 let com1 = &self.com;
230 let com2 = self.com.clone();
231 fabric_begin_end_proxy(
232 move |callback| unsafe {
233 com1.BeginGetClusterHealth2(desc, timeout_milliseconds, callback)
234 },
235 move |ctx| unsafe { com2.EndGetClusterHealth2(ctx) },
236 cancellation_token,
237 )
238 }
239
240 fn get_application_health_internal(
241 &self,
242 desc: &mssf_com::FabricTypes::FABRIC_APPLICATION_HEALTH_QUERY_DESCRIPTION,
243 timeout_milliseconds: u32,
244 cancellation_token: Option<BoxedCancelToken>,
245 ) -> FabricReceiver<crate::WinResult<mssf_com::FabricClient::IFabricApplicationHealthResult>>
246 {
247 let com1 = &self.com;
248 let com2 = self.com.clone();
249 fabric_begin_end_proxy(
250 move |callback| unsafe {
251 com1.BeginGetApplicationHealth2(desc, timeout_milliseconds, callback)
252 },
253 move |ctx| unsafe { com2.EndGetApplicationHealth2(ctx) },
254 cancellation_token,
255 )
256 }
257 fn get_partition_health_internal(
258 &self,
259 desc: &mssf_com::FabricTypes::FABRIC_PARTITION_HEALTH_QUERY_DESCRIPTION,
260 timeout_milliseconds: u32,
261 cancellation_token: Option<BoxedCancelToken>,
262 ) -> FabricReceiver<crate::WinResult<mssf_com::FabricClient::IFabricPartitionHealthResult>>
263 {
264 let com1 = &self.com;
265 let com2 = self.com.clone();
266 fabric_begin_end_proxy(
267 move |callback| unsafe {
268 com1.BeginGetPartitionHealth2(desc, timeout_milliseconds, callback)
269 },
270 move |ctx| unsafe { com2.EndGetPartitionHealth2(ctx) },
271 cancellation_token,
272 )
273 }
274 fn get_service_health_internal(
275 &self,
276 desc: &mssf_com::FabricTypes::FABRIC_SERVICE_HEALTH_QUERY_DESCRIPTION,
277 timeout_milliseconds: u32,
278 cancellation_token: Option<BoxedCancelToken>,
279 ) -> FabricReceiver<crate::WinResult<mssf_com::FabricClient::IFabricServiceHealthResult>> {
280 let com1 = &self.com;
281 let com2 = self.com.clone();
282 fabric_begin_end_proxy(
283 move |callback| unsafe {
284 com1.BeginGetServiceHealth2(desc, timeout_milliseconds, callback)
285 },
286 move |ctx| unsafe { com2.EndGetServiceHealth2(ctx) },
287 cancellation_token,
288 )
289 }
290 fn get_replica_health_internal(
291 &self,
292 desc: &mssf_com::FabricTypes::FABRIC_REPLICA_HEALTH_QUERY_DESCRIPTION,
293 timeout_milliseconds: u32,
294 cancellation_token: Option<BoxedCancelToken>,
295 ) -> FabricReceiver<crate::WinResult<mssf_com::FabricClient::IFabricReplicaHealthResult>> {
296 let com1 = &self.com;
297 let com2 = self.com.clone();
298 fabric_begin_end_proxy(
299 move |callback| unsafe {
300 com1.BeginGetReplicaHealth2(desc, timeout_milliseconds, callback)
301 },
302 move |ctx| unsafe { com2.EndGetReplicaHealth2(ctx) },
303 cancellation_token,
304 )
305 }
306}
307
308impl HealthClient {
309 pub async fn get_node_health(
313 &self,
314 desc: &NodeHealthQueryDescription,
315 timeout: Duration,
316 cancellation_token: Option<BoxedCancelToken>,
317 ) -> crate::Result<NodeHealthResult> {
318 let com = {
319 let health_policy_raw =
320 desc.health_policy
321 .as_ref()
322 .map(|h| FABRIC_CLUSTER_HEALTH_POLICY {
323 ConsiderWarningAsError: h.consider_warning_as_error,
324 MaxPercentUnhealthyNodes: h.max_percent_unhealthy_nodes,
325 MaxPercentUnhealthyApplications: h.max_percent_unhealthy_applications,
326 Reserved: std::ptr::null_mut(),
327 });
328 let event_filter_raw = desc.events_filter.as_ref().map(|f| {
329 mssf_com::FabricTypes::FABRIC_HEALTH_EVENTS_FILTER {
330 HealthStateFilter: f.health_state_filter.bits() as u32,
331 Reserved: std::ptr::null_mut(),
332 }
333 });
334 let desc_raw = mssf_com::FabricTypes::FABRIC_NODE_HEALTH_QUERY_DESCRIPTION {
335 NodeName: desc.node_name.as_pcwstr(),
336 HealthPolicy: health_policy_raw
337 .as_ref()
338 .map_or(std::ptr::null_mut(), |h| h as *const _ as *mut _),
339 EventsFilter: event_filter_raw
340 .as_ref()
341 .map_or(std::ptr::null_mut(), |f| f as *const _ as *mut _),
342 Reserved: std::ptr::null_mut(),
343 };
344 self.get_node_health_internal(&desc_raw, timeout.as_millis() as u32, cancellation_token)
345 }
346 .await??;
347 Ok(NodeHealthResult::from_com(&com))
348 }
349
350 pub async fn get_cluster_health(
352 &self,
353 desc: &crate::types::ClusterHealthQueryDescription,
354 timeout: Duration,
355 cancellation_token: Option<BoxedCancelToken>,
356 ) -> crate::Result<ClusterHealth> {
357 let com = {
358 let mut pool = BoxPool::new();
360 let desc_raw = desc.get_raw_with_pool(&mut pool);
361 self.get_cluster_health_internal(
362 &desc_raw,
363 timeout.as_millis() as u32,
364 cancellation_token,
365 )
366 }
367 .await??;
368 Ok(ClusterHealth::from(&com))
369 }
370
371 pub async fn get_application_health(
373 &self,
374 desc: &crate::types::ApplicationHealthQueryDescription,
375 timeout: Duration,
376 cancellation_token: Option<BoxedCancelToken>,
377 ) -> crate::Result<crate::types::ApplicationHealth> {
378 let com = {
379 let mut pool = BoxPool::new();
380 let desc_raw = desc.get_raw_with_pool(&mut pool);
381 self.get_application_health_internal(
382 &desc_raw,
383 timeout.as_millis() as u32,
384 cancellation_token,
385 )
386 }
387 .await??;
388 Ok(crate::types::ApplicationHealth::from(&com))
389 }
390
391 pub async fn get_partition_health(
392 &self,
393 desc: &crate::types::PartitionHealthQueryDescription,
394 timeout: Duration,
395 cancellation_token: Option<BoxedCancelToken>,
396 ) -> crate::Result<crate::types::PartitionHealthResult> {
397 let com = {
398 let mut pool = BoxPool::new();
399 let desc_raw = desc.get_raw_with_pool(&mut pool);
400 self.get_partition_health_internal(
401 &desc_raw,
402 timeout.as_millis() as u32,
403 cancellation_token,
404 )
405 }
406 .await??;
407 Ok(crate::types::PartitionHealthResult::from(&com))
408 }
409
410 pub async fn get_service_health(
412 &self,
413 desc: &crate::types::ServiceHealthQueryDescription,
414 timeout: Duration,
415 cancellation_token: Option<BoxedCancelToken>,
416 ) -> crate::Result<crate::types::ServiceHealthResult> {
417 let com = {
418 let mut pool = BoxPool::new();
419 let desc_raw = desc.get_raw_with_pool(&mut pool);
420 self.get_service_health_internal(
421 &desc_raw,
422 timeout.as_millis() as u32,
423 cancellation_token,
424 )
425 }
426 .await??;
427 Ok(crate::types::ServiceHealthResult::from(&com))
428 }
429
430 pub async fn get_replica_health(
432 &self,
433 desc: &crate::types::ReplicaHealthQueryDescription,
434 timeout: Duration,
435 cancellation_token: Option<BoxedCancelToken>,
436 ) -> crate::Result<crate::types::ReplicaHealthResult> {
437 let com = {
438 let mut pool = BoxPool::new();
439 let desc_raw = desc.get_raw_with_pool(&mut pool);
440 self.get_replica_health_internal(
441 &desc_raw,
442 timeout.as_millis() as u32,
443 cancellation_token,
444 )
445 }
446 .await??;
447 Ok(crate::types::ReplicaHealthResult::from(&com))
448 }
449}