Files
wrapped/app/services/wraps.py
T
Sergey Antropoff e4240a7be5 Init
2026-07-17 15:57:36 +03:00

76 lines
2.3 KiB
Python

from __future__ import annotations
import secrets
from datetime import datetime, timezone
from sqlalchemy import delete, select, update
from sqlalchemy.ext.asyncio import AsyncSession
from app.models import Wrap, WrapStatus
from app.services.client_ip import client_ip, request_meta
from app.services.storage import storage
def new_wrap_id() -> str:
return secrets.token_urlsafe(18).replace("-", "").replace("_", "")[:24]
async def expire_due_wraps(db: AsyncSession) -> int:
now = datetime.now(timezone.utc)
result = await db.execute(
select(Wrap).where(Wrap.status == WrapStatus.pending, Wrap.expires_at <= now)
)
rows = list(result.scalars().all())
for wrap in rows:
try:
await storage.delete(wrap.object_key)
except Exception:
pass
wrap.status = WrapStatus.expired
if rows:
await db.commit()
return len(rows)
async def delete_wrap_object(db: AsyncSession, wrap: Wrap) -> None:
try:
await storage.delete(wrap.object_key)
except Exception:
pass
async def cleanup_expired_meta(db: AsyncSession) -> int:
"""Remove long-expired wrap rows (objects already deleted)."""
now = datetime.now(timezone.utc)
result = await db.execute(
delete(Wrap).where(
Wrap.status.in_([WrapStatus.expired, WrapStatus.consumed]),
Wrap.expires_at < now,
)
)
await db.commit()
return result.rowcount or 0
async def mark_consumed(db: AsyncSession, wrap_id: str) -> Wrap | None:
now = datetime.now(timezone.utc)
result = await db.execute(
update(Wrap)
.where(Wrap.id == wrap_id, Wrap.status == WrapStatus.pending, Wrap.expires_at > now)
.values(status=WrapStatus.consumed, consumed_at=now)
.returning(Wrap)
)
row = result.scalar_one_or_none()
await db.commit()
return row
async def purge_all_wraps(db: AsyncSession) -> dict[str, int]:
"""Force-delete all wrap DB rows and all objects under wraps/ in MinIO."""
count_result = await db.execute(select(Wrap.id))
db_count = len(list(count_result.scalars().all()))
await db.execute(delete(Wrap))
await db.commit()
objects_deleted = await storage.delete_prefix("wraps/")
return {"wraps_deleted": db_count, "objects_deleted": objects_deleted}