baodan/api/insurance/db/migrate_022.py
wsb1224 c7df34d0cd 07-27 阶段 状态 进度
阶段 1:数据库与工作区	 完成	100%
阶段 2:Celery 后台任务	 完成	100%
阶段 3:前端刷新恢复与多工作区	 完成	100%
阶段 4:任务坞与任务中心	 完成	100%
阶段 5:版本化编辑	 完成	100%
阶段 6:测试与灰度	 未开始	0%
2026-07-28 17:53:14 +08:00

141 lines
5.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""迁移 022: 工作区与统一任务表。
按 docs/0728修复文件.md 阶段 1 实施:
- 扩展 insurance_ppt_sessions新增工作区字段
- 扩展 poster_records新增工作区字段
- 新建 insurance_generation_tasks统一任务执行表
兼容 PostgreSQL 和 MySQL。
"""
import logging
from sqlalchemy import text
logger = logging.getLogger(__name__)
def _column_exists(db, table: str, column: str) -> bool:
"""检查列是否存在(兼容 PostgreSQL 和 MySQL"""
try:
result = db.session.execute(text(
"SELECT COUNT(*) FROM information_schema.columns "
"WHERE table_name = :table AND column_name = :column"
), {"table": table, "column": column})
return result.scalar() > 0
except Exception:
return False
def _table_exists(db, table_name: str) -> bool:
"""检查表是否存在(兼容 PostgreSQL 和 MySQL"""
try:
result = db.session.execute(text(
"SELECT COUNT(*) FROM information_schema.tables "
"WHERE table_name = :table"
), {"table": table_name})
return result.scalar() > 0
except Exception:
return False
def _index_exists(db, index_name: str) -> bool:
"""检查索引是否存在(兼容 PostgreSQL 和 MySQL"""
try:
result = db.session.execute(text(
"SELECT COUNT(*) FROM pg_indexes WHERE indexname = :name"
), {"name": index_name})
return result.scalar() > 0
except Exception:
return False
def migrate():
"""执行迁移。"""
from insurance.db.compat import db
# ─── 扩展 PptSession ─────────────────────────────────────
ppt_columns = [
("title", "VARCHAR(200) DEFAULT ''"),
("workflow_step", "VARCHAR(20) DEFAULT 'upload'"),
("draft_options_json", "TEXT"),
("draft_revision", "INT DEFAULT 1"),
("generated_revision", "INT DEFAULT 0"),
("latest_task_id", "VARCHAR(36)"),
("latest_output_path", "VARCHAR(500)"),
("archived_at", "TIMESTAMP"),
]
for col_name, col_def in ppt_columns:
if not _column_exists(db, "insurance_ppt_sessions", col_name):
db.session.execute(text(
f"ALTER TABLE insurance_ppt_sessions ADD COLUMN {col_name} {col_def}"
))
logger.info(f"[migrate_022] 已为 insurance_ppt_sessions 添加 {col_name}")
# ─── 扩展 PosterRecord ───────────────────────────────────
poster_columns = [
("title", "VARCHAR(200) DEFAULT ''"),
("workflow_step", "VARCHAR(20) DEFAULT 'product'"),
("draft_status", "VARCHAR(20) DEFAULT 'active'"),
("draft_revision", "INT DEFAULT 1"),
("generated_revision", "INT DEFAULT 0"),
("latest_task_id", "VARCHAR(36)"),
("archived_at", "TIMESTAMP"),
]
for col_name, col_def in poster_columns:
if not _column_exists(db, "poster_records", col_name):
db.session.execute(text(
f"ALTER TABLE poster_records ADD COLUMN {col_name} {col_def}"
))
logger.info(f"[migrate_022] 已为 poster_records 添加 {col_name}")
# ─── 新建 insurance_generation_tasks ─────────────────────
if not _table_exists(db, "insurance_generation_tasks"):
db.session.execute(text("""
CREATE TABLE insurance_generation_tasks (
id VARCHAR(36) PRIMARY KEY,
user_id VARCHAR(64) NOT NULL,
artifact_type VARCHAR(10) NOT NULL,
operation VARCHAR(10) NOT NULL,
workspace_id VARCHAR(36) NOT NULL,
title_snapshot VARCHAR(200) DEFAULT '',
status VARCHAR(20) NOT NULL DEFAULT 'queued',
stage VARCHAR(30) DEFAULT '',
progress INT DEFAULT 0,
message VARCHAR(500) DEFAULT '',
error_code VARCHAR(50) DEFAULT '',
error_message TEXT,
input_revision INT DEFAULT 1,
input_snapshot_json TEXT,
output_json TEXT,
idempotency_key VARCHAR(100),
celery_task_id VARCHAR(200),
attempt_count INT DEFAULT 0,
heartbeat_at TIMESTAMP,
started_at TIMESTAMP,
finished_at TIMESTAMP,
viewed_at TIMESTAMP,
dock_hidden_at TIMESTAMP,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
"""))
logger.info("[migrate_022] 已创建 insurance_generation_tasks 表")
# 创建索引PostgreSQL 兼容)
indexes = [
("idx_gen_tasks_user_status", "user_id, status"),
("idx_gen_tasks_user_artifact", "user_id, artifact_type"),
("idx_gen_tasks_workspace", "workspace_id"),
("idx_gen_tasks_idempotency", "idempotency_key"),
]
for idx_name, idx_cols in indexes:
if not _index_exists(db, idx_name):
db.session.execute(text(
f"CREATE INDEX {idx_name} ON insurance_generation_tasks ({idx_cols})"
))
logger.info(f"[migrate_022] 已创建索引 {idx_name}")
db.session.commit()
logger.info("[migrate_022] 工作区与任务表迁移完成")