feat(crawler): coordinated browser restart gate in BrowserManager

Adds a Healthy/Draining/Restarting lifecycle gate. `acquire()` parks while
a restart is in progress; `coordinated_restart(deadline)` blocks new
acquires, drains in-flight leases (bounded, then forces), closes +
relaunches Chromium (re-running on_launch → re-inject session + probe),
then resumes parked acquirers. Concurrent restart requests collapse into
one relaunch; the phase always returns to Healthy so a failed relaunch
never wedges acquisition.

The metadata pass cooperates via is_restart_pending() at its per-manga
checkpoint, yielding its long-lived lease (recovery sweep next tick)
instead of stalling the drain.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-06-03 20:18:09 +02:00
parent 7a6815661f
commit 3f91bea768
2 changed files with 213 additions and 14 deletions

View File

@@ -192,6 +192,17 @@ pub async fn run_metadata_pass(
}
};
for r in batch {
// Cooperative checkpoint: if a coordinated browser restart is
// pending, yield our (long-lived) lease so the drain can
// proceed instead of stalling for the rest of the walk. The
// pass exits un-clean, so the next tick recovery-sweeps the
// tail we didn't reach.
if browser_manager.is_restart_pending() {
tracing::info!(
"metadata pass: browser restart pending — yielding (recovery sweep next tick)"
);
break 'outer;
}
if max_refs.map(|m| stats.discovered >= m).unwrap_or(false) {
hit_limit = true;
tracing::info!(cap = ?max_refs, "max_results reached; halting walk");