fix(daemon): fire-and-forget mark-title eval so load events don't stall#171
Open
mvanhorn wants to merge 1 commit intobrowser-use:mainfrom
Open
fix(daemon): fire-and-forget mark-title eval so load events don't stall#171mvanhorn wants to merge 1 commit intobrowser-use:mainfrom
mvanhorn wants to merge 1 commit intobrowser-use:mainfrom
Conversation
Contributor
There was a problem hiding this comment.
1 issue found across 1 file
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="daemon.py">
<violation number="1" location="daemon.py:164">
P2: Fire-and-forget `Runtime.evaluate` on load events removed timeout bounding, allowing pending tasks to accumulate indefinitely when CDP calls stall.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.
| elif method in ("Page.loadEventFired", "Page.domContentEventFired"): | ||
| try: await asyncio.wait_for(self.cdp.send_raw("Runtime.evaluate", {"expression": mark_js}, session_id=self.session), timeout=2) | ||
| except Exception: pass | ||
| asyncio.create_task(_silent(self.cdp.send_raw("Runtime.evaluate", {"expression": mark_js}, session_id=self.session))) |
Contributor
There was a problem hiding this comment.
P2: Fire-and-forget Runtime.evaluate on load events removed timeout bounding, allowing pending tasks to accumulate indefinitely when CDP calls stall.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At daemon.py, line 164:
<comment>Fire-and-forget `Runtime.evaluate` on load events removed timeout bounding, allowing pending tasks to accumulate indefinitely when CDP calls stall.</comment>
<file context>
@@ -154,8 +161,7 @@ async def tap(method, params, session_id=None):
elif method in ("Page.loadEventFired", "Page.domContentEventFired"):
- try: await asyncio.wait_for(self.cdp.send_raw("Runtime.evaluate", {"expression": mark_js}, session_id=self.session), timeout=2)
- except Exception: pass
+ asyncio.create_task(_silent(self.cdp.send_raw("Runtime.evaluate", {"expression": mark_js}, session_id=self.session)))
return await orig(method, params, session_id)
self.cdp._event_registry.handle_event = tap
</file context>
Suggested change
| asyncio.create_task(_silent(self.cdp.send_raw("Runtime.evaluate", {"expression": mark_js}, session_id=self.session))) | |
| asyncio.create_task(_silent(asyncio.wait_for(self.cdp.send_raw("Runtime.evaluate", {"expression": mark_js}, session_id=self.session), timeout=2))) |
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.
Per #136, the
taphandler awaitsRuntime.evaluateon bothPage.loadEventFiredandPage.domContentEventFired. Becausecdp-usedispatches events one at a time, the await ondomContentEventFiredholds uploadEventFiredin the queue, and Chrome's V8 thread is busy so the eval doesn't return in time. The user's nextjs(...)then queues behind the second eval on V8. Two ~2s waits compound per navigation.Reporter measured the median iteration time at 4.595s with the current double-await, dropping to 1.060s with fire-and-forget. Playwright baseline on the same browser is ~0.9s.
Change
Module-level
_silent(coro)wrapper preserves the currentexcept Exception: passbehavior (theset_sessionbranch at line 172 has the same pattern around the samesend_rawcall, and the generichandle()path explicitly handles"Session with given id not found", so the existing suppression is load-bearing, not cosmetic). TheloadEventFired/domContentEventFiredbranch usesasyncio.create_task(_silent(...))to fire-and-forget. The title mark still lands a moment later, just off the critical path.Scope
daemon.pyonly, +8 / -2mark_jsdefinition unchangedset_sessionbranch at line 172 intentionally NOT touched (runs per session-switch, not per navigation)python3 -m py_compile daemon.pyFixes #136
Summary by cubic
Make the mark-title eval fire-and-forget in
daemon.pysoPage.loadEventFired/Page.domContentEventFireddon’t stall the event queue. This removes ~2s per navigation delay and drops median iteration time from ~4.6s to ~1.06s. Fixes #136.Runtime.evaluatewithasyncio.create_task(_silent(...))in thetaphandler for load/DOMContent events._silent;mark_jsand theset_sessionpath remain unchanged.Written for commit 742fc8a. Summary will update on new commits.