""" 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