Files
fckbot/rag/alembic/env.py
2026-06-30 22:35:02 +00:00

109 lines
3.7 KiB
Python
Raw 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.
# rag/alembic/env.py
# -*- coding: utf-8 -*-
"""
Среда выполнения Alembic для управления схемой PostgreSQL.
Загружает конфигурацию из проекта (AppConfig) для получения строки подключения.
"""
import asyncio
import os
import sys
from logging.config import fileConfig
from sqlalchemy import engine_from_config, pool
from sqlalchemy.ext.asyncio import AsyncEngine, create_async_engine
from alembic import context
# Добавляем путь к проекту (чтобы импортировать модули)
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
from rag.config_models import AppConfig
from rag.utils.config_loader import load_config
# Это объект конфигурации Alembic, предоставляющий доступ к значениям из alembic.ini
config = context.config
# Настройка логирования (если указано в alembic.ini)
if config.config_file_name is not None:
fileConfig(config.config_file_name)
# Метаданные моделей (если используются SQLAlchemy ORM) пока None
target_metadata = None
def get_app_config() -> AppConfig:
"""
Загружает конфигурацию проекта из переменной окружения или из стандартного пути.
"""
profile_dir = os.environ.get('FCKBOT_PROFILE_DIR')
if profile_dir:
return load_config(profile_dir)
# Если не задано, пробуем стандартные пути (для разработки)
possible_paths = [
'/usr/local/etc/fckbot/bots/metabot', # по умолчанию методолог
'/usr/local/etc/fckbot/profiles/metabot',
'./profiles/metabot',
]
for path in possible_paths:
if os.path.exists(path):
try:
return load_config(path)
except Exception:
continue
raise RuntimeError(
"Не удалось загрузить конфигурацию проекта. "
"Установите переменную окружения FCKBOT_PROFILE_DIR с путём к профилю бота."
)
def run_migrations_offline() -> None:
"""
Запуск миграций в офлайн-режиме (без подключения к БД).
"""
app_config = get_app_config()
url = app_config.db_url # должно быть свойство, которое формирует URL
context.configure(
url=url,
target_metadata=target_metadata,
literal_binds=True,
dialect_opts={"paramstyle": "named"},
)
with context.begin_transaction():
context.run_migrations()
async def run_migrations_online() -> None:
"""
Запуск миграций в онлайн-режиме (с подключением к БД).
"""
app_config = get_app_config()
url = app_config.db_url
# Создаём асинхронный движок
connectable = create_async_engine(
url,
poolclass=pool.NullPool,
)
async with connectable.connect() as connection:
await connection.run_sync(do_run_migrations)
await connectable.dispose()
def do_run_migrations(connection):
"""
Выполняет миграции на синхронном соединении (обёртка для асинхронного).
"""
context.configure(connection=connection, target_metadata=target_metadata)
with context.begin_transaction():
context.run_migrations()
if context.is_offline_mode():
run_migrations_offline()
else:
asyncio.run(run_migrations_online())