Skip to content

Commit 6f01a7c

Browse files
authored
[Fix] check if callback is nil before calling it (#1036)
Co-authored-by: gunli <[email protected]>
1 parent 3da3e5d commit 6f01a7c

File tree

1 file changed

+30
-28
lines changed

1 file changed

+30
-28
lines changed

pulsar/producer_partition.go

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,14 @@ func (p *partitionProducer) Name() string {
467467
return p.producerName
468468
}
469469

470+
func runCallback(cb func(MessageID, *ProducerMessage, error), id MessageID, msg *ProducerMessage, err error) {
471+
if cb == nil {
472+
return
473+
}
474+
475+
cb(id, msg, err)
476+
}
477+
470478
func (p *partitionProducer) internalSend(request *sendRequest) {
471479
p.log.Debug("Received send request: ", *request.msg)
472480

@@ -480,7 +488,7 @@ func (p *partitionProducer) internalSend(request *sendRequest) {
480488
var err error
481489
if msg.Value != nil && msg.Payload != nil {
482490
p.log.Error("Can not set Value and Payload both")
483-
request.callback(nil, request.msg, errors.New("can not set Value and Payload both"))
491+
runCallback(request.callback, nil, request.msg, errors.New("can not set Value and Payload both"))
484492
return
485493
}
486494

@@ -494,7 +502,7 @@ func (p *partitionProducer) internalSend(request *sendRequest) {
494502
if msg.Schema != nil && p.options.Schema != nil &&
495503
msg.Schema.GetSchemaInfo().hash() != p.options.Schema.GetSchemaInfo().hash() {
496504
p.releaseSemaphoreAndMem(uncompressedPayloadSize)
497-
request.callback(nil, request.msg, fmt.Errorf("msg schema can not match with producer schema"))
505+
runCallback(request.callback, nil, request.msg, fmt.Errorf("msg schema can not match with producer schema"))
498506
p.log.WithError(err).Errorf("The producer %s of the topic %s is disabled the `MultiSchema`", p.producerName, p.topic)
499507
return
500508
}
@@ -513,7 +521,7 @@ func (p *partitionProducer) internalSend(request *sendRequest) {
513521
schemaPayload, err = schema.Encode(msg.Value)
514522
if err != nil {
515523
p.releaseSemaphoreAndMem(uncompressedPayloadSize)
516-
request.callback(nil, request.msg, newError(SchemaFailure, err.Error()))
524+
runCallback(request.callback, nil, request.msg, newError(SchemaFailure, err.Error()))
517525
p.log.WithError(err).Errorf("Schema encode message failed %s", msg.Value)
518526
return
519527
}
@@ -530,7 +538,7 @@ func (p *partitionProducer) internalSend(request *sendRequest) {
530538
if err != nil {
531539
p.releaseSemaphoreAndMem(uncompressedPayloadSize)
532540
p.log.WithError(err).Error("get schema version fail")
533-
request.callback(nil, request.msg, fmt.Errorf("get schema version fail, err: %w", err))
541+
runCallback(request.callback, nil, request.msg, fmt.Errorf("get schema version fail, err: %w", err))
534542
return
535543
}
536544
p.schemaCache.Put(schema.GetSchemaInfo(), schemaVersion)
@@ -589,7 +597,7 @@ func (p *partitionProducer) internalSend(request *sendRequest) {
589597
// if msg is too large and chunking is disabled
590598
if checkSize > maxMessageSize && !p.options.EnableChunking {
591599
p.releaseSemaphoreAndMem(uncompressedPayloadSize)
592-
request.callback(nil, request.msg, errMessageTooLarge)
600+
runCallback(request.callback, nil, request.msg, errMessageTooLarge)
593601
p.log.WithError(errMessageTooLarge).
594602
WithField("size", checkSize).
595603
WithField("properties", msg.Properties).
@@ -608,7 +616,7 @@ func (p *partitionProducer) internalSend(request *sendRequest) {
608616
payloadChunkSize = int(p._getConn().GetMaxMessageSize()) - proto.Size(mm)
609617
if payloadChunkSize <= 0 {
610618
p.releaseSemaphoreAndMem(uncompressedPayloadSize)
611-
request.callback(nil, msg, errMetaTooLarge)
619+
runCallback(request.callback, nil, msg, errMetaTooLarge)
612620
p.log.WithError(errMetaTooLarge).
613621
WithField("metadata size", proto.Size(mm)).
614622
WithField("properties", msg.Properties).
@@ -683,7 +691,7 @@ func (p *partitionProducer) internalSend(request *sendRequest) {
683691
if ok := addRequestToBatch(smm, p, uncompressedPayload, request, msg, deliverAt, schemaVersion,
684692
multiSchemaEnabled); !ok {
685693
p.releaseSemaphoreAndMem(uncompressedPayloadSize)
686-
request.callback(nil, request.msg, errFailAddToBatch)
694+
runCallback(request.callback, nil, request.msg, errFailAddToBatch)
687695
p.log.WithField("size", uncompressedSize).
688696
WithField("properties", msg.Properties).
689697
Error("unable to add message to batch")
@@ -835,7 +843,7 @@ func (p *partitionProducer) internalSingleSend(mm *pb.MessageMetadata,
835843
)
836844
}
837845
if err != nil {
838-
request.callback(nil, request.msg, err)
846+
runCallback(request.callback, nil, request.msg, err)
839847
p.releaseSemaphoreAndMem(int64(len(msg.Payload)))
840848
p.log.WithError(err).Errorf("Single message serialize failed %s", msg.Value)
841849
return
@@ -875,7 +883,7 @@ func (p *partitionProducer) internalFlushCurrentBatch() {
875883
if err != nil {
876884
for _, cb := range callbacks {
877885
if sr, ok := cb.(*sendRequest); ok {
878-
sr.callback(nil, sr.msg, err)
886+
runCallback(sr.callback, nil, sr.msg, err)
879887
}
880888
}
881889
if errors.Is(err, internal.ErrExceedMaxMessageSize) {
@@ -985,7 +993,7 @@ func (p *partitionProducer) failTimeoutMessages() {
985993

986994
if sr.callback != nil {
987995
sr.callbackOnce.Do(func() {
988-
sr.callback(nil, sr.msg, errSendTimeout)
996+
runCallback(sr.callback, nil, sr.msg, errSendTimeout)
989997
})
990998
}
991999
if sr.transaction != nil {
@@ -1018,7 +1026,7 @@ func (p *partitionProducer) internalFlushCurrentBatches() {
10181026
if errs[i] != nil {
10191027
for _, cb := range callbacks[i] {
10201028
if sr, ok := cb.(*sendRequest); ok {
1021-
sr.callback(nil, sr.msg, errs[i])
1029+
runCallback(sr.callback, nil, sr.msg, errs[i])
10221030
}
10231031
}
10241032
if errors.Is(errs[i], internal.ErrExceedMaxMessageSize) {
@@ -1106,34 +1114,34 @@ func (p *partitionProducer) SendAsync(ctx context.Context, msg *ProducerMessage,
11061114

11071115
func (p *partitionProducer) internalSendAsync(ctx context.Context, msg *ProducerMessage,
11081116
callback func(MessageID, *ProducerMessage, error), flushImmediately bool) {
1109-
//Register transaction operation to transaction and the transaction coordinator.
1117+
// Register transaction operation to transaction and the transaction coordinator.
11101118
var newCallback func(MessageID, *ProducerMessage, error)
11111119
if msg.Transaction != nil {
11121120
transactionImpl := (msg.Transaction).(*transaction)
11131121
if transactionImpl.state != TxnOpen {
11141122
p.log.WithField("state", transactionImpl.state).Error("Failed to send message" +
11151123
" by a non-open transaction.")
1116-
callback(nil, msg, newError(InvalidStatus, "Failed to send message by a non-open transaction."))
1124+
runCallback(callback, nil, msg, newError(InvalidStatus, "Failed to send message by a non-open transaction."))
11171125
return
11181126
}
11191127

11201128
if err := transactionImpl.registerProducerTopic(p.topic); err != nil {
1121-
callback(nil, msg, err)
1129+
runCallback(callback, nil, msg, err)
11221130
return
11231131
}
11241132
if err := transactionImpl.registerSendOrAckOp(); err != nil {
1125-
callback(nil, msg, err)
1133+
runCallback(callback, nil, msg, err)
11261134
}
11271135
newCallback = func(id MessageID, producerMessage *ProducerMessage, err error) {
1128-
callback(id, producerMessage, err)
1136+
runCallback(callback, id, producerMessage, err)
11291137
transactionImpl.endSendOrAckOp(err)
11301138
}
11311139
} else {
11321140
newCallback = callback
11331141
}
11341142
if p.getProducerState() != producerReady {
11351143
// Producer is closing
1136-
newCallback(nil, msg, errProducerClosed)
1144+
runCallback(newCallback, nil, msg, errProducerClosed)
11371145
return
11381146
}
11391147

@@ -1253,9 +1261,7 @@ func (p *partitionProducer) ReceivedSendReceipt(response *pb.CommandSendReceipt)
12531261
}
12541262

12551263
if sr.totalChunks <= 1 || sr.chunkID == sr.totalChunks-1 {
1256-
if sr.callback != nil {
1257-
sr.callback(msgID, sr.msg, nil)
1258-
}
1264+
runCallback(sr.callback, msgID, sr.msg, nil)
12591265
p.options.Interceptors.OnSendAcknowledgement(p, sr.msg, msgID)
12601266
}
12611267
}
@@ -1406,27 +1412,23 @@ func (p *partitionProducer) releaseSemaphoreAndMem(size int64) {
14061412
func (p *partitionProducer) canAddToQueue(sr *sendRequest, uncompressedPayloadSize int64) bool {
14071413
if p.options.DisableBlockIfQueueFull {
14081414
if !p.publishSemaphore.TryAcquire() {
1409-
if sr.callback != nil {
1410-
sr.callback(nil, sr.msg, errSendQueueIsFull)
1411-
}
1415+
runCallback(sr.callback, nil, sr.msg, errSendQueueIsFull)
14121416
return false
14131417
}
14141418
if !p.client.memLimit.TryReserveMemory(uncompressedPayloadSize) {
14151419
p.publishSemaphore.Release()
1416-
if sr.callback != nil {
1417-
sr.callback(nil, sr.msg, errMemoryBufferIsFull)
1418-
}
1420+
runCallback(sr.callback, nil, sr.msg, errMemoryBufferIsFull)
14191421
return false
14201422
}
14211423

14221424
} else {
14231425
if !p.publishSemaphore.Acquire(sr.ctx) {
1424-
sr.callback(nil, sr.msg, errContextExpired)
1426+
runCallback(sr.callback, nil, sr.msg, errContextExpired)
14251427
return false
14261428
}
14271429
if !p.client.memLimit.ReserveMemory(sr.ctx, uncompressedPayloadSize) {
14281430
p.publishSemaphore.Release()
1429-
sr.callback(nil, sr.msg, errContextExpired)
1431+
runCallback(sr.callback, nil, sr.msg, errContextExpired)
14301432
return false
14311433
}
14321434
}

0 commit comments

Comments
 (0)