@@ -417,37 +417,18 @@ void ProducerImpl::sendAsyncWithStatsUpdate(const Message& msg, const SendCallba
417
417
callback (result, {});
418
418
};
419
419
420
+ auto & msgMetadata = msg.impl_ ->metadata ;
420
421
const bool compressed = !canAddToBatch (msg);
421
422
const auto payload =
422
423
compressed ? applyCompression (uncompressedPayload, conf_.getCompressionType ()) : uncompressedPayload;
423
424
const auto compressedSize = static_cast <uint32_t >(payload.readableBytes ());
424
425
const auto maxMessageSize = static_cast <uint32_t >(ClientConnection::getMaxMessageSize ());
425
426
426
- if (compressed && compressedSize > ClientConnection::getMaxMessageSize () && !chunkingEnabled_) {
427
- LOG_WARN (getName () << " - compressed Message payload size " << payload.readableBytes ()
428
- << " cannot exceed " << ClientConnection::getMaxMessageSize ()
429
- << " bytes unless chunking is enabled" );
430
- handleFailedResult (ResultMessageTooBig);
431
- return ;
432
- }
433
-
434
- auto & msgMetadata = msg.impl_ ->metadata ;
435
427
if (!msgMetadata.has_replicated_from () && msgMetadata.has_producer_name ()) {
436
428
handleFailedResult (ResultInvalidMessage);
437
429
return ;
438
430
}
439
431
440
- const int totalChunks =
441
- canAddToBatch (msg) ? 1 : getNumOfChunks (compressedSize, ClientConnection::getMaxMessageSize ());
442
- // Each chunk should be sent individually, so try to acquire extra permits for chunks.
443
- for (int i = 0 ; i < (totalChunks - 1 ); i++) {
444
- const auto result = canEnqueueRequest (0 ); // size is 0 because the memory has already reserved
445
- if (result != ResultOk) {
446
- handleFailedResult (result);
447
- return ;
448
- }
449
- }
450
-
451
432
Lock lock (mutex_);
452
433
uint64_t sequenceId;
453
434
if (!msgMetadata.has_sequence_id ()) {
@@ -457,6 +438,31 @@ void ProducerImpl::sendAsyncWithStatsUpdate(const Message& msg, const SendCallba
457
438
}
458
439
setMessageMetadata (msg, sequenceId, uncompressedSize);
459
440
441
+ auto payloadChunkSize = maxMessageSize;
442
+ int totalChunks;
443
+ if (!compressed || !chunkingEnabled_) {
444
+ totalChunks = 1 ;
445
+ } else {
446
+ const auto metadataSize = static_cast <uint32_t >(msgMetadata.ByteSizeLong ());
447
+ if (metadataSize >= maxMessageSize) {
448
+ LOG_WARN (getName () << " - metadata size " << metadataSize << " cannot exceed " << maxMessageSize
449
+ << " bytes" );
450
+ handleFailedResult (ResultMessageTooBig);
451
+ return ;
452
+ }
453
+ payloadChunkSize = maxMessageSize - metadataSize;
454
+ totalChunks = getNumOfChunks (compressedSize, payloadChunkSize);
455
+ }
456
+
457
+ // Each chunk should be sent individually, so try to acquire extra permits for chunks.
458
+ for (int i = 0 ; i < (totalChunks - 1 ); i++) {
459
+ const auto result = canEnqueueRequest (0 ); // size is 0 because the memory has already reserved
460
+ if (result != ResultOk) {
461
+ handleFailedResult (result);
462
+ return ;
463
+ }
464
+ }
465
+
460
466
if (canAddToBatch (msg)) {
461
467
// Batching is enabled and the message is not delayed
462
468
if (!batchMessageContainer_->hasEnoughSpace (msg)) {
@@ -508,7 +514,7 @@ void ProducerImpl::sendAsyncWithStatsUpdate(const Message& msg, const SendCallba
508
514
if (sendChunks) {
509
515
msgMetadata.set_chunk_id (chunkId);
510
516
}
511
- const uint32_t endIndex = std::min (compressedSize, beginIndex + maxMessageSize );
517
+ const uint32_t endIndex = std::min (compressedSize, beginIndex + payloadChunkSize );
512
518
auto chunkedPayload = payload.slice (beginIndex, endIndex - beginIndex);
513
519
beginIndex = endIndex;
514
520
@@ -517,10 +523,26 @@ void ProducerImpl::sendAsyncWithStatsUpdate(const Message& msg, const SendCallba
517
523
handleFailedResult (ResultCryptoError);
518
524
return ;
519
525
}
526
+ OpSendMsg op{msgMetadata, encryptedPayload, (chunkId == totalChunks - 1 ) ? callback : nullptr ,
527
+ producerId_, sequenceId, conf_.getSendTimeout (),
528
+ 1 , uncompressedSize};
529
+
530
+ if (!chunkingEnabled_) {
531
+ const uint32_t msgMetadataSize = op.metadata_ .ByteSize ();
532
+ const uint32_t payloadSize = op.payload_ .readableBytes ();
533
+ const uint32_t msgHeadersAndPayloadSize = msgMetadataSize + payloadSize;
534
+ if (msgHeadersAndPayloadSize > maxMessageSize) {
535
+ lock.unlock ();
536
+ releaseSemaphoreForSendOp (op);
537
+ LOG_WARN (getName ()
538
+ << " - compressed Message size " << msgHeadersAndPayloadSize << " cannot exceed "
539
+ << maxMessageSize << " bytes unless chunking is enabled" );
540
+ handleFailedResult (ResultMessageTooBig);
541
+ return ;
542
+ }
543
+ }
520
544
521
- sendMessage (OpSendMsg{msgMetadata, encryptedPayload,
522
- (chunkId == totalChunks - 1 ) ? callback : nullptr , producerId_, sequenceId,
523
- conf_.getSendTimeout (), 1 , uncompressedSize});
545
+ sendMessage (op);
524
546
}
525
547
}
526
548
}
0 commit comments