Небольшие изменения
This commit is contained in:
@@ -2,7 +2,9 @@
|
||||
|
||||
from typing import Optional, List
|
||||
from datetime import datetime
|
||||
from sqlalchemy.orm import Session
|
||||
from fastapi import HTTPException
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.orm import Session, selectinload
|
||||
from app.core.database import db_connector
|
||||
from app.models.replication import ReplicationMetadata, ReplicationLog, ReplicationSchedule
|
||||
from app.core.logging import migration_logger
|
||||
@@ -21,25 +23,25 @@ class ReplicationMetadataRepo:
|
||||
Base.metadata.create_all(self.engine)
|
||||
migration_logger.info("Таблица replication_metadata создана/проверена")
|
||||
|
||||
def get_table_metadata(self, table_name: str) -> Optional[ReplicationMetadata]:
|
||||
def get_table_metadata(self, metadata_id: int) -> Optional[ReplicationMetadata]:
|
||||
"""Получает метаданные для таблицы"""
|
||||
session = self.SessionLocal()
|
||||
try:
|
||||
metadata = session.query(ReplicationMetadata).filter_by(
|
||||
table_name=table_name
|
||||
id=metadata_id
|
||||
).first()
|
||||
|
||||
# Если нет, создаем
|
||||
if not metadata:
|
||||
metadata = ReplicationMetadata.create_if_not_exists(session, table_name)
|
||||
# if not metadata:
|
||||
# metadata = ReplicationMetadata.create_if_not_exists(session, table_name)
|
||||
|
||||
return metadata
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
def get_last_sync_time(self, table_name: str) -> Optional[datetime]:
|
||||
def get_last_sync_time(self, metadata_id: int) -> Optional[datetime]:
|
||||
"""Получает время последней синхронизации таблицы"""
|
||||
metadata = self.get_table_metadata(table_name)
|
||||
metadata = self.get_table_metadata(metadata_id)
|
||||
return metadata.last_sync_time if metadata else None
|
||||
|
||||
def get_last_id(self, table_name: str) -> Optional[int]:
|
||||
@@ -47,31 +49,29 @@ class ReplicationMetadataRepo:
|
||||
metadata = self.get_table_metadata(table_name)
|
||||
return metadata.last_id if metadata else None
|
||||
|
||||
def update_sync_time(self, table_name: str) -> bool:
|
||||
def update_sync_time(self, schedule_id: int) -> bool:
|
||||
"""Обновляет время синхронизации таблицы"""
|
||||
session = self.SessionLocal()
|
||||
try:
|
||||
metadata = session.query(ReplicationMetadata).filter_by(
|
||||
table_name=table_name
|
||||
schedule = session.query(ReplicationSchedule).filter_by(
|
||||
id=schedule_id
|
||||
).first()
|
||||
|
||||
if not metadata:
|
||||
metadata = ReplicationMetadata(
|
||||
table_name=table_name,
|
||||
last_sync_time=datetime.now(),
|
||||
last_id=0
|
||||
)
|
||||
session.add(metadata)
|
||||
if not schedule:
|
||||
return False
|
||||
else:
|
||||
metadata.last_sync_time = datetime.now()
|
||||
metadata.updated_at = datetime.now()
|
||||
datenow = datetime.now()
|
||||
schedule.last_run = datenow
|
||||
metadata = schedule.table
|
||||
metadata.last_sync_time = datenow
|
||||
metadata.updated_at = datenow
|
||||
|
||||
session.commit()
|
||||
migration_logger.debug(f"Updated sync time for {table_name} to {metadata.last_sync_time}")
|
||||
migration_logger.debug(f"Updated sync time for {metadata.table_name} to {metadata.last_sync_time}")
|
||||
return True
|
||||
except Exception as e:
|
||||
session.rollback()
|
||||
migration_logger.error(f"Error updating sync time for {table_name}: {e}")
|
||||
migration_logger.error(f"Ошибка при обновлении времени синхронизации распиания с ID: {schedule_id}: {e}")
|
||||
return False
|
||||
finally:
|
||||
session.close()
|
||||
@@ -80,20 +80,16 @@ class ReplicationMetadataRepo:
|
||||
"""Обновляет последний обработанный ID"""
|
||||
session = self.SessionLocal()
|
||||
try:
|
||||
metadata = session.query(ReplicationMetadata).filter_by(
|
||||
metadatas = session.query(ReplicationMetadata).filter_by(
|
||||
table_name=table_name
|
||||
).first()
|
||||
).all()
|
||||
|
||||
if not metadata:
|
||||
metadata = ReplicationMetadata(
|
||||
table_name=table_name,
|
||||
last_sync_time=datetime.now(),
|
||||
last_id=last_id
|
||||
)
|
||||
session.add(metadata)
|
||||
if not metadatas:
|
||||
return False
|
||||
else:
|
||||
metadata.last_id = last_id
|
||||
metadata.updated_at = datetime.now()
|
||||
for metadata in metadatas:
|
||||
metadata.last_id = last_id
|
||||
metadata.updated_at = datetime.now()
|
||||
|
||||
session.commit()
|
||||
migration_logger.debug(f"Updated last_id for {table_name} to {last_id}")
|
||||
@@ -186,37 +182,74 @@ class ReplicationMetadataRepo:
|
||||
|
||||
# ========== Методы для расписаний ==========
|
||||
|
||||
def init_default_schedules(self, table_names: List[str]):
|
||||
def init_default_schedules(self, metadatas: List[ReplicationMetadata]):
|
||||
"""Инициализирует расписания по умолчанию для списка таблиц"""
|
||||
session = self.get_session()
|
||||
try:
|
||||
for table_name in table_names:
|
||||
init_count = 0
|
||||
for metadata in metadatas:
|
||||
# Проверяем, есть ли уже расписание
|
||||
schedule = session.query(ReplicationSchedule).filter_by(
|
||||
table_name=table_name
|
||||
).first()
|
||||
query = session.query(ReplicationSchedule).filter_by(
|
||||
metadata_id=metadata.id
|
||||
)
|
||||
|
||||
schedule_exist = session.query(query.exists())
|
||||
|
||||
if not schedule:
|
||||
if not schedule_exist:
|
||||
job_name = f"{metadata.table_name} - расписание по умолчанию"
|
||||
# Создаем расписание по умолчанию (каждый день в 00:00)
|
||||
schedule = ReplicationSchedule(
|
||||
table_name=table_name,
|
||||
metadata_id=metadata.id,
|
||||
name=job_name,
|
||||
schedule_time=datetime.strptime("00:00", "%H:%M").time(),
|
||||
days=[], # Пустой список = все дни
|
||||
full_reload=False,
|
||||
enabled=True
|
||||
enabled=False
|
||||
)
|
||||
session.add(schedule)
|
||||
migration_logger.debug(f"Создано расписание по умолчанию для {table_name}")
|
||||
migration_logger.debug(f"Создано расписание по умолчанию для {metadata.table_name}")
|
||||
init_count += 1
|
||||
|
||||
session.commit()
|
||||
migration_logger.info(f"Инициализированы расписания по умолчанию для {len(table_names)} таблиц")
|
||||
migration_logger.info(f"Инициализированы расписания по умолчанию для {init_count} таблиц")
|
||||
except Exception as e:
|
||||
session.rollback()
|
||||
migration_logger.error(f"Ошибка инициализации расписаний: {e}")
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
def add_metadata(self, table_name: str, life_table_name: Optional[str] = None,
|
||||
description: Optional[str] = None, enabled: Optional[bool] = False) -> Optional[ReplicationMetadata]:
|
||||
"""Добавить метадату"""
|
||||
session = self.get_session()
|
||||
try:
|
||||
metadata_exists = session.query(ReplicationMetadata).filter_by(
|
||||
table_name=table_name
|
||||
).first()
|
||||
|
||||
if metadata_exists:
|
||||
raise HTTPException(status_code=400, detail=f"Метадата с таблицей {metadata_exists.table_name} существует")
|
||||
|
||||
metadata = ReplicationMetadata(
|
||||
table_name=table_name,
|
||||
life_table_name=life_table_name,
|
||||
description=description,
|
||||
is_active=enabled
|
||||
)
|
||||
|
||||
session.add(metadata)
|
||||
session.commit()
|
||||
|
||||
migration_logger.info(f"Добавлена новая метадата для {metadata.table_name}")
|
||||
return metadata
|
||||
except Exception as e:
|
||||
session.rollback()
|
||||
migration_logger.error(f"Ошибка добавления расписания: {e}")
|
||||
return None
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
def add_schedule(self, table_name: str, schedule_time: str, days: Optional[List[str]] = None,
|
||||
def add_schedule(self, metadata_id: int, schedule_time: str, days: Optional[List[str]] = None,
|
||||
full_reload: bool = False, enabled: bool = True,
|
||||
name: Optional[str] = None, description: Optional[str] = None) -> Optional[ReplicationSchedule]:
|
||||
"""Добавить НОВОЕ расписание для таблицы"""
|
||||
@@ -224,33 +257,33 @@ class ReplicationMetadataRepo:
|
||||
try:
|
||||
# Проверяем, существует ли метаданные
|
||||
metadata = session.query(ReplicationMetadata).filter_by(
|
||||
table_name=table_name
|
||||
id=metadata_id
|
||||
).first()
|
||||
|
||||
if not metadata:
|
||||
metadata = self._create_metadata(session, table_name)
|
||||
raise HTTPException(status_code=404, detail=f"Метадата с ID {metadata_id} не найдена")
|
||||
|
||||
# Парсим время
|
||||
time_obj = datetime.strptime(schedule_time, "%H:%M").time()
|
||||
|
||||
# Создаем новое расписание
|
||||
schedule = ReplicationSchedule(
|
||||
table_name=table_name,
|
||||
metadata_id=metadata_id,
|
||||
schedule_time=time_obj,
|
||||
days=days if days else [],
|
||||
full_reload=full_reload,
|
||||
enabled=enabled,
|
||||
name=name or f"{schedule_time} - {'полная' if full_reload else 'инкремент'}",
|
||||
name=name or f"{metadata.table_name} - {'полная' if full_reload else 'инкремент'}",
|
||||
description=description
|
||||
)
|
||||
session.add(schedule)
|
||||
session.commit()
|
||||
|
||||
migration_logger.info(f"Добавлено новое расписание для {table_name} в {schedule_time}")
|
||||
migration_logger.info(f"Добавлено новое расписание для {metadata.table_name} в {schedule_time}")
|
||||
return schedule.to_dict()
|
||||
except Exception as e:
|
||||
session.rollback()
|
||||
migration_logger.error(f"Ошибка добавления расписания для {table_name}: {e}")
|
||||
migration_logger.error(f"Ошибка добавления расписания: {e}")
|
||||
return None
|
||||
finally:
|
||||
session.close()
|
||||
@@ -266,7 +299,7 @@ class ReplicationMetadataRepo:
|
||||
if schedule:
|
||||
session.delete(schedule)
|
||||
session.commit()
|
||||
migration_logger.info(f"Удалено расписание ID={schedule_id} для {schedule.table_name}")
|
||||
migration_logger.info(f"Удалено расписание ID={schedule_id} для {schedule.table.table_name}")
|
||||
return True
|
||||
return False
|
||||
except Exception as e:
|
||||
@@ -303,12 +336,12 @@ class ReplicationMetadataRepo:
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
def get_schedule(self, table_name: str) -> List[ReplicationSchedule]:
|
||||
def get_schedule(self, metadata_id: int) -> List[ReplicationSchedule]:
|
||||
"""Получает расписание для таблицы"""
|
||||
session = self.get_session()
|
||||
try:
|
||||
schedule = session.query(ReplicationSchedule).filter_by(
|
||||
table_name=table_name
|
||||
metadata_id=metadata_id
|
||||
).all()
|
||||
return schedule
|
||||
finally:
|
||||
@@ -318,7 +351,24 @@ class ReplicationMetadataRepo:
|
||||
"""Получает все расписания"""
|
||||
session = self.get_session()
|
||||
try:
|
||||
return session.query(ReplicationSchedule).all()
|
||||
schedules = session.execute(
|
||||
select(ReplicationSchedule)
|
||||
.options(selectinload(ReplicationSchedule.table))
|
||||
).scalars().all()
|
||||
|
||||
# Явно пометить сессию как не expiring (чтобы объекты не expire после commit)
|
||||
for schedule in schedules:
|
||||
session.expunge(schedule) # Удалить из сессии, но сохранить данные
|
||||
|
||||
return schedules
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
def get_all_metadata(self) -> List[ReplicationMetadata]:
|
||||
"""Получает все метадаты"""
|
||||
session = self.get_session()
|
||||
try:
|
||||
return session.query(ReplicationMetadata).all()
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
@@ -351,12 +401,12 @@ class ReplicationMetadataRepo:
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
def update_schedule_last_run(self, table_name: str) -> bool:
|
||||
def update_schedule_last_run(self, schedule_id: int) -> bool:
|
||||
"""Обновляет время последнего запуска расписания"""
|
||||
session = self.get_session()
|
||||
try:
|
||||
schedule = session.query(ReplicationSchedule).filter_by(
|
||||
table_name=table_name
|
||||
id=schedule_id
|
||||
).first()
|
||||
|
||||
if schedule:
|
||||
@@ -367,51 +417,51 @@ class ReplicationMetadataRepo:
|
||||
return False
|
||||
except Exception as e:
|
||||
session.rollback()
|
||||
migration_logger.error(f"Ошибка обновления last_run для {table_name}: {e}")
|
||||
migration_logger.error(f"Ошибка обновления last_run: {e}")
|
||||
return False
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
def disable_schedule(self, table_name: str) -> bool:
|
||||
def disable_schedule(self, schedule_id: int) -> bool:
|
||||
"""Отключает расписание"""
|
||||
session = self.get_session()
|
||||
try:
|
||||
schedule = session.query(ReplicationSchedule).filter_by(
|
||||
table_name=table_name
|
||||
id=schedule_id
|
||||
).first()
|
||||
|
||||
if schedule:
|
||||
schedule.enabled = False
|
||||
schedule.updated_at = datetime.now()
|
||||
session.commit()
|
||||
migration_logger.info(f"Отключено расписание для {table_name}")
|
||||
migration_logger.info(f"Отключено расписание ID={schedule_id} для {schedule.table.table_name}")
|
||||
return True
|
||||
return False
|
||||
except Exception as e:
|
||||
session.rollback()
|
||||
migration_logger.error(f"Ошибка отключения расписания для {table_name}: {e}")
|
||||
migration_logger.error(f"Ошибка отключения расписания: {e}")
|
||||
return False
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
def enable_schedule(self, table_name: str) -> bool:
|
||||
def enable_schedule(self, schedule_id: int) -> bool:
|
||||
"""Включает расписание"""
|
||||
session = self.get_session()
|
||||
try:
|
||||
schedule = session.query(ReplicationSchedule).filter_by(
|
||||
table_name=table_name
|
||||
id=schedule_id
|
||||
).first()
|
||||
|
||||
if schedule:
|
||||
schedule.enabled = True
|
||||
schedule.updated_at = datetime.now()
|
||||
session.commit()
|
||||
migration_logger.info(f"Включено расписание для {table_name}")
|
||||
migration_logger.info(f"Включено расписание ID={schedule_id} для {schedule.table.table_name}")
|
||||
return True
|
||||
return False
|
||||
except Exception as e:
|
||||
session.rollback()
|
||||
migration_logger.error(f"Ошибка включения расписания для {table_name}: {e}")
|
||||
migration_logger.error(f"Ошибка включения расписания: {e}")
|
||||
return False
|
||||
finally:
|
||||
session.close()
|
||||
@@ -428,15 +478,16 @@ class ReplicationMetadataRepo:
|
||||
|
||||
session = self.get_session()
|
||||
try:
|
||||
metadata = session.query(ReplicationMetadata).filter_by(
|
||||
metadatas = session.query(ReplicationMetadata).filter_by(
|
||||
table_name=table_name
|
||||
).first()
|
||||
|
||||
if metadata:
|
||||
metadata.total_rows = stats['total_rows']
|
||||
metadata.last_id = stats['max_id']
|
||||
metadata.updated_at = datetime.now()
|
||||
session.commit()
|
||||
).all()
|
||||
|
||||
if metadatas:
|
||||
for metadata in metadatas:
|
||||
metadata.total_rows = stats['total_rows']
|
||||
metadata.last_id = stats['max_id']
|
||||
metadata.updated_at = datetime.now()
|
||||
session.commit()
|
||||
|
||||
migration_logger.info(f"Синхронизирована статистика {table_name}: {stats['total_rows']} строк, max_id={stats['max_id']}")
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user