uchill/backend/apps/core/tasks.py

93 lines
3.3 KiB
Python

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