package producer import ( "context" "joybuywork/internal/app" "joybuywork/internal/consts" "joybuywork/internal/consts/ckey" "joybuywork/internal/plugins/jsonm" "joybuywork/internal/utils" "fmt" "time" "github.com/Shopify/sarama" "github.com/rs/xid" "gits.branchcn.com/backend/microcode/plugins/derivative/delay" "gits.branchcn.com/backend/microcode/plugins/kafka" ) var AP *AsyncProducer func SetUp() { AP, _ = NewAsyncProducer(kafka.DefaultProducerConfig()) initCommonProducer() } type AsyncProducer struct { producer sarama.AsyncProducer } func NewAsyncProducer(config *sarama.Config) (*AsyncProducer, error) { p, err := app.Kafka.NewAsyncProducer(config) if err != nil { return nil, err } ap := &AsyncProducer{producer: p} // 监听消息发送结果 app.GoSafe(ap.handleSuccesses, "默认生产者监听发送成功消息") app.GoSafe(ap.handleErrors, "默认生产者监听发送错误消息") return ap, nil } func (p *AsyncProducer) Produce(ctx context.Context, topic string, key string, value any, setHeader ...sarama.RecordHeader) (err error) { b, err := jsonm.Marshal(value) if err != nil { return } var headers = []sarama.RecordHeader{ { Key: []byte(consts.CtxMsgId), Value: []byte(xid.New().String()), }, } traceId := ctx.Value(consts.TraceIdKey) if traceId == nil { headers = append(headers, sarama.RecordHeader{ Key: []byte(consts.TraceIdKey), Value: []byte(xid.New().String()), }) } else { headers = append(headers, sarama.RecordHeader{ Key: []byte(consts.TraceIdKey), Value: []byte(traceId.(string)), }) } for _, header := range setHeader { headers = append(headers, header) } m := &sarama.ProducerMessage{ Headers: headers, Topic: topic, Key: sarama.StringEncoder(key), Value: sarama.ByteEncoder(b), Timestamp: time.Now(), } p.producer.Input() <- m return } func (p *AsyncProducer) handleSuccesses() { for v := range p.producer.Successes() { ctx := context.Background() for _, header := range v.Headers { ctx = context.WithValue(ctx, utils.Bs(header.Key), utils.Bs(header.Value)) } key, _ := v.Key.Encode() val, _ := v.Value.Encode() app.Logger.Info(ctx, fmt.Sprintf("默认生产者发送消息成功, key: %s, val: %s", utils.Bs(key), utils.Bs(val))) } } func (p *AsyncProducer) handleErrors() { for v := range p.producer.Errors() { ctx := context.Background() for _, header := range v.Msg.Headers { ctx = context.WithValue(ctx, utils.Bs(header.Key), utils.Bs(header.Value)) } key, _ := v.Msg.Key.Encode() val, _ := v.Msg.Value.Encode() app.Logger.Info(ctx, fmt.Sprintf("默认生产者发送消息失败:%v, key: %s, val: %s", v.Err, utils.Bs(key), utils.Bs(val))) } } var DelayCommon *delay.Producer func initCommonProducer() { DelayCommon = delay.NewRedisDelayQueue(context.Background(), app.Redis.Cache, ckey.DelayCommonKey()).Producer() }