Skip to content

Commit

Permalink
Health Check service
Browse files Browse the repository at this point in the history
  • Loading branch information
lemaitre-aneo committed Dec 11, 2024
1 parent 3351efc commit db6062d
Show file tree
Hide file tree
Showing 13 changed files with 269 additions and 15 deletions.
28 changes: 14 additions & 14 deletions packages/rust/armonik/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/rust/armonik/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ license = "Apache-2.0"
readme = "README.md"
name = "armonik"
repository = "https://github.com/aneoconsulting/ArmoniK.Api"
version = "3.21.0-beta-2"
version = "3.21.0-beta-3"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

Expand Down
2 changes: 2 additions & 0 deletions packages/rust/armonik/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
"protos/V1/events_service.proto",
"protos/V1/filters_common.proto",
"protos/V1/objects.proto",
"protos/V1/health_checks_common.proto",
"protos/V1/health_checks_service.proto",
"protos/V1/partitions_common.proto",
"protos/V1/partitions_fields.proto",
"protos/V1/partitions_filters.proto",
Expand Down
3 changes: 3 additions & 0 deletions packages/rust/armonik/src/api/v3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ pub mod auth {
pub mod events {
tonic::include_proto!("armonik.api.grpc.v1.events");
}
pub mod health_checks {
tonic::include_proto!("armonik.api.grpc.v1.health_checks");
}
pub mod partitions {
tonic::include_proto!("armonik.api.grpc.v1.partitions");
}
Expand Down
91 changes: 91 additions & 0 deletions packages/rust/armonik/src/client/health_checks.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
use snafu::ResultExt;

use crate::api::v3;
use crate::health_checks::check;

use super::GrpcCall;

/// Service for authentication management.
#[derive(Clone)]
pub struct HealthChecksClient<T> {
inner: v3::health_checks::health_checks_service_client::HealthChecksServiceClient<T>,
}

impl<T> HealthChecksClient<T>
where
T: tonic::client::GrpcService<tonic::body::BoxBody>,
T::Error: Into<tonic::codegen::StdError>,
T::ResponseBody: tonic::codegen::Body<Data = tonic::codegen::Bytes> + Send + 'static,
<T::ResponseBody as tonic::codegen::Body>::Error: Into<tonic::codegen::StdError> + Send,
{
/// Build a client from a gRPC channel
pub fn with_channel(channel: T) -> Self {
Self {
inner: v3::health_checks::health_checks_service_client::HealthChecksServiceClient::new(
channel,
),
}
}

/// Checks the health of the cluster. This can be used to verify that the cluster is up and running.
pub async fn check(
&mut self,
) -> Result<Vec<crate::health_checks::ServiceHealth>, super::RequestError> {
Ok(self.call(check::Request {}).await?.services)
}

/// Perform a gRPC call from a raw request.
pub async fn call<Request>(
&mut self,
request: Request,
) -> Result<<&mut Self as GrpcCall<Request>>::Response, <&mut Self as GrpcCall<Request>>::Error>
where
for<'a> &'a mut Self: GrpcCall<Request>,
{
<&mut Self as GrpcCall<Request>>::call(self, request).await
}
}

super::impl_call! {
HealthChecksClient {
async fn call(self, request: check::Request) -> Result<check::Response> {
Ok(self
.inner
.check_health(request)
.await
.context(super::GrpcSnafu {})?
.into_inner()
.into())
}
}
}

#[cfg(test)]
#[serial_test::serial(auth)]
mod tests {
use crate::Client;

// Named methods

#[tokio::test]
async fn check() {
let before = Client::get_nb_request("HealthChecksService", "CheckHealth").await;
let mut client = Client::new().await.unwrap().health_checks();
client.check().await.unwrap();
let after = Client::get_nb_request("HealthChecksService", "CheckHealth").await;
assert_eq!(after - before, 1);
}
// Explicit call request

#[tokio::test]
async fn check_call() {
let before = Client::get_nb_request("HealthChecksService", "CheckHealth").await;
let mut client = Client::new().await.unwrap().health_checks();
client
.call(crate::health_checks::check::Request {})
.await
.unwrap();
let after = Client::get_nb_request("HealthChecksService", "CheckHealth").await;
assert_eq!(after - before, 1);
}
}
15 changes: 15 additions & 0 deletions packages/rust/armonik/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ mod config;
#[cfg(feature = "client")]
mod events;
#[cfg(feature = "client")]
mod health_checks;
#[cfg(feature = "client")]
mod partitions;
#[cfg(feature = "client")]
mod results;
Expand All @@ -42,6 +44,8 @@ pub use config::{ClientConfig, ClientConfigArgs, ConfigError};
#[cfg(feature = "client")]
pub use events::EventsClient;
#[cfg(feature = "client")]
pub use health_checks::HealthChecksClient;
#[cfg(feature = "client")]
pub use partitions::PartitionsClient;
#[cfg(feature = "client")]
pub use results::ResultsClient;
Expand Down Expand Up @@ -257,6 +261,17 @@ where
EventsClient::with_channel(self.channel)
}

