Files
shaguabijia-app-server/alembic/versions/guide_video_play_user_seq_unique.py
T
zuochenyong 3f7b5167fa 功能:新手引导视频 + 美团券首页分页索引 (#167)
Co-authored-by: guke <guke@wonderable.ai>
Co-authored-by: 左辰勇 <exinglang@gmail.com>
Reviewed-on: #167
Co-authored-by: zuochenyong <zuochenyong@wonderable.ai>
Co-committed-by: zuochenyong <zuochenyong@wonderable.ai>
2026-07-24 14:48:40 +08:00

41 lines
1.5 KiB
Python

"""guide_video_play 加 (user_id, seq) 唯一约束:堵住并发 /start 绕过次数上限
start_play 是无锁 check-then-insert(读 COUNT(*) 算 seq=used+1 再插一行),N 个并发
/start 会都读到同一个 used、算出同一个 seq、各插一行拿到各自的 play_token,于是 3 次
上限被绕过、每个 token 都能换 120 金币。加唯一键后并发同 seq 必撞,start_play 捕获
IntegrityError 降级为 should_play=false(客户端照旧放广告)。
用 unique index 而不是 batch_alter_table 加 UniqueConstraint:SQLite 加约束要整表重建,
而 CREATE UNIQUE INDEX 两边都原生支持,回滚也干净。
注:若库里已有并发产生的重复 (user_id, seq),建索引会失败 —— 本功能尚未上线,表通常是空的;
真撞上了先按 seq 去重(留 id 最小的一行,多发的金币按 scripts/reset_guide_video.py 的口径退)。
Revision ID: guide_video_user_seq_uq
Revises: d9c03cc3ea07
Create Date: 2026-07-24 10:00:00.000000
"""
from typing import Sequence, Union
from alembic import op
# revision identifiers, used by Alembic.
revision: str = "guide_video_user_seq_uq"
down_revision: Union[str, Sequence[str], None] = "d9c03cc3ea07"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
op.create_index(
"uq_guide_video_play_user_seq",
"guide_video_play",
["user_id", "seq"],
unique=True,
)
def downgrade() -> None:
op.drop_index("uq_guide_video_play_user_seq", table_name="guide_video_play")