browser sessions v2 - backend (#4515)

Signed-off-by: Benji Visser <benji@093b.org>
This commit is contained in:
Benji Visser
2026-01-21 22:27:16 -05:00
committed by GitHub
parent f781a6f0ef
commit b5ff547a3a
15 changed files with 273 additions and 35 deletions

View File

@@ -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: