feat(server): ingest v2事件级归属+session_resume+stay区间并集重算+响应明细契约
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -77,14 +77,28 @@ def sanitize_payload(obj):
|
||||
return obj
|
||||
|
||||
|
||||
def validate_event(ev) -> str | None:
|
||||
def validate_event(ev, *, v2=False, batch_site_id="", batch_visitor_id="") -> str | None:
|
||||
"""返回 None 表示通过;否则返回拒绝原因码。类型/白名单/体积/深度全在此守门。
|
||||
通过时会就地截断/清洗并写回 ev(path 先 sanitize_url 再截 MAX_PATH_LEN,title 截
|
||||
MAX_TITLE_LEN)——Task 6 的 ingest 依赖此写回契约。"""
|
||||
MAX_TITLE_LEN)——Task 6 的 ingest 依赖此写回契约。
|
||||
|
||||
v2=True(批级 schema_version==2):额外校验事件级归属四元组——site_id/visitor_id
|
||||
必须与批级一致、session_id 非空 str(归属依据从 v1 信封转移到事件级);
|
||||
page_id 必须为非空 ≤64 的合法 UTF-8(session_resume 可空——它归属会话而非页面)。
|
||||
不一致 → attribution_mismatch;page_id 非法 → invalid_page_id。"""
|
||||
if not isinstance(ev, dict):
|
||||
return "event_invalid_shape"
|
||||
if ev.get("event_name") not in C.EVENT_NAMES:
|
||||
return "event_name_not_allowed"
|
||||
if v2:
|
||||
if (ev.get("site_id") != batch_site_id
|
||||
or ev.get("visitor_id") != batch_visitor_id
|
||||
or not isinstance(ev.get("session_id"), str) or not ev["session_id"]):
|
||||
return "attribution_mismatch"
|
||||
pid = ev.get("page_id")
|
||||
if ev["event_name"] != "session_resume" and (
|
||||
not isinstance(pid, str) or not pid or len(pid) > 64 or not _utf8_ok(pid)):
|
||||
return "invalid_page_id"
|
||||
eid = ev.get("event_id")
|
||||
if not isinstance(eid, str) or not eid or len(eid) > 64 or not _utf8_ok(eid):
|
||||
return "invalid_event_id"
|
||||
|
||||
Reference in New Issue
Block a user