docs(gateway): gateway 剩余文件注释改中文(逐行 1:1,代码零字节改动)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled

主人 2026-10-03 拍板「注释一律中文」;gateway 至此整包注释中文化完成(本会话共 3 批:
已推库 16 个文件 + 本批剩余文件)。
校验:机械校验(非注释改动行)= 空;剥注释后代码文本逐行比对全等(不一致文件数 0);
全树 go test ./... 58 包 ok / 0 FAIL;交叉编译绿。
This commit is contained in:
AskaEth committed 2026-10-03 22:28:25 +08:00
1 parent 91e8d7a029
commit 074ffc4ebf
73 files changed
+2529 -2529

No files matched your search

+28 -28
View File
@@ -11,13 +11,13 @@ import (
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/history"
)
// These tests cover the D4 read-cursor contract (Android collaboration B3): the
// unreadCount carried by GET /api/v1/sessions, the advance endpoint
// POST /api/v1/sessions/{id}/read, and the `session_read` frame that clears the badge
// on the account's other browsers.
// 这些测试覆盖 D4 读游标契约(Android 协作 B3):
// GET /api/v1/sessions 携带的 unreadCount、推进端点
// POST /api/v1/sessions/{id}/read,以及为该账号其他浏览器清除角标的
// `session_read` 帧。
// unreadBySession decodes GET /api/v1/sessions into a map of session id → unreadCount via
// the wire key, so the test asserts the JSON contract rather than the in-package struct.
// unreadBySession 经线上键把 GET /api/v1/sessions 解码为 session id → unreadCount 的
// map,因此测试断言的是 JSON 契约,而不是包内结构体。
func unreadBySession(t *testing.T, ts *httptest.Server, tok string) map[string]int {
t.Helper()
resp, body := doReq(t, http.MethodGet, ts.URL+"/api/v1/sessions", nil, tok)
@@ -36,10 +36,10 @@ func unreadBySession(t *testing.T, ts *httptest.Server, tok string) map[string]i
return out
}
// TestSessionsUnreadCountAndMarkRead covers the happy path end to end: a session with
// unread messages reports the count, POST /read moves the cursor and answers
// {sessionId, readAt}, the list drops to the messages sent after the cursor, and a
// body-less POST (mark everything seen) clears the badge.
// TestSessionsUnreadCountAndMarkRead 端到端覆盖顺路径:有未读消息的
// 会话报告计数,POST /read 推进游标并返回
// {sessionId, readAt},列表降到游标之后发送的消息,而无请求体的
// POST(全部标记为已见)清除角标。
func TestSessionsUnreadCountAndMarkRead(t *testing.T) {
t.Parallel()
_, ts, jwt, st := newHistoryEnv(t)
@@ -61,12 +61,12 @@ func TestSessionsUnreadCountAndMarkRead(t *testing.T) {
tok := signAny(t, jwt, "acct", auth.RoleOwner)
base := ts.URL + "/api/v1/sessions/" + history.MainSessionID + "/read"
// Nothing read yet: the main session is fully unread, the sub session independently so.
// 尚未读过任何内容:主会话全未读,子会话各自独立地同样如此。
if got := unreadBySession(t, ts, tok); got[history.MainSessionID] != 3 || got[sub] != 1 {
t.Fatalf("initial unread = %+v, want main 3 / sub 1", got)
}
// Advance the main cursor to 2000: messages at or before it are read.
// 把主游标推进到 2000:等于或早于它的消息即已读。
resp, body := doReq(t, http.MethodPost, base, map[string]any{"before": 2000}, tok)
if resp.StatusCode != http.StatusOK {
t.Fatalf("mark read status = %d, want 200 (body=%s)", resp.StatusCode, body)
@@ -86,12 +86,12 @@ func TestSessionsUnreadCountAndMarkRead(t *testing.T) {
t.Fatalf("read data = %+v, want sessionId %s readAt 2000", data, history.MainSessionID)
}
// Only the later message stays unread, and the sub session is untouched.
// 只有较晚那条消息保持未读,且子会话未被触碰。
if got := unreadBySession(t, ts, tok); got[history.MainSessionID] != 1 || got[sub] != 1 {
t.Fatalf("unread after cursor 2000 = %+v, want main 1 / sub 1", got)
}
// No body = "mark everything I have seen read" (resolved to now server-side).
// 无请求体 = 「把我已见的一切标记为已读」(服务端解析为 now)。
resp, body = doReq(t, http.MethodPost, base, nil, tok)
if resp.StatusCode != http.StatusOK {
t.Fatalf("body-less mark status = %d, want 200 (body=%s)", resp.StatusCode, body)
@@ -107,7 +107,7 @@ func TestSessionsUnreadCountAndMarkRead(t *testing.T) {
}
markedNow := data.ReadAt
// The cursor only moves forward: re-posting a stale cursor must not re-open the badge.
// 游标只向前移动:重发陈旧游标不得重新打开角标。
resp, body = doReq(t, http.MethodPost, base, map[string]any{"before": 1000}, tok)
if resp.StatusCode != http.StatusOK {
t.Fatalf("stale mark status = %d, want 200 (body=%s)", resp.StatusCode, body)
@@ -123,9 +123,9 @@ func TestSessionsUnreadCountAndMarkRead(t *testing.T) {
}
}
// TestMarkSessionReadValidation covers the failure contract: a present but unusable
// `before` answers 400, an unknown session 404, a viewer 403 and a missing HistoryStore
// 501 — none of which may be mistaken for a successful read.
// TestMarkSessionReadValidation 覆盖失败契约:存在但不可用的
// `before` 返回 400,未知会话 404,viewer 403,HistoryStore
// 缺失 501 —— 其中任何一个都不得被误认为读成功。
func TestMarkSessionReadValidation(t *testing.T) {
t.Parallel()
_, ts, jwt, _ := newHistoryEnv(t)
@@ -150,34 +150,34 @@ func TestMarkSessionReadValidation(t *testing.T) {
})
}
// An empty object means "now", not "no-op".
// 空对象意味着「现在」,而不是「空操作」。
resp, body := doReq(t, http.MethodPost, base, map[string]any{}, tok)
if resp.StatusCode != http.StatusOK {
t.Fatalf("empty object status = %d, want 200 (body=%s)", resp.StatusCode, body)
}
// Unknown session → 404; the session id is not auto-created.
// 未知会话 → 404;会话 id 不会被自动创建。
resp, body = doReq(t, http.MethodPost, ts.URL+"/api/v1/sessions/web:missing/read", map[string]any{"before": 1000}, tok)
if resp.StatusCode != http.StatusNotFound {
t.Fatalf("unknown session status = %d, want 404 (body=%s)", resp.StatusCode, body)
}
// A viewer cannot write the cursor (owner/admin history write, like PATCH /sessions).
// viewer 不能写游标(owner/admin 历史写,与 PATCH /sessions 同)。
viewer := signAny(t, jwt, "acct", auth.RoleViewer)
resp, body = doReq(t, http.MethodPost, base, map[string]any{"before": 1000}, viewer)
if resp.StatusCode != http.StatusForbidden {
t.Fatalf("viewer status = %d, want 403 (body=%s)", resp.StatusCode, body)
}
// And no token at all is 401, not a silent success.
// 而完全不带 token 是 401,不是静默成功。
resp, body = doReq(t, http.MethodPost, base, map[string]any{"before": 1000}, "")
if resp.StatusCode != http.StatusUnauthorized {
t.Fatalf("anonymous status = %d, want 401 (body=%s)", resp.StatusCode, body)
}
}
// TestMarkSessionReadNotWired pins the honest degradation: with no HistoryStore injected
// the endpoint answers 501 not_implemented rather than pretending the cursor moved.
// TestMarkSessionReadNotWired 钉住诚实的退化:未注入 HistoryStore 时
// 端点返回 501 not_implemented,而不是假装游标已移动。
func TestMarkSessionReadNotWired(t *testing.T) {
t.Parallel()
_, ts, jwt := buildEnv(t, cfgDefault(), Deps{})
@@ -190,9 +190,9 @@ func TestMarkSessionReadNotWired(t *testing.T) {
wantErrorShape(t, body)
}
// TestMarkSessionReadBroadcasts asserts the cross-end sync frame: a successful advance
// pushes exactly one `session_read` frame scoped to that session and carrying the new
// cursor, while a failed one (404) pushes nothing.
// TestMarkSessionReadBroadcasts 断言跨端同步帧:成功的推进恰好
// 推送一个 `session_read` 帧,作用域为该会话并携带新的
// 游标;而失败的推进(404)什么也不推。
func TestMarkSessionReadBroadcasts(t *testing.T) {
t.Parallel()
srv, ts, jwt, _ := newHistoryEnv(t)
@@ -222,7 +222,7 @@ func TestMarkSessionReadBroadcasts(t *testing.T) {
t.Fatal(err)
}
// A failed advance must not tell other ends the badge was cleared.
// 失败的推进不得告诉其他端角标已被清除。
resp, body = doReq(t, http.MethodPost, ts.URL+"/api/v1/sessions/web:missing/read", map[string]any{"before": 2000}, tok)
if resp.StatusCode != http.StatusNotFound {
t.Fatalf("unknown status = %d, want 404 (body=%s)", resp.StatusCode, body)