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

@@ -12,17 +12,17 @@ import (
"git.yeij.top/AskaEth/Cyrene_v2/internal/auth"
)
// These tests pin the contract that broke in production (2026-10-03 21:00:28):
// MetricsCollector.Snapshot must hand back DETACHED counter maps, because the
// admin handler JSON-encodes the snapshot after the collector's lock is released.
// Returning the collector's own maps let a concurrent Record write a map while the
// encoder iterated it → unrecoverable
// "fatal error: concurrent map iteration and map write" → the whole backend died,
// and with it every admin page (the reported「全链路流程功能无效」).
// 这些测试钉住生产中坏掉的那个契约(2026-10-03 21:00:28):
// MetricsCollector.Snapshot 必须交回脱离的计数器 map,因为
// 管理 handler 在收集器锁释放后对快照做 JSON 编码。
// 返回收集器自己的 map 会让并发的 Record 在编码器遍历它时
// 写该 map → 不可恢复的
// "fatal error: concurrent map iteration and map write" → 整个后端死亡,
// 随之所有管理页面也死(上报的「全链路流程功能无效」)。
// TestMetricsSnapshotDetachesMaps is the deterministic regression: a value read out
// of a snapshot must not change when the collector is counted afterwards, and
// writing into a snapshot must not reach the collector.
// TestMetricsSnapshotDetachesMaps 是确定性的回归:从快照读出的
// 值不得在之后对收集器计数时改变,且写入
// 快照不得触达收集器。
func TestMetricsSnapshotDetachesMaps(t *testing.T) {
t.Parallel()
m := newMetricsCollector()
@@ -36,7 +36,7 @@ func TestMetricsSnapshotDetachesMaps(t *testing.T) {
t.Fatalf("PerMethod[GET] = %d, want 1", got)
}
// A count recorded after the snapshot must not appear in the older snapshot.
// 快照之后记录的计数不得出现在较旧的快照中。
m.Record(http.MethodPost, "/api/v1/b", http.StatusTeapot, 1)
if _, ok := snap.PerPath["/api/v1/b"]; ok {
t.Fatalf("snapshot shares the collector's perPath map: later path leaked into it (%v)", snap.PerPath)
@@ -52,8 +52,8 @@ func TestMetricsSnapshotDetachesMaps(t *testing.T) {
assertCollectorNotMutatedBySnapshot(t, m)
}
// assertSnapshotWriteIsolation writes into the snapshot's maps and checks the
// collector is untouched afterwards.
// assertSnapshotWriteIsolation 写入快照的 map 并检查
// 之后收集器未被触碰。
func assertSnapshotWriteIsolation(t *testing.T, m *MetricsCollector, snap AdminMetrics) {
t.Helper()
snap.PerPath["/api/v1/evil"] = 999
@@ -78,8 +78,8 @@ func assertSnapshotWriteIsolation(t *testing.T, m *MetricsCollector, snap AdminM
}
}
// assertCollectorNotMutatedBySnapshot re-reads a counter the collector recorded
// before the isolation writes to prove no counter value was disturbed.
// assertCollectorNotMutatedBySnapshot 重新读取收集器在隔离写入之前
// 记录的一个计数器,以证明没有任何计数值被扰动。
func assertCollectorNotMutatedBySnapshot(t *testing.T, m *MetricsCollector) {
t.Helper()
final := m.Snapshot(time.Now())
@@ -91,11 +91,11 @@ func assertCollectorNotMutatedBySnapshot(t *testing.T, m *MetricsCollector) {
}
}
// TestMetricsSnapshotEncodedConcurrently runs the exact interleaving that crashed
// production: one goroutine counts requests (the logging middleware does this on
// every request) while another encodes snapshots (the admin handler does this
// outside the lock). Under -race a shared live map is reported as a data race; on
// an unpatched build it can also abort the process outright.
// TestMetricsSnapshotEncodedConcurrently 运行让生产崩溃的那个确切
// 交错:一个 goroutine 计请求(logging 中间件对每个请求都
// 这么做),另一个编码快照(管理 handler 在锁外
// 这么做)。在 -race 下共享活 map 会被报告为数据竞争;在
// 未打补丁的构建上它还可能直接把进程搞崩。
func TestMetricsSnapshotEncodedConcurrently(t *testing.T) {
t.Parallel()
m := newMetricsCollector()
@@ -127,18 +127,18 @@ func TestMetricsSnapshotEncodedConcurrently(t *testing.T) {
wg.Wait()
}
// TestAdminMetricsEndpointConcurrentPoll drives the real HTTP path — the admin
// panel polls every module in parallel, so one request can be encoding the metrics
// JSON while another request's logging middleware records into the collector. This
// is the production crash reproduced end-to-end through the middleware + handler.
// TestAdminMetricsEndpointConcurrentPoll 驱动真实 HTTP 路径 —— 管理
// 面板并行轮询每个模块,因此一个请求可能在编码指标
// JSON,而另一个请求的 logging 中间件正在往收集器里记录。这
// 是生产崩溃经中间件 + handler 端到端复现。
func TestAdminMetricsEndpointConcurrentPoll(t *testing.T) {
env := newEnv(t, nil, false)
tok := env.token(t, auth.RoleOwner)
metricsURL := env.ts.URL + "/api/v1/admin/observability/metrics"
healthURL := env.ts.URL + "/api/v1/health"
// Both jobs run concurrently: the panel's metrics reads race the load requests
// that keep recording into the collector.
// 两个任务并发运行:面板的指标读与持续往收集器
// 记录的负载请求相互竞争。
for _, err := range runConcurrent(
func() error { return driveRequests(healthURL, "", 4, 25) },
func() error { return driveRequests(metricsURL, tok, 6, 25) },
@@ -169,7 +169,7 @@ func TestAdminMetricsEndpointConcurrentPoll(t *testing.T) {
}
}
// runConcurrent runs every job in its own goroutine and returns the non-nil errors.
// runConcurrent 在各自 goroutine 中运行每个任务并返回非 nil 错误。
func runConcurrent(jobs ...func() error) []error {
var wg sync.WaitGroup
errs := make([]error, len(jobs))
@@ -184,8 +184,8 @@ func runConcurrent(jobs ...func() error) []error {
return errs
}
// driveRequests issues n GETs of url, workers of them in parallel, using token as
// a bearer credential when non-empty. It returns the first failure (status or I/O).
// driveRequests 对 url 发起 n 次 GET,其中 workers 个并行,token 非空
// 时作为 bearer 凭据。它返回首个失败(状态或 I/O)。
func driveRequests(url, token string, workers, n int) error {
var wg sync.WaitGroup
fail := make(chan error, workers)