// Package event ... // // Description : 基于redis实现事件生产 + 消费 // // Author : go_developer@163.com<白茶清欢> // // Date : 2025-08-22 16:34 package delay import ( "context" "fmt" "os" "time" "git.zhangdeman.cn/zhangdeman/network/util" "git.zhangdeman.cn/zhangdeman/queue/abstract" "git.zhangdeman.cn/zhangdeman/queue/define" "git.zhangdeman.cn/zhangdeman/redis" "git.zhangdeman.cn/zhangdeman/serialize" "git.zhangdeman.cn/zhangdeman/wrapper/op_string" ) // NewRedisProducer 获取基于redis的生产者实例 func NewRedisProducer( queueName string, queueCnt int, redisFlag string, producerHandler abstract.IProducerHandler, ) abstract.IProducer { if queueName == "" || redisFlag == "" { panic("init redis producer: queue name or redis flag is empty") } // 验证redis实例是否存在 if _, err := redis.Client.GetRealClientWithError(redisFlag); nil != err { panic(err.Error()) } if queueCnt <= 0 { queueCnt = 1 // 默认单队列 } if nil == producerHandler { producerHandler = abstract.DefaultProducerHandler{} } return &redisProducer{ queueCnt: queueCnt, queueName: queueName, redisFlag: redisFlag, producerHandler: producerHandler, } } type redisProducer struct { redisFlag string // redis 标识, 必须是使用统一的 pkg/redis 进行管理的 queueName string // 队列名称,基础公共前缀,尾部后缀会自动根据 shard cnt 进行哈希 queueCnt int // 队列数量 producerHandler abstract.IProducerHandler // 生产数据的处理逻辑 } // fillEventData 填充一些系统数据数据 func (r *redisProducer) fillEventData(data *define.EventData) { if len(data.Key) == 0 { data.Key = data.MsgID // 不设置和MsgID一致 } if len(data.TraceID) == 0 { data.TraceID = data.Key } data.SystemTimestamp = time.Now().UnixMilli() // 系统时间 if data.Timestamp <= 0 { data.Timestamp = data.SystemTimestamp } data.Hostname, _ = os.Hostname() // 服务器 hostname data.HostIp = util.IP.GetHostIP() // 服务器IP } // Sync 同步发送 func (r *redisProducer) Sync(ctx context.Context, data *define.EventData) { if nil == data { return } r.fillEventData(data) realQueue := r.getRealQueue(data) sendRedisRes := redis.Wrapper.LPush(ctx, r.redisFlag, realQueue, serialize.JSON.MarshalForStringIgnoreError(data)) res := &define.EventProduceResult{ Queue: realQueue, Success: sendRedisRes.Err == nil, Err: sendRedisRes.Err, Cost: sendRedisRes.UsedTime, } if res.Success { r.producerHandler.SuccessCallback(ctx, data, res) } else { r.producerHandler.FailureCallback(ctx, data, res) } } // Async 异步发送 func (r *redisProducer) Async(ctx context.Context, data *define.EventData) { go func() { defer func() { // 如果出现panic, 则触发失败回调 if err := recover(); nil != err { r.producerHandler.PanicCallback(ctx, data, err) } }() r.Sync(ctx, data) }() } // GetProducerHandler 获取producer处理器 func (r *redisProducer) GetProducerHandler() abstract.IProducerHandler { return r.producerHandler } // getRealQueue 获取真实的队列key func (r *redisProducer) getRealQueue(data *define.EventData) string { queueIdx := op_string.HashNumber(data.Key).Value % uint64(r.queueCnt) return fmt.Sprintf("%v_%v", r.queueName, queueIdx) }