github.com/openimsdk/tools@v0.0.49/mq/kafka/producer.go (about) 1 // Copyright © 2023 OpenIM. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package kafka 16 17 import ( 18 "context" 19 "github.com/IBM/sarama" 20 "github.com/openimsdk/tools/errs" 21 "google.golang.org/protobuf/proto" 22 ) 23 24 // Producer represents a Kafka producer. 25 type Producer struct { 26 addr []string 27 topic string 28 config *sarama.Config 29 producer sarama.SyncProducer 30 } 31 32 func NewKafkaProducer(config *sarama.Config, addr []string, topic string) (*Producer, error) { 33 producer, err := NewProducer(config, addr) 34 if err != nil { 35 return nil, err 36 } 37 return &Producer{ 38 addr: addr, 39 topic: topic, 40 config: config, 41 producer: producer, 42 }, nil 43 } 44 45 // SendMessage sends a message to the Kafka topic configured in the Producer. 46 func (p *Producer) SendMessage(ctx context.Context, key string, msg proto.Message) (int32, int64, error) { 47 // Marshal the protobuf message 48 bMsg, err := proto.Marshal(msg) 49 if err != nil { 50 return 0, 0, errs.WrapMsg(err, "kafka proto Marshal err") 51 } 52 if len(bMsg) == 0 { 53 return 0, 0, errs.WrapMsg(errEmptyMsg, "kafka proto Marshal err") 54 } 55 56 // Prepare Kafka message 57 kMsg := &sarama.ProducerMessage{ 58 Topic: p.topic, 59 Key: sarama.StringEncoder(key), 60 Value: sarama.ByteEncoder(bMsg), 61 } 62 63 // Validate message key and value 64 if kMsg.Key.Length() == 0 || kMsg.Value.Length() == 0 { 65 return 0, 0, errs.Wrap(errEmptyMsg) 66 } 67 68 // Attach context metadata as headers 69 header, err := GetMQHeaderWithContext(ctx) 70 if err != nil { 71 return 0, 0, err 72 } 73 kMsg.Headers = header 74 75 // Send the message 76 partition, offset, err := p.producer.SendMessage(kMsg) 77 if err != nil { 78 return 0, 0, errs.WrapMsg(err, "p.producer.SendMessage error") 79 } 80 81 return partition, offset, nil 82 }