마이그레이션 버그 수정

This commit is contained in:
2026-05-21 12:06:59 +00:00
parent 4bf6b554a7
commit 600963158e
2 changed files with 23 additions and 10 deletions
@@ -10,6 +10,7 @@ before running this migration in a live environment.
from __future__ import annotations
import os
import sqlalchemy as sa
from alembic import op
from sqlalchemy import inspect, text
@@ -20,7 +21,8 @@ branch_labels = None
depends_on = None
# Operator must confirm this user ID exists in the users table before running.
MIGRATION_ADMIN_ID = "migration-admin"
# Can be overridden via MIGRATION_ADMIN_ID environment variable.
MIGRATION_ADMIN_ID = os.environ.get("MIGRATION_ADMIN_ID", "migration-admin")
def _table_exists(inspector: sa.engine.Inspector, table_name: str) -> bool:
@@ -28,16 +30,20 @@ def _table_exists(inspector: sa.engine.Inspector, table_name: str) -> bool:
def run_migration(connection, admin_user_id: str) -> None:
"""Core migration logic — extracted for testability."""
"""Core migration logic — extracted for testability.
admin_user_id can be either a UUID (id) or username.
"""
# Try to find user by id (UUID) first, then by username
result = connection.execute(
text("SELECT COUNT(*) FROM users WHERE id = :uid"),
text("SELECT id FROM users WHERE id = :uid OR username = :uid LIMIT 1"),
{"uid": admin_user_id},
)
count = result.scalar()
if not count:
user_id = result.scalar()
if not user_id:
raise ValueError(
f"Migration admin user not found in users table: {admin_user_id}. "
"Set MIGRATION_ADMIN_ID to a valid user ID before running."
"Set MIGRATION_ADMIN_ID to a valid user ID (UUID) or username before running."
)
# Migrate distinct (lowercased) tag_values from portfolio_tags → tags master
@@ -49,7 +55,7 @@ def run_migration(connection, admin_user_id: str) -> None:
GROUP BY LOWER(tag_value)
ON CONFLICT (name) DO NOTHING
"""),
{"admin_id": admin_user_id},
{"admin_id": user_id},
)
# Fill portfolios.tag_ids from the migrated tags
@@ -25,14 +25,21 @@ def upgrade() -> None:
bind = op.get_bind()
inspector = inspect(bind)
# First, commit any pending transaction before changing isolation level
bind.commit()
# Set AUTOCOMMIT mode for CREATE UNIQUE INDEX CONCURRENTLY
autocommit_bind = bind.execution_options(isolation_level="AUTOCOMMIT")
# Drop old index if it exists (non-partial index)
if _index_exists(inspector, "auth_tokens", "idx_auth_tokens_service_name_unique"):
bind.execute(
autocommit_bind.execute(
__import__("sqlalchemy").text(
"DROP INDEX IF EXISTS idx_auth_tokens_service_name_unique"
)
)
autocommit_bind = bind.execution_options(isolation_level="AUTOCOMMIT")
# Create new partial unique index with WHERE clause
autocommit_bind.execute(
__import__("sqlalchemy").text(
"""