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:
@@ -1,8 +1,12 @@
|
||||
from collections.abc import AsyncIterator
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from sqlalchemy.ext.asyncio import AsyncEngine
|
||||
|
||||
from app.config import AccessSettings, RuntimeSettings, Settings, TelegramSettings
|
||||
from app.db.migrate import upgrade
|
||||
from app.db.session import SessionMaker, make_engine, make_sessionmaker
|
||||
from app.texts import Texts, load_texts
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
@@ -22,3 +26,17 @@ def settings(tmp_path: Path) -> Settings:
|
||||
access=AccessSettings(admin_ids=frozenset({ADMIN})),
|
||||
runtime=RuntimeSettings(config_dir=ROOT / "config", heartbeat_file=tmp_path / "hb"),
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def engine() -> AsyncIterator[AsyncEngine]:
|
||||
"""Fresh in-memory SQLite with all migrations applied — the same path the bot takes at startup."""
|
||||
eng = make_engine("sqlite+aiosqlite://")
|
||||
await upgrade(eng)
|
||||
yield eng
|
||||
await eng.dispose()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sessions(engine: AsyncEngine) -> SessionMaker:
|
||||
return make_sessionmaker(engine)
|
||||
|
||||
Reference in New Issue
Block a user