Skip to content

Commit 4e905ee

Browse files
committed
refactor: update BrowserManagerHandle to use CommandExecutionContext
1 parent f205ebf commit 4e905ee

1 file changed

Lines changed: 39 additions & 33 deletions

File tree

openwpm/browser_manager.py

Lines changed: 39 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,14 @@
1212
import traceback
1313
from pathlib import Path
1414
from queue import Empty as EmptyQueue
15-
from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple, Type, Union
15+
from typing import Any, Dict, Optional, Tuple, Type, Union
1616

1717
import psutil
1818
from multiprocess import Queue
1919
from selenium.common.exceptions import WebDriverException
2020
from tblib import Traceback, pickling_support
2121

22+
from .command_execution_context import CommandExecutionContext
2223
from .command_sequence import CommandSequence
2324
from .commands.browser_commands import FinalizeCommand
2425
from .commands.profile_commands import dump_profile
@@ -27,6 +28,7 @@
2728
from .config import BrowserParamsInternal, ManagerParamsInternal
2829
from .deploy_browsers import deploy_firefox
2930
from .errors import BrowserConfigError, BrowserCrashError, ProfileLoadError
31+
from .failure_tracker import CommandFailure
3032
from .socket_interface import ClientSocket
3133
from .storage.storage_providers import TableName
3234
from .types import BrowserId, VisitId
@@ -39,9 +41,6 @@
3941

4042
pickling_support.install()
4143

42-
if TYPE_CHECKING:
43-
from .task_manager import TaskManager
44-
4544

4645
class BrowserManagerHandle:
4746
"""The BrowserManagerHandle class is responsible for holding all the
@@ -343,16 +342,23 @@ def close_browser_manager(self, force: bool = False) -> None:
343342

344343
def execute_command_sequence(
345344
self,
346-
# Quoting to break cyclic import, see https://stackoverflow.com/a/39757388
347-
task_manager: "TaskManager",
345+
context: CommandExecutionContext,
348346
command_sequence: CommandSequence,
349347
) -> None:
350348
"""
351-
Sends CommandSequence to the BrowserManager one command at a time
349+
Sends CommandSequence to the BrowserManager one command at a time.
350+
351+
Parameters
352+
----------
353+
context : CommandExecutionContext
354+
Provides storage and failure tracking without requiring a
355+
direct reference to TaskManager.
356+
command_sequence : CommandSequence
357+
The sequence of commands to execute.
352358
"""
353359
assert self.browser_id is not None
354360
assert self.curr_visit_id is not None
355-
task_manager.sock.store_record(
361+
context.store_record(
356362
TableName("site_visits"),
357363
self.curr_visit_id,
358364
{
@@ -412,11 +418,9 @@ def execute_command_sequence(
412418
"process while executing command %s. Setting failure "
413419
"status." % (self.browser_id, str(command))
414420
)
415-
task_manager.failure_status = {
416-
"ErrorType": "CriticalChildException",
417-
"CommandSequence": command_sequence,
418-
"Exception": status[1],
419-
}
421+
context.failure_tracker.set_critical_failure(
422+
"CriticalChildException", command_sequence, exception=status[1]
423+
)
420424
error_text, tb = self._unpack_pickled_error(status[1])
421425
elif status[0] == "FAILED":
422426
command_status = "error"
@@ -436,7 +440,7 @@ def execute_command_sequence(
436440
else:
437441
raise ValueError("Unknown browser status message %s" % status)
438442

439-
task_manager.sock.store_record(
443+
context.store_record(
440444
TableName("crawl_history"),
441445
self.curr_visit_id,
442446
{
@@ -455,39 +459,42 @@ def execute_command_sequence(
455459
)
456460

457461
if command_status == "critical":
458-
task_manager.sock.finalize_visit_id(
459-
success=False,
462+
context.finalize_visit_id(
460463
visit_id=self.curr_visit_id,
464+
success=False,
461465
)
462466
return
463467

464468
if command_status != "ok":
465-
with task_manager.threadlock:
466-
task_manager.failure_count += 1
467-
if task_manager.failure_count > task_manager.failure_limit:
469+
over_limit = context.failure_tracker.record_failure(
470+
CommandFailure(
471+
browser_id=self.browser_id,
472+
command=repr(command),
473+
command_status=command_status,
474+
error=error_text,
475+
traceback=tb,
476+
)
477+
)
478+
if over_limit:
468479
self.logger.critical(
469480
"BROWSER %i: Command execution failure pushes failure "
470481
"count above the allowable limit. Setting "
471482
"failure_status." % self.browser_id
472483
)
473-
task_manager.failure_status = {
474-
"ErrorType": "ExceedCommandFailureLimit",
475-
"CommandSequence": command_sequence,
476-
}
484+
context.failure_tracker.set_critical_failure(
485+
"ExceedCommandFailureLimit", command_sequence
486+
)
477487
return
478488
self.restart_required = True
479489
self.logger.debug(
480490
"BROWSER %i: Browser restart required" % self.browser_id
481491
)
482492
# Reset failure_count at the end of each successful command sequence
483493
elif type(command) is FinalizeCommand:
484-
with task_manager.threadlock:
485-
task_manager.failure_count = 0
494+
context.failure_tracker.reset()
486495

487496
if self.restart_required:
488-
task_manager.sock.finalize_visit_id(
489-
success=False, visit_id=self.curr_visit_id
490-
)
497+
context.finalize_visit_id(visit_id=self.curr_visit_id, success=False)
491498
break
492499

493500
self.logger.info(
@@ -500,7 +507,7 @@ def execute_command_sequence(
500507
# internal buffers to drain. Stopgap in support of #135
501508
time.sleep(2)
502509

503-
if task_manager.closing:
510+
if context.closing:
504511
return
505512

506513
# Allow StorageWatchdog to utilize built-in browser reset functionality
@@ -520,10 +527,9 @@ def execute_command_sequence(
520527
"BROWSER %i: Exceeded the maximum allowable consecutive "
521528
"browser launch failures. Setting failure_status." % self.browser_id
522529
)
523-
task_manager.failure_status = {
524-
"ErrorType": "ExceedLaunchFailureLimit",
525-
"CommandSequence": command_sequence,
526-
}
530+
context.failure_tracker.set_critical_failure(
531+
"ExceedLaunchFailureLimit", command_sequence
532+
)
527533
return
528534
self.restart_required = False
529535

0 commit comments

Comments
 (0)