fix(admin): clear session-expired flag on successful browser restart (0.53.1)

A successful `coordinated_restart` re-runs `on_launch`, which re-injects
PHPSESSID and re-probes via `verify_session_with_recircuit` — so reaching
`Ok(())` proves the session is live. But the handler never dropped the
sticky `session_expired` flag, so the admin UI continued to report
"Session Expired" and chapter workers kept idling until the operator
made a second click on "Clear expired" (or pushed a new cookie).

The fix is one line in `restart_browser`: on `Ok(())`, call
`c.session.clear_expired()`. The error path still leaves the flag set
since a failed restart means the probe didn't confirm.

Adds a focused `clear_expired_flips_sticky_flag_without_touching_session`
unit test to pin the controller-side semantic; the existing
`update_persists_and_clears_expired_then_round_trips` test continues to
cover the cookie-refresh path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-06-04 19:49:28 +02:00
parent da6e320836
commit fb4182f68d
5 changed files with 23 additions and 3 deletions

2
backend/Cargo.lock generated
View File

@@ -1470,7 +1470,7 @@ checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
[[package]] [[package]]
name = "mangalord" name = "mangalord"
version = "0.53.0" version = "0.53.1"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"argon2", "argon2",

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "mangalord" name = "mangalord"
version = "0.53.0" version = "0.53.1"
edition = "2021" edition = "2021"
default-run = "mangalord" default-run = "mangalord"

View File

@@ -233,6 +233,13 @@ async fn restart_browser(
) -> AppResult<Json<RestartResponse>> { ) -> AppResult<Json<RestartResponse>> {
let c = require_crawler(&state)?; let c = require_crawler(&state)?;
let result = c.browser_manager.coordinated_restart(c.drain_deadline).await; let result = c.browser_manager.coordinated_restart(c.drain_deadline).await;
// A successful coordinated_restart re-runs on_launch, which re-injects
// PHPSESSID and re-probes — i.e. the session is live. Drop the sticky
// `session_expired` flag so chapter workers stop idling without
// requiring a second click on "Clear expired".
if result.is_ok() {
c.session.clear_expired();
}
// Push the post-restart browser phase to live subscribers immediately. // Push the post-restart browser phase to live subscribers immediately.
c.status.poke(); c.status.poke();
repo::admin_audit::insert( repo::admin_audit::insert(

View File

@@ -164,4 +164,17 @@ mod tests {
Some("good-sid-123") Some("good-sid-123")
); );
} }
#[sqlx::test(migrations = "./migrations")]
async fn clear_expired_flips_sticky_flag_without_touching_session(pool: PgPool) {
// The flag starts `true` per `controller(pool)`'s test wiring.
let c = controller(pool);
assert!(c.is_expired(), "test fixture starts with the flag set");
c.clear_expired();
assert!(!c.is_expired(), "clear_expired flips the sticky flag to false");
assert!(
c.current().await.is_none(),
"clear_expired does not invent a session"
);
}
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "mangalord-frontend", "name": "mangalord-frontend",
"version": "0.53.0", "version": "0.53.1",
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {