""" Celery задачи для системных операций (бэкапы, очистка и т.д.) """ from celery import shared_task import logging from django.core.management import call_command from django.conf import settings import os logger = logging.getLogger(__name__) @shared_task def backup_database(): """ Автоматическое создание бэкапа базы данных. Запускается через Celery Beat. """ try: backup_dir = os.path.join(settings.BASE_DIR.parent, 'backups', 'database') retention_days = int(os.getenv('BACKUP_RETENTION_DAYS', '30')) logger.info(f'Starting database backup to {backup_dir}') call_command( 'backup_database', output_dir=backup_dir, retention_days=retention_days, compress=True, ) logger.info('Database backup completed successfully') return 'Database backup completed' except Exception as e: logger.error(f'Error creating database backup: {e}', exc_info=True) raise @shared_task def cleanup_old_backups(): """ Очистка старых бэкапов. Удаляет бэкапы старше указанного количества дней. """ try: from datetime import timedelta from django.utils import timezone import glob backup_dir = os.path.join(settings.BASE_DIR.parent, 'backups', 'database') retention_days = int(os.getenv('BACKUP_RETENTION_DAYS', '30')) cutoff_date = timezone.now() - timedelta(days=retention_days) if not os.path.exists(backup_dir): logger.warning(f'Backup directory does not exist: {backup_dir}') return 'Backup directory does not exist' deleted_count = 0 total_size_freed = 0 # Ищем все файлы бэкапов backup_patterns = [ os.path.join(backup_dir, 'db_backup_*.sql'), os.path.join(backup_dir, 'db_backup_*.sql.gz'), ] for pattern in backup_patterns: for backup_file in glob.glob(pattern): try: file_mtime = os.path.getmtime(backup_file) file_date = timezone.datetime.fromtimestamp(file_mtime, tz=timezone.utc) if file_date < cutoff_date: file_size = os.path.getsize(backup_file) os.remove(backup_file) deleted_count += 1 total_size_freed += file_size logger.info(f'Deleted old backup: {os.path.basename(backup_file)}') except Exception as e: logger.error(f'Error deleting backup {backup_file}: {e}') size_mb = total_size_freed / (1024 * 1024) logger.info(f'Cleanup completed: {deleted_count} backups deleted, {size_mb:.2f} MB freed') return f'Deleted {deleted_count} old backups, freed {size_mb:.2f} MB' except Exception as e: logger.error(f'Error cleaning up old backups: {e}', exc_info=True) raise