Редактировать env.py

This commit is contained in:
Markov Andrey
2026-06-30 22:35:02 +00:00
parent bf9a21721a
commit 44e9fc1927

View File

@@ -1,46 +1,109 @@
from logging.config import fileConfig
from sqlalchemy import pool
from sqlalchemy.ext.asyncio import create_async_engine
from alembic import context
import asyncio
# 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 run_migrations_offline():
url = config.get_main_option("sqlalchemy.url")
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()
def run_migrations_online():
async def run_migrations_online() -> None:
"""
Запуск миграций в онлайн-режиме (с подключением к БД).
"""
app_config = get_app_config()
url = app_config.db_url
# Создаём асинхронный движок
connectable = create_async_engine(
config.get_main_option("sqlalchemy.url"),
url,
poolclass=pool.NullPool,
)
async def run_async_migrations():
async with connectable.connect() as connection:
await connection.run_sync(do_run_migrations)
await connectable.dispose()
async with connectable.connect() as connection:
await connection.run_sync(do_run_migrations)
def do_run_migrations(connection):
context.configure(connection=connection, target_metadata=target_metadata)
with context.begin_transaction():
context.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()
asyncio.run(run_async_migrations())
if context.is_offline_mode():
run_migrations_offline()
else:
run_migrations_online()
asyncio.run(run_migrations_online())