102 lines
3.9 KiB
Python
102 lines
3.9 KiB
Python
"""
|
||
Celery задачи для материалов.
|
||
"""
|
||
|
||
from celery import shared_task
|
||
import logging
|
||
from django.utils import timezone
|
||
from datetime import timedelta
|
||
from .models import Material
|
||
from .services import StorageService
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
|
||
@shared_task
|
||
def cleanup_old_unused_materials(days_old=90):
|
||
"""
|
||
Автоматическая очистка старых неиспользуемых материалов.
|
||
|
||
Args:
|
||
days_old: Возраст файлов в днях для удаления (по умолчанию 90)
|
||
|
||
Запускается через Celery Beat.
|
||
"""
|
||
try:
|
||
# Получаем всех пользователей с материалами
|
||
users_with_materials = Material.objects.filter(
|
||
is_deleted=False
|
||
).values_list('owner_id', flat=True).distinct()
|
||
|
||
total_deleted = 0
|
||
total_freed_mb = 0
|
||
|
||
from apps.users.models import User
|
||
|
||
# Оптимизация: получаем всех пользователей одним запросом вместо N запросов GET
|
||
user_ids_list = list(users_with_materials)
|
||
users_dict = {user.id: user for user in User.objects.filter(id__in=user_ids_list)}
|
||
|
||
for user_id in user_ids_list:
|
||
try:
|
||
user = users_dict.get(user_id)
|
||
if not user:
|
||
logger.warning(f'User {user_id} not found')
|
||
continue
|
||
result = StorageService.cleanup_old_unused_files(user, days_old=days_old)
|
||
total_deleted += result['deleted_count']
|
||
total_freed_mb += result['freed_space_mb']
|
||
except Exception as e:
|
||
logger.error(f'Error cleaning up materials for user {user_id}: {e}')
|
||
|
||
logger.info(
|
||
f'Cleanup completed: {total_deleted} materials deleted, '
|
||
f'{total_freed_mb:.2f} MB freed'
|
||
)
|
||
|
||
return f'Удалено {total_deleted} материалов, освобождено {total_freed_mb:.2f} МБ'
|
||
|
||
except Exception as e:
|
||
logger.error(f'Error in cleanup_old_unused_materials: {e}', exc_info=True)
|
||
raise
|
||
|
||
|
||
@shared_task
|
||
def sync_all_storage_quotas():
|
||
"""
|
||
Синхронизация всех квот хранилища с подписками.
|
||
|
||
Запускается периодически для синхронизации квот.
|
||
"""
|
||
try:
|
||
from apps.subscriptions.models import Subscription
|
||
from apps.users.models import User
|
||
|
||
# Получаем всех пользователей с активными подписками
|
||
active_subscriptions = Subscription.objects.filter(
|
||
status='active'
|
||
).select_related('user', 'plan').values_list('user_id', flat=True).distinct()
|
||
|
||
synced_count = 0
|
||
# Оптимизация: получаем всех пользователей одним запросом вместо N запросов GET
|
||
user_ids_list = list(active_subscriptions)
|
||
users_dict = {user.id: user for user in User.objects.filter(id__in=user_ids_list)}
|
||
|
||
for user_id in user_ids_list:
|
||
try:
|
||
user = users_dict.get(user_id)
|
||
if not user:
|
||
logger.warning(f'User {user_id} not found')
|
||
continue
|
||
StorageService.sync_quota_with_subscription(user)
|
||
synced_count += 1
|
||
except Exception as e:
|
||
logger.error(f'Error syncing quota for user {user_id}: {e}')
|
||
|
||
logger.info(f'Synced storage quotas for {synced_count} users')
|
||
return f'Синхронизировано квот для {synced_count} пользователей'
|
||
|
||
except Exception as e:
|
||
logger.error(f'Error in sync_all_storage_quotas: {e}', exc_info=True)
|
||
raise
|