feature: воркер удаляет профили, не использованные PROFILE_TTL_DAYS дней (#20)

Отметка последнего использования — mtime файла в профиле, ставится при открытии и
закрытии окна. Очистка при старте воркера и раз в час; профили с открытым окном
(на этом воркере или по ключу сессии в Redis) не трогаются.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
protokeyandClaude Opus 5.5 committed 2026-10-13 20:58:56 +04:00
1 parent 1075267d27
commit 4c8394eb4c
6 files changed
+97 -8

No files matched your search

+17 -5
View File
@@ -31,10 +31,11 @@ BROWSER_SLOTS = int(os.getenv("BROWSER_SLOTS", "4"))
# через сколько задача без свободного слота снова попадёт в очередь
NO_SLOT_DELAY_MS = 2000
HEARTBEAT_INTERVAL = 10
PROFILE_CLEANUP_INTERVAL = 3600
TASK_TIME_LIMIT_MS = task_store.RUNNING_TTL * 1000
_pool: WindowPool | None = None
_background: asyncio.Task | None = None
_background: list[asyncio.Task] = []
def _run(coro):
@@ -52,17 +53,28 @@ async def _heartbeat_loop(pool: WindowPool) -> None:
await asyncio.sleep(HEARTBEAT_INTERVAL)
async def _cleanup_loop(pool: WindowPool) -> None:
"""Удаление старых профилей: сразу при старте и затем раз в час."""
while True:
try:
await pool.cleanup_profiles()
except Exception:
log.warning("profile cleanup failed", exc_info=True)
await asyncio.sleep(PROFILE_CLEANUP_INTERVAL)
async def _start() -> None:
global _pool, _background
global _pool
_pool = WindowPool(task_store.TaskStore(task_store.connect()), WORKER_ID, BROWSER_SLOTS)
await _pool.report()
_background = asyncio.create_task(_heartbeat_loop(_pool))
_background.extend([asyncio.create_task(_heartbeat_loop(_pool)), asyncio.create_task(_cleanup_loop(_pool))])
log.info("worker %s: %d browser slots, queues %s, %s", WORKER_ID, BROWSER_SLOTS, COMMON_QUEUE, personal_queue(WORKER_ID))
async def _stop() -> None:
if _background:
_background.cancel()
for task in _background:
task.cancel()
_background.clear()
await _pool.close_all()
await _pool.store.remove_worker(WORKER_ID)