FastAPI + Celery + Next.js + Postgres/Redis app with company monitoring, source collection, LLM-based change analysis, enrichment, and account security (Turnstile, escalating lockout, email verification).
44 lines
1.4 KiB
Python
44 lines
1.4 KiB
Python
"""Celery Beat-triggered housekeeping. Currently just the data-retention
|
|
purge (DATA_RETENTION_DAYS) - only SourceDocument rows are ever deleted
|
|
here; see SourceDocumentRepository.delete_older_than for why that's the
|
|
only safe target in the current FK graph.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import UTC, datetime, timedelta
|
|
|
|
from structlog.contextvars import bound_contextvars
|
|
|
|
from app.core.config import get_settings
|
|
from app.core.logging import get_logger
|
|
from app.db.session import get_sessionmaker
|
|
from app.repositories.source_repository import SourceDocumentRepository
|
|
from app.tasks.base import run_async_task
|
|
from app.tasks.celery_app import celery_app
|
|
|
|
logger = get_logger(__name__)
|
|
|
|
|
|
@celery_app.task(bind=True, name="app.tasks.maintenance.purge_expired_data")
|
|
def purge_expired_data(self) -> None:
|
|
with bound_contextvars(task_id=self.request.id):
|
|
run_async_task(_purge_expired_data_async())
|
|
|
|
|
|
async def _purge_expired_data_async() -> None:
|
|
settings = get_settings()
|
|
cutoff = datetime.now(UTC) - timedelta(days=settings.data_retention_days)
|
|
|
|
session_factory = get_sessionmaker()
|
|
async with session_factory() as db:
|
|
deleted = await SourceDocumentRepository(db).delete_older_than(cutoff)
|
|
await db.commit()
|
|
|
|
logger.info(
|
|
"data_retention_purge_completed",
|
|
deleted_source_documents=deleted,
|
|
retention_days=settings.data_retention_days,
|
|
cutoff=cutoff.isoformat(),
|
|
)
|