c051c2dbf8
Co-authored-by: multica-agent <github@multica.ai>
10 KiB
10 KiB
Work Log - 修复 API 启动阶段 users 主键列兼容问题(2026-05-01)
-
背景:
- 启动报错
psycopg.errors.UndefinedColumn: column users.user_id does not exist,触发点在seed_defaults -> _seed_permissions的关系加载 SQL。 - 当前 ORM 与外键约定统一使用
users.user_id,但历史库可能残留users.id主键列命名。
- 启动报错
-
本次改动:
api/app/core/database.py- 新增
_ensure_user_pk_column_compatibility()。 - 在
init_db()执行Base.metadata.create_all()前,针对 PostgreSQL 做一次兼容检查:- 若
users表存在,且检测到仅有id而没有user_id,自动执行:ALTER TABLE users RENAME COLUMN id TO user_id。 - 其余情况不改动(已是
user_id或两者都不存在时直接跳过)。
- 若
- 新增
-
验证:
- 在
fquiz-api容器内执行init_db():init_db_ok。 - 在
fquiz-api容器内执行查询,确认当前数据库users列包含user_id。
- 在
-
风险与影响:
- 影响范围:仅 PostgreSQL 且仅触发于“存在
users.id且缺少users.user_id”的历史库。 - 该变更属于启动期一次性 DDL 兼容动作;对已规范为
users.user_id的库无行为变化。
- 影响范围:仅 PostgreSQL 且仅触发于“存在
Work Log - 修复 API 启动时报 users.user_name / users.username 列不一致(2026-05-01)
-
背景:
- API 启动阶段在
seed_defaults -> _seed_permissions查询中触发 ORM 关系预加载,SQL 使用了users.user_name,但当前 PostgreSQLusers表实际字段为username,导致psycopg.errors.UndefinedColumn,服务启动失败。
- API 启动阶段在
-
本次改动(最小闭环):
- 文件:
api/app/core/config.py- 新增配置
user_username_column(环境变量USER_USERNAME_COLUMN),可选值username/user_name,默认username。
- 新增配置
- 文件:
api/app/models/user.pyUser.username列改为基于settings.user_username_column动态映射,兼容两类历史库结构。
- 文件:
docker-compose.yml- 为
api/celery-worker/celery-beat注入USER_USERNAME_COLUMN环境变量透传。
- 为
- 文件:
.env.example- 新增
USER_USERNAME_COLUMN=username示例配置。
- 新增
- 文件:
-
验证:
python3 -m py_compile api/app/core/config.py api/app/models/user.py api/app/services/seed_service.py-> 通过。USER_USERNAME_COLUMN=user_name POSTGRES_PORT=5434 docker compose up -d --no-deps api-> 启动成功。USER_USERNAME_COLUMN=user_name POSTGRES_PORT=5434 docker compose ps api->Up (healthy)。curl -fsS http://127.0.0.1:8000/health->{"status":"ok","service":"fquiz-api","version":"0.1.0"}。
-
风险与影响:
- 影响面集中在
User模型用户名字段映射。 - 运行环境需明确
USER_USERNAME_COLUMN与目标数据库实际字段一致;配置错误会在启动阶段继续抛UndefinedColumn。
- 影响面集中在
Work Log - GitHub Actions 部署分支切换为 dev(2026-05-01)
-
背景:
- 当前 workflow 仅监听
mainpush,且 deploy job 条件写死为refs/heads/main,导致dev推送不触发自动部署。
- 当前 workflow 仅监听
-
本次改动(最小改动):
- 文件:
.github/workflows/main.ymlon.push.branches从main改为dev。deploy.if从github.ref == 'refs/heads/main'改为github.ref == 'refs/heads/dev'。
- 文件:
-
预期行为:
git push origin dev:自动触发构建,并在构建成功后执行 deploy。main分支 push:不再触发该 workflow 自动部署链路。
-
风险与影响:
- 生产发布入口从
main切换到dev,需确认团队分支策略已同步。 workflow_dispatch若在非dev分支触发,deploy job 会被if条件跳过。
- 生产发布入口从
Work Log - 修复 docker db 端口 5433 冲突并改为 5434(2026-05-01)
-
背景:
docker compose启动db报错:Bind for 0.0.0.0:5433 failed: port is already allocated。- 现有默认口径为宿主机映射
5433->5432,与本机已占用端口冲突。
-
本次改动(最小闭环):
- 文件:
docker-compose.ymldb.ports默认映射从${POSTGRES_PORT:-5433}:5432改为${POSTGRES_PORT:-5434}:5432。
- 文件:
.env.examplePOSTGRES_PORT默认值从5433改为5434。- 本机直连
DB_PORT默认值从5433改为5434。
- 文件:
api/app/core/config.pydb_port默认值从5433改为5434,与环境模板和 compose 默认保持一致。
- 文件:
README.md- 本地 PostgreSQL 示例端口从
localhost:5433更新为localhost:5434。
- 本地 PostgreSQL 示例端口从
- 文件:
MEMORY.md- 宿主机默认
POSTGRES_PORT与本机直连DB_PORT长期口径同步更新为5434。
- 宿主机默认
- 文件:
-
验证:
POSTGRES_PORT=5434 docker compose up -d db->fquiz-db启动成功。docker compose ps -a->fquiz-db状态Up ... (healthy)。docker inspect fquiz-db --format '{{json .HostConfig.PortBindings}}'->5432/tcp映射HostPort=5434。
-
风险与影响:
- 影响范围:本地/部署侧依赖默认
5433的连接配置需同步为5434,否则会出现连接失败。 - 容器内服务间连接不受影响,仍通过
db:5432通信。
- 影响范围:本地/部署侧依赖默认
Work Log - 统一 GitHub 发布默认 PostgreSQL 端口为 5434(2026-05-01)
-
背景:
- 仓库本地
docker-compose.yml默认端口已是5434,但 GitHub Actions 发布脚本内联的docker-compose.prod.yml与首次生成.env仍使用5433,存在口径不一致。
- 仓库本地
-
本次改动(最小改动):
- 文件:
.github/workflows/main.yml- 将发布脚本中
db.ports默认映射从${POSTGRES_PORT:-5433}:5432改为${POSTGRES_PORT:-5434}:5432。 - 将首次初始化
.env模板中的POSTGRES_PORT=5433改为POSTGRES_PORT=5434。
- 将发布脚本中
- 文件:
-
验证:
rg -n "POSTGRES_PORT:-5434|POSTGRES_PORT=5434" .github/workflows/main.yml命中两处,未发现 workflow 内5433残留。
-
风险与影响:
- 影响范围:仅 GitHub 发布脚本默认值,不影响已存在且手工维护的服务器
.env。 - 若线上环境明确依赖
5433,需在服务器.env显式保留POSTGRES_PORT=5433。
- 影响范围:仅 GitHub 发布脚本默认值,不影响已存在且手工维护的服务器
Work Log - 修复 API 启动时报 users.password 列不存在(2026-05-01)
-
背景:
- 启动报错
psycopg.errors.UndefinedColumn: column users.password does not exist。 - 触发点在
seed_defaults -> _seed_permissions的查询过程中,SQLAlchemy 关系预加载Role.users时会查询users全字段;当前 ORM 将password_hash绑定到users.password,但目标库字段为password_hash。
- 启动报错
-
本次改动(最小闭环):
- 文件:
api/app/core/config.py- 新增配置
user_password_column(环境变量USER_PASSWORD_COLUMN),可选值password/password_hash,默认password_hash。
- 新增配置
- 文件:
api/app/models/user.pyUser.password_hash改为基于settings.user_password_column动态映射,兼容两类历史库结构。
- 文件:
docker-compose.yml- 为
api/celery-worker/celery-beat注入USER_PASSWORD_COLUMN环境变量透传。
- 为
- 文件:
.env.example- 新增
USER_PASSWORD_COLUMN=password_hash示例配置。
- 新增
- 文件:
-
验证:
python3 -m py_compile api/app/core/config.py api/app/models/user.py api/app/services/seed_service.py-> 通过。rg -n "USER_PASSWORD_COLUMN|user_password_column" ...命中配置、模型、compose、env 示例,映射链路完整。
-
风险与影响:
- 影响面集中在
User模型密码字段映射。 - 运行环境需确保
USER_PASSWORD_COLUMN与目标数据库实际字段一致;若配置错误,启动阶段仍可能抛UndefinedColumn。
- 影响面集中在
Work Log - 修复 API 启动时报 users.state 列不存在(2026-05-01)
-
背景:
- 启动报错
psycopg.errors.UndefinedColumn: column users.state does not exist。 - 触发点同样在
seed_defaults -> _seed_permissions的关系预加载过程中,ORM 查询users全字段时固定引用了state,但目标库实际字段为status。
- 启动报错
-
本次改动(最小闭环):
- 文件:
api/app/core/config.py- 新增配置
user_status_column(环境变量USER_STATUS_COLUMN),可选值status/state,默认status。
- 新增配置
- 文件:
api/app/models/user.pyUser.status列改为基于settings.user_status_column动态映射,兼容两类历史库结构。
- 文件:
docker-compose.yml- 为
api/celery-worker/celery-beat注入USER_STATUS_COLUMN环境变量透传。
- 为
- 文件:
.env.example- 新增
USER_STATUS_COLUMN=status示例配置。
- 新增
- 文件:
-
验证:
rg -n "USER_STATUS_COLUMN|user_status_column"命中配置、模型、compose、env 示例,映射链路完整。git diff检查仅包含本次预期的 4 个文件改动。
-
风险与影响:
- 影响面集中在
User模型状态字段映射。 - 运行环境需确保
USER_STATUS_COLUMN与目标数据库实际字段一致;若配置错误,启动阶段仍可能抛UndefinedColumn。
- 影响面集中在
Work Log - 修复 API 启动时报 users.create_user / users.update_user 列不存在(2026-05-01)
-
背景:
- 发布部署日志报错
psycopg.errors.UndefinedColumn: column users.create_user does not exist,容器持续重启。 - 触发点在
init_db -> seed_defaults,Role.users关系预加载会查询users全字段;当历史库缺失create_user/update_user时,启动阶段直接失败。
- 发布部署日志报错
-
本次改动(最小闭环):
- 文件:
api/app/core/database.py- 新增
_ensure_user_audit_column_compatibility()并在init_db()中接入(位于Base.metadata.create_all()前执行)。 - 兼容策略:
- 若存在历史列
create_by/created_by,自动重命名为create_user。 - 若存在历史列
update_by/updated_by,自动重命名为update_user。 - 若目标列仍缺失,自动补齐 nullable 列:
ALTER TABLE users ADD COLUMN IF NOT EXISTS create_user VARCHAR(64)ALTER TABLE users ADD COLUMN IF NOT EXISTS update_user VARCHAR(64)
- 若存在历史列
- 新增
- 文件:
-
验证:
git diff检查改动仅落在api/app/core/database.py与记忆文档。- 启动期兼容逻辑为 PostgreSQL 定向执行;仅在
users表存在且列不一致时触发 DDL,已对齐环境不会产生变更。
-
风险与影响:
- 影响面限定在 PostgreSQL 的
users表审计字段兼容处理。 - 该兼容动作为启动期一次性 DDL,可能短暂持有
users表 DDL 锁;对已有规范列名的库无行为变化。
- 影响面限定在 PostgreSQL 的