use std::time::Duration;
use mssf_com::{
FabricClient::{IFabricHealthClient4, IFabricNodeHealthResult},
FabricTypes::{
FABRIC_APPLICATION_HEALTH_REPORT, FABRIC_CLUSTER_HEALTH_QUERY_DESCRIPTION,
FABRIC_CLUSTER_HEALTH_REPORT, FABRIC_DEPLOYED_APPLICATION_HEALTH_REPORT,
FABRIC_DEPLOYED_SERVICE_PACKAGE_HEALTH_REPORT, FABRIC_HEALTH_INFORMATION,
FABRIC_HEALTH_REPORT, FABRIC_HEALTH_REPORT_KIND_APPLICATION,
FABRIC_HEALTH_REPORT_KIND_CLUSTER, FABRIC_HEALTH_REPORT_KIND_DEPLOYED_APPLICATION,
FABRIC_HEALTH_REPORT_KIND_DEPLOYED_SERVICE_PACKAGE, FABRIC_HEALTH_REPORT_KIND_INVALID,
FABRIC_HEALTH_REPORT_KIND_NODE, FABRIC_HEALTH_REPORT_KIND_PARTITION,
FABRIC_HEALTH_REPORT_KIND_SERVICE, FABRIC_HEALTH_REPORT_KIND_STATEFUL_SERVICE_REPLICA,
FABRIC_HEALTH_REPORT_KIND_STATELESS_SERVICE_INSTANCE, FABRIC_NODE_HEALTH_QUERY_DESCRIPTION,
FABRIC_NODE_HEALTH_REPORT, FABRIC_PARTITION_HEALTH_REPORT, FABRIC_SERVICE_HEALTH_REPORT,
FABRIC_STATEFUL_SERVICE_REPLICA_HEALTH_REPORT,
FABRIC_STATELESS_SERVICE_INSTANCE_HEALTH_REPORT, FABRIC_URI,
},
};
use crate::{
mem::{BoxPool, GetRawWithBoxPool},
runtime::executor::BoxedCancelToken,
sync::{FabricReceiver, fabric_begin_end_proxy},
types::{ClusterHealth, HealthReport, NodeHealthQueryDescription, NodeHealthResult},
};
#[derive(Debug, Clone)]
pub struct HealthClient {
com: IFabricHealthClient4,
}
impl From<IFabricHealthClient4> for HealthClient {
fn from(value: IFabricHealthClient4) -> Self {
Self { com: value }
}
}
impl From<HealthClient> for IFabricHealthClient4 {
fn from(value: HealthClient) -> Self {
value.com
}
}
impl HealthClient {
pub fn report_health(&self, health_report: &HealthReport) -> crate::Result<()> {
match health_report {
HealthReport::Invalid => {
let fabric_health_report = FABRIC_HEALTH_REPORT {
Kind: FABRIC_HEALTH_REPORT_KIND_INVALID,
Value: std::ptr::null_mut(),
};
unsafe { self.com.ReportHealth(&fabric_health_report) }
}
HealthReport::StatefulServiceReplica(health_report) => {
let fabric_health_info =
FABRIC_HEALTH_INFORMATION::from(&health_report.health_information);
let fabric_health_report_value = FABRIC_STATEFUL_SERVICE_REPLICA_HEALTH_REPORT {
PartitionId: health_report.partition_id,
ReplicaId: health_report.replica_id,
HealthInformation: &fabric_health_info,
Reserved: std::ptr::null_mut(),
};
let fabric_health_report = FABRIC_HEALTH_REPORT {
Kind: FABRIC_HEALTH_REPORT_KIND_STATEFUL_SERVICE_REPLICA,
Value: &fabric_health_report_value as *const _ as *mut _,
};
unsafe { self.com.ReportHealth(&fabric_health_report) }
}
HealthReport::StatelessServiceInstance(health_report) => {
let fabric_health_info =
FABRIC_HEALTH_INFORMATION::from(&health_report.health_information);
let fabric_health_report_value = FABRIC_STATELESS_SERVICE_INSTANCE_HEALTH_REPORT {
PartitionId: health_report.partition_id,
InstanceId: health_report.instance_id,
HealthInformation: &fabric_health_info,
Reserved: std::ptr::null_mut(),
};
let fabric_health_report = FABRIC_HEALTH_REPORT {
Kind: FABRIC_HEALTH_REPORT_KIND_STATELESS_SERVICE_INSTANCE,
Value: &fabric_health_report_value as *const _ as *mut _,
};
unsafe { self.com.ReportHealth(&fabric_health_report) }
}
HealthReport::Partition(health_report) => {
let fabric_health_info =
FABRIC_HEALTH_INFORMATION::from(&health_report.health_information);
let fabric_health_report_value = FABRIC_PARTITION_HEALTH_REPORT {
PartitionId: health_report.partition_id,
HealthInformation: &fabric_health_info,
Reserved: std::ptr::null_mut(),
};
let fabric_health_report = FABRIC_HEALTH_REPORT {
Kind: FABRIC_HEALTH_REPORT_KIND_PARTITION,
Value: &fabric_health_report_value as *const _ as *mut _,
};
unsafe { self.com.ReportHealth(&fabric_health_report) }
}
HealthReport::Node(health_report) => {
let fabric_health_info =
FABRIC_HEALTH_INFORMATION::from(&health_report.health_information);
let fabric_health_report_value = FABRIC_NODE_HEALTH_REPORT {
NodeName: health_report.node_name.as_pcwstr(),
HealthInformation: &fabric_health_info,
Reserved: std::ptr::null_mut(),
};
let fabric_health_report = FABRIC_HEALTH_REPORT {
Kind: FABRIC_HEALTH_REPORT_KIND_NODE,
Value: &fabric_health_report_value as *const _ as *mut _,
};
unsafe { self.com.ReportHealth(&fabric_health_report) }
}
HealthReport::Service(health_report) => {
let fabric_health_info =
FABRIC_HEALTH_INFORMATION::from(&health_report.health_information);
let fabric_health_report_value = FABRIC_SERVICE_HEALTH_REPORT {
ServiceName: FABRIC_URI(health_report.service_name.as_ptr() as *mut u16),
HealthInformation: &fabric_health_info,
Reserved: std::ptr::null_mut(),
};
let fabric_health_report = FABRIC_HEALTH_REPORT {
Kind: FABRIC_HEALTH_REPORT_KIND_SERVICE,
Value: &fabric_health_report_value as *const _ as *mut _,
};
unsafe { self.com.ReportHealth(&fabric_health_report) }
}
HealthReport::Application(health_report) => {
let fabric_health_info =
FABRIC_HEALTH_INFORMATION::from(&health_report.health_information);
let fabric_health_report_value = FABRIC_APPLICATION_HEALTH_REPORT {
ApplicationName: FABRIC_URI(health_report.application_name.as_ptr() as *mut u16),
HealthInformation: &fabric_health_info,
Reserved: std::ptr::null_mut(),
};
let fabric_health_report = FABRIC_HEALTH_REPORT {
Kind: FABRIC_HEALTH_REPORT_KIND_APPLICATION,
Value: &fabric_health_report_value as *const _ as *mut _,
};
unsafe { self.com.ReportHealth(&fabric_health_report) }
}
HealthReport::DeployedApplication(health_report) => {
let fabric_health_info =
FABRIC_HEALTH_INFORMATION::from(&health_report.health_information);
let fabric_health_report_value = FABRIC_DEPLOYED_APPLICATION_HEALTH_REPORT {
ApplicationName: FABRIC_URI(health_report.application_name.as_ptr() as *mut u16),
NodeName: health_report.node_name.as_pcwstr(),
HealthInformation: &fabric_health_info,
Reserved: std::ptr::null_mut(),
};
let fabric_health_report = FABRIC_HEALTH_REPORT {
Kind: FABRIC_HEALTH_REPORT_KIND_DEPLOYED_APPLICATION,
Value: &fabric_health_report_value as *const _ as *mut _,
};
unsafe { self.com.ReportHealth(&fabric_health_report) }
}
HealthReport::DeployedServicePackage(health_report) => {
let fabric_health_info =
FABRIC_HEALTH_INFORMATION::from(&health_report.health_information);
let fabric_health_report_value = FABRIC_DEPLOYED_SERVICE_PACKAGE_HEALTH_REPORT {
ApplicationName: FABRIC_URI(health_report.application_name.as_ptr() as *mut u16),
ServiceManifestName: health_report.service_manifest_name.as_pcwstr(),
NodeName: health_report.node_name.as_pcwstr(),
HealthInformation: &fabric_health_info,
Reserved: std::ptr::null_mut(),
};
let fabric_health_report = FABRIC_HEALTH_REPORT {
Kind: FABRIC_HEALTH_REPORT_KIND_DEPLOYED_SERVICE_PACKAGE,
Value: &fabric_health_report_value as *const _ as *mut _,
};
unsafe { self.com.ReportHealth(&fabric_health_report) }
}
HealthReport::Cluster(health_report) => {
let fabric_health_info =
FABRIC_HEALTH_INFORMATION::from(&health_report.health_information);
let fabric_health_report_value = FABRIC_CLUSTER_HEALTH_REPORT {
HealthInformation: &fabric_health_info,
Reserved: std::ptr::null_mut(),
};
let fabric_health_report = FABRIC_HEALTH_REPORT {
Kind: FABRIC_HEALTH_REPORT_KIND_CLUSTER,
Value: &fabric_health_report_value as *const _ as *mut _,
};
unsafe { self.com.ReportHealth(&fabric_health_report) }
}
}.map_err(crate::Error::from)
}
}
impl HealthClient {
fn get_node_health_internal(
&self,
desc: &FABRIC_NODE_HEALTH_QUERY_DESCRIPTION,
timeout_milliseconds: u32,
cancellation_token: Option<BoxedCancelToken>,
) -> FabricReceiver<crate::WinResult<IFabricNodeHealthResult>> {
let com1 = &self.com;
let com2 = self.com.clone();
fabric_begin_end_proxy(
move |callback| unsafe {
com1.BeginGetNodeHealth2(desc, timeout_milliseconds, callback)
},
move |ctx| unsafe { com2.EndGetNodeHealth2(ctx) },
cancellation_token,
)
}
fn get_cluster_health_internal(
&self,
desc: &FABRIC_CLUSTER_HEALTH_QUERY_DESCRIPTION,
timeout_milliseconds: u32,
cancellation_token: Option<BoxedCancelToken>,
) -> FabricReceiver<crate::WinResult<mssf_com::FabricClient::IFabricClusterHealthResult>> {
let com1 = &self.com;
let com2 = self.com.clone();
fabric_begin_end_proxy(
move |callback| unsafe {
com1.BeginGetClusterHealth2(desc, timeout_milliseconds, callback)
},
move |ctx| unsafe { com2.EndGetClusterHealth2(ctx) },
cancellation_token,
)
}
fn get_application_health_internal(
&self,
desc: &mssf_com::FabricTypes::FABRIC_APPLICATION_HEALTH_QUERY_DESCRIPTION,
timeout_milliseconds: u32,
cancellation_token: Option<BoxedCancelToken>,
) -> FabricReceiver<crate::WinResult<mssf_com::FabricClient::IFabricApplicationHealthResult>>
{
let com1 = &self.com;
let com2 = self.com.clone();
fabric_begin_end_proxy(
move |callback| unsafe {
com1.BeginGetApplicationHealth2(desc, timeout_milliseconds, callback)
},
move |ctx| unsafe { com2.EndGetApplicationHealth2(ctx) },
cancellation_token,
)
}
fn get_partition_health_internal(
&self,
desc: &mssf_com::FabricTypes::FABRIC_PARTITION_HEALTH_QUERY_DESCRIPTION,
timeout_milliseconds: u32,
cancellation_token: Option<BoxedCancelToken>,
) -> FabricReceiver<crate::WinResult<mssf_com::FabricClient::IFabricPartitionHealthResult>>
{
let com1 = &self.com;
let com2 = self.com.clone();
fabric_begin_end_proxy(
move |callback| unsafe {
com1.BeginGetPartitionHealth2(desc, timeout_milliseconds, callback)
},
move |ctx| unsafe { com2.EndGetPartitionHealth2(ctx) },
cancellation_token,
)
}
fn get_service_health_internal(
&self,
desc: &mssf_com::FabricTypes::FABRIC_SERVICE_HEALTH_QUERY_DESCRIPTION,
timeout_milliseconds: u32,
cancellation_token: Option<BoxedCancelToken>,
) -> FabricReceiver<crate::WinResult<mssf_com::FabricClient::IFabricServiceHealthResult>> {
let com1 = &self.com;
let com2 = self.com.clone();
fabric_begin_end_proxy(
move |callback| unsafe {
com1.BeginGetServiceHealth2(desc, timeout_milliseconds, callback)
},
move |ctx| unsafe { com2.EndGetServiceHealth2(ctx) },
cancellation_token,
)
}
fn get_replica_health_internal(
&self,
desc: &mssf_com::FabricTypes::FABRIC_REPLICA_HEALTH_QUERY_DESCRIPTION,
timeout_milliseconds: u32,
cancellation_token: Option<BoxedCancelToken>,
) -> FabricReceiver<crate::WinResult<mssf_com::FabricClient::IFabricReplicaHealthResult>> {
let com1 = &self.com;
let com2 = self.com.clone();
fabric_begin_end_proxy(
move |callback| unsafe {
com1.BeginGetReplicaHealth2(desc, timeout_milliseconds, callback)
},
move |ctx| unsafe { com2.EndGetReplicaHealth2(ctx) },
cancellation_token,
)
}
}
impl HealthClient {
pub async fn get_node_health(
&self,
desc: &NodeHealthQueryDescription,
timeout: Duration,
cancellation_token: Option<BoxedCancelToken>,
) -> crate::Result<NodeHealthResult> {
let com = {
let mut pool = BoxPool::new();
let desc_raw = desc.get_raw_with_pool(&mut pool);
self.get_node_health_internal(&desc_raw, timeout.as_millis() as u32, cancellation_token)
}
.await??;
Ok(NodeHealthResult::from_com(&com))
}
pub async fn get_cluster_health(
&self,
desc: &crate::types::ClusterHealthQueryDescription,
timeout: Duration,
cancellation_token: Option<BoxedCancelToken>,
) -> crate::Result<ClusterHealth> {
let com = {
let mut pool = BoxPool::new();
let desc_raw = desc.get_raw_with_pool(&mut pool);
self.get_cluster_health_internal(
&desc_raw,
timeout.as_millis() as u32,
cancellation_token,
)
}
.await??;
Ok(ClusterHealth::from(&com))
}
pub async fn get_application_health(
&self,
desc: &crate::types::ApplicationHealthQueryDescription,
timeout: Duration,
cancellation_token: Option<BoxedCancelToken>,
) -> crate::Result<crate::types::ApplicationHealth> {
let com = {
let mut pool = BoxPool::new();
let desc_raw = desc.get_raw_with_pool(&mut pool);
self.get_application_health_internal(
&desc_raw,
timeout.as_millis() as u32,
cancellation_token,
)
}
.await??;
Ok(crate::types::ApplicationHealth::from(&com))
}
pub async fn get_partition_health(
&self,
desc: &crate::types::PartitionHealthQueryDescription,
timeout: Duration,
cancellation_token: Option<BoxedCancelToken>,
) -> crate::Result<crate::types::PartitionHealthResult> {
let com = {
let mut pool = BoxPool::new();
let desc_raw = desc.get_raw_with_pool(&mut pool);
self.get_partition_health_internal(
&desc_raw,
timeout.as_millis() as u32,
cancellation_token,
)
}
.await??;
Ok(crate::types::PartitionHealthResult::from(&com))
}
pub async fn get_service_health(
&self,
desc: &crate::types::ServiceHealthQueryDescription,
timeout: Duration,
cancellation_token: Option<BoxedCancelToken>,
) -> crate::Result<crate::types::ServiceHealthResult> {
let com = {
let mut pool = BoxPool::new();
let desc_raw = desc.get_raw_with_pool(&mut pool);
self.get_service_health_internal(
&desc_raw,
timeout.as_millis() as u32,
cancellation_token,
)
}
.await??;
Ok(crate::types::ServiceHealthResult::from(&com))
}
pub async fn get_replica_health(
&self,
desc: &crate::types::ReplicaHealthQueryDescription,
timeout: Duration,
cancellation_token: Option<BoxedCancelToken>,
) -> crate::Result<crate::types::ReplicaHealthResult> {
let com = {
let mut pool = BoxPool::new();
let desc_raw = desc.get_raw_with_pool(&mut pool);
self.get_replica_health_internal(
&desc_raw,
timeout.as_millis() as u32,
cancellation_token,
)
}
.await??;
Ok(crate::types::ReplicaHealthResult::from(&com))
}
}