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.3 KiB

Credit Service 部署修复

日期: 2026-01-28
类型: Bugfix
影响范围: Credit Service 数据库迁移

问题描述

在执行 Credit Service 数据库迁移时遇到两个问题:

1. Python 语法错误

  • 位置: server/app/models/credit/package.py 第 38 行
  • 错误: 字段描述中使用了中文引号 "热销"、"推荐" 导致 Python 解析失败
  • 错误信息: SyntaxError: invalid character '"' (U+201C)

2. Alembic 迁移脚本错误

  • 位置: server/alembic/versions/20260128_2200_create_credit_service_tables.py
  • 错误: asyncpg 不支持在单个 op.execute() 中执行多条 SQL 语句
  • 错误信息: asyncpg.exceptions.PostgresSyntaxError: cannot insert multiple commands into a prepared statement

修复方案

1. 修复 Python 语法错误

修改文件: server/app/models/credit/package.py

# ❌ 错误(中文引号)
badge_text: Optional[str] = Field(default=None, description="徽章文本(如"热销"、"推荐"等)")

# ✅ 正确(转义引号)
badge_text: Optional[str] = Field(default=None, description="徽章文本(如\"热销\"\"推荐\"等)")

2. 修复 Alembic 迁移脚本

修改文件: server/alembic/versions/20260128_2200_create_credit_service_tables.py

将所有多条 SQL 语句拆分为单独的 op.execute() 调用:

# ❌ 错误(多条语句)
op.execute("""
    CREATE INDEX idx1 ON table1(col1);
    CREATE INDEX idx2 ON table2(col2);
""")

# ✅ 正确(单条语句)
op.execute("CREATE INDEX idx1 ON table1(col1)")
op.execute("CREATE INDEX idx2 ON table2(col2)")

修改内容

  • 索引创建:27 条索引语句拆分为 27 个独立调用
  • 表注释:5 条注释语句拆分为 5 个独立调用
  • 字段注释:55 条注释语句保持循环执行(已是单条)
  • 触发器创建:4 条触发器语句拆分为 4 个独立调用
  • downgrade 函数:5 条 DROP 语句拆分为 5 个独立调用

验证结果

1. 迁移执行成功

docker exec jointo-server-app alembic upgrade head
# ✅ 成功创建 5 个表
# ✅ 成功创建 27 个索引
# ✅ 成功添加 5 个表注释
# ✅ 成功添加 55 个字段注释
# ✅ 成功创建 4 个触发器

2. 表结构验证

-- credit_transactions 表
\d+ credit_transactions
-- ✅ 11 个字段,所有字段都有中文注释
-- ✅ 8 个索引(包括主键)
-- ✅ 1 个 updated_at 触发器

-- credit_consumption_logs 表
\d+ credit_consumption_logs
-- ✅ 16 个字段,所有字段都有中文注释
-- ✅ 11 个索引(包括主键)
-- ✅ 1 个 updated_at 触发器

-- credit_packages 表
\d+ credit_packages
-- ✅ 12 个字段,所有字段都有中文注释
-- ✅ 2 个索引(包括主键)
-- ✅ 1 个 updated_at 触发器

-- credit_pricing 表
\d+ credit_pricing
-- ✅ 7 个字段,所有字段都有中文注释
-- ✅ 2 个索引(包括主键)
-- ✅ 1 个 updated_at 触发器

-- credit_gifts 表
\d+ credit_gifts
-- ✅ 9 个字段,所有字段都有中文注释
-- ✅ 5 个索引(包括主键)
-- ✅ 无触发器(无 updated_at 字段)

经验总结

1. Python 字符串规范

  • 禁止使用中文引号""'' 会导致语法错误
  • 使用英文引号""''
  • 引号嵌套:使用转义 \" 或单双引号混用

2. Alembic + asyncpg 规范

  • 单条语句原则:每个 op.execute() 只执行一条 SQL 语句
  • 避免批量执行:不要使用 ; 分隔多条语句
  • 循环执行:对于大量相似语句,使用 Python 循环

3. 数据库注释规范

  • 表注释COMMENT ON TABLE table_name IS '描述'
  • 字段注释COMMENT ON COLUMN table.column IS '描述'
  • 时区标注:时间字段注释需标注 (UTC)
  • 关联标注:关联字段注释需标注 - 应用层验证

相关文档

  • 设计文档:docs/requirements/backend/04-services/user/credit-service.md
  • 实施文档:docs/server/changelogs/2026-01-28-credit-service-implementation.md
  • 技术栈规范:.claude/skills/jointo-tech-stack/references/database.md

下一步

  1. 数据库迁移完成
  2. ⏭️ 注册 API 路由到 FastAPI
  3. ⏭️ 配置 Celery Beat 定时任务
  4. ⏭️ 编写单元测试
  5. ⏭️ API 功能测试