Skip to content

Commit d4ac13a

Browse files
committed
Worker version 20260216.01. Use brozzler idle check. Also tweaks:
- increase custom JS timeout to 90s - reset size overrides after screenshot to maybe increase stability
1 parent d59ca37 commit d4ac13a

2 files changed

Lines changed: 19 additions & 35 deletions

File tree

client/worker/browse.py

Lines changed: 18 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,6 @@ def __init__(self, job: Job):
5858
}),
5959
}
6060
self.websock_thread_lock = threading.Lock()
61-
self.active_connections = 0
62-
self.last_network_activity = time.time()
6361
self.url_log: dict[str, Chain] = {}
6462

6563
# Shim for _handle_message so we can log responses
@@ -140,10 +138,9 @@ def _on_screenshot(self, screenshot):
140138
def _on_cjs_screenshot(self, screenshot):
141139
self.custom_js_screenshot = screenshot
142140

143-
def _run_cdp_command(self, method: str, params: dict | None = None) -> typing.Any:
141+
def _run_cdp_command(self, method: str, params: dict | None = None, timeout = 45) -> typing.Any:
144142
# Abuse brozzler's innards a bit to run a custom CDP command.
145143
# If this breaks, I was never here.
146-
# TODO: Burn with fire.
147144
params = params or {}
148145
logger.debug(f"running CDP command {method}")
149146
assert self.browser.websock_thread
@@ -155,7 +152,7 @@ def _run_cdp_command(self, method: str, params: dict | None = None) -> typing.An
155152
logger.debug("waiting for response")
156153
self._wait_for(
157154
lambda : self.browser.websock_thread.received_result(msg_id),
158-
45,
155+
timeout,
159156
"CDP result"
160157
)
161158
message = self.browser.websock_thread.pop_result(msg_id)
@@ -198,8 +195,6 @@ def _best_effort_proxy_url(cls, url: str, headers: dict):
198195
def _message_handler(self, websock, json_message: str):
199196
"""
200197
Shim for browser.websock_thread._handle_message.
201-
202-
Keeps track of network requests for logging and checking for idle.
203198
"""
204199
# brozzler gets priority so an exception can't lose messages
205200
self.previous_message_handler(websock, json_message)
@@ -209,37 +204,27 @@ def _message_handler(self, websock, json_message: str):
209204
method = message['method']
210205
params = message['params']
211206
if method == "Network.requestWillBeSent":
212-
self.active_connections += 1
213207
request_id = params['requestId']
214208
if request_id not in self.url_log:
215209
self.url_log[request_id] = Chain([], request_id)
216210
if redirect_response := params.get("redirectResponse"):
217211
self.url_log[request_id].chain[-1].response = Response.from_dict(redirect_response)
218212
request = Request.from_params(params)
219213
self.url_log[request_id].chain.append(Pair(request, None))
220-
self.last_network_activity = time.time()
221214
elif method == "Network.responseReceived":
222215
request_id = params['requestId']
223216
response = Response.from_params(params)
224217
self.url_log[request_id].chain[-1].response = response
225-
self.last_network_activity = time.time()
226218
elif method == "Network.dataReceived":
227219
request_id = params['requestId']
228220
self.url_log[request_id].chain[-1].response.length += params['dataLength']
229-
self.last_network_activity = time.time()
230221
elif method == "Network.loadingFinished":
231222
# Future: Submit log to websocket
232-
self.active_connections -= 1
233-
self.last_network_activity = time.time()
234223
pass
235224
elif method == "Network.loadingFailed":
236-
self.active_connections -= 1
237-
self.last_network_activity = time.time()
238225
request_id = params['requestId']
239226
error = Error(text = params['errorText'])
240227
self.url_log[request_id].chain[-1].response = error
241-
if self.active_connections < 0:
242-
self.active_connections = 0
243228

244229
# Shamelessly stolen from brozzler's Worker._browse_page.
245230
# Apparently service workers don't get added to the right WARC:
@@ -303,7 +288,8 @@ def _run_custom_js(self):
303288
"replMode": True,
304289
# Makes it actually return the value
305290
"returnByValue": True,
306-
}
291+
},
292+
timeout = 90,
307293
)
308294
try:
309295
custom_js_result = {
@@ -331,18 +317,6 @@ def _browser_version(self):
331317
logger.debug("got browser version %s", version)
332318
return version
333319

334-
def _wait_for_idle(self, *, idle_time: float, timeout: int):
335-
"""
336-
Waits up to timeout seconds for network to have been idle for idle_time.
337-
"""
338-
logger.debug("waiting for network idle")
339-
def is_idle():
340-
with self.websock_thread_lock:
341-
diff = time.time() - self.last_network_activity
342-
return self.active_connections == 0 and diff > idle_time
343-
self._wait_for(is_idle, timeout, "idle")
344-
logger.debug("got network idle!")
345-
346320
def _capture_dom(self) -> str:
347321
# First get the root node ID using DOM.getDocument (which gets the root node).
348322
logger.debug("getting root node ID")
@@ -352,6 +326,15 @@ def _capture_dom(self) -> str:
352326
outer_html = self._run_cdp_command("DOM.getOuterHTML", {"nodeId": root_node_id})['result']['outerHTML']
353327
return outer_html
354328

329+
def _set_metrics_override(self, width = 0, height = 0, device_scale_factor = 0):
330+
req = dict(
331+
width = width,
332+
height = height,
333+
deviceScaleFactor = device_scale_factor,
334+
mobile = False,
335+
)
336+
self._run_cdp_command("Emulation.setDeviceMetricsOverride", req)
337+
355338
def _brozzle(self) -> Result:
356339
assert self.browser.is_running()
357340

@@ -391,13 +374,12 @@ def _brozzle(self) -> Result:
391374
)
392375
assert len(outlinks) == 0, "Brozzler didn't listen to us :["
393376
self.status_code: int = self.browser.websock_thread.page_status
394-
try:
395-
self._wait_for_idle(idle_time = 3, timeout = 10)
396-
except Timeout:
397-
logger.info("timed out waiting for idle; ignoring issue")
377+
logger.debug("waiting for idle")
378+
self.browser._wait_for_idle(idle_time = 3, timeout = 10)
398379

399380
logger.debug("taking screenshot")
400381
self.browser._try_screenshot(self._on_screenshot, full_page = True)
382+
self._set_metrics_override()
401383
logger.debug("took screenshot!")
402384

403385
outer_html = self._capture_dom()
@@ -408,6 +390,8 @@ def _brozzle(self) -> Result:
408390
custom_js_screenshot = None
409391
if self.job.custom_js:
410392
custom_js_result = self._run_custom_js()
393+
logger.debug("waiting for idle after custom JS")
394+
self.browser._wait_for_idle(idle_time = 3, timeout = 5)
411395
self.browser._try_screenshot(self._on_cjs_screenshot, full_page = True)
412396
if self.custom_js_screenshot:
413397
custom_js_screenshot = base64.b85encode(self.custom_js_screenshot).decode()

client/worker/shared.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
# Update this whenever you make a change, cosmetic or not.
88
# During development you can ignore it, but when you actually
99
# push it to prod, it *must* be updated.
10-
VERSION = "20260207.01"
10+
VERSION = "20260216.01"
1111

1212
DEBUG = os.environ.get("DEBUG") == "1"
1313
if DEBUG:

0 commit comments

Comments
 (0)