fix: per-user nav health tracking, session-scoped recovery, single-flight race - #9324
Open
dyiapanis wants to merge 1 commit into
Open
fix: per-user nav health tracking, session-scoped recovery, single-flight race#9324dyiapanis wants to merge 1 commit into
dyiapanis wants to merge 1 commit into
Conversation
…ight race - Replace process-global healthState.consecutiveNavFailures with Map<userId, UserNavHealth> for per-user failure tracking (jo-inc#9321) - Wire recordNavSuccess(userId)/recordNavFailure(userId) into all navigation routes: POST /tabs, POST /tabs/:tabId/navigate, POST /tabs/open, POST /navigate, and handleRouteError for /act (jo-inc#9323) - Add recoverUserSession(userId) for session-scoped recovery instead of restartBrowser() killing all sessions on nav failures (jo-inc#9322) - Remove manual browserLaunchPromise = null in restartBrowser() — ensureBrowser() owns the single-flight primitive (jo-inc#8554) - Clean up per-user nav health on destroySession() - Aggregate per-user failures in /health endpoint - Add tests/unit/navHealthRecovery.test.js (8 tests) Fixes jo-inc#9321, jo-inc#9322, jo-inc#9323 Relates to jo-inc#8554
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes three bugs in the browser health tracking system:
healthStatewas process-global, so interleaved navigation failures from different users corrupted each other's failure counters and triggered recovery for the wrong user.restartBrowser()calledcloseAllSessions()unconditionally, destroying every user's session when one user's navigation failed.recordNavSuccess()/recordNavFailure()were never called by any route handler — the health tracking infrastructure was dead code.Also fixes #8554 —
restartBrowser()clearedbrowserLaunchPromisebefore callingensureBrowser(), creating a window for a concurrent second browser launch.Changes
Per-user health tracking (#9321)
Replaced the single
healthState.consecutiveNavFailurescounter with aMap<userId, UserNavHealth>.recordNavSuccess(userId)andrecordNavFailure(userId)now accept auserIdparameter and operate only on that user's entry. Process-global fields (activeOps,isRecovering,lastSuccessfulNav) remain on the sharedhealthStateobject for the health probe and/healthendpoint.Session-scoped recovery (#9322)
Added
recoverUserSession(userId, reason)which destroys only the failing user's session viadestroySession(userId)instead ofcloseAllSessions().restartBrowser()is still used for browser-level failures (health probe failure, disconnection), but per-user nav failures now trigger session-scoped recovery.Wired nav health into routes (#9323)
All five navigation entry points now call the health functions:
POST /tabs— after successfulpage.goto()and on failurePOST /tabs/:tabId/navigate— after successful navigation and on failurePOST /tabs/open— after successful navigation and on failurePOST /navigate(OpenClaw) — after successful navigation and on failurehandleRouteError()— records nav failure for navigation-related timeouts (covers/actclicks)On successful navigation:
recordNavSuccess(userId)resets the user's failure counter.On failed navigation:
recordNavFailure(userId)increments the counter. When the counter reachesFAILURE_THRESHOLD(3),recoverUserSession(userId)fires — destroying and recreating only that user's session.Single-flight race fix (#8554)
Removed the
browserLaunchPromise = nullassignment fromrestartBrowser().ensureBrowser()already owns the single-flight primitive — its.finally(() => { browserLaunchPromise = null })handles cleanup. Clearing it manually opened a window where a concurrent request could start a second launch.Cleanup
destroySession(userId)now callsdeleteUserNavHealth(userId)to clean up per-user state./healthendpoint aggregates per-user failures viaArray.from(userNavHealth.values()).reduce(...).Testing
New test file
tests/unit/navHealthRecovery.test.js(8 tests) verifies:recordNavSuccessresets only the specified user's counterrecordNavFailurereturns true only when the user's own threshold is exceededdeleteUserNavHealthremoves only the specified userrecordNavFailurewith no userId is a no-opFixes #9321, #9322, #9323
Relates to #8554