uchill/backend/apps/materials/tasks.py

102 lines
3.9 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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