You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

117 lines
2.9 KiB
Go

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()
}