rebase
This commit is contained in:
11
CHANGELOG.md
11
CHANGELOG.md
@@ -4,6 +4,17 @@ All notable changes to AI-RPG are documented here.
|
||||
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [1.0.5] — 2026-06-20
|
||||
|
||||
### Fixed
|
||||
- **app/main.py**: added `create_all_tables(engine)` call at the start of `lifespan`. Without this, the backend started but crashed on every DB query with `relation "settings" does not exist` because tables were never created in PostgreSQL. Tables are now created idempotently on every startup via `Base.metadata.create_all` ( SQLAlchemy skips tables that already exist).
|
||||
- **app/main.py**: also added `seed_builtin_presets(session)` call so the 2 builtin presets (Classic Fantasy, Deep Space Outpost) are seeded on first startup, not just settings.
|
||||
- **app/migrations/versions/**: renamed `001_initial_schema.py` → `_001_initial_schema.py`. Python module names cannot start with a digit, so `from app.migrations.versions.001_initial_schema import create_all_tables` was a SyntaxError. The leading underscore is a conventional marker for "internal" modules.
|
||||
- **README.md**: updated references to the renamed migration file.
|
||||
|
||||
### Why this happened
|
||||
The lifespan handler was supposed to run DB migrations as its first step, but I forgot to wire it up. The `seed_default_settings()` call immediately tried to `SELECT FROM settings` against a fresh PostgreSQL database with no tables. SQLAlchemy 2.x's `create_all` is idempotent (skips existing tables), so this is safe to call on every startup — equivalent to `alembic upgrade head` for our single-migration MVP.
|
||||
|
||||
## [1.0.4] — 2026-06-20
|
||||
|
||||
### Fixed (proper fix for CORS env parsing)
|
||||
|
||||
@@ -107,7 +107,7 @@ pip install -r requirements.txt
|
||||
docker compose up -d db qdrant
|
||||
|
||||
# Применить миграции (создаёт все таблицы)
|
||||
python -c "import asyncio; from app.db import get_engine; from app.migrations.versions.001_initial_schema import create_all_tables; asyncio.run(create_all_tables(get_engine()))"
|
||||
python -c "import asyncio; from app.db import get_engine; from app.migrations.versions._001_initial_schema import create_all_tables; asyncio.run(create_all_tables(get_engine()))"
|
||||
|
||||
# Запустить backend
|
||||
uvicorn app.main:app --reload --port 8000
|
||||
@@ -187,7 +187,7 @@ ai-rpg/
|
||||
│ │ ├── init_db.py # init_db(session)
|
||||
│ │ ├── init_qdrant.py # re-export init_qdrant_collections
|
||||
│ │ ├── seed.py # builtin presets (fantasy, sci-fi)
|
||||
│ │ └── versions/001_initial_schema.py
|
||||
│ │ └── versions/_001_initial_schema.py
|
||||
│ ├── config.py # Settings (pydantic-settings)
|
||||
│ ├── db.py # async engine + session factory
|
||||
│ └── main.py # FastAPI app + lifespan
|
||||
|
||||
25
app/main.py
25
app/main.py
@@ -35,6 +35,20 @@ async def lifespan(app: FastAPI) -> AsyncIterator[None]:
|
||||
_logger.info("app_starting", version=__version__, debug=cfg.debug)
|
||||
|
||||
# Startup -------------------------------------------------------------
|
||||
# Step 0: Create all DB tables (idempotent — equivalent to alembic upgrade head).
|
||||
# This must run BEFORE any settings query, otherwise seed_default_settings
|
||||
# crashes with "relation 'settings' does not exist".
|
||||
from app.db import get_engine
|
||||
from app.migrations.versions._001_initial_schema import create_all_tables
|
||||
|
||||
try:
|
||||
engine = get_engine()
|
||||
await create_all_tables(engine)
|
||||
_logger.info("db_tables_ready")
|
||||
except Exception as e: # noqa: BLE001
|
||||
_logger.error("db_tables_create_failed", error=str(e))
|
||||
# Continue anyway — /api/health will reflect the broken state
|
||||
|
||||
sm = get_sessionmaker()
|
||||
try:
|
||||
async with sm() as session:
|
||||
@@ -61,12 +75,21 @@ async def lifespan(app: FastAPI) -> AsyncIterator[None]:
|
||||
print(f"===========================\n")
|
||||
else:
|
||||
_logger.info("admins_present", count=admins_count)
|
||||
# 4) Init Qdrant collections
|
||||
# 4) seed builtin presets (idempotent)
|
||||
from app.migrations.seed import seed_builtin_presets
|
||||
|
||||
try:
|
||||
await seed_builtin_presets(session)
|
||||
_logger.info("presets_seeded")
|
||||
except Exception as e: # noqa: BLE001
|
||||
_logger.warning("presets_seed_failed", error=str(e))
|
||||
# 5) Init Qdrant collections
|
||||
from app.core.settings_service import get_setting
|
||||
|
||||
dim = int(await get_setting(session, "embeddings.dimension") or 256)
|
||||
try:
|
||||
await init_qdrant_collections(dim)
|
||||
_logger.info("qdrant_collections_ready", dimension=dim)
|
||||
except Exception as e: # noqa: BLE001
|
||||
_logger.warning("qdrant_init_failed", error=str(e))
|
||||
except Exception as e: # noqa: BLE001
|
||||
|
||||
Reference in New Issue
Block a user