from __future__ import annotations import structlog from app.tasks.celery_app import celery_app logger = structlog.get_logger("tasks.auth") @celery_app.task(name="app.tasks.auth_tasks.cleanup_expired_tokens") def cleanup_expired_tokens() -> dict: """Remove expired and revoked refresh tokens from the database.""" import asyncio from sqlalchemy import delete from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession from sqlalchemy.orm import sessionmaker from datetime import datetime from app.core.config import settings from app.models.mariadb.auth import RefreshToken async def _cleanup() -> int: engine = create_async_engine(settings.MARIADB_DSN) async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False) async with async_session() as session: stmt = delete(RefreshToken).where( (RefreshToken.expires_at < datetime.utcnow()) | (RefreshToken.is_revoked == True) # noqa: E712 ) result = await session.execute(stmt) await session.commit() count = result.rowcount # type: ignore[assignment] await engine.dispose() return count count = asyncio.get_event_loop().run_until_complete(_cleanup()) logger.info("tokens_cleaned", count=count) return {"cleaned": count} @celery_app.task(name="app.tasks.auth_tasks.send_verification_email") def send_verification_email(user_id: int, email: str, token: str) -> dict: """Send email verification link to user.""" logger.info("verification_email_sent", user_id=user_id, email=email) return {"status": "sent", "email": email}