browser sessions v2 - backend (#4515)
Signed-off-by: Benji Visser <benji@093b.org>
This commit is contained in:
@@ -613,8 +613,8 @@ async def _create_cdp_connection_browser(
|
||||
"--remote-debugging-port=9222",
|
||||
"--no-first-run",
|
||||
"--no-default-browser-check",
|
||||
"--remote-debugging-address=0.0.0.0",
|
||||
"--user-data-dir=./tmp/user_data_dir",
|
||||
"--remote-debugging-address=0.0.0.0",
|
||||
],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
|
||||
@@ -3,6 +3,7 @@ from __future__ import annotations
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from math import floor
|
||||
from pathlib import Path
|
||||
|
||||
import structlog
|
||||
from playwright._impl._errors import TargetClosedError
|
||||
@@ -161,10 +162,13 @@ async def update_status(
|
||||
organization_id=organization_id,
|
||||
browser_status=status,
|
||||
)
|
||||
|
||||
completed_at = datetime.now(timezone.utc) if is_final_status(status) else None
|
||||
persistent_browser_session = await db.update_persistent_browser_session(
|
||||
session_id,
|
||||
status=status,
|
||||
organization_id=organization_id,
|
||||
completed_at=completed_at,
|
||||
)
|
||||
|
||||
return persistent_browser_session
|
||||
@@ -264,15 +268,14 @@ class DefaultPersistentSessionsManager(PersistentSessionsManager):
|
||||
timeout_minutes: int | None = None,
|
||||
extensions: list[Extensions] | None = None,
|
||||
browser_type: PersistentBrowserType | None = None,
|
||||
is_high_priority: bool = False,
|
||||
) -> PersistentBrowserSession:
|
||||
"""Create a new browser session for an organization and return its ID with the browser state."""
|
||||
|
||||
LOG.info(
|
||||
"Creating new browser session",
|
||||
organization_id=organization_id,
|
||||
)
|
||||
|
||||
browser_session_db = await self.database.create_persistent_browser_session(
|
||||
return await self.database.create_persistent_browser_session(
|
||||
organization_id=organization_id,
|
||||
runnable_type=runnable_type,
|
||||
runnable_id=runnable_id,
|
||||
@@ -282,8 +285,6 @@ class DefaultPersistentSessionsManager(PersistentSessionsManager):
|
||||
browser_type=browser_type,
|
||||
)
|
||||
|
||||
return browser_session_db
|
||||
|
||||
async def occupy_browser_session(
|
||||
self,
|
||||
session_id: str,
|
||||
@@ -324,7 +325,6 @@ class DefaultPersistentSessionsManager(PersistentSessionsManager):
|
||||
organization_id=organization_id,
|
||||
session_id=browser_session_id,
|
||||
)
|
||||
|
||||
# Export session profile before closing (so it can be used to create browser profiles)
|
||||
browser_artifacts = browser_session.browser_state.browser_artifacts
|
||||
if browser_artifacts and browser_artifacts.browser_session_dir:
|
||||
@@ -346,6 +346,29 @@ class DefaultPersistentSessionsManager(PersistentSessionsManager):
|
||||
organization_id=organization_id,
|
||||
)
|
||||
|
||||
if browser_artifacts and browser_artifacts.video_artifacts:
|
||||
for video_artifact in browser_artifacts.video_artifacts:
|
||||
if video_artifact.video_path:
|
||||
try:
|
||||
video_path = Path(video_artifact.video_path)
|
||||
if video_path.exists():
|
||||
date = video_path.parent.name
|
||||
await app.STORAGE.sync_browser_session_file(
|
||||
organization_id=organization_id,
|
||||
browser_session_id=browser_session_id,
|
||||
artifact_type="videos",
|
||||
local_file_path=str(video_path),
|
||||
remote_path=video_path.name,
|
||||
date=date,
|
||||
)
|
||||
except Exception:
|
||||
LOG.exception(
|
||||
"Failed to sync video recording",
|
||||
browser_session_id=browser_session_id,
|
||||
organization_id=organization_id,
|
||||
video_path=video_artifact.video_path,
|
||||
)
|
||||
|
||||
self._browser_sessions.pop(browser_session_id, None)
|
||||
|
||||
try:
|
||||
|
||||
@@ -67,6 +67,7 @@ class PersistentSessionsManager(Protocol):
|
||||
timeout_minutes: int | None = None,
|
||||
extensions: list[Extensions] | None = None,
|
||||
browser_type: PersistentBrowserType | None = None,
|
||||
is_high_priority: bool = False,
|
||||
) -> PersistentBrowserSession:
|
||||
"""Create a new browser session."""
|
||||
...
|
||||
|
||||
@@ -27,6 +27,11 @@ class BrowserSessionResponse(BaseModel):
|
||||
examples=["pbs_123456"],
|
||||
)
|
||||
organization_id: str = Field(description="ID of the organization that owns this session")
|
||||
status: str | None = Field(
|
||||
None,
|
||||
description="Current status of the browser session",
|
||||
examples=["created", "running", "completed", "failed", "timeout"],
|
||||
)
|
||||
runnable_type: str | None = Field(
|
||||
None,
|
||||
description="Type of the current runnable associated with this session (workflow, task etc)",
|
||||
@@ -124,6 +129,7 @@ class BrowserSessionResponse(BaseModel):
|
||||
return cls(
|
||||
browser_session_id=browser_session.persistent_browser_session_id,
|
||||
organization_id=browser_session.organization_id,
|
||||
status=browser_session.status,
|
||||
runnable_type=browser_session.runnable_type,
|
||||
runnable_id=browser_session.runnable_id,
|
||||
timeout=browser_session.timeout_minutes,
|
||||
|
||||
Reference in New Issue
Block a user