feat(ov): windowed dedup visit counting with retention cleanup

Task 8 (P2): POST /public/albums/{token}/visits with visit_sessions
window dedup (VISIT_WINDOW_MINUTES), requestId idempotent replay
(echoes stored outcome; expired beyond VISIT_REQUEST_TTL_MINUTES
rejected), album_stats viewCount/statVersion authority + outbox_stat_events
views snapshots, WS stats.updated broadcast, visitorId+IP fixed-window
rate limit (VISIT_WINDOW_REQUESTS), and ov CleanupModule scheduler
(setInterval, CLEANUP_INTERVAL_MINUTES) deleting like_batches /
visit_requests / visit_sessions past their windows — totals never
touched. Contract prose aligned to replay semantics; constants
VISIT_WINDOW_REQUESTS / CLEANUP_INTERVAL_MINUTES added.

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-09-18 18:14:01 +08:00
parent 85b2da3db5
commit 1f2a0c658f
14 changed files with 1398 additions and 25 deletions
+4
View File
@@ -28,3 +28,7 @@ export const LIKE_IP_WINDOW_DELTA = 2000;
export const LIKE_BURST_MERGE_MS = 500;
/** 浏览上报 requestId 保留分钟:过期 requestId 拒绝重放(≥ 去重窗口)。 */
export const VISIT_REQUEST_TTL_MINUTES = 35;
/** 浏览上报基础限速:visitorId+IP 固定窗(=去重窗口)内请求数上限,超限 429。 */
export const VISIT_WINDOW_REQUESTS = 60;
/** ov 互动流水清理调度间隔分钟(like_batches/visit_requests/visit_sessions)。 */
export const CLEANUP_INTERVAL_MINUTES = 60;