功能:限制每位用户每天最多发起 100 次比价 (#165)
## 变更内容 - 登录用户按北京时间自然日计算比价发起次数,每人每天最多 100 次。 - 第 101 次起返回 HTTP 429,并提示“今日已比价超过100次,请明天再试”。 - 同一 trace_id 的网络重试按幂等处理,不会重复计数。 - 使用用户行锁串行化同一账号的并发请求,避免并发突破上限。 - 复用现有 comparison_record 的 running 记录,无需新增数据库迁移。 ## 本地验证 - 比价额度专项测试 11 项通过。 - 本次修改涉及文件的 Ruff 检查通过。 - 已覆盖未登录、重复 trace_id、跨自然日、第 100 次放行及第 101 次拒绝。 --------- Co-authored-by: CodexSandboxOffline <798648091@qq.com> Reviewed-on: #165 Co-authored-by: linkeyu <linkeyu@wonderable.ai> Co-committed-by: linkeyu <linkeyu@wonderable.ai>
This commit was merged in pull request #165.
This commit is contained in:
@@ -20,6 +20,8 @@ from app.db.session import SessionLocal
|
||||
from app.models.comparison import ComparisonRecord
|
||||
from app.repositories import comparison as crud_compare
|
||||
from app.schemas.compare_record import (
|
||||
CompareStartReserveIn,
|
||||
CompareStartReserveOut,
|
||||
CompareStatsOut,
|
||||
ComparisonRecordCreatedOut,
|
||||
ComparisonRecordDetailOut,
|
||||
@@ -35,6 +37,41 @@ logger = logging.getLogger("shagua.compare_record")
|
||||
router = APIRouter(prefix="/api/v1/compare", tags=["compare-record"])
|
||||
|
||||
|
||||
@router.post(
|
||||
"/start",
|
||||
response_model=CompareStartReserveOut,
|
||||
summary="预占一次当日比价发起次数(每人每天最多100次)",
|
||||
)
|
||||
def reserve_compare_start(
|
||||
payload: CompareStartReserveIn,
|
||||
user: CurrentUser,
|
||||
db: DbSession,
|
||||
) -> CompareStartReserveOut:
|
||||
try:
|
||||
_, used = crud_compare.reserve_daily_start(
|
||||
db,
|
||||
user_id=user.id,
|
||||
trace_id=payload.trace_id,
|
||||
business_type=payload.business_type,
|
||||
device_id=payload.device_id,
|
||||
)
|
||||
except crud_compare.DailyCompareStartLimitExceeded:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_429_TOO_MANY_REQUESTS,
|
||||
detail="今日已比价超过100次,请明天再试",
|
||||
) from None
|
||||
except crud_compare.ComparisonTraceOwnershipError:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_409_CONFLICT,
|
||||
detail="比价任务标识冲突,请重新发起",
|
||||
) from None
|
||||
return CompareStartReserveOut(
|
||||
limit=crud_compare.DAILY_COMPARE_START_LIMIT,
|
||||
used=used,
|
||||
remaining=max(crud_compare.DAILY_COMPARE_START_LIMIT - used, 0),
|
||||
)
|
||||
|
||||
|
||||
@router.post(
|
||||
"/record",
|
||||
response_model=ComparisonRecordCreatedOut,
|
||||
|
||||
Reference in New Issue
Block a user