fix(db): 修复 alembic 多 head 导致后端启动失败

迁移图存在两处问题导致 `alembic upgrade head`(网关启动时执行)报
"Multiple head revisions are present":
1. 20260612_01 分叉出 20260615_01 与 20260616_03 两个 head 未合并;
2. 20260611_01、20260616_02 各被两个文件重复占用,污染 DAG 产生幽灵 head。

处理:
- roundtable_draft_task_id 20260611_01 -> 20260611_02(接在 square_id 之后),
  20260612_01 父节点改指 20260611_02;
- skill_favorites 20260616_02 -> 20260616_04(接在 knowledge_folders 之后),
  20260616_03 父节点改指 20260616_04;
- 新增 no-op 合并迁移 20260617_01 合并 (20260615_01, 20260616_03)。

保留 20260611_01 / 20260616_02 原 id 不变,仅重命名重复副本,已 stamp 的库不受影响;
所有迁移均有 _has_table/_has_column 守卫,全链路在已建表的库上重跑为安全 no-op。
`alembic heads` 现仅余单一 head 20260617_01,无重复告警。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
吉鑫升andClaude Opus 4.8 committed 2026-06-17 17:19:29 +08:00
1 parent a2bb8c80a2
commit 392394b4c9
6 files changed
+55 -13

No files matched your search

+1 -1
View File
@@ -368,7 +368,7 @@ shown to users ARE the **recommended questions** (`recommended_questions` table)
types into the existing "我的" tables, idempotently:
- agents → `agent_favorites` rows with `origin='position'`
- **skills → `skill_favorites` rows with `origin='position'`** (table
`SkillFavoriteRow`, migration `20260616_02`, auto-created by `create_all`)
`SkillFavoriteRow`, migration `20260616_04`, auto-created by `create_all`)
- scheduled tasks → `scheduled_task_subscriptions` rows with `origin='position'`
Skills behave **exactly like agents**: a position only *adds* its tagged skills
@@ -7,8 +7,14 @@ draft is keyed/shared by ``task_id`` and is no longer partitioned by ``user_id``
``create_all`` adds the column for brand-new DBs; this revision patches DBs that
already have the table.
Revision ID: 20260611_01
Revises: 20260609_02
Note: this migration originally shared the revision id ``20260611_01`` with
``20260611_01_agents_skills_square_id`` (both branched off ``20260609_02``),
which corrupted the alembic DAG ("present more than once" + phantom heads). It
was renumbered to ``20260611_02`` and re-chained after that revision so the
history is linear and single-headed.
Revision ID: 20260611_02
Revises: 20260611_01
Create Date: 2026-06-11
"""
@@ -19,8 +25,8 @@ from alembic import op
from sqlalchemy import inspect
revision = "20260611_01"
down_revision = "20260609_02"
revision = "20260611_02"
down_revision = "20260611_01"
branch_labels = None
depends_on = None
@@ -6,7 +6,7 @@
LONGTEXT(计划 JSON 可超 64 KB)。
Revision ID: 20260612_01
Revises: 20260611_01
Revises: 20260611_02
Create Date: 2026-06-12
"""
@@ -19,7 +19,7 @@ from sqlalchemy.dialects.mysql import LONGTEXT
revision = "20260612_01"
down_revision = "20260611_01"
down_revision = "20260611_02"
branch_labels = None
depends_on = None
@@ -1,7 +1,7 @@
"""Add always_on (常驻/免压缩) column to skills table.
Revision ID: 20260616_03
Revises: 20260616_02
Revises: 20260616_04
Create Date: 2026-06-16
"""
@@ -13,7 +13,7 @@ from sqlalchemy import inspect
revision = "20260616_03"
down_revision = "20260616_02"
down_revision = "20260616_04"
branch_labels = None
depends_on = None
@@ -10,8 +10,14 @@ startup (new tables are always created, even on existing DBs); this migration
keeps the alembic history consistent per the repo convention (see
backend/CLAUDE.md → Schema Migrations).
Revision ID: 20260616_02
Revises: 20260616_01
Note: this migration originally shared the revision id ``20260616_02`` with
``20260616_02_knowledge_folders_templates`` (both branched off ``20260616_01``),
which corrupted the alembic DAG ("present more than once" + phantom heads). It
was renumbered to ``20260616_04`` and re-chained after that revision so the
history is linear and single-headed.
Revision ID: 20260616_04
Revises: 20260616_02
Create Date: 2026-06-16
"""
@@ -22,8 +28,8 @@ from alembic import op
from sqlalchemy import inspect
revision = "20260616_02"
down_revision = "20260616_01"
revision = "20260616_04"
down_revision = "20260616_02"
branch_labels = None
depends_on = None
@@ -0,0 +1,30 @@
"""Merge the chain-seat-mode and skill-always-on migration heads.
Two lineages both descend from ``20260612_01`` (roundtable_jobs orchestration
plan): ``20260615_01`` (chain seat mode) branched directly off it, while the
``20260616_*`` line (positions → knowledge folders/templates → skill_favorites →
skill always_on) is the other branch. That left the graph with two heads
(``20260615_01`` and ``20260616_03``) so ``alembic upgrade head`` failed with
"Multiple head revisions are present". This no-op merge revision joins both
lineages so ``upgrade head`` resolves to a single head again.
Revision ID: 20260617_01
Revises: 20260615_01, 20260616_03
Create Date: 2026-06-17
"""
from __future__ import annotations
revision = "20260617_01"
down_revision = ("20260615_01", "20260616_03")
branch_labels = None
depends_on = None
def upgrade() -> None:
pass
def downgrade() -> None:
pass