Watch
1
0
Fork
You've already forked Seyyed_arc
0
forked from hesabix/arc
Seyyed_arc/hesabixAPI/app/services/storage_cleanup_service.py
2026-04-14 19:34:55 +03:30

123 lines
3.4 KiB
Python
Executable file

"""
سرویس حذف خودکار فایل‌های کسب‌وکارهایی که grace period تمام شده
"""
from __future__ import annotations
from typing import Dict, Any, List
from datetime import datetime, timedelta
from sqlalchemy.orm import Session
from sqlalchemy import and_, or_
from adapters.db.models.storage_plan import BusinessStorageSubscription
from adapters.db.models.file_storage import FileStorage
from app.services.file_storage_service import FileStorageService
import logging
logger = logging.getLogger(__name__)
def mark_files_for_deletion(
db: Session,
) -> Dict[str, Any]:
"""علامت‌گذاری فایل‌های کسب‌وکارهایی که grace period تمام شده"""
now = datetime.utcnow()
# دریافت کسب‌وکارهایی که grace_period_ends_at گذشته
expired_businesses = db.query(BusinessStorageSubscription.business_id).filter(
and_(
BusinessStorageSubscription.grace_period_ends_at.isnot(None),
BusinessStorageSubscription.grace_period_ends_at < now,
BusinessStorageSubscription.status.in_(["expired", "cancelled"])
)
).distinct().all()
business_ids = [b[0] for b in expired_businesses]
if not business_ids:
return {
"marked_count": 0,
"business_count": 0,
}
# علامت‌گذاری فایل‌های این کسب‌وکارها
marked = db.query(FileStorage).filter(
and_(
FileStorage.business_id.in_(business_ids),
FileStorage.deleted_at.is_(None),
FileStorage.is_marked_for_deletion == False
)
).update({
"is_marked_for_deletion": True,
"marked_for_deletion_at": now
}, synchronize_session=False)
db.commit()
logger.info(f"Marked {marked} files for deletion from {len(business_ids)} businesses")
return {
"marked_count": marked,
"business_count": len(business_ids),
"business_ids": business_ids,
}
async def delete_marked_files(
db: Session,
days_after_mark: int = 7,
) -> Dict[str, Any]:
"""حذف فایل‌های علامت‌گذاری شده (بعد از days_after_mark روز)"""
cutoff_date = datetime.utcnow() - timedelta(days=days_after_mark)
# دریافت فایل‌های علامت‌گذاری شده که زمان حذف آن‌ها رسیده
files_to_delete = db.query(FileStorage).filter(
and_(
FileStorage.is_marked_for_deletion == True,
FileStorage.marked_for_deletion_at.isnot(None),
FileStorage.marked_for_deletion_at < cutoff_date,
FileStorage.deleted_at.is_(None)
)
).all()
deleted_count = 0
failed_count = 0
file_service = FileStorageService(db)
for file_storage in files_to_delete:
try:
# حذف فایل از storage
from uuid import UUID
file_id = UUID(file_storage.id)
await file_service.delete_file(file_id)
deleted_count += 1
except Exception as e:
logger.error(f"Failed to delete file {file_storage.id}: {str(e)}")
failed_count += 1
logger.info(f"Deleted {deleted_count} files, {failed_count} failed")
return {
"deleted_count": deleted_count,
"failed_count": failed_count,
"total_marked": len(files_to_delete),
}
async def cleanup_expired_files(
db: Session,
) -> Dict[str, Any]:
"""اجرای کامل فرآیند پاک‌سازی"""
# مرحله 1: علامت‌گذاری
mark_result = mark_files_for_deletion(db)
# مرحله 2: حذف
delete_result = delete_marked_files(db)
return {
"mark_result": mark_result,
"delete_result": delete_result,
}