|
@@ -493,7 +493,27 @@ func (pp *partitionProducer) dispatch() {
|
|
|
pp.brokerProducer.input <- &ProducerMessage{Topic: pp.topic, Partition: pp.partition, flags: syn}
|
|
pp.brokerProducer.input <- &ProducerMessage{Topic: pp.topic, Partition: pp.partition, flags: syn}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ defer func() {
|
|
|
|
|
+ if pp.brokerProducer != nil {
|
|
|
|
|
+ pp.parent.unrefBrokerProducer(pp.leader, pp.brokerProducer)
|
|
|
|
|
+ }
|
|
|
|
|
+ }()
|
|
|
|
|
+
|
|
|
for msg := range pp.input {
|
|
for msg := range pp.input {
|
|
|
|
|
+
|
|
|
|
|
+ if pp.brokerProducer != nil && pp.brokerProducer.abandoned != nil {
|
|
|
|
|
+ select {
|
|
|
|
|
+ case <-pp.brokerProducer.abandoned:
|
|
|
|
|
+ // a message on the abandoned channel means that our current broker selection is out of date
|
|
|
|
|
+ Logger.Printf("producer/leader/%s/%d abandoning broker %d\n", pp.topic, pp.partition, pp.leader.ID())
|
|
|
|
|
+ pp.parent.unrefBrokerProducer(pp.leader, pp.brokerProducer)
|
|
|
|
|
+ pp.brokerProducer = nil
|
|
|
|
|
+ time.Sleep(pp.parent.conf.Producer.Retry.Backoff)
|
|
|
|
|
+ default:
|
|
|
|
|
+ // producer connection is still open.
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if msg.retries > pp.highWatermark {
|
|
if msg.retries > pp.highWatermark {
|
|
|
// a new, higher, retry level; handle it and then back off
|
|
// a new, higher, retry level; handle it and then back off
|
|
|
pp.newHighWatermark(msg.retries)
|
|
pp.newHighWatermark(msg.retries)
|
|
@@ -533,10 +553,6 @@ func (pp *partitionProducer) dispatch() {
|
|
|
|
|
|
|
|
pp.brokerProducer.input <- msg
|
|
pp.brokerProducer.input <- msg
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- if pp.brokerProducer != nil {
|
|
|
|
|
- pp.parent.unrefBrokerProducer(pp.leader, pp.brokerProducer)
|
|
|
|
|
- }
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func (pp *partitionProducer) newHighWatermark(hwm int) {
|
|
func (pp *partitionProducer) newHighWatermark(hwm int) {
|
|
@@ -637,6 +653,10 @@ func (p *asyncProducer) newBrokerProducer(broker *Broker) *brokerProducer {
|
|
|
close(responses)
|
|
close(responses)
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
|
|
+ if p.conf.Producer.Retry.Max <= 0 {
|
|
|
|
|
+ bp.abandoned = make(chan struct{})
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return bp
|
|
return bp
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -655,6 +675,7 @@ type brokerProducer struct {
|
|
|
input chan *ProducerMessage
|
|
input chan *ProducerMessage
|
|
|
output chan<- *produceSet
|
|
output chan<- *produceSet
|
|
|
responses <-chan *brokerProducerResponse
|
|
responses <-chan *brokerProducerResponse
|
|
|
|
|
+ abandoned chan struct{}
|
|
|
|
|
|
|
|
buffer *produceSet
|
|
buffer *produceSet
|
|
|
timer <-chan time.Time
|
|
timer <-chan time.Time
|
|
@@ -829,9 +850,17 @@ func (bp *brokerProducer) handleSuccess(sent *produceSet, response *ProduceRespo
|
|
|
// Retriable errors
|
|
// Retriable errors
|
|
|
case ErrInvalidMessage, ErrUnknownTopicOrPartition, ErrLeaderNotAvailable, ErrNotLeaderForPartition,
|
|
case ErrInvalidMessage, ErrUnknownTopicOrPartition, ErrLeaderNotAvailable, ErrNotLeaderForPartition,
|
|
|
ErrRequestTimedOut, ErrNotEnoughReplicas, ErrNotEnoughReplicasAfterAppend:
|
|
ErrRequestTimedOut, ErrNotEnoughReplicas, ErrNotEnoughReplicasAfterAppend:
|
|
|
- retryTopics = append(retryTopics, topic)
|
|
|
|
|
|
|
+ if bp.parent.conf.Producer.Retry.Max <= 0 {
|
|
|
|
|
+ bp.parent.abandonBrokerConnection(bp.broker)
|
|
|
|
|
+ bp.parent.returnErrors(pSet.msgs, block.Err)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ retryTopics = append(retryTopics, topic)
|
|
|
|
|
+ }
|
|
|
// Other non-retriable errors
|
|
// Other non-retriable errors
|
|
|
default:
|
|
default:
|
|
|
|
|
+ if bp.parent.conf.Producer.Retry.Max <= 0 {
|
|
|
|
|
+ bp.parent.abandonBrokerConnection(bp.broker)
|
|
|
|
|
+ }
|
|
|
bp.parent.returnErrors(pSet.msgs, block.Err)
|
|
bp.parent.returnErrors(pSet.msgs, block.Err)
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
@@ -1048,5 +1077,10 @@ func (p *asyncProducer) abandonBrokerConnection(broker *Broker) {
|
|
|
p.brokerLock.Lock()
|
|
p.brokerLock.Lock()
|
|
|
defer p.brokerLock.Unlock()
|
|
defer p.brokerLock.Unlock()
|
|
|
|
|
|
|
|
|
|
+ bc, ok := p.brokers[broker]
|
|
|
|
|
+ if ok && bc.abandoned != nil {
|
|
|
|
|
+ close(bc.abandoned)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
delete(p.brokers, broker)
|
|
delete(p.brokers, broker)
|
|
|
}
|
|
}
|