Skip to content

Commit e44bd04

Browse files
GilthonielRobertIndie
authored andcommitted
[fix] Avoid a data race when flushing with load (#1261)
Fixes #1258 ### Motivation While flushing, the data channel is switched if a new allocated one which can cause the loss of messages because the length can be zero which would stop the procedure and at the same time a new message can be sent to the channel. ### Modifications Instead of allocating a new channel, it empties the existing one up to the length of the buffer of the channel before proceeding with the flush. (cherry picked from commit 8dd4ed1)
1 parent 53fc938 commit e44bd04

1 file changed

Lines changed: 20 additions & 13 deletions

File tree

pulsar/producer_partition.go

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -338,10 +338,6 @@ func (p *partitionProducer) grabCnx(assignedBrokerURL string) error {
338338
p.schemaCache.Put(p.schemaInfo, schemaVersion)
339339
}
340340

341-
if err != nil {
342-
return err
343-
}
344-
345341
if !p.options.DisableBatching && p.batchBuilder == nil {
346342
provider, err := GetBatcherBuilderProvider(p.options.BatcherBuilderType)
347343
if err != nil {
@@ -1022,15 +1018,7 @@ func (p *partitionProducer) internalFlushCurrentBatches() {
10221018
}
10231019

10241020
func (p *partitionProducer) internalFlush(fr *flushRequest) {
1025-
// clear all the messages which have sent to dataChan before flush
1026-
if len(p.dataChan) != 0 {
1027-
oldDataChan := p.dataChan
1028-
p.dataChan = make(chan *sendRequest, p.options.MaxPendingMessages)
1029-
for len(oldDataChan) != 0 {
1030-
pendingData := <-oldDataChan
1031-
p.internalSend(pendingData)
1032-
}
1033-
}
1021+
p.clearPendingSendRequests()
10341022

10351023
if !p.options.DisableBatching {
10361024
p.internalFlushCurrentBatch()
@@ -1061,6 +1049,25 @@ func (p *partitionProducer) internalFlush(fr *flushRequest) {
10611049
}
10621050
}
10631051

1052+
// clearPendingSendRequests makes sure to push forward previous sending requests
1053+
// by emptying the data channel.
1054+
func (p *partitionProducer) clearPendingSendRequests() {
1055+
sizeBeforeFlushing := len(p.dataChan)
1056+
1057+
// Bound the for loop to the current length of the channel to ensure that it
1058+
// will eventually stop as we only want to ensure that existing messages are
1059+
// flushed.
1060+
for i := 0; i < sizeBeforeFlushing; i++ {
1061+
select {
1062+
case pendingData := <-p.dataChan:
1063+
p.internalSend(pendingData)
1064+
1065+
default:
1066+
return
1067+
}
1068+
}
1069+
}
1070+
10641071
func (p *partitionProducer) Send(ctx context.Context, msg *ProducerMessage) (MessageID, error) {
10651072
var err error
10661073
var msgID MessageID

0 commit comments

Comments
 (0)