github.com/streamdal/segmentio-kafka-go@v0.4.47-streamdal/protocol/produce/produce.go (about)

     1  package produce
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/segmentio/kafka-go/protocol"
     7  )
     8  
     9  func init() {
    10  	protocol.Register(&Request{}, &Response{})
    11  }
    12  
    13  type Request struct {
    14  	TransactionalID string         `kafka:"min=v3,max=v8,nullable"`
    15  	Acks            int16          `kafka:"min=v0,max=v8"`
    16  	Timeout         int32          `kafka:"min=v0,max=v8"`
    17  	Topics          []RequestTopic `kafka:"min=v0,max=v8"`
    18  }
    19  
    20  func (r *Request) ApiKey() protocol.ApiKey { return protocol.Produce }
    21  
    22  func (r *Request) Broker(cluster protocol.Cluster) (protocol.Broker, error) {
    23  	broker := protocol.Broker{ID: -1}
    24  
    25  	for i := range r.Topics {
    26  		t := &r.Topics[i]
    27  
    28  		topic, ok := cluster.Topics[t.Topic]
    29  		if !ok {
    30  			return broker, NewError(protocol.NewErrNoTopic(t.Topic))
    31  		}
    32  
    33  		for j := range t.Partitions {
    34  			p := &t.Partitions[j]
    35  
    36  			partition, ok := topic.Partitions[p.Partition]
    37  			if !ok {
    38  				return broker, NewError(protocol.NewErrNoPartition(t.Topic, p.Partition))
    39  			}
    40  
    41  			if b, ok := cluster.Brokers[partition.Leader]; !ok {
    42  				return broker, NewError(protocol.NewErrNoLeader(t.Topic, p.Partition))
    43  			} else if broker.ID < 0 {
    44  				broker = b
    45  			} else if b.ID != broker.ID {
    46  				return broker, NewError(fmt.Errorf("mismatching leaders (%d!=%d)", b.ID, broker.ID))
    47  			}
    48  		}
    49  	}
    50  
    51  	return broker, nil
    52  }
    53  
    54  func (r *Request) Prepare(apiVersion int16) {
    55  	// Determine which version of the message should be used, based on which
    56  	// version of the Produce API is supported by the server.
    57  	//
    58  	// In version 0.11, kafka gives this error:
    59  	//
    60  	//   org.apache.kafka.common.record.InvalidRecordException
    61  	//   Produce requests with version 3 are only allowed to contain record batches with magic version.
    62  	//
    63  	// In version 2.x, kafka refuses the message claiming that the CRC32
    64  	// checksum is invalid.
    65  	var recordVersion int8
    66  
    67  	if apiVersion < 3 {
    68  		recordVersion = 1
    69  	} else {
    70  		recordVersion = 2
    71  	}
    72  
    73  	for i := range r.Topics {
    74  		t := &r.Topics[i]
    75  
    76  		for j := range t.Partitions {
    77  			p := &t.Partitions[j]
    78  
    79  			// Allow the program to overload the version if really needed.
    80  			if p.RecordSet.Version == 0 {
    81  				p.RecordSet.Version = recordVersion
    82  			}
    83  		}
    84  	}
    85  }
    86  
    87  func (r *Request) HasResponse() bool {
    88  	return r.Acks != 0
    89  }
    90  
    91  type RequestTopic struct {
    92  	Topic      string             `kafka:"min=v0,max=v8"`
    93  	Partitions []RequestPartition `kafka:"min=v0,max=v8"`
    94  }
    95  
    96  type RequestPartition struct {
    97  	Partition int32              `kafka:"min=v0,max=v8"`
    98  	RecordSet protocol.RecordSet `kafka:"min=v0,max=v8"`
    99  }
   100  
   101  type Response struct {
   102  	Topics         []ResponseTopic `kafka:"min=v0,max=v8"`
   103  	ThrottleTimeMs int32           `kafka:"min=v1,max=v8"`
   104  }
   105  
   106  func (r *Response) ApiKey() protocol.ApiKey { return protocol.Produce }
   107  
   108  type ResponseTopic struct {
   109  	Topic      string              `kafka:"min=v0,max=v8"`
   110  	Partitions []ResponsePartition `kafka:"min=v0,max=v8"`
   111  }
   112  
   113  type ResponsePartition struct {
   114  	Partition      int32           `kafka:"min=v0,max=v8"`
   115  	ErrorCode      int16           `kafka:"min=v0,max=v8"`
   116  	BaseOffset     int64           `kafka:"min=v0,max=v8"`
   117  	LogAppendTime  int64           `kafka:"min=v2,max=v8"`
   118  	LogStartOffset int64           `kafka:"min=v5,max=v8"`
   119  	RecordErrors   []ResponseError `kafka:"min=v8,max=v8"`
   120  	ErrorMessage   string          `kafka:"min=v8,max=v8,nullable"`
   121  }
   122  
   123  type ResponseError struct {
   124  	BatchIndex             int32  `kafka:"min=v8,max=v8"`
   125  	BatchIndexErrorMessage string `kafka:"min=v8,max=v8,nullable"`
   126  }
   127  
   128  var (
   129  	_ protocol.BrokerMessage   = (*Request)(nil)
   130  	_ protocol.PreparedMessage = (*Request)(nil)
   131  )
   132  
   133  type Error struct {
   134  	Err error
   135  }
   136  
   137  func NewError(err error) *Error {
   138  	return &Error{Err: err}
   139  }
   140  
   141  func (e *Error) Error() string {
   142  	return fmt.Sprintf("fetch request error: %v", e.Err)
   143  }
   144  
   145  func (e *Error) Unwrap() error {
   146  	return e.Err
   147  }