refactor: improve system stability, performance, and code structure
This commit introduces several architectural improvements and optimizations across the codebase: - **Performance & Reliability**: - Implemented Redis pipelining in `ConversationCache.CacheMessage` to reduce network round-trips. - Added a circuit breaker to the JPush client to prevent cascading failures. - Introduced batch deletion and batch member addition capabilities in repositories. - Added message idempotency support using `client_msg_id` and a Redis-based cache. - Optimized WebSocket handling with connection limits (total and per-user) and improved error logging. - **Code Refactoring**: - Refactored `Router` to use a `RouterDeps` struct, simplifying the constructor and improving maintainability. - Unified model ID generation logic using new `id_helper.go` (supporting UUID and Snowflake). - Standardized JSON serialization/deserialization in models using `json_helper.go`. - Refactored DTO conversion logic, specifically for `UserResponse` (using functional options) and `Report` responses. - Removed redundant/deprecated DTOs like `PostDetailResponse` and `TradeItemDetailResponse`. - **Cache Improvements**: - Enhanced `LayeredCache` with `SetRaw` to avoid double-encoding when promoting values from Redis to local cache. - Added `DeleteBatch` support to the cache interface. - **Other Changes**: - Cleaned up `config.go` by removing redundant default values and explicit environment variable overrides. - Improved WebSocket registration flow to handle connection limits gracefully.
This commit is contained in:
41
internal/cache/conversation_cache.go
vendored
41
internal/cache/conversation_cache.go
vendored
@@ -6,6 +6,8 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/redis/go-redis/v9"
|
||||
|
||||
"with_you/internal/model"
|
||||
|
||||
"go.uber.org/zap"
|
||||
@@ -618,11 +620,11 @@ func (c *ConversationCache) GetMessagesBeforeSeq(ctx context.Context, convID str
|
||||
return messages, nil
|
||||
}
|
||||
|
||||
// CacheMessage 缓存单条消息(立即写入缓存)
|
||||
// 写入 Hash、Sorted Set、更新计数
|
||||
// CacheMessage 缓存单条消息(使用 Redis Pipeline 减少网络往返)
|
||||
func (c *ConversationCache) CacheMessage(ctx context.Context, convID string, msg *model.Message) error {
|
||||
hashKey := MessageHashKey(convID)
|
||||
indexKey := MessageIndexKey(convID)
|
||||
countKey := MessageCountKey(convID)
|
||||
|
||||
msgData := MessageCacheDataFromModel(msg)
|
||||
data, err := json.Marshal(msgData)
|
||||
@@ -630,23 +632,34 @@ func (c *ConversationCache) CacheMessage(ctx context.Context, convID string, msg
|
||||
return fmt.Errorf("failed to marshal message: %w", err)
|
||||
}
|
||||
|
||||
// HSET 消息详情
|
||||
if err := c.cache.HSet(ctx, hashKey, fmt.Sprintf("%d", msg.Seq), string(data)); err != nil {
|
||||
hashKey = ResolveKey(hashKey)
|
||||
indexKey = ResolveKey(indexKey)
|
||||
countKey = ResolveKey(countKey)
|
||||
|
||||
redisCache, ok := c.cache.(*RedisCache)
|
||||
if ok {
|
||||
rdb := redisCache.GetRedisClient().GetClient()
|
||||
pipe := rdb.Pipeline()
|
||||
pipe.HSet(ctx, hashKey, fmt.Sprintf("%d", msg.Seq), string(data))
|
||||
pipe.ZAdd(ctx, indexKey, redis.Z{Score: float64(msg.Seq), Member: fmt.Sprintf("%d", msg.Seq)})
|
||||
pipe.Expire(ctx, hashKey, c.settings.MessageDetailTTL)
|
||||
pipe.Expire(ctx, indexKey, c.settings.MessageIndexTTL)
|
||||
pipe.Incr(ctx, countKey)
|
||||
if _, err := pipe.Exec(ctx); err != nil {
|
||||
return fmt.Errorf("failed to pipeline cache message: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := c.cache.HSet(ctx, MessageHashKey(convID), fmt.Sprintf("%d", msg.Seq), string(data)); err != nil {
|
||||
return fmt.Errorf("failed to set hash: %w", err)
|
||||
}
|
||||
|
||||
// ZADD 消息索引
|
||||
if err := c.cache.ZAdd(ctx, indexKey, float64(msg.Seq), fmt.Sprintf("%d", msg.Seq)); err != nil {
|
||||
if err := c.cache.ZAdd(ctx, MessageIndexKey(convID), float64(msg.Seq), fmt.Sprintf("%d", msg.Seq)); err != nil {
|
||||
return fmt.Errorf("failed to add to sorted set: %w", err)
|
||||
}
|
||||
|
||||
// 设置 TTL
|
||||
c.cache.Expire(ctx, hashKey, c.settings.MessageDetailTTL)
|
||||
c.cache.Expire(ctx, indexKey, c.settings.MessageIndexTTL)
|
||||
|
||||
// INCR 消息计数
|
||||
c.cache.Expire(ctx, MessageHashKey(convID), c.settings.MessageDetailTTL)
|
||||
c.cache.Expire(ctx, MessageIndexKey(convID), c.settings.MessageIndexTTL)
|
||||
c.cache.Incr(ctx, MessageCountKey(convID))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user