feat(bot): модель данных, миграции Alembic, FSM в БД, TTL-чистка
- app/db/models.py: 13 таблиц (ARCHITECTURE §2.10); перечисления — VARCHAR + CHECK, JSON → JSONB на Postgres, BIGINT/INTEGER-ключи для SQLite - миграция 0001 (автогенерация + ручная чистка: импорт sa.Text, дубли CHECK) - миграции применяются при старте бота программно (app.db.migrate), script_location из пакета - SqlStorage: FSM aiogram поверх fsm_state — состояние переживает рестарт (перенесено из #4) - cleanup_loop: истёкшие черновики, снимки контейнеров и попытки входа старше суток - тесты: upgrade/downgrade, дрейф моделей и миграций, CHECK, CASCADE, FSM, чистка Refs #5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
"""Alembic environment. Runs on a connection handed over by app.db.migrate (or the CLI via alembic.ini)."""
|
||||
|
||||
import asyncio
|
||||
|
||||
from alembic import context
|
||||
from sqlalchemy.engine import Connection
|
||||
|
||||
from app.config import DatabaseSettings
|
||||
from app.db.models import Base
|
||||
from app.db.session import make_engine
|
||||
|
||||
target_metadata = Base.metadata
|
||||
|
||||
|
||||
def _run(connection: Connection) -> None:
|
||||
context.configure(
|
||||
connection=connection,
|
||||
target_metadata=target_metadata,
|
||||
render_as_batch=connection.dialect.name == "sqlite", # SQLite can't ALTER most things in place
|
||||
compare_type=True,
|
||||
)
|
||||
with context.begin_transaction():
|
||||
context.run_migrations()
|
||||
|
||||
|
||||
async def _run_cli() -> None:
|
||||
engine = make_engine(DatabaseSettings().url)
|
||||
try:
|
||||
async with engine.begin() as conn:
|
||||
await conn.run_sync(_run)
|
||||
finally:
|
||||
await engine.dispose()
|
||||
|
||||
|
||||
connection = context.config.attributes.get("connection")
|
||||
if connection is not None:
|
||||
_run(connection)
|
||||
else:
|
||||
asyncio.run(_run_cli())
|
||||
Reference in New Issue
Block a user