Skip to content

Commit 00e03ab

Browse files
authored
test: widen daemon_idle liveness window to de-flake under parallel load (#51)
daemon_idle_exits_after_last_client asserted is_process_alive 200ms after client disconnect inside a 500ms idle window (~40% of the window). Under heavy cargo test --workspace parallel load, scheduling drift could stretch that 200ms observation past the idle window so the daemon had already idle-exited, flipping alive_before_idle to false and panicking. Widen the test's configured idle timeout 500 -> 2000ms so the 200ms liveness observation is only 10% of the window (>1.5s margin), and bump wait_until_gone 8s -> 10s for headroom. Both assertions stay meaningful: alive-before-idle and idle-exit-after. Sibling alive-asserting tests (daemon_stays_alive_with_active_client, client_without_hello_is_never_swept) observe PAST their windows already (the safe direction) and need no change. Test-only; no product code, daemon default, golden, or version touched.
1 parent 2ecfe5a commit 00e03ab

1 file changed

Lines changed: 13 additions & 9 deletions

File tree

‎crates/codegraph-cli/tests/daemon_idle.rs‎

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
//!
33
//! The daemon lives in a SEPARATE detached process, so we assert lifecycle via
44
//! pid liveness (`is_process_alive`) at timed checkpoints, not via stdout (it is
5-
//! detached + logs to `.codegraph/daemon.log`). With `CODEGRAPH_DAEMON_IDLE_TIMEOUT_MS=500`
6-
//! the daemon should LINGER while a client is connected and shortly after the
7-
//! LAST client disconnects, then EXIT once the idle window elapses with zero
8-
//! clients. De-flake by polling pid liveness against a clear deadline.
5+
//! detached + logs to `.codegraph/daemon.log`). With a multi-second
6+
//! `CODEGRAPH_DAEMON_IDLE_TIMEOUT_MS` the daemon should LINGER while a client is
7+
//! connected and shortly after the LAST client disconnects, then EXIT once the
8+
//! idle window elapses with zero clients. De-flake by polling pid liveness
9+
//! against a clear deadline AND by keeping the "still alive" observation a tiny
10+
//! fraction of the idle window so CI scheduling jitter cannot flip the edge.
911
1012
#![cfg(unix)]
1113

@@ -172,14 +174,14 @@ fn wait_until_gone(pid: u32, timeout: Duration) -> bool {
172174
process_is_gone_or_zombie(pid)
173175
}
174176

175-
/// HAPPY: with a 500ms idle timeout, the daemon stays alive right after the last
177+
/// HAPPY: with a 2000ms idle timeout, the daemon stays alive right after the last
176178
/// client disconnects (< idle) and idle-exits once the window elapses (> idle).
177179
#[test]
178180
fn daemon_idle_exits_after_last_client() {
179181
let (_dir, project) = indexed_project("exits");
180182
let socket = daemon_socket_path(&project);
181183

182-
spawn_idle_daemon(&project, "500");
184+
spawn_idle_daemon(&project, "2000");
183185
let pid = poll_for_daemon_pid(&socket, Duration::from_millis(3000))
184186
.expect("daemon socket + hello pid within poll window");
185187

@@ -190,15 +192,17 @@ fn daemon_idle_exits_after_last_client() {
190192
drop(client);
191193
}
192194

193-
// At ~200ms after disconnect (< 500ms idle) the daemon must still be alive.
195+
// At ~200ms after disconnect (≪ 2000ms idle) the daemon must still be alive.
196+
// 200ms is a tiny fraction (10%) of the idle window, so even heavy CI
197+
// scheduling jitter cannot stretch this observation past idle-exit.
194198
std::thread::sleep(Duration::from_millis(200));
195199
let alive_before_idle = is_process_alive(pid);
196200

197201
// GENEROUS deadline, not a tight margin: `wait_until_gone` polls every 20ms and
198202
// returns the instant the process is gone, so the happy path still finishes in
199-
// ~500-800ms — an 8s ceiling costs nothing on a quiet machine but stops a loaded
203+
// ~2-2.5s — a 10s ceiling costs nothing on a quiet machine but stops a loaded
200204
// CI runner's slow idle-sweep + teardown from false-negativing (de-flake).
201-
let exited = wait_until_gone(pid, Duration::from_secs(8));
205+
let exited = wait_until_gone(pid, Duration::from_secs(10));
202206

203207
// TEARDOWN before asserting so a failing assert never leaks the process.
204208
if !exited {

0 commit comments

Comments
 (0)