2026-05-01 08:54:24 +08:00
|
|
|
|
## 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` 的库无行为变化。
|
2026-05-01 10:05:26 +08:00
|
|
|
|
|
|
|
|
|
|
## Work Log - 修复 API 启动时报 users.user_name / users.username 列不一致(2026-05-01)
|
|
|
|
|
|
|
|
|
|
|
|
- 背景:
|
|
|
|
|
|
- API 启动阶段在 `seed_defaults -> _seed_permissions` 查询中触发 ORM 关系预加载,SQL 使用了 `users.user_name`,但当前 PostgreSQL `users` 表实际字段为 `username`,导致 `psycopg.errors.UndefinedColumn`,服务启动失败。
|
|
|
|
|
|
|
|
|
|
|
|
- 本次改动(最小闭环):
|
|
|
|
|
|
- 文件:`api/app/core/config.py`
|
|
|
|
|
|
- 新增配置 `user_username_column`(环境变量 `USER_USERNAME_COLUMN`),可选值 `username` / `user_name`,默认 `username`。
|
|
|
|
|
|
- 文件:`api/app/models/user.py`
|
|
|
|
|
|
- `User.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`。
|
2026-05-01 10:31:56 +08:00
|
|
|
|
|
|
|
|
|
|
## Work Log - GitHub Actions 部署分支切换为 dev(2026-05-01)
|
|
|
|
|
|
|
|
|
|
|
|
- 背景:
|
|
|
|
|
|
- 当前 workflow 仅监听 `main` push,且 deploy job 条件写死为 `refs/heads/main`,导致 `dev` 推送不触发自动部署。
|
|
|
|
|
|
|
|
|
|
|
|
- 本次改动(最小改动):
|
|
|
|
|
|
- 文件:`.github/workflows/main.yml`
|
|
|
|
|
|
- `on.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` 条件跳过。
|
2026-05-01 10:49:29 +08:00
|
|
|
|
|
|
|
|
|
|
## 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.yml`
|
|
|
|
|
|
- `db.ports` 默认映射从 `${POSTGRES_PORT:-5433}:5432` 改为 `${POSTGRES_PORT:-5434}:5432`。
|
|
|
|
|
|
- 文件:`.env.example`
|
|
|
|
|
|
- `POSTGRES_PORT` 默认值从 `5433` 改为 `5434`。
|
|
|
|
|
|
- 本机直连 `DB_PORT` 默认值从 `5433` 改为 `5434`。
|
|
|
|
|
|
- 文件:`api/app/core/config.py`
|
|
|
|
|
|
- `db_port` 默认值从 `5433` 改为 `5434`,与环境模板和 compose 默认保持一致。
|
|
|
|
|
|
- 文件:`README.md`
|
|
|
|
|
|
- 本地 PostgreSQL 示例端口从 `localhost:5433` 更新为 `localhost:5434`。
|
|
|
|
|
|
- 文件:`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` 通信。
|
2026-05-01 11:00:08 +08:00
|
|
|
|
|
|
|
|
|
|
## 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`。
|
2026-05-01 11:21:57 +08:00
|
|
|
|
|
|
|
|
|
|
## 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.py`
|
|
|
|
|
|
- `User.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`。
|
2026-05-01 11:39:17 +08:00
|
|
|
|
|
|
|
|
|
|
## 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.py`
|
|
|
|
|
|
- `User.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`。
|