Небольшие изменения
This commit is contained in:
@@ -13,27 +13,6 @@ from app.taskiq.broker import refresh_schedules
|
||||
|
||||
router = APIRouter(prefix="/api/v1")
|
||||
|
||||
|
||||
@router.post("/migrate/start")
|
||||
async def start_migration(background_tasks: BackgroundTasks, full_reload: bool = False):
|
||||
"""Запуск миграции"""
|
||||
if migrator.is_running:
|
||||
raise HTTPException(status_code=400, detail="Миграция уже выполняется")
|
||||
|
||||
background_tasks.add_task(run_migration_task, full_reload)
|
||||
return {"message": "Миграция запущена", "full_reload": full_reload}
|
||||
|
||||
|
||||
@router.post("/migrate/stop")
|
||||
async def stop_migration():
|
||||
migrator.stop_migration()
|
||||
return {"message": "Миграция останавливается"}
|
||||
|
||||
|
||||
@router.get("/migrate/status")
|
||||
async def get_status():
|
||||
return migrator.get_status()
|
||||
|
||||
@router.get("/replication/last")
|
||||
async def get_last_replication():
|
||||
"""Получить информацию о последней репликации (максимальное время по всем таблицам)"""
|
||||
@@ -64,14 +43,14 @@ async def get_tables_status():
|
||||
}
|
||||
|
||||
|
||||
@router.get("/replication/tables/{table_name}")
|
||||
async def get_table_status(table_name: str):
|
||||
@router.get("/replication/tables/{metadata_id}")
|
||||
async def get_table_status(metadata_id: int):
|
||||
"""Получить статус конкретной таблицы"""
|
||||
from app.repository.replication_metadata_repo import replication_metadata_repo
|
||||
|
||||
metadata = replication_metadata_repo.get_table_metadata(table_name)
|
||||
metadata = replication_metadata_repo.get_table_metadata(metadata_id)
|
||||
if not metadata:
|
||||
raise HTTPException(status_code=404, detail=f"Таблица {table_name} не найдена")
|
||||
raise HTTPException(status_code=404, detail=f"Метадата с ID={metadata_id} не найдена")
|
||||
|
||||
return {
|
||||
"table": metadata.table_name,
|
||||
@@ -85,29 +64,34 @@ async def get_table_status(table_name: str):
|
||||
}
|
||||
|
||||
|
||||
@router.post("/replication/tables/{table_name}/reset")
|
||||
async def reset_table(table_name: str):
|
||||
"""Сбросить состояние таблицы (обнулить last_id и last_sync_time)"""
|
||||
from app.repository.replication_metadata_repo import replication_metadata_repo
|
||||
|
||||
session = replication_metadata_repo.get_session()
|
||||
@router.post("/replication/tables")
|
||||
async def add_metadata(
|
||||
table_name: str = Query(None, description="Наименование таблицы"),
|
||||
life_table_name: Optional[str] = Query(None, description="Наименование Life таблицы"),
|
||||
description: Optional[str] = Query(None, description="Описание"),
|
||||
enabled: bool = Query(True, description="Включено"),
|
||||
):
|
||||
"""Добавить метадату"""
|
||||
try:
|
||||
metadata = session.query(ReplicationMetadata).filter_by(table_name=table_name).first()
|
||||
from app.repository.replication_metadata_repo import replication_metadata_repo
|
||||
|
||||
metadata = replication_metadata_repo.add_metadata(
|
||||
table_name=table_name,
|
||||
life_table_name=life_table_name,
|
||||
description=description,
|
||||
enabled=enabled,
|
||||
)
|
||||
|
||||
if metadata:
|
||||
metadata.last_id = 0
|
||||
metadata.last_sync_time = datetime(1900, 1, 1)
|
||||
metadata.total_rows = 0
|
||||
metadata.last_error = None
|
||||
metadata.updated_at = datetime.now()
|
||||
session.commit()
|
||||
|
||||
migration_logger.info(f"Сброшено состояние таблицы {table_name}")
|
||||
return {"message": f"Состояние таблицы {table_name} сброшено"}
|
||||
return {
|
||||
"message": f"Метадата для таблицы {metadata.table_name} создана",
|
||||
"metadata": metadata
|
||||
}
|
||||
else:
|
||||
raise HTTPException(status_code=404, detail=f"Таблица {table_name} не найдена")
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
raise HTTPException(status_code=500, detail="Ошибка создания метадаты")
|
||||
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
|
||||
@router.get("/replication/logs")
|
||||
async def get_replication_logs(
|
||||
@@ -146,26 +130,6 @@ async def get_replication_logs(
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
@router.post("/test-email")
|
||||
async def test_email():
|
||||
"""Тест отправки email"""
|
||||
success = email_sender.send_email(
|
||||
subject="Тестовое письмо",
|
||||
body=f"Это тестовое письмо от Migration Service\n\nВремя: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
|
||||
)
|
||||
if success:
|
||||
return {"message": "Тестовое письмо отправлено"}
|
||||
else:
|
||||
raise HTTPException(status_code=500, detail="Ошибка отправки письма")
|
||||
|
||||
|
||||
def run_migration_task(full_reload: bool):
|
||||
try:
|
||||
migrator.run_migration(full_reload=full_reload)
|
||||
except Exception as e:
|
||||
migration_logger.error("Ошибка в фоновой задаче", e)
|
||||
|
||||
|
||||
# ==================== РАСПИСАНИЯ ====================
|
||||
|
||||
@router.get("/schedules")
|
||||
@@ -203,10 +167,10 @@ async def get_next_runs(limit: int = 10):
|
||||
|
||||
if time_diff <= 1 and check_weekday in schedule.days_list:
|
||||
# Получаем статистику таблицы
|
||||
metadata = replication_metadata_repo.get_table_metadata(schedule.table_name)
|
||||
metadata = schedule.table
|
||||
|
||||
runs.append({
|
||||
'table': schedule.table_name,
|
||||
'table': metadata.table_name,
|
||||
'time': check_time.strftime('%Y-%m-%d %H:%M'),
|
||||
'day': check_time.strftime('%A'),
|
||||
'days_schedule': schedule.days_display,
|
||||
@@ -224,37 +188,37 @@ async def get_next_runs(limit: int = 10):
|
||||
return runs[:limit]
|
||||
|
||||
|
||||
@router.post("/schedules/run-now")
|
||||
async def run_scheduled_now(background_tasks: BackgroundTasks):
|
||||
"""Принудительно запустить все запланированные на текущее время миграции"""
|
||||
due = scheduler.get_due_tables()
|
||||
if not due:
|
||||
return {'message': 'Нет таблиц для миграции в текущее время и день'}
|
||||
# @router.post("/schedules/run-now")
|
||||
# async def run_scheduled_now(background_tasks: BackgroundTasks):
|
||||
# """Принудительно запустить все запланированные на текущее время миграции"""
|
||||
# due = scheduler.get_due_tables()
|
||||
# if not due:
|
||||
# return {'message': 'Нет таблиц для миграции в текущее время и день'}
|
||||
|
||||
for schedule in due:
|
||||
background_tasks.add_task(
|
||||
run_scheduled_migration,
|
||||
schedule.table_name,
|
||||
schedule.full_reload
|
||||
)
|
||||
# for schedule in due:
|
||||
# background_tasks.add_task(
|
||||
# run_scheduled_migration,
|
||||
# schedule.table.table_name,
|
||||
# schedule.full_reload
|
||||
# )
|
||||
|
||||
return {
|
||||
'message': f'Запущено {len(due)} миграций',
|
||||
'tables': [
|
||||
{
|
||||
'name': s.table_name,
|
||||
'time': s.schedule_time.strftime("%H:%M"),
|
||||
'days': s.days_display,
|
||||
'full_reload': s.full_reload
|
||||
}
|
||||
for s in due
|
||||
]
|
||||
}
|
||||
# return {
|
||||
# 'message': f'Запущено {len(due)} миграций',
|
||||
# 'tables': [
|
||||
# {
|
||||
# 'name': s.table.table_name,
|
||||
# 'time': s.schedule_time.strftime("%H:%M"),
|
||||
# 'days': s.days_display,
|
||||
# 'full_reload': s.full_reload
|
||||
# }
|
||||
# for s in due
|
||||
# ]
|
||||
# }
|
||||
|
||||
|
||||
@router.post("/schedules/{table_name}")
|
||||
async def set_schedule(
|
||||
table_name: str,
|
||||
metadata_id: int = Query('ID', description="ID метадаты таблицы"),
|
||||
schedule_time: str = Query("00:00", description="Время в формате HH:MM"),
|
||||
days: Optional[str] = Query(None, description="Дни недели через запятую: пн,вт,ср,чт,пт,сб,вс"),
|
||||
full_reload: bool = Query(False, description="Полная перезагрузка"),
|
||||
@@ -264,8 +228,8 @@ async def set_schedule(
|
||||
):
|
||||
"""Добавить новое расписание для таблицы"""
|
||||
try:
|
||||
if table_name not in settings.TABLES_TO_COPY:
|
||||
raise HTTPException(status_code=404, detail=f"Таблица {table_name} не найдена")
|
||||
# if table_name not in settings.TABLES_TO_COPY:
|
||||
# raise HTTPException(status_code=404, detail=f"Таблица {table_name} не найдена")
|
||||
|
||||
days_list = None
|
||||
if days:
|
||||
@@ -274,7 +238,7 @@ async def set_schedule(
|
||||
from app.repository.replication_metadata_repo import replication_metadata_repo
|
||||
|
||||
schedule = replication_metadata_repo.add_schedule(
|
||||
table_name=table_name,
|
||||
metadata_id=metadata_id,
|
||||
schedule_time=schedule_time,
|
||||
days=days_list,
|
||||
full_reload=full_reload,
|
||||
@@ -286,7 +250,7 @@ async def set_schedule(
|
||||
if schedule:
|
||||
await refresh_schedules()
|
||||
return {
|
||||
"message": f"Расписание добавлено для {table_name} в {schedule_time}",
|
||||
"message": f"Расписание добавлено",
|
||||
"schedule": schedule
|
||||
}
|
||||
else:
|
||||
@@ -295,19 +259,25 @@ async def set_schedule(
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
|
||||
@router.get("/schedules/{table_name}")
|
||||
async def get_table_schedule(table_name: str):
|
||||
@router.get("/schedules/{metadata_id}")
|
||||
async def get_table_schedule(metadata_id: int):
|
||||
"""Получить расписание для конкретной таблицы"""
|
||||
schedule = replication_metadata_repo.get_schedule(table_name)
|
||||
if not schedule:
|
||||
schedules = replication_metadata_repo.get_schedule(metadata_id)
|
||||
if not schedules:
|
||||
raise HTTPException(status_code=404, detail="Расписание не найдено")
|
||||
|
||||
# Получаем статистику таблицы
|
||||
metadata = replication_metadata_repo.get_table_metadata(table_name)
|
||||
metadata = replication_metadata_repo.get_table_metadata(metadata_id)
|
||||
|
||||
result = schedule.to_dict()
|
||||
result = {}
|
||||
result['schedules'] = []
|
||||
|
||||
for schedule in schedules:
|
||||
result['schedules'].append(schedule)
|
||||
|
||||
if metadata:
|
||||
result['table_stats'] = {
|
||||
'table_name': metadata.table_name,
|
||||
'rows_count': metadata.total_rows,
|
||||
'last_sync': metadata.last_sync_time.isoformat() if metadata.last_sync_time else None,
|
||||
'last_id': metadata.last_id
|
||||
@@ -350,72 +320,71 @@ async def update_schedule(
|
||||
else:
|
||||
raise HTTPException(status_code=404, detail=f"Расписание {schedule_id} не найдено")
|
||||
|
||||
@router.post("/schedules/{table_name}/disable")
|
||||
async def disable_schedule(table_name: str):
|
||||
@router.post("/schedules/{schedule_id}/disable")
|
||||
async def disable_schedule(schedule_id: int):
|
||||
"""Отключить расписание"""
|
||||
success = replication_metadata_repo.disable_schedule(table_name)
|
||||
success = replication_metadata_repo.disable_schedule(schedule_id)
|
||||
if success:
|
||||
await refresh_schedules()
|
||||
return {'message': f'Расписание для {table_name} отключено'}
|
||||
return {'message': f'Расписание отключено'}
|
||||
else:
|
||||
raise HTTPException(status_code=404, detail=f"Расписание для {table_name} не найдено")
|
||||
raise HTTPException(status_code=404, detail=f"Расписание с ID={schedule_id} не найдено")
|
||||
|
||||
|
||||
@router.post("/schedules/{table_name}/enable")
|
||||
async def enable_schedule(table_name: str):
|
||||
@router.post("/schedules/{schedule_id}/enable")
|
||||
async def enable_schedule(schedule_id: int):
|
||||
"""Включить расписание"""
|
||||
success = replication_metadata_repo.enable_schedule(table_name)
|
||||
success = replication_metadata_repo.enable_schedule(schedule_id)
|
||||
if success:
|
||||
await refresh_schedules()
|
||||
return {'message': f'Расписание для {table_name} включено'}
|
||||
return {'message': f'Расписание включено'}
|
||||
else:
|
||||
raise HTTPException(status_code=404, detail=f"Расписание для {table_name} не найдено")
|
||||
raise HTTPException(status_code=404, detail=f"Расписание с ID={schedule_id} не найдено")
|
||||
|
||||
# ==================== Фоновые задачи ====================
|
||||
|
||||
def run_migration_task(full_reload: bool):
|
||||
"""Фоновая задача для миграции всех таблиц"""
|
||||
try:
|
||||
migrator.run_migration(full_reload=full_reload)
|
||||
except Exception as e:
|
||||
migration_logger.error(f"Ошибка в фоновой задаче: {e}")
|
||||
migration_logger.exception(e)
|
||||
# def run_migration_task(full_reload: bool):
|
||||
# """Фоновая задача для миграции всех таблиц"""
|
||||
# try:
|
||||
# migrator.run_migration(full_reload=full_reload)
|
||||
# except Exception as e:
|
||||
# migration_logger.error(f"Ошибка в фоновой задаче: {e}")
|
||||
|
||||
|
||||
def run_scheduled_migration(table_name: str, full_reload: bool):
|
||||
"""Фоновая задача для запланированной миграции одной таблицы"""
|
||||
try:
|
||||
migration_logger.info(f"Запуск запланированной миграции для {table_name}")
|
||||
# def run_scheduled_migration(table_name: str, full_reload: bool):
|
||||
# """Фоновая задача для запланированной миграции одной таблицы"""
|
||||
# try:
|
||||
# migration_logger.info(f"Запуск запланированной миграции для {table_name}")
|
||||
|
||||
migrator.run_migration(
|
||||
tables=[table_name],
|
||||
full_reload=full_reload,
|
||||
send_email=True
|
||||
)
|
||||
# migrator.run_migration(
|
||||
# tables=[table_name],
|
||||
# full_reload=full_reload,
|
||||
# send_email=True
|
||||
# )
|
||||
|
||||
# Обновляем время последнего запуска в расписании
|
||||
replication_metadata_repo.update_schedule_last_run(table_name)
|
||||
# # Обновляем время последнего запуска в расписании
|
||||
# replication_metadata_repo.update_schedule_last_run(table_name)
|
||||
|
||||
# Логируем успешный запуск
|
||||
replication_metadata_repo.log_operation(
|
||||
table_name=table_name,
|
||||
operation='SCHEDULED',
|
||||
records_count=0,
|
||||
status='SUCCESS'
|
||||
)
|
||||
# # Логируем успешный запуск
|
||||
# replication_metadata_repo.log_operation(
|
||||
# table_name=table_name,
|
||||
# operation='SCHEDULED',
|
||||
# records_count=0,
|
||||
# status='SUCCESS'
|
||||
# )
|
||||
|
||||
migration_logger.info(f"Запланированная миграция для {table_name} завершена")
|
||||
# migration_logger.info(f"Запланированная миграция для {table_name} завершена")
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Ошибка в запланированной миграции для {table_name}: {e}"
|
||||
migration_logger.error(error_msg)
|
||||
migration_logger.exception(e)
|
||||
# except Exception as e:
|
||||
# error_msg = f"Ошибка в запланированной миграции для {table_name}: {e}"
|
||||
# migration_logger.error(error_msg)
|
||||
# migration_logger.exception(e)
|
||||
|
||||
# Логируем ошибку
|
||||
replication_metadata_repo.log_operation(
|
||||
table_name=table_name,
|
||||
operation='SCHEDULED',
|
||||
records_count=0,
|
||||
status='ERROR',
|
||||
error_message=str(e)[:500]
|
||||
)
|
||||
# # Логируем ошибку
|
||||
# replication_metadata_repo.log_operation(
|
||||
# table_name=table_name,
|
||||
# operation='SCHEDULED',
|
||||
# records_count=0,
|
||||
# status='ERROR',
|
||||
# error_message=str(e)[:500]
|
||||
# )
|
||||
Reference in New Issue
Block a user