You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

4.2 KiB

UUID 生成重构:统一使用 Python 层生成

日期: 2026-01-27
类型: 重构
影响范围: 所有表主键生成逻辑

变更概述

将所有表的 UUID 主键生成从数据库层(gen_uuid_v7() 函数)迁移到 Python 应用层(generate_uuid 函数),统一 UUID 生成逻辑。

变更详情

1. Model 层修改

AI 服务 Models(4 个文件)

修复主键类型和默认值

  • server/app/models/ai_model.py

    • model_id: sa.Text() + server_default="gen_uuid_v7()"sa.UUID() + default=generate_uuid
  • server/app/models/ai_quota.py

    • quota_id: sa.Text() + server_default="gen_uuid_v7()"sa.UUID() + default=generate_uuid
  • server/app/models/ai_job.py

    • ai_job_id: sa.Text() + server_default="gen_uuid_v7()"sa.UUID() + default=generate_uuid
    • storyboard_id: sa.Text()sa.UUID()
    • consumption_log_id: sa.Text()sa.UUID()
    • model_id: sa.Text()sa.UUID()
  • server/app/models/ai_usage_log.py

    • usage_log_id: sa.Text() + server_default="gen_uuid_v7()"sa.UUID() + default=generate_uuid
    • ai_job_id: sa.Text()sa.UUID()
    • model_id: sa.Text()sa.UUID()

Credit Models(1 个文件)

移除数据库默认值

  • server/app/models/credit.py
    • transaction_id: 移除 server_default=text("gen_uuid_v7()"),改用 default=generate_uuid
    • consumption_id: 移除 server_default=text("gen_uuid_v7()"),改用 default=generate_uuid
    • package_id: 移除 server_default=text("gen_uuid_v7()"),改用 default=generate_uuid
    • pricing_id: 移除 server_default=text("gen_uuid_v7()"),改用 default=generate_uuid
    • gift_id: 移除 server_default=text("gen_uuid_v7()"),改用 default=generate_uuid

2. 数据库迁移

Alembic 迁移: 20260127_2006_300b80f7e512_remove_gen_uuid_v7_function_.py

变更内容

  • 移除所有表主键的 server_default
  • 修改 AI 服务表主键类型从 TEXT 改为 UUID
  • 修改 AI 服务表关联字段类型从 TEXT 改为 UUID

影响的表

  • ai_models - 主键类型修正
  • ai_quotas - 主键类型修正
  • ai_jobs - 主键和关联字段类型修正
  • ai_usage_logs - 主键和关联字段类型修正
  • credit_transactions - 移除 server_default
  • credit_consumption_logs - 移除 server_default
  • credit_packages - 移除 server_default
  • credit_pricing - 移除 server_default
  • credit_gifts - 移除 server_default

技术细节

UUID 生成方式

之前

# Model 定义
model_id: Optional[str] = Field(
    default=None,
    sa_column=Column(Text, primary_key=True, server_default="gen_uuid_v7()")
)

# 数据库函数
CREATE OR REPLACE FUNCTION gen_uuid_v7() RETURNS uuid AS $$
  -- PostgreSQL 函数实现
$$ LANGUAGE plpgsql VOLATILE;

现在

# Model 定义
model_id: UUID = Field(
    sa_column=Column(PG_UUID(as_uuid=True), primary_key=True, default=generate_uuid)
)

# Python 函数
from uuid_utils import uuid7

def generate_uuid() -> UUID:
    return uuid7()

优势

  1. 逻辑统一:所有 UUID 生成逻辑集中在 Python 层
  2. 易于测试:可以在测试中 Mock generate_uuid 函数
  3. 类型安全:使用 UUID 类型而非 TEXT,避免类型不一致
  4. 简化部署:无需维护数据库函数
  5. 符合架构原则:应用层控制业务逻辑

兼容性

  • 向后兼容:现有数据不受影响
  • 迁移安全:Alembic 自动生成迁移脚本
  • 回滚支持:提供完整的 downgrade 逻辑

部署步骤

  1. 更新代码到最新版本
  2. 执行数据库迁移:
    docker exec jointo-server-app alembic upgrade head
    
  3. 重启应用服务

注意事项

  • 迁移过程中会修改表结构,建议在低峰期执行
  • 迁移完成后,数据库中的 gen_uuid_v7() 函数仍然存在但不再使用
  • 新创建的记录将由 Python 层生成 UUID

相关文件

  • Models: server/app/models/ai_*.py, server/app/models/credit.py
  • 迁移: server/alembic/versions/20260127_2006_300b80f7e512_*.py
  • UUID 生成器: server/app/utils/id_generator.py