feat(cache): implement database fallback for conversation sequence management
Improve the reliability of conversation sequence generation by implementing a fallback mechanism to the database when Redis is unavailable or when keys are missing. - Add `GetNextSeq` to `MessageRepository` and implement it in `MessageRepositoryAdapter`. - Update `ConversationCache` to fallback to DB in `GetConvMaxSeq`, `GetConvMaxSeqBatch`, and `GetNextSeq`. - Ensure Redis TTL is refreshed after every `INCR` operation to prevent sequence counter expiration. - Refactor service layers to handle sequence generation errors more explicitly. - Add `IsEnabled` helper to `LayeredCache` for cleaner availability checks.
This commit is contained in:
@@ -348,13 +348,9 @@ func (s *chatServiceImpl) SendMessage(ctx context.Context, senderID string, conv
|
||||
if s.conversationCache != nil {
|
||||
seq, err := s.conversationCache.GetNextSeq(ctx, conversationID)
|
||||
if err != nil {
|
||||
zap.L().Warn("redis get next seq failed, falling back to DB",
|
||||
zap.String("convID", conversationID),
|
||||
zap.Error(err),
|
||||
)
|
||||
} else {
|
||||
message.Seq = seq
|
||||
return nil, fmt.Errorf("failed to get next seq for conversation %s: %w", conversationID, err)
|
||||
}
|
||||
message.Seq = seq
|
||||
}
|
||||
|
||||
// 使用事务创建消息并更新seq
|
||||
@@ -916,13 +912,9 @@ func (s *chatServiceImpl) SaveMessage(ctx context.Context, senderID string, conv
|
||||
if s.conversationCache != nil {
|
||||
seq, err := s.conversationCache.GetNextSeq(ctx, conversationID)
|
||||
if err != nil {
|
||||
zap.L().Warn("redis get next seq failed, falling back to DB",
|
||||
zap.String("convID", conversationID),
|
||||
zap.Error(err),
|
||||
)
|
||||
} else {
|
||||
message.Seq = seq
|
||||
return nil, fmt.Errorf("failed to get next seq for conversation %s: %w", conversationID, err)
|
||||
}
|
||||
message.Seq = seq
|
||||
}
|
||||
|
||||
if err := s.repo.CreateMessageWithSeq(message); err != nil {
|
||||
|
||||
@@ -474,13 +474,13 @@ func (s *groupService) broadcastMemberJoinNotice(groupID string, targetUserID st
|
||||
if s.conversationCache != nil {
|
||||
seq, seqErr := s.conversationCache.GetNextSeq(context.Background(), conv.ID)
|
||||
if seqErr != nil {
|
||||
zap.L().Warn("redis get next seq failed, falling back to DB",
|
||||
zap.L().Warn("get next seq failed, skipping system message",
|
||||
zap.String("convID", conv.ID),
|
||||
zap.Error(seqErr),
|
||||
)
|
||||
} else {
|
||||
msg.Seq = seq
|
||||
return
|
||||
}
|
||||
msg.Seq = seq
|
||||
}
|
||||
if err := s.messageRepo.CreateMessageWithSeq(msg); err != nil {
|
||||
zap.L().Warn("保存入群提示消息失败",
|
||||
@@ -1399,13 +1399,13 @@ func (s *groupService) MuteMember(userID string, groupID string, targetUserID st
|
||||
if s.conversationCache != nil {
|
||||
seq, seqErr := s.conversationCache.GetNextSeq(context.Background(), conv.ID)
|
||||
if seqErr != nil {
|
||||
zap.L().Warn("redis get next seq failed, falling back to DB",
|
||||
zap.L().Warn("get next seq failed, skipping system message",
|
||||
zap.String("convID", conv.ID),
|
||||
zap.Error(seqErr),
|
||||
)
|
||||
} else {
|
||||
msg.Seq = seq
|
||||
return nil
|
||||
}
|
||||
msg.Seq = seq
|
||||
}
|
||||
|
||||
if err := s.messageRepo.CreateMessageWithSeq(msg); err != nil {
|
||||
|
||||
@@ -2,6 +2,7 @@ package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"with_you/internal/cache"
|
||||
@@ -90,13 +91,9 @@ func (s *MessageService) SendMessage(ctx context.Context, senderID, receiverID s
|
||||
if s.conversationCache != nil {
|
||||
seq, seqErr := s.conversationCache.GetNextSeq(context.Background(), conv.ID)
|
||||
if seqErr != nil {
|
||||
zap.L().Warn("redis get next seq failed, falling back to DB",
|
||||
zap.String("convID", conv.ID),
|
||||
zap.Error(seqErr),
|
||||
)
|
||||
} else {
|
||||
msg.Seq = seq
|
||||
return nil, fmt.Errorf("failed to get next seq for conversation %s: %w", conv.ID, seqErr)
|
||||
}
|
||||
msg.Seq = seq
|
||||
}
|
||||
|
||||
// 使用事务创建消息并更新seq
|
||||
|
||||
Reference in New Issue
Block a user