feat(chat): implement sequence pre-allocation, versioned sync, and push worker
All checks were successful
Build Backend / build (push) Successful in 4m20s
Build Backend / build-docker (push) Successful in 1m7s

Introduce several performance and synchronization enhancements:
- Implement `SeqBufferManager` to allow sequence number pre-allocation via Redis Lua scripts, reducing atomic increment overhead.
- Add `PushWorker` to handle asynchronous message pushing using Redis Streams.
- Implement incremental conversation synchronization via `ConversationVersionLog` to allow clients to fetch only recent changes.
- Add support for Gzip compression in WebSocket communications to reduce bandwidth usage.
- Update dependency injection and configuration to support these new components.
This commit is contained in:
2026-05-17 23:38:04 +08:00
parent f63c795dcb
commit 6bf87fec46
26 changed files with 1450 additions and 82 deletions

View File

@@ -230,22 +230,24 @@ type MessageRepository interface {
// ConversationCache 会话缓存管理器
type ConversationCache struct {
cache Cache // 底层缓存
settings *ConversationCacheSettings // 配置
repo ConversationRepository // 数据仓库接口(用于 cache-aside 回源)
msgRepo MessageRepository // 消息数据仓库接口(用于消息缓存回源)
cache Cache // 底层缓存
settings *ConversationCacheSettings // 配置
repo ConversationRepository // 数据仓库接口(用于 cache-aside 回源)
msgRepo MessageRepository // 消息数据仓库接口(用于消息缓存回源)
seqBufferMgr *SeqBufferManager // seq 预分配管理器nil 则使用旧 INCR 逻辑)
}
// NewConversationCache 创建会话缓存管理器
func NewConversationCache(cache Cache, repo ConversationRepository, msgRepo MessageRepository, settings *ConversationCacheSettings) *ConversationCache {
func NewConversationCache(cache Cache, repo ConversationRepository, msgRepo MessageRepository, settings *ConversationCacheSettings, seqBufferMgr *SeqBufferManager) *ConversationCache {
if settings == nil {
settings = DefaultConversationCacheSettings()
}
return &ConversationCache{
cache: cache,
settings: settings,
repo: repo,
msgRepo: msgRepo,
cache: cache,
settings: settings,
repo: repo,
msgRepo: msgRepo,
seqBufferMgr: seqBufferMgr,
}
}
@@ -694,8 +696,16 @@ func (c *ConversationCache) ComputeAllUnreadCount(ctx context.Context, userID st
}
// GetNextSeq 获取会话的下一个 seq 值(原子递增)
// 使用 Redis INCR 实现,首次调用时从 DB 初始化并补齐差值
// 启用 seq 预分配时使用本地缓冲区 + Redis Lua 分配;否则使用旧 INCR 逻辑
func (c *ConversationCache) GetNextSeq(ctx context.Context, convID string) (int64, error) {
// 优先使用 seq 预分配
if c.seqBufferMgr != nil && c.seqBufferMgr.IsEnabled() {
// 判断是否群聊(通过会话类型判断,这里先按私聊处理,由上层传入 isGroup
// 由于接口只传 convID这里默认私聊逻辑群聊的 isGroup 由调用方决定
return c.seqBufferMgr.GetNextSeq(ctx, convID, false)
}
// 降级到旧 INCR 逻辑
seqKey := MessageSeqKey(convID)
newSeq, err := c.cache.Incr(ctx, seqKey)
@@ -732,6 +742,14 @@ func (c *ConversationCache) GetNextSeq(ctx context.Context, convID string) (int6
return newSeq, nil
}
// GetNextSeqWithGroup 获取会话的下一个 seq 值(支持群聊标识,用于 seq 预分配步长区分)
func (c *ConversationCache) GetNextSeqWithGroup(ctx context.Context, convID string, isGroup bool) (int64, error) {
if c.seqBufferMgr != nil && c.seqBufferMgr.IsEnabled() {
return c.seqBufferMgr.GetNextSeq(ctx, convID, isGroup)
}
return c.GetNextSeq(ctx, convID)
}
// ============================================================
// 消息缓存方法
// ============================================================