#[cfg(feature = "client")]
/// Create a [`HealthChecksClient`]
pub fn health_checks(&self) -> HealthChecksClient<T> {
HealthChecksClient::with_channel(self.channel.clone())
}
#[cfg(feature = "client")]
/// Create a [`HealthChecksClient`]
pub fn into_health_checks(self) -> HealthChecksClient<T> {
HealthChecksClient::with_channel(self.channel)
}

#[cfg(feature = "client")]
/// Create a [`PartitionsClient`]
pub fn partitions(&self) -> PartitionsClient<T> {
Expand Down
24 changes: 24 additions & 0 deletions packages/rust/armonik/src/objects/health_checks/check.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use crate::api::v3;

use super::ServiceHealth;

/// Request to check if all services are healthy.
#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Request {}

super::super::impl_convert!(
struct Request = v3::health_checks::CheckHealthRequest {
}
);

/// Response to check if all services are healthy.
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct Response {
pub services: Vec<ServiceHealth>,
}

super::super::impl_convert!(
struct Response = v3::health_checks::CheckHealthResponse {
list services,
}
);
9 changes: 9 additions & 0 deletions packages/rust/armonik/src/objects/health_checks/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//! ArmoniK objects related to the Health Checks service
mod service_health;
mod status;

pub mod check;

pub use service_health::ServiceHealth;
pub use status::Status;
21 changes: 21 additions & 0 deletions packages/rust/armonik/src/objects/health_checks/service_health.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use crate::api::v3;

use super::Status;

#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct ServiceHealth {
/// Name of the service (e.g. "control_plane", "database", "redis").
pub name: String,
/// Message.
pub message: String,
/// Health status.
pub health: Status,
}

super::super::impl_convert!(
struct ServiceHealth = v3::health_checks::check_health_response::ServiceHealth {
name,
message,
health = enum healthy,
}
);
51 changes: 51 additions & 0 deletions packages/rust/armonik/src/objects/health_checks/status.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use crate::api::v3;

#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(i32)]
pub enum Status {
/// Unspecified.
#[default]
Unspecified = 0,
/// Service is working without issues.
Healthy = 1,
/// Service has issues but still works.
Degraded = 2,
/// Service does not work.
Unhealthy = 3,
}

impl From<i32> for Status {
fn from(value: i32) -> Self {
match value {
0 => Self::Unspecified,
1 => Self::Healthy,
2 => Self::Degraded,
3 => Self::Unhealthy,
_ => Default::default(),
}
}
}

impl From<Status> for v3::health_checks::HealthStatusEnum {
fn from(value: Status) -> Self {
match value {
Status::Unspecified => Self::Unspecified,
Status::Healthy => Self::Healthy,
Status::Degraded => Self::Degraded,
Status::Unhealthy => Self::Unhealthy,
}
}
}

impl From<v3::health_checks::HealthStatusEnum> for Status {
fn from(value: v3::health_checks::HealthStatusEnum) -> Self {
match value {
v3::health_checks::HealthStatusEnum::Unspecified => Self::Unspecified,
v3::health_checks::HealthStatusEnum::Healthy => Self::Healthy,
v3::health_checks::HealthStatusEnum::Degraded => Self::Degraded,
v3::health_checks::HealthStatusEnum::Unhealthy => Self::Unhealthy,
}
}
}

super::super::impl_convert!(req Status : v3::health_checks::HealthStatusEnum);
1 change: 1 addition & 0 deletions packages/rust/armonik/src/objects/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ pub mod agent;
pub mod applications;
pub mod auth;
pub mod events;
pub mod health_checks;
pub mod partitions;
pub mod results;
pub mod sessions;
Expand Down
33 changes: 33 additions & 0 deletions packages/rust/armonik/src/server/health_checks.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use std::sync::Arc;

use crate::api::v3;
use crate::health_checks;

super::define_trait_methods! {
trait HealthChecksService {
/// Checks the health of the cluster. This can be used to verify that the cluster is up and running.
fn health_checks::check;
}
}

pub trait HealthChecksServiceExt {
fn health_checks_server(
self,
) -> v3::health_checks::health_checks_service_server::HealthChecksServiceServer<Self>
where
Self: Sized;
}

impl<T: HealthChecksService + Send + Sync + 'static> HealthChecksServiceExt for T {
fn health_checks_server(
self,
) -> v3::health_checks::health_checks_service_server::HealthChecksServiceServer<Self> {
v3::health_checks::health_checks_service_server::HealthChecksServiceServer::new(self)
}
}

super::impl_trait_methods! {
impl (v3::health_checks::health_checks_service_server::HealthChecksService) for HealthChecksService {
fn check_health(v3::health_checks::CheckHealthRequest) -> v3::health_checks::CheckHealthResponse { check }
}
}
Loading

0 comments on commit db6062d

Please sign in to comment.