witchcraft_server/health/
mod.rs1pub use api::objects::HealthState;
16use conjure_object::Any;
17pub use registry::HealthCheckRegistry;
18use serde::Serialize;
19use staged_builder::staged_builder;
20use std::any::TypeId;
21use std::collections::BTreeMap;
22use std::sync::Arc;
23
24#[allow(warnings)]
25#[rustfmt::skip]
26pub(crate) mod api;
27pub(crate) mod config_reload;
28pub(crate) mod endpoint_500s;
29pub(crate) mod minidump;
30pub(crate) mod panics;
31mod registry;
32pub(crate) mod service_dependency;
33
34mod private {
35 pub struct PrivacyToken;
36}
37
38pub trait HealthCheck: 'static + Sync + Send {
40 fn type_(&self) -> &str;
44
45 fn result(&self) -> HealthCheckResult;
47
48 #[doc(hidden)]
52 fn __private_api_type_id(&self, _: private::PrivacyToken) -> TypeId
53 where
54 Self: 'static,
55 {
56 TypeId::of::<Self>()
57 }
58}
59
60impl dyn HealthCheck {
61 pub fn is<T>(&self) -> bool
63 where
64 T: HealthCheck,
65 {
66 self.__private_api_type_id(private::PrivacyToken) == TypeId::of::<T>()
67 }
68
69 pub fn downcast_ref<T>(&self) -> Option<&T>
71 where
72 T: HealthCheck,
73 {
74 if self.is::<T>() {
75 unsafe { Some(&*(self as *const dyn HealthCheck as *const T)) }
76 } else {
77 None
78 }
79 }
80
81 pub fn downcast_arc<T>(self: Arc<Self>) -> Result<Arc<T>, Arc<Self>>
83 where
84 T: HealthCheck,
85 {
86 if self.is::<T>() {
87 unsafe { Ok(Arc::from_raw(Arc::into_raw(self).cast::<T>())) }
88 } else {
89 Err(self)
90 }
91 }
92}
93
94#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
96#[staged_builder]
97pub struct HealthCheckResult {
98 state: HealthState,
99 #[builder(default, into)]
100 message: Option<String>,
101 #[builder(map(key(type = String, into), value(custom(type = impl Serialize, convert = serialize))))]
102 params: BTreeMap<String, Any>,
103}
104
105fn serialize(arg: impl Serialize) -> Any {
106 Any::new(arg).expect("value failed to serialize")
107}
108
109impl HealthCheckResult {
110 #[inline]
112 pub fn state(&self) -> &HealthState {
113 &self.state
114 }
115
116 #[inline]
119 pub fn message(&self) -> Option<&str> {
120 self.message.as_deref()
121 }
122
123 #[inline]
125 pub fn params(&self) -> &BTreeMap<String, Any> {
126 &self.params
127 }
128}