Introduce boot_time to evaluate_state

The `boot_time` parameter is introduced to `evaluate_state` and its
callers. This parameter acts as a lower bound for the "seen at"
timestamp used in determining the `Idle` state for cases.

Previously, the `elapsed` duration was calculated as
`now.duration_since(latest_mtime)`. This meant that a server restart
could immediately cause old recordings to be classified as `Idle` if
their modification times were significantly in the past, potentially
triggering a large number of LLM calls upon the first render of the
`/cases` page.

By using `seen_at = std::cmp::max(latest_mtime, boot_time)`, the idle
calculation now ensures that a fresh server start respects a grace
period. Old recordings will not satisfy the idle threshold until the
elapsed time since the server's boot (or the recording's modification
time, whichever is later) exceeds the `idle_threshold`.

`SystemTime::UNIX_EPOCH` is used as the default `boot_time` in tests and
in `create_router_and_session_store_with_settings`. This preserves
existing test behavior where the idle grace period is effectively
disabled. For production, `main.rs` now captures the server's actual
boot time and passes it down.

This change also refactors `evaluate_case` and `try_enqueue` to accept
the new `boot_time` parameter. `try_enqueue_all_for_user` is updated to
pass `boot_time` along. `boot_scan_state` and `compute_state_for_user`
in `recovery.rs` also receive `boot_time`.

Additionally, a new test case
`analyze_required_endpoint_enqueues_only_required_cases` is added to
verify the behavior of the `/cases/analyze-required` endpoint. This
endpoint now correctly enqueues only `Required`
This commit is contained in:
2026-05-05 15:12:08 +02:00
parent bd133e9944
commit 16ef0bbe78
10 changed files with 392 additions and 41 deletions
+4 -2
View File
@@ -197,15 +197,16 @@ async fn main() {
vocab.clone(),
events_tx.clone(),
));
let server_boot_time = std::time::SystemTime::now();
{
let data_path = config.data_path.clone();
let idle_threshold =
std::time::Duration::from_secs(config.analysis_idle_threshold_secs);
let idle_threshold = std::time::Duration::from_secs(config.analysis_idle_threshold_secs);
tokio::spawn(async move {
analyze::recovery::boot_scan_state(
&data_path,
idle_threshold,
std::time::SystemTime::now(),
server_boot_time,
)
.await;
});
@@ -225,6 +226,7 @@ async fn main() {
events_tx,
http_client,
vocab,
boot_time: doctate_server::BootTime(server_boot_time),
};
let addr = format!("0.0.0.0:{}", config.server_port);