From 9ff2c994198c0caa53d931fc89227c9f21d29112 Mon Sep 17 00:00:00 2001 From: chihlasm Date: Sat, 7 Mar 2026 00:20:37 -0500 Subject: [PATCH] feat: add APScheduler task to auto-archive stale AI chat sessions Archives AI chat sessions with no activity for 30 days, runs daily at 3 AM. Co-Authored-By: Claude Opus 4.6 --- backend/app/main.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/backend/app/main.py b/backend/app/main.py index f8e8c388..dbfedb41 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -22,6 +22,27 @@ setup_logging() logger = logging.getLogger(__name__) +async def archive_stale_ai_sessions(): + """Archive AI chat sessions with no activity for 30 days.""" + from app.models.ai_chat_session import AIChatSession + from sqlalchemy import update + from datetime import datetime, timezone, timedelta + + cutoff = datetime.now(timezone.utc) - timedelta(days=30) + async with async_session_maker() as db: + result = await db.execute( + update(AIChatSession) + .where( + AIChatSession.updated_at < cutoff, + AIChatSession.archived_at.is_(None), + AIChatSession.status != "abandoned", + ) + .values(archived_at=datetime.now(timezone.utc)) + ) + await db.commit() + logger.info(f"[archive] Archived {result.rowcount} stale AI chat sessions") + + def _configure_seed_module(mod: object, api_url: str, email: str, password: str) -> None: """Set globals on a seed script module.""" mod.API_BASE_URL = api_url # type: ignore[attr-defined] @@ -132,6 +153,15 @@ async def lifespan(app: FastAPI): replace_existing=True, ) + # Auto-archive stale AI chat sessions (daily at 3 AM) + scheduler.add_job( + archive_stale_ai_sessions, + "cron", + hour=3, + id="archive_stale_ai_sessions", + replace_existing=True, + ) + # Auto-seed trees in background on PR environments seed_task = None if settings.SEED_ON_DEPLOY: