a2270ee1b2
新手引导视频:运营后台上传 MP4(上限 100MB,魔数校验只认 ISO BMFF), App 端在领券等候浮层前 N 次以引导视频替代广告。新增 guide_video 的 model/schema/repository/router(App 侧 + 后台侧)与播放记录表迁移。 美团券:首页「销量最高 / 智能推荐」两个 tab 改游标分页,配套两条 (city_id, dedup_key, 排序键 DESC) 复合索引,让 Postgres 顺着索引流式 去重,免掉每翻一页重排整城券的开销。美团 CPS client 在 lifespan 预热 并在关闭时释放连接池。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
51 lines
2.2 KiB
Python
51 lines
2.2 KiB
Python
"""新手引导视频播放记录表(领券浮层前 N 次替代广告)
|
|
|
|
见 app/models/guide_video.py:按账号计次(开播即计数)、play_token 幂等发币。
|
|
配置(开关 / 视频地址 / 次数 / 金币)复用既有 app_config 表,无需建表。
|
|
|
|
Revision ID: guide_video_play_table
|
|
Revises: meituan_coupon_feed_indexes
|
|
Create Date: 2026-07-23 12:00:00.000000
|
|
|
|
"""
|
|
from typing import Sequence, Union
|
|
|
|
import sqlalchemy as sa
|
|
from alembic import op
|
|
|
|
# revision identifiers, used by Alembic.
|
|
revision: str = "guide_video_play_table"
|
|
down_revision: Union[str, Sequence[str], None] = "meituan_coupon_feed_indexes"
|
|
branch_labels: Union[str, Sequence[str], None] = None
|
|
depends_on: Union[str, Sequence[str], None] = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
op.create_table(
|
|
"guide_video_play",
|
|
sa.Column("id", sa.Integer(), autoincrement=True, nullable=False),
|
|
sa.Column("user_id", sa.Integer(), nullable=False),
|
|
sa.Column("play_token", sa.String(length=64), nullable=False),
|
|
sa.Column("scene", sa.String(length=16), nullable=False, server_default="coupon"),
|
|
sa.Column("seq", sa.Integer(), nullable=False, server_default="1"),
|
|
sa.Column("video_url", sa.String(length=512), nullable=True),
|
|
sa.Column("coin", sa.Integer(), nullable=False, server_default="0"),
|
|
sa.Column("status", sa.String(length=16), nullable=False, server_default="playing"),
|
|
sa.Column("completed", sa.Integer(), nullable=False, server_default="0"),
|
|
sa.Column(
|
|
"started_at", sa.DateTime(timezone=True), server_default=sa.func.now(), nullable=False
|
|
),
|
|
sa.Column("granted_at", sa.DateTime(timezone=True), nullable=True),
|
|
sa.ForeignKeyConstraint(["user_id"], ["user.id"]),
|
|
sa.PrimaryKeyConstraint("id"),
|
|
sa.UniqueConstraint("play_token", name="uq_guide_video_play_token"),
|
|
)
|
|
op.create_index("ix_guide_video_play_user_id", "guide_video_play", ["user_id"])
|
|
op.create_index("ix_guide_video_play_started_at", "guide_video_play", ["started_at"])
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.drop_index("ix_guide_video_play_started_at", table_name="guide_video_play")
|
|
op.drop_index("ix_guide_video_play_user_id", table_name="guide_video_play")
|
|
op.drop_table("guide_video_play")
|