miningniti-api / scripts /migrate.py
milan1's picture
Deploy 679d3a45 from GitHub Actions
e86dfae verified
Raw
History Blame Contribute Delete
2.67 kB
"""
Migration runner used at container start.
Three situations have to be handled, because this project ran
Base.metadata.create_all() at startup for a long time and never ran Alembic:
1. Fresh database, nothing in it
-> upgrade to head normally.
2. Existing database created by create_all(), no alembic_version table
-> the tables already exist, so running the baseline revision would
fail with "relation already exists". Adopt the schema by stamping
it at the baseline, then apply anything newer.
3. Database already under Alembic control
-> upgrade to head normally.
Run directly: python -m scripts.migrate
"""
import logging
import sys
from sqlalchemy import inspect
from alembic import command
from alembic.config import Config
from app.db.session import engine, ensure_indexes
logging.basicConfig(
level=logging.INFO, format="%(asctime)s - migrate - %(levelname)s - %(message)s"
)
logger = logging.getLogger(__name__)
# The revision whose schema matches what create_all() produced.
BASELINE_REVISION = "001"
def _alembic_config() -> Config:
cfg = Config("alembic.ini")
cfg.set_main_option("sqlalchemy.url", str(engine.url))
return cfg
def run() -> None:
inspector = inspect(engine)
tables = set(inspector.get_table_names())
cfg = _alembic_config()
if "alembic_version" in tables:
logger.info("Database is under Alembic control — upgrading to head")
command.upgrade(cfg, "head")
elif "documents" in tables:
# Case 2: pre-Alembic schema built by create_all().
logger.warning(
"Found an existing schema with no alembic_version table. "
"Adopting it at revision %s, then applying newer revisions.",
BASELINE_REVISION,
)
command.stamp(cfg, BASELINE_REVISION)
command.upgrade(cfg, "head")
# Stamping marks the baseline as applied without running it, so the
# indexes that revision creates are skipped. create_all() never made
# them either — which is precisely why production has been doing
# sequential scans instead of using idx_embeddings_hnsw. Create them
# explicitly for adopted databases.
logger.info("Ensuring vector/trigram indexes on the adopted schema")
ensure_indexes()
else:
logger.info("Fresh database — creating schema from the baseline")
command.upgrade(cfg, "head")
logger.info("Migrations complete")
if __name__ == "__main__":
try:
run()
except Exception as e:
logger.error(f"Migration failed: {e}", exc_info=True)
sys.exit(1)