Files
photo-live/services/api/src/interactions/dto.ts
T
浅念 1f2a0c658f 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>
2026-09-18 18:14:01 +08:00

39 lines
1.4 KiB
TypeScript
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.
// services/api/src/interactions/dto.ts —— 互动上报请求体(P2 Task 7 点赞批次 /
// Task 8 浏览上报)。校验边界与契约 LikeBatchRequest / VisitReportRequest
// 逐字段对齐(sessionId/batchId 1..64、delta 1..20 整数;visitorId/requestId
// 8..128);越界一律 400 VALIDATION_FAILED(全局 ValidationPipe whitelist
// 剥离未声明字段)。delta 必须是 JSON number 整数(管道未开 transform,
// 字符串数字不静默转换——公开匿名端点从严)。
import { IsInt, IsString, Length, Max, Min } from 'class-validator';
export class LikeBatchDto {
/** 会话标识(客户端随机生成、会话期间复用;限速滑窗的键之一)。 */
@IsString()
@Length(1, 64)
sessionId!: string;
/** 批次幂等键:同批失败重试必须复用,跨批次不得复用。 */
@IsString()
@Length(1, 64)
batchId!: string;
/** 本批新增点赞数(客户端短窗合并后的累计点击数)。 */
@IsInt()
@Min(1)
@Max(20)
delta!: number;
}
/** 浏览上报请求体(P2 Task 8;契约 VisitReportRequest)。 */
export class VisitReportDto {
/** 访客标识(客户端持久化并在标签页间共享;去重窗口与限速的键)。 */
@IsString()
@Length(8, 128)
visitorId!: string;
/** 上报幂等键:counted 确认前跨刷新/重试持久复用(建议 UUID)。 */
@IsString()
@Length(8, 128)
requestId!: string;
}