Files
EchoChat/backend/go-service/pkg/logs/trace.go
bujinyuan ea2bf96c2f fix(meeting): Task 16 修复 code-reviewer 审计 P1 八项
按 docs/reviews/2026-04-23-phase2e-2-code-review.md 清单落地 P1 批次:

- P1-1 主持人转让原子性:MeetingParticipantDAO.TransferHost 内部事务
  合并 meeting_rooms.host_id 更新,service/lifecycle 移除冗余 UpdateHost
- P1-2 ListChatMessages / ListMyMeetings 回归 DAO:新增
  MeetingChatDAO.ListByRoomBefore 反向游标,service 移除 s.db 直查
- P1-3 ListMyMeetings N+1 放大优化:新增
  MeetingParticipantDAO.ListJoinedRoomsByUser JOIN + DISTINCT 单次 SQL
- P1-4 EndRoom 行锁 + 事务:s.db.Transaction 包裹
  SELECT FOR UPDATE → 快照 → MarkEnded → LeaveAllActive;DAO 补
  WithTx(*gorm.DB) 和 GetByIDForUpdate
- P1-5 后台 goroutine trace_id 保留:新增 logs.DetachContext(ctx);
  替换 meeting_service / meeting_signal_service 共 10 处 context.Background();
  meeting_ws_handler 每条 WS 消息分配独立 trace_id
- P1-6 _broadcastSelfState 重试:最多 2 次指数退避(700ms→2100ms),
  检测 localAudioEnabled/localVideoEnabled 已被后续动作覆盖时放弃旧 patch
- P1-7 HandleHostGraceExpired / HandleEmptyRoomExpired 处理锁:
  独立 host_grace_handling:<code> / empty_ttl_handling:<code> SETNX + 60s TTL,
  消除 Redis 自然过期 + 本地 timer 到点 + DEL 返回 0 的盲区
- P1-8 pushExistingRoomState 同步化:OnRoomJoin 返回前完成补推,
  消除与 REST member.joined 并行造成的前端状态闪烁

并附带修复 .gitignore 中 logs/ 规则误伤 pkg/logs/ 代码目录的历史遗留问题,
将 logger.go / trace.go 正式纳入版本控制。

验证:backend go build + go vet 通过;frontend npm run build:h5 通过。

Made-with: Cursor
2026-04-23 16:53:30 +08:00

45 lines
1.1 KiB
Go
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.

package logs
import (
"context"
"github.com/google/uuid"
)
type contextKey string
const traceIDKey contextKey = "trace_id"
// GenerateTraceID 生成唯一的链路追踪 IDUUID v4
func GenerateTraceID() string {
return uuid.New().String()
}
// WithTraceID 将 trace_id 注入 context
func WithTraceID(ctx context.Context, traceID string) context.Context {
return context.WithValue(ctx, traceIDKey, traceID)
}
// GetTraceID 从 context 提取 trace_id不存在则返回空字符串
func GetTraceID(ctx context.Context) string {
if ctx == nil {
return ""
}
if traceID, ok := ctx.Value(traceIDKey).(string); ok {
return traceID
}
return ""
}
// DetachContext 剥离父 ctx 的 Deadline/Cancel 但保留 trace_id
// 用于启动后台 goroutine 时避免随 HTTP 请求结束被取消,同时保持日志链路追踪连续性
// 典型使用go func() { ... }(logs.DetachContext(ctx))
// Task 16 P1-3后台 goroutine trace_id 保留 新增
func DetachContext(ctx context.Context) context.Context {
bg := context.Background()
if traceID := GetTraceID(ctx); traceID != "" {
return WithTraceID(bg, traceID)
}
return bg
}