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:
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user