feat(chat): implement sequence pre-allocation, versioned sync, and push worker
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:
@@ -18,6 +18,7 @@ import (
|
||||
"with_you/internal/repository"
|
||||
"with_you/internal/service"
|
||||
|
||||
redisPkg "github.com/redis/go-redis/v9"
|
||||
"github.com/google/wire"
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
@@ -49,6 +50,12 @@ var InfrastructureSet = wire.NewSet(
|
||||
// WebSocket MessagePublisher
|
||||
ProvideWSMessagePublisher,
|
||||
|
||||
// Seq 预分配管理器
|
||||
ProvideSeqBufferManager,
|
||||
|
||||
// 推送 Worker
|
||||
ProvidePushWorker,
|
||||
|
||||
// 外部服务客户端
|
||||
ProvideOpenAIClient,
|
||||
ProvideTencentClient,
|
||||
@@ -275,3 +282,47 @@ func ProvideLogger() *zap.Logger {
|
||||
zap.ReplaceGlobals(logger)
|
||||
return logger
|
||||
}
|
||||
|
||||
// ProvideSeqBufferManager 提供 Seq 预分配管理器
|
||||
func ProvideSeqBufferManager(cfg *config.Config, redisClient *redis.Client, cacheBackend cache.Cache) *cache.SeqBufferManager {
|
||||
seqCfg := cache.SeqBufferConfig{
|
||||
Enabled: cfg.SeqBuffer.Enabled,
|
||||
PrivateBufferSize: cfg.SeqBuffer.PrivateBufferSize,
|
||||
GroupBufferSize: cfg.SeqBuffer.GroupBufferSize,
|
||||
LockTimeoutMs: cfg.SeqBuffer.LockTimeoutMs,
|
||||
MaxRetries: cfg.SeqBuffer.MaxRetries,
|
||||
}
|
||||
if !seqCfg.Enabled {
|
||||
return cache.NewSeqBufferManager(nil, seqCfg, nil, nil)
|
||||
}
|
||||
return cache.NewSeqBufferManagerFromRedisPkg(redisClient, seqCfg, nil, nil)
|
||||
}
|
||||
|
||||
// ProvidePushWorker 提供推送 Worker(Redis Stream 异步推送)
|
||||
func ProvidePushWorker(
|
||||
cfg *config.Config,
|
||||
redisClient *redis.Client,
|
||||
publisher ws.MessagePublisher,
|
||||
pushSvc service.PushService,
|
||||
msgRepo repository.MessageRepository,
|
||||
userRepo repository.UserRepository,
|
||||
) *service.PushWorker {
|
||||
pushCfg := service.PushWorkerConfig{
|
||||
Enabled: cfg.PushWorker.Enabled,
|
||||
Stream: cfg.PushWorker.Stream,
|
||||
Group: cfg.PushWorker.Group,
|
||||
BatchSize: cfg.PushWorker.BatchSize,
|
||||
PollTimeoutMs: cfg.PushWorker.PollTimeoutMs,
|
||||
MaxRetries: cfg.PushWorker.MaxRetries,
|
||||
MaxStreamLen: cfg.PushWorker.MaxStreamLen,
|
||||
IdleTimeoutMs: cfg.PushWorker.IdleTimeoutMs,
|
||||
}
|
||||
if !pushCfg.Enabled {
|
||||
return service.NewPushWorker(nil, nil, nil, nil, nil, pushCfg)
|
||||
}
|
||||
var rdb *redisPkg.Client
|
||||
if redisClient != nil {
|
||||
rdb = redisClient.GetClient()
|
||||
}
|
||||
return service.NewPushWorker(rdb, publisher, pushSvc, msgRepo, userRepo, pushCfg)
|
||||
}
|
||||
|
||||
@@ -51,6 +51,9 @@ var RepositorySet = wire.NewSet(
|
||||
|
||||
// 二手交易相关
|
||||
repository.NewTradeRepository,
|
||||
|
||||
// 版本日志同步
|
||||
repository.NewConversationVersionLogRepository,
|
||||
)
|
||||
|
||||
// ProvideUserActivityRepository 提供用户活跃数据仓储
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
"with_you/internal/service"
|
||||
|
||||
"github.com/google/wire"
|
||||
redislib "github.com/redis/go-redis/v9"
|
||||
redisPkg "github.com/redis/go-redis/v9"
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@@ -212,8 +212,21 @@ func ProvideChatService(
|
||||
cacheBackend cache.Cache,
|
||||
uploadService *service.UploadService,
|
||||
pushService service.PushService,
|
||||
seqBufferMgr *cache.SeqBufferManager,
|
||||
pushWorker *service.PushWorker,
|
||||
redisClient *redis.Client,
|
||||
versionLogRepo repository.ConversationVersionLogRepository,
|
||||
cfg *config.Config,
|
||||
) service.ChatService {
|
||||
return service.NewChatService(messageRepo, userRepo, nil, publisher, cacheBackend, uploadService, pushService)
|
||||
var vlogOpt []repository.ConversationVersionLogRepository
|
||||
if cfg.VersionLog.Enabled {
|
||||
vlogOpt = []repository.ConversationVersionLogRepository{versionLogRepo}
|
||||
}
|
||||
var rdb *redisPkg.Client
|
||||
if redisClient != nil {
|
||||
rdb = redisClient.GetClient()
|
||||
}
|
||||
return service.NewChatService(messageRepo, userRepo, nil, publisher, cacheBackend, uploadService, pushService, seqBufferMgr, pushWorker, rdb, vlogOpt...)
|
||||
}
|
||||
|
||||
// ProvideScheduleService 提供日程服务
|
||||
@@ -398,7 +411,7 @@ func ProvideLogService(
|
||||
|
||||
// ProvideQRCodeLoginService 提供二维码登录服务
|
||||
func ProvideHotRankWorker(cfg *config.Config, postRepo repository.PostRepository, channelRepo repository.ChannelRepository, cacheBackend cache.Cache, redisClient *redis.Client) *service.HotRankWorker {
|
||||
var rdb *redislib.Client
|
||||
var rdb *redisPkg.Client
|
||||
if redisClient != nil {
|
||||
rdb = redisClient.GetClient()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user