Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ members = [
"src/health_monitoring_lib",
"examples/rust_supervised_app",
]
default-members = ["src/health_monitoring_lib"]

[workspace.package]
edition = "2021"
Expand Down
3 changes: 3 additions & 0 deletions src/health_monitoring_lib/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ CC_HDRS = [
rust_library(
name = "health_monitoring_lib",
srcs = glob(["rust/**/*.rs"]),
crate_features = ["score_supervisor_api_client"],
crate_root = "rust/lib.rs",
proc_macro_deps = PROC_MACRO_DEPS,
visibility = ["//visibility:public"],
Expand All @@ -65,6 +66,7 @@ cc_library(
rust_static_library(
name = "health_monitoring_lib_ffi",
srcs = glob(["rust/**/*.rs"]),
crate_features = ["score_supervisor_api_client"],
crate_name = "health_monitoring_lib",
crate_root = "rust/lib.rs",
proc_macro_deps = [
Expand Down Expand Up @@ -100,6 +102,7 @@ cc_library(
rust_test(
name = "tests",
crate = ":health_monitoring_lib",
crate_features = ["stub_supervisor_api_client"],
rustc_flags = [
"-C",
"link-arg=-lm",
Expand Down
6 changes: 3 additions & 3 deletions src/health_monitoring_lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ edition.workspace = true
authors.workspace = true
license-file.workspace = true


[lib]
path = "rust/lib.rs"

Expand All @@ -18,11 +17,12 @@ workspace = true
score_log.workspace = true
score_testing_macros.workspace = true
containers.workspace = true
monitor_rs.workspace = true
monitor_rs = { workspace = true, optional = true }

[dev-dependencies]
stdout_logger.workspace = true

[features]
default = []
default = ["stub_supervisor_api_client"]
stub_supervisor_api_client = []
score_supervisor_api_client = ["monitor_rs"]
3 changes: 3 additions & 0 deletions src/health_monitoring_lib/rust/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ pub(crate) enum MonitorEvaluationError {

/// Trait for evaluating monitors and reporting errors to be used by HealthMonitor.
pub(crate) trait MonitorEvaluator {
/// Run monitor evaluation.
///
/// - `on_error` - error handling, containing tag of failing object and error code.
fn evaluate(&self, on_error: &mut dyn FnMut(&MonitorTag, MonitorEvaluationError));
}

Expand Down
14 changes: 8 additions & 6 deletions src/health_monitoring_lib/rust/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ mod common;
mod ffi;
mod log;
mod protected_memory;
mod supervisor_api_client;
mod tag;
mod worker;

Expand Down Expand Up @@ -217,12 +218,13 @@ impl HealthMonitor {
let monitoring_logic = worker::MonitoringLogic::new(
monitors,
self.supervisor_api_cycle,
// Currently only `ScoreSupervisorAPIClient` and `StubSupervisorAPIClient` are supported.
// The later is meant to be used for testing purposes.
#[cfg(not(any(test, feature = "stub_supervisor_api_client")))]
worker::ScoreSupervisorAPIClient::new(),
#[cfg(any(test, feature = "stub_supervisor_api_client"))]
worker::StubSupervisorAPIClient {},
#[cfg(all(not(test), feature = "score_supervisor_api_client"))]
supervisor_api_client::score_supervisor_api_client::ScoreSupervisorAPIClient::new(),
#[cfg(any(
test,
all(feature = "stub_supervisor_api_client", not(feature = "score_supervisor_api_client"))
))]
supervisor_api_client::stub_supervisor_api_client::StubSupervisorAPIClient::new(),
);

self.worker.start(monitoring_logic)
Expand Down
28 changes: 28 additions & 0 deletions src/health_monitoring_lib/rust/supervisor_api_client/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// *******************************************************************************
// Copyright (c) 2026 Contributors to the Eclipse Foundation
//
// See the NOTICE file(s) distributed with this work for additional
// information regarding copyright ownership.
//
// This program and the accompanying materials are made available under the
// terms of the Apache License Version 2.0 which is available at
// <https://www.apache.org/licenses/LICENSE-2.0>
//
// SPDX-License-Identifier: Apache-2.0
// *******************************************************************************

//! Module providing [`SupervisorAPIClient`] implementations.
//! Currently `ScoreSupervisorAPIClient` and `StubSupervisorAPIClient` are supported.
//! The latter is meant for testing purposes.

/// An abstraction over the API used to notify the supervisor about process liveness.
pub trait SupervisorAPIClient {
fn notify_alive(&self);
}

// NOTE: various implementations are not mutually exclusive.

#[cfg(feature = "score_supervisor_api_client")]
pub mod score_supervisor_api_client;
#[cfg(feature = "stub_supervisor_api_client")]
pub mod stub_supervisor_api_client;
Comment on lines +25 to +28
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There’s currently no compile-time guard to prevent enabling both score_supervisor_api_client and stub_supervisor_api_client (or neither). Adding compile_error! checks for these invalid feature combinations would prevent surprising runtime selection and avoid Cargo configurations that otherwise fail to compile.

Copilot uses AI. Check for mistakes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// *******************************************************************************
// Copyright (c) 2026 Contributors to the Eclipse Foundation
//
// See the NOTICE file(s) distributed with this work for additional
// information regarding copyright ownership.
//
// This program and the accompanying materials are made available under the
// terms of the Apache License Version 2.0 which is available at
// <https://www.apache.org/licenses/LICENSE-2.0>
//
// SPDX-License-Identifier: Apache-2.0
// *******************************************************************************

#![allow(dead_code)]

use crate::log::debug;
use crate::supervisor_api_client::SupervisorAPIClient;
use crate::worker::Checks;

pub struct ScoreSupervisorAPIClient {
supervisor_link: monitor_rs::Monitor<Checks>,
}

unsafe impl Send for ScoreSupervisorAPIClient {} // Just assuming it's safe to send across threads, this is a temporary solution

impl ScoreSupervisorAPIClient {
pub fn new() -> Self {
let value = std::env::var("IDENTIFIER").expect("IDENTIFIER env not set");
debug!("ScoreSupervisorAPIClient: Creating with IDENTIFIER={}", value);
// This is only temporary usage so unwrap is fine here.
let supervisor_link = monitor_rs::Monitor::<Checks>::new(&value).expect("Failed to create supervisor_link");
Self { supervisor_link }
}
}

impl SupervisorAPIClient for ScoreSupervisorAPIClient {
fn notify_alive(&self) {
self.supervisor_link.report_checkpoint(Checks::WorkerCheckpoint);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// *******************************************************************************
// Copyright (c) 2026 Contributors to the Eclipse Foundation
//
// See the NOTICE file(s) distributed with this work for additional
// information regarding copyright ownership.
//
// This program and the accompanying materials are made available under the
// terms of the Apache License Version 2.0 which is available at
// <https://www.apache.org/licenses/LICENSE-2.0>
//
// SPDX-License-Identifier: Apache-2.0
// *******************************************************************************

#![allow(dead_code)]

use crate::log::warn;
use crate::supervisor_api_client::SupervisorAPIClient;

/// A stub implementation of the SupervisorAPIClient that logs alive notifications.
pub struct StubSupervisorAPIClient;

impl StubSupervisorAPIClient {
pub fn new() -> Self {
Self
}
}

impl SupervisorAPIClient for StubSupervisorAPIClient {
fn notify_alive(&self) {
warn!("StubSupervisorAPIClient: notify_alive called");
}
}
42 changes: 35 additions & 7 deletions src/health_monitoring_lib/rust/tag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,13 +247,41 @@ mod tests {
}

#[test]
fn tag_hash() {
let example_str = "EXAMPLE";
let tag = Tag::from(example_str.to_string());
let mut hasher = DefaultHasher::new();
tag.hash(&mut hasher);
let hash = hasher.finish();
assert_eq!(hash, 14738755424381306335);
fn tag_hash_is_eq() {
let tag1 = Tag::from("same");
let hash1 = {
let mut hasher = DefaultHasher::new();
tag1.hash(&mut hasher);
hasher.finish()
};

let tag2 = Tag::from("same");
let hash2 = {
let mut hasher = DefaultHasher::new();
tag2.hash(&mut hasher);
hasher.finish()
};

assert_eq!(hash1, hash2);
}

#[test]
fn tag_hash_is_ne() {
let tag1 = Tag::from("first");
let hash1 = {
let mut hasher = DefaultHasher::new();
tag1.hash(&mut hasher);
hasher.finish()
};

let tag2 = Tag::from("second");
let hash2 = {
let mut hasher = DefaultHasher::new();
tag2.hash(&mut hasher);
hasher.finish()
};

assert_ne!(hash1, hash2);
}

#[test]
Expand Down
Loading
Loading