Files
taiji-AI-PAD/services/mcp-server/migrations/run_016_migration.py
T
2026-01-14 13:42:36 +00:00

145 lines
4.5 KiB
Python

#!/usr/bin/env python3
"""
Migration 016: Add Agent Access Info Fields
为 agent_billing_records 表添加访问信息字段(域名、外网IP等)
Usage:
python migrations/run_016_migration.py
"""
import asyncio
import os
import sys
# 添加项目根目录到 Python 路径
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from sqlalchemy import text
from database import engine
async def run_migration():
"""运行迁移"""
print("=" * 60)
print("Migration 016: Add Agent Access Info Fields")
print("=" * 60)
# 读取 SQL 文件
sql_file = os.path.join(os.path.dirname(__file__), "016_add_agent_access_info_fields.sql")
with open(sql_file, "r", encoding="utf-8") as f:
sql_content = f.read()
# 分割 SQL 语句
statements = []
current_stmt = []
in_do_block = False
for line in sql_content.split("\n"):
line_stripped = line.strip()
# 跳过注释和空行(但保留 DO 块中的内容)
if not in_do_block:
if line_stripped.startswith("--") or not line_stripped:
continue
# 检测 DO 块开始
if line_stripped.upper().startswith("DO $$"):
in_do_block = True
current_stmt.append(line)
continue
# 检测 DO 块结束
if in_do_block and line_stripped == "END $$;":
current_stmt.append(line)
statements.append("\n".join(current_stmt))
current_stmt = []
in_do_block = False
continue
if in_do_block:
current_stmt.append(line)
continue
# 普通语句处理
current_stmt.append(line)
if line_stripped.endswith(";"):
stmt = "\n".join(current_stmt)
if stmt.strip():
statements.append(stmt)
current_stmt = []
# 执行迁移
async with engine.begin() as conn:
for i, stmt in enumerate(statements, 1):
try:
# 打印语句摘要
stmt_preview = stmt.strip()[:80].replace("\n", " ")
if len(stmt.strip()) > 80:
stmt_preview += "..."
print(f"\n[{i}/{len(statements)}] Executing: {stmt_preview}")
await conn.execute(text(stmt))
print(f" ✓ Success")
except Exception as e:
error_msg = str(e)
# 忽略 "column already exists" 错误
if "already exists" in error_msg.lower():
print(f" ⚠ Skipped (already exists)")
else:
print(f" ✗ Error: {error_msg}")
raise
print("\n" + "=" * 60)
print("Migration 016 completed successfully!")
print("=" * 60)
async def verify_migration():
"""验证迁移结果"""
print("\nVerifying migration...")
async with engine.begin() as conn:
# 检查新字段是否存在
result = await conn.execute(text("""
SELECT column_name, data_type, character_maximum_length
FROM information_schema.columns
WHERE table_name = 'agent_billing_records'
AND column_name IN ('external_ip', 'domain', 'domain_url', 'access_url', 'service_port', 'namespace')
ORDER BY column_name
"""))
columns = result.fetchall()
print(f"\nNew columns in agent_billing_records table:")
print("-" * 50)
for col in columns:
col_name, data_type, max_len = col
type_info = f"{data_type}({max_len})" if max_len else data_type
print(f" ✓ {col_name}: {type_info}")
expected_columns = {'external_ip', 'domain', 'domain_url', 'access_url', 'service_port', 'namespace'}
found_columns = {col[0] for col in columns}
if found_columns == expected_columns:
print(f"\n✓ All {len(expected_columns)} columns verified successfully!")
else:
missing = expected_columns - found_columns
if missing:
print(f"\n✗ Missing columns: {missing}")
return False
return True
if __name__ == "__main__":
try:
asyncio.run(run_migration())
asyncio.run(verify_migration())
except KeyboardInterrupt:
print("\nMigration cancelled.")
sys.exit(1)
except Exception as e:
print(f"\nMigration failed: {e}")
sys.exit(1)