refactor: replace standard log with zap logger and optimize code patterns

- Migrate all log.Printf/log.Println calls to structured zap logging
- Use cmp.Or for cleaner default value handling
- Replace manual loops with slices.ContainsFunc/IndexFunc
- Add batch query methods (IsLikedBatch, IsFavoritedBatch) to solve N+1 problem
- Update JSON tags from omitempty to omitzero for numeric fields
- Use errgroup-style wg.Go for worker goroutines
- Remove duplicate casbin/v2 dependency (keeping v3)
- Add plans/ to gitignore
This commit is contained in:
lafay
2026-03-17 00:47:17 +08:00
parent b028f7e1d3
commit 5d6c982c9c
38 changed files with 2256 additions and 290 deletions

View File

@@ -1,9 +1,11 @@
package service
import (
"cmp"
"errors"
"fmt"
"log"
"maps"
"slices"
"strconv"
"time"
@@ -14,6 +16,7 @@ import (
"carrot_bbs/internal/pkg/utils"
"carrot_bbs/internal/repository"
"go.uber.org/zap"
"gorm.io/gorm"
)
@@ -137,7 +140,10 @@ type groupNoticeMessage struct {
func (s *groupService) publishGroupNotice(groupID string, notice groupNoticeMessage) {
members, _, err := s.groupRepo.GetMembers(groupID, 1, 1000)
if err != nil {
log.Printf("[groupService] 获取群成员失败: groupID=%s, err=%v", groupID, err)
zap.L().Error("获取群成员失败",
zap.String("groupID", groupID),
zap.Error(err),
)
return
}
if s.sseHub != nil {
@@ -368,7 +374,10 @@ func (s *groupService) DissolveGroup(userID string, groupID string) error {
// 先删除群组对应的会话(包括参与者、消息)
if s.messageRepo != nil {
if err := s.messageRepo.DeleteConversationByGroupID(groupID); err != nil {
log.Printf("[DissolveGroup] 删除会话失败: groupID=%s, err=%v", groupID, err)
zap.L().Warn("删除会话失败",
zap.String("groupID", groupID),
zap.Error(err),
)
// 继续删除群组,不因为会话删除失败而中断
}
}
@@ -453,7 +462,12 @@ func (s *groupService) createSystemNotification(receiverID string, notifyType mo
ExtraData: extra,
}
if err := s.notifyRepo.Create(notification); err != nil {
log.Printf("[groupService] create system notification failed: receiverID=%s type=%s err=%v", receiverID, notifyType, err)
zap.L().Warn("create system notification failed",
zap.String("component", "groupService"),
zap.String("receiverID", receiverID),
zap.String("type", string(notifyType)),
zap.Error(err),
)
}
}
@@ -482,13 +496,22 @@ func (s *groupService) broadcastMemberJoinNotice(groupID string, targetUserID st
Category: model.CategoryNotification,
}
if err := s.messageRepo.CreateMessageWithSeq(msg); err != nil {
log.Printf("[broadcastMemberJoinNotice] 保存入群提示消息失败: groupID=%s, userID=%s, err=%v", groupID, targetUserID, err)
zap.L().Warn("保存入群提示消息失败",
zap.String("component", "broadcastMemberJoinNotice"),
zap.String("groupID", groupID),
zap.String("userID", targetUserID),
zap.Error(err),
)
} else {
savedMessage = msg
s.invalidateConversationCachesAfterSystemMessage(conv.ID)
}
} else {
log.Printf("[broadcastMemberJoinNotice] 获取群组会话失败: groupID=%s, err=%v", groupID, err)
zap.L().Warn("获取群组会话失败",
zap.String("component", "broadcastMemberJoinNotice"),
zap.String("groupID", groupID),
zap.Error(err),
)
}
}
@@ -542,7 +565,12 @@ func (s *groupService) addMemberToGroupAndConversation(group *model.Group, userI
conv, err := s.messageRepo.GetConversationByGroupID(group.ID)
if err == nil && conv != nil {
if err := s.messageRepo.AddParticipant(conv.ID, userID); err != nil {
log.Printf("[addMemberToGroupAndConversation] 添加会话参与者失败: groupID=%s, userID=%s, err=%v", group.ID, userID, err)
zap.L().Warn("添加会话参与者失败",
zap.String("component", "addMemberToGroupAndConversation"),
zap.String("groupID", group.ID),
zap.String("userID", userID),
zap.Error(err),
)
}
s.invalidateConversationCachesAfterMembershipChange(conv.ID, userID)
}
@@ -568,11 +596,7 @@ func (s *groupService) collectGroupReviewerIDs(groupID string, ownerID string, s
}
}
result := make([]string, 0, len(reviewerSet))
for id := range reviewerSet {
result = append(result, id)
}
return result
return slices.Collect(maps.Keys(reviewerSet))
}
func (s *groupService) notifyJoinApplyReviewers(
@@ -655,10 +679,8 @@ func (s *groupService) InviteMembers(userID string, groupID string, memberIDs []
inviter, _ := s.userRepo.GetByID(userID)
inviterName := "群成员"
inviterAvatar := ""
if inviter != nil && inviter.Nickname != "" {
inviterName = inviter.Nickname
}
if inviter != nil {
inviterName = cmp.Or(inviter.Nickname, "群成员")
inviterAvatar = inviter.Avatar
}
@@ -743,10 +765,8 @@ func (s *groupService) JoinGroup(userID string, groupID string) error {
applicant, _ := s.userRepo.GetByID(userID)
applicantName := "用户"
applicantAvatar := ""
if applicant != nil && applicant.Nickname != "" {
applicantName = applicant.Nickname
}
if applicant != nil {
applicantName = cmp.Or(applicant.Nickname, "用户")
applicantAvatar = applicant.Avatar
}
// 已有待审批单时补发一次提醒,避免管理端漏看
@@ -767,10 +787,8 @@ func (s *groupService) JoinGroup(userID string, groupID string) error {
applicant, _ := s.userRepo.GetByID(userID)
applicantName := "用户"
applicantAvatar := ""
if applicant != nil && applicant.Nickname != "" {
applicantName = applicant.Nickname
}
if applicant != nil {
applicantName = cmp.Or(applicant.Nickname, "用户")
applicantAvatar = applicant.Avatar
}
expireAt := time.Now().Add(72 * time.Hour)
@@ -856,9 +874,7 @@ func (s *groupService) RespondInvite(userID string, flag string, approve bool, r
targetUserName := "用户"
targetUserAvatar := ""
if u, e := s.userRepo.GetByID(userID); e == nil && u != nil {
if u.Nickname != "" {
targetUserName = u.Nickname
}
targetUserName = cmp.Or(u.Nickname, "用户")
targetUserAvatar = u.Avatar
}
@@ -866,9 +882,7 @@ func (s *groupService) RespondInvite(userID string, flag string, approve bool, r
inviterName := "群成员"
inviterAvatar := ""
if u, e := s.userRepo.GetByID(req.InitiatorID); e == nil && u != nil {
if u.Nickname != "" {
inviterName = u.Nickname
}
inviterName = cmp.Or(u.Nickname, "群成员")
inviterAvatar = u.Avatar
}
@@ -962,15 +976,13 @@ func (s *groupService) SetGroupAddRequest(userID string, flag string, approve bo
// 保存管理员ID到ReviewerID覆盖被邀请人的ID
req.Reason = reason
targetUserName := "用户"
if u, e := s.userRepo.GetByID(req.TargetUserID); e == nil && u != nil && u.Nickname != "" {
targetUserName = u.Nickname
if u, e := s.userRepo.GetByID(req.TargetUserID); e == nil && u != nil {
targetUserName = cmp.Or(u.Nickname, "用户")
}
reviewerName := "管理员"
reviewerAvatar := ""
if u, e := s.userRepo.GetByID(userID); e == nil && u != nil {
if u.Nickname != "" {
reviewerName = u.Nickname
}
reviewerName = cmp.Or(u.Nickname, "管理员")
reviewerAvatar = u.Avatar
}
@@ -1185,7 +1197,12 @@ func (s *groupService) RemoveMember(userID string, groupID string, targetUserID
conv, err := s.messageRepo.GetConversationByGroupID(groupID)
if err == nil && conv != nil {
if err := s.messageRepo.RemoveParticipant(conv.ID, targetUserID); err != nil {
log.Printf("[RemoveMember] 移除会话参与者失败: groupID=%s, userID=%s, err=%v", groupID, targetUserID, err)
zap.L().Warn("移除会话参与者失败",
zap.String("component", "RemoveMember"),
zap.String("groupID", groupID),
zap.String("userID", targetUserID),
zap.Error(err),
)
}
s.invalidateConversationCachesAfterMembershipChange(conv.ID, targetUserID)
}
@@ -1330,22 +1347,35 @@ func (s *groupService) MuteMember(userID string, groupID string, targetUserID st
member, err := s.groupRepo.GetMember(groupID, targetUserID)
if err != nil {
log.Printf("[MuteMember] 获取成员失败: %v", err)
zap.L().Warn("获取成员失败",
zap.String("component", "MuteMember"),
zap.Error(err),
)
return err
}
log.Printf("[MuteMember] 禁言前状态: member.Muted=%v, 即将设置 muted=%v", member.Muted, muted)
zap.L().Debug("禁言前状态",
zap.String("component", "MuteMember"),
zap.Bool("member.Muted", member.Muted),
zap.Bool("muted", muted),
)
member.Muted = muted
if err := s.groupRepo.UpdateMember(member); err != nil {
log.Printf("[MuteMember] 更新成员失败: %v", err)
zap.L().Warn("更新成员失败",
zap.String("component", "MuteMember"),
zap.Error(err),
)
return err
}
log.Printf("[MuteMember] 禁言状态已更新到数据库")
zap.L().Debug("禁言状态已更新到数据库", zap.String("component", "MuteMember"))
// 验证更新结果
updatedMember, _ := s.groupRepo.GetMember(groupID, targetUserID)
if updatedMember != nil {
log.Printf("[MuteMember] 验证: member.Muted=%v", updatedMember.Muted)
zap.L().Debug("验证成员状态",
zap.String("component", "MuteMember"),
zap.Bool("member.Muted", updatedMember.Muted),
)
}
// 获取被禁言用户的显示名称
@@ -1382,14 +1412,24 @@ func (s *groupService) MuteMember(userID string, groupID string, targetUserID st
// 保存消息并获取 seq
if err := s.messageRepo.CreateMessageWithSeq(msg); err != nil {
log.Printf("[MuteMember] 保存禁言消息失败: %v", err)
zap.L().Warn("保存禁言消息失败",
zap.String("component", "MuteMember"),
zap.Error(err),
)
} else {
savedMessage = msg
log.Printf("[MuteMember] 禁言消息已保存, ID=%s, Seq=%d", msg.ID, msg.Seq)
zap.L().Debug("禁言消息已保存",
zap.String("component", "MuteMember"),
zap.String("msgID", msg.ID),
zap.Int64("seq", msg.Seq),
)
s.invalidateConversationCachesAfterSystemMessage(conv.ID)
}
} else {
log.Printf("[MuteMember] 获取群组会话失败: %v", err)
zap.L().Warn("获取群组会话失败",
zap.String("component", "MuteMember"),
zap.Error(err),
)
}
}